blob: 3cc2d4a81f3bc271042455bd71a9e54d27656778 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.security.auth.login;
27
28import javax.security.auth.AuthPermission;
29
30import java.io.*;
31import java.util.*;
32import java.net.URI;
33import java.security.AccessController;
34import java.security.PrivilegedAction;
35import java.security.PrivilegedExceptionAction;
36import java.security.PrivilegedActionException;
37import java.security.NoSuchAlgorithmException;
38import java.security.NoSuchProviderException;
39import java.security.Provider;
40import java.security.Security;
41import java.security.SecurityPermission;
42
43import sun.security.jca.GetInstance;
44
45/**
46 * A Configuration object is responsible for specifying which LoginModules
47 * should be used for a particular application, and in what order the
48 * LoginModules should be invoked.
49 *
50 * <p> A login configuration contains the following information.
51 * Note that this example only represents the default syntax for the
52 * <code>Configuration</code>. Subclass implementations of this class
53 * may implement alternative syntaxes and may retrieve the
54 * <code>Configuration</code> from any source such as files, databases,
55 * or servers.
56 *
57 * <pre>
58 * Name {
59 * ModuleClass Flag ModuleOptions;
60 * ModuleClass Flag ModuleOptions;
61 * ModuleClass Flag ModuleOptions;
62 * };
63 * Name {
64 * ModuleClass Flag ModuleOptions;
65 * ModuleClass Flag ModuleOptions;
66 * };
67 * other {
68 * ModuleClass Flag ModuleOptions;
69 * ModuleClass Flag ModuleOptions;
70 * };
71 * </pre>
72 *
73 * <p> Each entry in the <code>Configuration</code> is indexed via an
74 * application name, <i>Name</i>, and contains a list of
75 * LoginModules configured for that application. Each <code>LoginModule</code>
76 * is specified via its fully qualified class name.
77 * Authentication proceeds down the module list in the exact order specified.
78 * If an application does not have specific entry,
79 * it defaults to the specific entry for "<i>other</i>".
80 *
81 * <p> The <i>Flag</i> value controls the overall behavior as authentication
82 * proceeds down the stack. The following represents a description of the
83 * valid values for <i>Flag</i> and their respective semantics:
84 *
85 * <pre>
86 * 1) Required - The <code>LoginModule</code> is required to succeed.
87 * If it succeeds or fails, authentication still continues
88 * to proceed down the <code>LoginModule</code> list.
89 *
90 * 2) Requisite - The <code>LoginModule</code> is required to succeed.
91 * If it succeeds, authentication continues down the
92 * <code>LoginModule</code> list. If it fails,
93 * control immediately returns to the application
94 * (authentication does not proceed down the
95 * <code>LoginModule</code> list).
96 *
97 * 3) Sufficient - The <code>LoginModule</code> is not required to
98 * succeed. If it does succeed, control immediately
99 * 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 &lt;JAVA_HOME&gt;/lib/security/java.security.
180 * &lt;JAVA_HOME&gt; 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 &amp; Reference </a>
190 * for a list of standard Configuration types.
191 *
192 * @see javax.security.auth.login.LoginContext
193 */
194public abstract class Configuration {
195
196 private static Configuration configuration;
197 private static ClassLoader contextClassLoader;
198
199 static {
200 contextClassLoader = AccessController.doPrivileged
201 (new PrivilegedAction<ClassLoader>() {
202 public ClassLoader run() {
203 return Thread.currentThread().getContextClassLoader();
204 }
205 });
206 };
207
208 private static void checkPermission(String type) {
209 SecurityManager sm = System.getSecurityManager();
210 if (sm != null) {
211 sm.checkPermission(new AuthPermission
212 ("createLoginConfiguration." + type));
213 }
214 }
215
216 /**
217 * Sole constructor. (For invocation by subclass constructors, typically
218 * implicit.)
219 */
220 protected Configuration() { }
221
222 /**
223 * Get the installed login Configuration.
224 *
225 * <p>
226 *
227 * @return the login Configuration. If a Configuration object was set
228 * via the <code>Configuration.setConfiguration</code> method,
229 * then that object is returned. Otherwise, a default
230 * Configuration object is returned.
231 *
232 * @exception SecurityException if the caller does not have permission
233 * to retrieve the Configuration.
234 *
235 * @see #setConfiguration
236 */
237 public static synchronized Configuration getConfiguration() {
238
239 SecurityManager sm = System.getSecurityManager();
240 if (sm != null)
241 sm.checkPermission(new AuthPermission("getLoginConfiguration"));
242
243 if (configuration == null) {
244 String config_class = null;
245 config_class = AccessController.doPrivileged
246 (new PrivilegedAction<String>() {
247 public String run() {
248 return java.security.Security.getProperty
249 ("login.configuration.provider");
250 }
251 });
252 if (config_class == null) {
253 config_class = "com.sun.security.auth.login.ConfigFile";
254 }
255
256 try {
257 final String finalClass = config_class;
258 configuration = AccessController.doPrivileged
259 (new PrivilegedExceptionAction<Configuration>() {
260 public Configuration run() throws ClassNotFoundException,
261 InstantiationException,
262 IllegalAccessException {
263 return (Configuration)Class.forName
264 (finalClass,
265 true,
266 contextClassLoader).newInstance();
267 }
268 });
269 } catch (PrivilegedActionException e) {
270 Exception ee = e.getException();
271 if (ee instanceof InstantiationException) {
272 throw (SecurityException) new
273 SecurityException
274 ("Configuration error:" +
275 ee.getCause().getMessage() +
276 "\n").initCause(ee.getCause());
277 } else {
278 throw (SecurityException) new
279 SecurityException
280 ("Configuration error: " +
281 ee.toString() +
282 "\n").initCause(ee);
283 }
284 }
285 }
286 return configuration;
287 }
288
289 /**
290 * Set the login <code>Configuration</code>.
291 *
292 * <p>
293 *
294 * @param configuration the new <code>Configuration</code>
295 *
296 * @exception SecurityException if the current thread does not have
297 * Permission to set the <code>Configuration</code>.
298 *
299 * @see #getConfiguration
300 */
301 public static void setConfiguration(Configuration configuration) {
302 SecurityManager sm = System.getSecurityManager();
303 if (sm != null)
304 sm.checkPermission(new AuthPermission("setLoginConfiguration"));
305 Configuration.configuration = configuration;
306 }
307
308 /**
309 * Returns a Configuration object of the specified type.
310 *
311 * <p> This method traverses the list of registered security providers,
312 * starting with the most preferred Provider.
313 * A new Configuration object encapsulating the
314 * ConfigurationSpi implementation from the first
315 * Provider that supports the specified type is returned.
316 *
317 * <p> Note that the list of registered providers may be retrieved via
318 * the {@link Security#getProviders() Security.getProviders()} method.
319 *
320 * @param type the specified Configuration type. See Appendix A in the
321 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
322 * Java Cryptography Architecture API Specification &amp; Reference </a>
323 * for a list of standard Configuration types.
324 *
325 * @param params parameters for the Configuration, which may be null.
326 *
327 * @return the new Configuration object.
328 *
329 * @exception SecurityException if the caller does not have permission
330 * to get a Configuration instance for the specified type.
331 *
332 * @exception NullPointerException if the specified type is null.
333 *
334 * @exception IllegalArgumentException if the specified parameters
335 * are not understood by the ConfigurationSpi implementation
336 * from the selected Provider.
337 *
338 * @exception NoSuchAlgorithmException if no Provider supports a
339 * ConfigurationSpi implementation for the specified type.
340 *
341 * @see Provider
342 * @since 1.6
343 */
344 public static Configuration getInstance(String type,
345 Configuration.Parameters params)
346 throws NoSuchAlgorithmException {
347
348 checkPermission(type);
349 try {
350 GetInstance.Instance instance = GetInstance.getInstance
351 ("Configuration",
352 ConfigurationSpi.class,
353 type,
354 params);
355 return new ConfigDelegate((ConfigurationSpi)instance.impl,
356 instance.provider,
357 type,
358 params);
359 } catch (NoSuchAlgorithmException nsae) {
360 return handleException (nsae);
361 }
362 }
363
364 /**
365 * Returns a Configuration object of the specified type.
366 *
367 * <p> A new Configuration object encapsulating the
368 * ConfigurationSpi implementation from the specified provider
369 * is returned. The specified provider must be registered
370 * in the provider list.
371 *
372 * <p> Note that the list of registered providers may be retrieved via
373 * the {@link Security#getProviders() Security.getProviders()} method.
374 *
375 * @param type the specified Configuration type. See Appendix A in the
376 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
377 * Java Cryptography Architecture API Specification &amp; Reference </a>
378 * for a list of standard Configuration types.
379 *
380 * @param params parameters for the Configuration, which may be null.
381 *
382 * @param provider the provider.
383 *
384 * @return the new Configuration object.
385 *
386 * @exception SecurityException if the caller does not have permission
387 * to get a Configuration instance for the specified type.
388 *
389 * @exception NullPointerException if the specified type is null.
390 *
391 * @exception IllegalArgumentException if the specified provider
392 * is null or empty,
393 * or if the specified parameters are not understood by
394 * the ConfigurationSpi implementation from the specified provider.
395 *
396 * @exception NoSuchProviderException if the specified provider is not
397 * registered in the security provider list.
398 *
399 * @exception NoSuchAlgorithmException if the specified provider does not
400 * support a ConfigurationSpi implementation for the specified
401 * type.
402 *
403 * @see Provider
404 * @since 1.6
405 */
406 public static Configuration getInstance(String type,
407 Configuration.Parameters params,
408 String provider)
409 throws NoSuchProviderException, NoSuchAlgorithmException {
410
411 if (provider == null || provider.length() == 0) {
412 throw new IllegalArgumentException("missing provider");
413 }
414
415 checkPermission(type);
416 try {
417 GetInstance.Instance instance = GetInstance.getInstance
418 ("Configuration",
419 ConfigurationSpi.class,
420 type,
421 params,
422 provider);
423 return new ConfigDelegate((ConfigurationSpi)instance.impl,
424 instance.provider,
425 type,
426 params);
427 } catch (NoSuchAlgorithmException nsae) {
428 return handleException (nsae);
429 }
430 }
431
432 /**
433 * Returns a Configuration object of the specified type.
434 *
435 * <p> A new Configuration object encapsulating the
436 * ConfigurationSpi implementation from the specified Provider
437 * object is returned. Note that the specified Provider object
438 * does not have to be registered in the provider list.
439 *
440 * @param type the specified Configuration type. See Appendix A in the
441 * <a href="../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
442 * Java Cryptography Architecture API Specification &amp; Reference </a>
443 * for a list of standard Configuration types.
444 *
445 * @param params parameters for the Configuration, which may be null.
446 *
447 * @param provider the Provider.
448 *
449 * @return the new Configuration object.
450 *
451 * @exception SecurityException if the caller does not have permission
452 * to get a Configuration instance for the specified type.
453 *
454 * @exception NullPointerException if the specified type is null.
455 *
456 * @exception IllegalArgumentException if the specified Provider is null,
457 * or if the specified parameters are not understood by
458 * the ConfigurationSpi implementation from the specified Provider.
459 *
460 * @exception NoSuchAlgorithmException if the specified Provider does not
461 * support a ConfigurationSpi implementation for the specified
462 * type.
463 *
464 * @see Provider
465 * @since 1.6
466 */
467 public static Configuration getInstance(String type,
468 Configuration.Parameters params,
469 Provider provider)
470 throws NoSuchAlgorithmException {
471
472 if (provider == null) {
473 throw new IllegalArgumentException("missing provider");
474 }
475
476 checkPermission(type);
477 try {
478 GetInstance.Instance instance = GetInstance.getInstance
479 ("Configuration",
480 ConfigurationSpi.class,
481 type,
482 params,
483 provider);
484 return new ConfigDelegate((ConfigurationSpi)instance.impl,
485 instance.provider,
486 type,
487 params);
488 } catch (NoSuchAlgorithmException nsae) {
489 return handleException (nsae);
490 }
491 }
492
493 private static Configuration handleException(NoSuchAlgorithmException nsae)
494 throws NoSuchAlgorithmException {
495 Throwable cause = nsae.getCause();
496 if (cause instanceof IllegalArgumentException) {
497 throw (IllegalArgumentException)cause;
498 }
499 throw nsae;
500 }
501
502 /**
503 * Return the Provider of this Configuration.
504 *
505 * <p> This Configuration instance will only have a Provider if it
506 * was obtained via a call to <code>Configuration.getInstance</code>.
507 * Otherwise this method returns null.
508 *
509 * @return the Provider of this Configuration, or null.
510 *
511 * @since 1.6
512 */
513 public Provider getProvider() {
514 return null;
515 }
516
517 /**
518 * Return the type of this Configuration.
519 *
520 * <p> This Configuration instance will only have a type if it
521 * was obtained via a call to <code>Configuration.getInstance</code>.
522 * Otherwise this method returns null.
523 *
524 * @return the type of this Configuration, or null.
525 *
526 * @since 1.6
527 */
528 public String getType() {
529 return null;
530 }
531
532 /**
533 * Return Configuration parameters.
534 *
535 * <p> This Configuration instance will only have parameters if it
536 * was obtained via a call to <code>Configuration.getInstance</code>.
537 * Otherwise this method returns null.
538 *
539 * @return Configuration parameters, or null.
540 *
541 * @since 1.6
542 */
543 public Configuration.Parameters getParameters() {
544 return null;
545 }
546
547 /**
548 * Retrieve the AppConfigurationEntries for the specified <i>name</i>
549 * from this Configuration.
550 *
551 * <p>
552 *
553 * @param name the name used to index the Configuration.
554 *
555 * @return an array of AppConfigurationEntries for the specified <i>name</i>
556 * from this Configuration, or null if there are no entries
557 * for the specified <i>name</i>
558 */
559 public abstract AppConfigurationEntry[] getAppConfigurationEntry
560 (String name);
561
562 /**
563 * Refresh and reload the Configuration.
564 *
565 * <p> This method causes this Configuration object to refresh/reload its
566 * contents in an implementation-dependent manner.
567 * For example, if this Configuration object stores its entries in a file,
568 * calling <code>refresh</code> may cause the file to be re-read.
569 *
570 * <p> The default implementation of this method does nothing.
571 * This method should be overridden if a refresh operation is supported
572 * by the implementation.
573 *
574 * @exception SecurityException if the caller does not have permission
575 * to refresh its Configuration.
576 */
577 public void refresh() { }
578
579 /**
580 * This subclass is returned by the getInstance calls. All Configuration
581 * calls are delegated to the underlying ConfigurationSpi.
582 */
583 private static class ConfigDelegate extends Configuration {
584
585 private ConfigurationSpi spi;
586 private Provider p;
587 private String type;
588 private Configuration.Parameters params;
589
590 private ConfigDelegate(ConfigurationSpi spi, Provider p,
591 String type, Configuration.Parameters params) {
592 this.spi = spi;
593 this.p = p;
594 this.type = type;
595 this.params = params;
596 }
597
598 public String getType() { return type; }
599
600 public Configuration.Parameters getParameters() { return params; }
601
602 public Provider getProvider() { return p; }
603
604 public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
605 return spi.engineGetAppConfigurationEntry(name);
606 }
607
608 public void refresh() {
609 spi.engineRefresh();
610 }
611 }
612
613 /**
614 * This represents a marker interface for Configuration parameters.
615 *
616 * @since 1.6
617 */
618 public static interface Parameters { }
619}