001 /*
002 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.security.auth.login;
027
028 import javax.security.auth.AuthPermission;
029
030 import java.io.*;
031 import java.util.*;
032 import java.net.URI;
033 import java.security.AccessController;
034 import java.security.PrivilegedAction;
035 import java.security.PrivilegedExceptionAction;
036 import java.security.PrivilegedActionException;
037 import java.security.NoSuchAlgorithmException;
038 import java.security.NoSuchProviderException;
039 import java.security.Provider;
040 import java.security.Security;
041 import java.security.SecurityPermission;
042
043 import sun.security.jca.GetInstance;
044
045 /**
046 * A Configuration object is responsible for specifying which LoginModules
047 * should be used for a particular application, and in what order the
048 * LoginModules should be invoked.
049 *
050 * <p> A login configuration contains the following information.
051 * Note that this example only represents the default syntax for the
052 * <code>Configuration</code>. Subclass implementations of this class
053 * may implement alternative syntaxes and may retrieve the
054 * <code>Configuration</code> from any source such as files, databases,
055 * or servers.
056 *
057 * <pre>
058 * Name {
059 * ModuleClass Flag ModuleOptions;
060 * ModuleClass Flag ModuleOptions;
061 * ModuleClass Flag ModuleOptions;
062 * };
063 * Name {
064 * ModuleClass Flag ModuleOptions;
065 * ModuleClass Flag ModuleOptions;
066 * };
067 * other {
068 * ModuleClass Flag ModuleOptions;
069 * ModuleClass Flag ModuleOptions;
070 * };
071 * </pre>
072 *
073 * <p> Each entry in the <code>Configuration</code> is indexed via an
074 * application name, <i>Name</i>, and contains a list of
075 * LoginModules configured for that application. Each <code>LoginModule</code>
076 * is specified via its fully qualified class name.
077 * Authentication proceeds down the module list in the exact order specified.
078 * If an application does not have specific entry,
079 * it defaults to the specific entry for "<i>other</i>".
080 *
081 * <p> The <i>Flag</i> value controls the overall behavior as authentication
082 * proceeds down the stack. The following represents a description of the
083 * valid values for <i>Flag</i> and their respective semantics:
084 *
085 * <pre>
086 * 1) Required - The <code>LoginModule</code> is required to succeed.
087 * If it succeeds or fails, authentication still continues
088 * to proceed down the <code>LoginModule</code> list.
089 *
090 * 2) Requisite - The <code>LoginModule</code> is required to succeed.
091 * If it succeeds, authentication continues down the
092 * <code>LoginModule</code> list. If it fails,
093 * control immediately returns to the application
094 * (authentication does not proceed down the
095 * <code>LoginModule</code> list).
096 *
097 * 3) Sufficient - The <code>LoginModule</code> is not required to
098 * succeed. If it does succeed, control immediately
099 * returns to the application (authentication does not
100 * proceed down the <code>LoginModule</code> list).
101 * If it fails, authentication continues down the
102 * <code>LoginModule</code> list.
103 *
104 * 4) Optional - The <code>LoginModule</code> is not required to
105 * succeed. If it succeeds or fails,
106 * authentication still continues to proceed down the
107 * <code>LoginModule</code> list.
108 * </pre>
109 *
110 * <p> The overall authentication succeeds only if all <i>Required</i> and
111 * <i>Requisite</i> LoginModules succeed. If a <i>Sufficient</i>
112 * <code>LoginModule</code> is configured and succeeds,
113 * then only the <i>Required</i> and <i>Requisite</i> LoginModules prior to
114 * that <i>Sufficient</i> <code>LoginModule</code> need to have succeeded for
115 * the overall authentication to succeed. If no <i>Required</i> or
116 * <i>Requisite</i> LoginModules are configured for an application,
117 * then at least one <i>Sufficient</i> or <i>Optional</i>
118 * <code>LoginModule</code> must succeed.
119 *
120 * <p> <i>ModuleOptions</i> is a space separated list of
121 * <code>LoginModule</code>-specific values which are passed directly to
122 * the underlying LoginModules. Options are defined by the
123 * <code>LoginModule</code> itself, and control the behavior within it.
124 * For example, a <code>LoginModule</code> may define options to support
125 * debugging/testing capabilities. The correct way to specify options in the
126 * <code>Configuration</code> is by using the following key-value pairing:
127 * <i>debug="true"</i>. The key and value should be separated by an
128 * 'equals' symbol, and the value should be surrounded by double quotes.
129 * If a String in the form, ${system.property}, occurs in the value,
130 * it will be expanded to the value of the system property.
131 * Note that there is no limit to the number of
132 * options a <code>LoginModule</code> may define.
133 *
134 * <p> The following represents an example <code>Configuration</code> entry
135 * based on the syntax above:
136 *
137 * <pre>
138 * Login {
139 * com.sun.security.auth.module.UnixLoginModule required;
140 * com.sun.security.auth.module.Krb5LoginModule optional
141 * useTicketCache="true"
142 * ticketCache="${user.home}${/}tickets";
143 * };
144 * </pre>
145 *
146 * <p> This <code>Configuration</code> specifies that an application named,
147 * "Login", requires users to first authenticate to the
148 * <i>com.sun.security.auth.module.UnixLoginModule</i>, which is
149 * required to succeed. Even if the <i>UnixLoginModule</i>
150 * authentication fails, the
151 * <i>com.sun.security.auth.module.Krb5LoginModule</i>
152 * still gets invoked. This helps hide the source of failure.
153 * Since the <i>Krb5LoginModule</i> is <i>Optional</i>, the overall
154 * authentication succeeds only if the <i>UnixLoginModule</i>
155 * (<i>Required</i>) succeeds.
156 *
157 * <p> Also note that the LoginModule-specific options,
158 * <i>useTicketCache="true"</i> and
159 * <i>ticketCache=${user.home}${/}tickets"</i>,
160 * are passed to the <i>Krb5LoginModule</i>.
161 * These options instruct the <i>Krb5LoginModule</i> to
162 * use the ticket cache at the specified location.
163 * The system properties, <i>user.home</i> and <i>/</i>
164 * (file.separator), are expanded to their respective values.
165 *
166 * <p> There is only one Configuration object installed in the runtime at any
167 * given time. A Configuration object can be installed by calling the
168 * <code>setConfiguration</code> method. The installed Configuration object
169 * can be obtained by calling the <code>getConfiguration</code> method.
170 *
171 * <p> If no Configuration object has been installed in the runtime, a call to
172 * <code>getConfiguration</code> installs an instance of the default
173 * Configuration implementation (a default subclass implementation of this
174 * abstract class).
175 * The default Configuration implementation can be changed by setting the value
176 * of the "login.configuration.provider" security property (in the Java
177 * security properties file) to the fully qualified name of the desired
178 * Configuration subclass implementation. The Java security properties file
179 * is located in the file named <JAVA_HOME>/lib/security/java.security.
180 * <JAVA_HOME> refers to the value of the java.home system property,
181 * and specifies the directory where the JRE is installed.
182 *
183 * <p> Application code can directly subclass Configuration to provide a custom
184 * implementation. In addition, an instance of a Configuration object can be
185 * constructed by invoking one of the <code>getInstance</code> factory methods
186 * with a standard type. The default policy type is "JavaLoginConfig".
187 * See Appendix A in the
188 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
189 * Java Cryptography Architecture API Specification & Reference </a>
190 * for a list of standard Configuration types.
191 *
192 * @version 1.70, 05/05/07
193 * @see javax.security.auth.login.LoginContext
194 */
195 public abstract class Configuration {
196
197 private static Configuration configuration;
198 private static ClassLoader contextClassLoader;
199
200 static {
201 contextClassLoader = AccessController
202 .doPrivileged(new PrivilegedAction<ClassLoader>() {
203 public ClassLoader run() {
204 return Thread.currentThread()
205 .getContextClassLoader();
206 }
207 });
208 };
209
210 private static void checkPermission(String type) {
211 SecurityManager sm = System.getSecurityManager();
212 if (sm != null) {
213 sm.checkPermission(new AuthPermission(
214 "createLoginConfiguration." + type));
215 }
216 }
217
218 /**
219 * Sole constructor. (For invocation by subclass constructors, typically
220 * implicit.)
221 */
222 protected Configuration() {
223 }
224
225 /**
226 * Get the installed login Configuration.
227 *
228 * <p>
229 *
230 * @return the login Configuration. If a Configuration object was set
231 * via the <code>Configuration.setConfiguration</code> method,
232 * then that object is returned. Otherwise, a default
233 * Configuration object is returned.
234 *
235 * @exception SecurityException if the caller does not have permission
236 * to retrieve the Configuration.
237 *
238 * @see #setConfiguration
239 */
240 public static synchronized Configuration getConfiguration() {
241
242 SecurityManager sm = System.getSecurityManager();
243 if (sm != null)
244 sm.checkPermission(new AuthPermission(
245 "getLoginConfiguration"));
246
247 if (configuration == null) {
248 String config_class = null;
249 config_class = AccessController
250 .doPrivileged(new PrivilegedAction<String>() {
251 public String run() {
252 return java.security.Security
253 .getProperty("login.configuration.provider");
254 }
255 });
256 if (config_class == null) {
257 config_class = "com.sun.security.auth.login.ConfigFile";
258 }
259
260 try {
261 final String finalClass = config_class;
262 configuration = AccessController
263 .doPrivileged(new PrivilegedExceptionAction<Configuration>() {
264 public Configuration run()
265 throws ClassNotFoundException,
266 InstantiationException,
267 IllegalAccessException {
268 return (Configuration) Class.forName(
269 finalClass, true,
270 contextClassLoader)
271 .newInstance();
272 }
273 });
274 } catch (PrivilegedActionException e) {
275 Exception ee = e.getException();
276 if (ee instanceof InstantiationException) {
277 throw (SecurityException) new SecurityException(
278 "Configuration error:"
279 + ee.getCause().getMessage() + "\n")
280 .initCause(ee.getCause());
281 } else {
282 throw (SecurityException) new SecurityException(
283 "Configuration error: " + ee.toString()
284 + "\n").initCause(ee);
285 }
286 }
287 }
288 return configuration;
289 }
290
291 /**
292 * Set the login <code>Configuration</code>.
293 *
294 * <p>
295 *
296 * @param configuration the new <code>Configuration</code>
297 *
298 * @exception SecurityException if the current thread does not have
299 * Permission to set the <code>Configuration</code>.
300 *
301 * @see #getConfiguration
302 */
303 public static void setConfiguration(Configuration configuration) {
304 SecurityManager sm = System.getSecurityManager();
305 if (sm != null)
306 sm.checkPermission(new AuthPermission(
307 "setLoginConfiguration"));
308 Configuration.configuration = configuration;
309 }
310
311 /**
312 * Returns a Configuration object of the specified type.
313 *
314 * <p> This method traverses the list of registered security providers,
315 * starting with the most preferred Provider.
316 * A new Configuration object encapsulating the
317 * ConfigurationSpi implementation from the first
318 * Provider that supports the specified type is returned.
319 *
320 * <p> Note that the list of registered providers may be retrieved via
321 * the {@link Security#getProviders() Security.getProviders()} method.
322 *
323 * @param type the specified Configuration type. See Appendix A in the
324 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
325 * Java Cryptography Architecture API Specification & Reference </a>
326 * for a list of standard Configuration types.
327 *
328 * @param params parameters for the Configuration, which may be null.
329 *
330 * @return the new Configuration object.
331 *
332 * @exception SecurityException if the caller does not have permission
333 * to get a Configuration instance for the specified type.
334 *
335 * @exception NullPointerException if the specified type is null.
336 *
337 * @exception IllegalArgumentException if the specified parameters
338 * are not understood by the ConfigurationSpi implementation
339 * from the selected Provider.
340 *
341 * @exception NoSuchAlgorithmException if no Provider supports a
342 * ConfigurationSpi implementation for the specified type.
343 *
344 * @see Provider
345 * @since 1.6
346 */
347 public static Configuration getInstance(String type,
348 Configuration.Parameters params)
349 throws NoSuchAlgorithmException {
350
351 checkPermission(type);
352 try {
353 GetInstance.Instance instance = GetInstance.getInstance(
354 "Configuration", ConfigurationSpi.class, type,
355 params);
356 return new ConfigDelegate((ConfigurationSpi) instance.impl,
357 instance.provider, type, params);
358 } catch (NoSuchAlgorithmException nsae) {
359 return handleException(nsae);
360 }
361 }
362
363 /**
364 * Returns a Configuration object of the specified type.
365 *
366 * <p> A new Configuration object encapsulating the
367 * ConfigurationSpi implementation from the specified provider
368 * is returned. The specified provider must be registered
369 * in the provider list.
370 *
371 * <p> Note that the list of registered providers may be retrieved via
372 * the {@link Security#getProviders() Security.getProviders()} method.
373 *
374 * @param type the specified Configuration type. See Appendix A in the
375 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
376 * Java Cryptography Architecture API Specification & Reference </a>
377 * for a list of standard Configuration types.
378 *
379 * @param params parameters for the Configuration, which may be null.
380 *
381 * @param provider the provider.
382 *
383 * @return the new Configuration object.
384 *
385 * @exception SecurityException if the caller does not have permission
386 * to get a Configuration instance for the specified type.
387 *
388 * @exception NullPointerException if the specified type is null.
389 *
390 * @exception IllegalArgumentException if the specified provider
391 * is null or empty,
392 * or if the specified parameters are not understood by
393 * the ConfigurationSpi implementation from the specified provider.
394 *
395 * @exception NoSuchProviderException if the specified provider is not
396 * registered in the security provider list.
397 *
398 * @exception NoSuchAlgorithmException if the specified provider does not
399 * support a ConfigurationSpi implementation for the specified
400 * type.
401 *
402 * @see Provider
403 * @since 1.6
404 */
405 public static Configuration getInstance(String type,
406 Configuration.Parameters params, String provider)
407 throws NoSuchProviderException, NoSuchAlgorithmException {
408
409 if (provider == null || provider.length() == 0) {
410 throw new IllegalArgumentException("missing provider");
411 }
412
413 checkPermission(type);
414 try {
415 GetInstance.Instance instance = GetInstance.getInstance(
416 "Configuration", ConfigurationSpi.class, type,
417 params, provider);
418 return new ConfigDelegate((ConfigurationSpi) instance.impl,
419 instance.provider, type, params);
420 } catch (NoSuchAlgorithmException nsae) {
421 return handleException(nsae);
422 }
423 }
424
425 /**
426 * Returns a Configuration object of the specified type.
427 *
428 * <p> A new Configuration object encapsulating the
429 * ConfigurationSpi implementation from the specified Provider
430 * object is returned. Note that the specified Provider object
431 * does not have to be registered in the provider list.
432 *
433 * @param type the specified Configuration type. See Appendix A in the
434 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
435 * Java Cryptography Architecture API Specification & Reference </a>
436 * for a list of standard Configuration types.
437 *
438 * @param params parameters for the Configuration, which may be null.
439 *
440 * @param provider the Provider.
441 *
442 * @return the new Configuration object.
443 *
444 * @exception SecurityException if the caller does not have permission
445 * to get a Configuration instance for the specified type.
446 *
447 * @exception NullPointerException if the specified type is null.
448 *
449 * @exception IllegalArgumentException if the specified Provider is null,
450 * or if the specified parameters are not understood by
451 * the ConfigurationSpi implementation from the specified Provider.
452 *
453 * @exception NoSuchAlgorithmException if the specified Provider does not
454 * support a ConfigurationSpi implementation for the specified
455 * type.
456 *
457 * @see Provider
458 * @since 1.6
459 */
460 public static Configuration getInstance(String type,
461 Configuration.Parameters params, Provider provider)
462 throws NoSuchAlgorithmException {
463
464 if (provider == null) {
465 throw new IllegalArgumentException("missing provider");
466 }
467
468 checkPermission(type);
469 try {
470 GetInstance.Instance instance = GetInstance.getInstance(
471 "Configuration", ConfigurationSpi.class, type,
472 params, provider);
473 return new ConfigDelegate((ConfigurationSpi) instance.impl,
474 instance.provider, type, params);
475 } catch (NoSuchAlgorithmException nsae) {
476 return handleException(nsae);
477 }
478 }
479
480 private static Configuration handleException(
481 NoSuchAlgorithmException nsae)
482 throws NoSuchAlgorithmException {
483 Throwable cause = nsae.getCause();
484 if (cause instanceof IllegalArgumentException) {
485 throw (IllegalArgumentException) cause;
486 }
487 throw nsae;
488 }
489
490 /**
491 * Return the Provider of this Configuration.
492 *
493 * <p> This Configuration instance will only have a Provider if it
494 * was obtained via a call to <code>Configuration.getInstance</code>.
495 * Otherwise this method returns null.
496 *
497 * @return the Provider of this Configuration, or null.
498 *
499 * @since 1.6
500 */
501 public Provider getProvider() {
502 return null;
503 }
504
505 /**
506 * Return the type of this Configuration.
507 *
508 * <p> This Configuration instance will only have a type if it
509 * was obtained via a call to <code>Configuration.getInstance</code>.
510 * Otherwise this method returns null.
511 *
512 * @return the type of this Configuration, or null.
513 *
514 * @since 1.6
515 */
516 public String getType() {
517 return null;
518 }
519
520 /**
521 * Return Configuration parameters.
522 *
523 * <p> This Configuration instance will only have parameters if it
524 * was obtained via a call to <code>Configuration.getInstance</code>.
525 * Otherwise this method returns null.
526 *
527 * @return Configuration parameters, or null.
528 *
529 * @since 1.6
530 */
531 public Configuration.Parameters getParameters() {
532 return null;
533 }
534
535 /**
536 * Retrieve the AppConfigurationEntries for the specified <i>name</i>
537 * from this Configuration.
538 *
539 * <p>
540 *
541 * @param name the name used to index the Configuration.
542 *
543 * @return an array of AppConfigurationEntries for the specified <i>name</i>
544 * from this Configuration, or null if there are no entries
545 * for the specified <i>name</i>
546 */
547 public abstract AppConfigurationEntry[] getAppConfigurationEntry(
548 String name);
549
550 /**
551 * Refresh and reload the Configuration.
552 *
553 * <p> This method causes this Configuration object to refresh/reload its
554 * contents in an implementation-dependent manner.
555 * For example, if this Configuration object stores its entries in a file,
556 * calling <code>refresh</code> may cause the file to be re-read.
557 *
558 * <p> The default implementation of this method does nothing.
559 * This method should be overridden if a refresh operation is supported
560 * by the implementation.
561 *
562 * @exception SecurityException if the caller does not have permission
563 * to refresh its Configuration.
564 */
565 public void refresh() {
566 }
567
568 /**
569 * This subclass is returned by the getInstance calls. All Configuration
570 * calls are delegated to the underlying ConfigurationSpi.
571 */
572 private static class ConfigDelegate extends Configuration {
573
574 private ConfigurationSpi spi;
575 private Provider p;
576 private String type;
577 private Configuration.Parameters params;
578
579 private ConfigDelegate(ConfigurationSpi spi, Provider p,
580 String type, Configuration.Parameters params) {
581 this .spi = spi;
582 this .p = p;
583 this .type = type;
584 this .params = params;
585 }
586
587 public String getType() {
588 return type;
589 }
590
591 public Configuration.Parameters getParameters() {
592 return params;
593 }
594
595 public Provider getProvider() {
596 return p;
597 }
598
599 public AppConfigurationEntry[] getAppConfigurationEntry(
600 String name) {
601 return spi.engineGetAppConfigurationEntry(name);
602 }
603
604 public void refresh() {
605 spi.engineRefresh();
606 }
607 }
608
609 /**
610 * This represents a marker interface for Configuration parameters.
611 *
612 * @since 1.6
613 */
614 public static interface Parameters {
615 }
616 }
|