1 /* 2 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.security.auth.login; 27 28 import javax.security.auth.AuthPermission; 29 30 import java.security.AccessController; 31 import java.security.PrivilegedAction; 32 import java.security.PrivilegedExceptionAction; 33 import java.security.PrivilegedActionException; 34 import java.security.NoSuchAlgorithmException; 35 import java.security.NoSuchProviderException; 36 import java.security.Provider; 37 import java.security.Security; 38 import java.util.Objects; 39 40 import sun.security.jca.GetInstance; 41 42 /** 43 * A Configuration object is responsible for specifying which LoginModules 44 * should be used for a particular application, and in what order the 45 * LoginModules should be invoked. 46 * 47 * <p> A login configuration contains the following information. 48 * Note that this example only represents the default syntax for the 49 * {@code Configuration}. Subclass implementations of this class 50 * may implement alternative syntaxes and may retrieve the 51 * {@code Configuration} from any source such as files, databases, 52 * or servers. 53 * 54 * <pre> 55 * Name { 56 * ModuleClass Flag ModuleOptions; 57 * ModuleClass Flag ModuleOptions; 58 * ModuleClass Flag ModuleOptions; 59 * }; 60 * Name { 61 * ModuleClass Flag ModuleOptions; 62 * ModuleClass Flag ModuleOptions; 63 * }; 64 * other { 65 * ModuleClass Flag ModuleOptions; 66 * ModuleClass Flag ModuleOptions; 67 * }; 68 * </pre> 69 * 70 * <p> Each entry in the {@code Configuration} is indexed via an 71 * application name, <i>Name</i>, and contains a list of 72 * LoginModules configured for that application. Each {@code LoginModule} 73 * is specified via its fully qualified class name. 74 * Authentication proceeds down the module list in the exact order specified. 75 * If an application does not have a specific entry, 76 * it defaults to the specific entry for "<i>other</i>". 77 * 78 * <p> The <i>Flag</i> value controls the overall behavior as authentication 79 * proceeds down the stack. The following represents a description of the 80 * valid values for <i>Flag</i> and their respective semantics: 81 * 82 * <pre> 83 * 1) Required - The {@code LoginModule} is required to succeed. 84 * If it succeeds or fails, authentication still continues 85 * to proceed down the {@code LoginModule} list. 86 * 87 * 2) Requisite - The {@code LoginModule} is required to succeed. 88 * If it succeeds, authentication continues down the 89 * {@code LoginModule} list. If it fails, 90 * control immediately returns to the application 91 * (authentication does not proceed down the 92 * {@code LoginModule} list). 93 * 94 * 3) Sufficient - The {@code LoginModule} is not required to 95 * succeed. If it does succeed, control immediately 96 * returns to the application (authentication does not 97 * proceed down the {@code LoginModule} list). 98 * If it fails, authentication continues down the 99 * {@code LoginModule} list. 100 * 101 * 4) Optional - The {@code LoginModule} is not required to 102 * succeed. If it succeeds or fails, 103 * authentication still continues to proceed down the 104 * {@code LoginModule} list. 105 * </pre> 106 * 107 * <p> The overall authentication succeeds only if all <i>Required</i> and 108 * <i>Requisite</i> LoginModules succeed. If a <i>Sufficient</i> 109 * {@code LoginModule} is configured and succeeds, 110 * then only the <i>Required</i> and <i>Requisite</i> LoginModules prior to 111 * that <i>Sufficient</i> {@code LoginModule} need to have succeeded for 112 * the overall authentication to succeed. If no <i>Required</i> or 113 * <i>Requisite</i> LoginModules are configured for an application, 114 * then at least one <i>Sufficient</i> or <i>Optional</i> 115 * {@code LoginModule} must succeed. 116 * 117 * <p> <i>ModuleOptions</i> is a space separated list of 118 * {@code LoginModule}-specific values which are passed directly to 119 * the underlying LoginModules. Options are defined by the 120 * {@code LoginModule} itself, and control the behavior within it. 121 * For example, a {@code LoginModule} may define options to support 122 * debugging/testing capabilities. The correct way to specify options in the 123 * {@code Configuration} is by using the following key-value pairing: 124 * <i>debug="true"</i>. The key and value should be separated by an 125 * 'equals' symbol, and the value should be surrounded by double quotes. 126 * If a String in the form, ${system.property}, occurs in the value, 127 * it will be expanded to the value of the system property. 128 * Note that there is no limit to the number of 129 * options a {@code LoginModule} may define. 130 * 131 * <p> The following represents an example {@code Configuration} entry 132 * based on the syntax above: 133 * 134 * <pre> 135 * Login { 136 * com.sun.security.auth.module.UnixLoginModule required; 137 * com.sun.security.auth.module.Krb5LoginModule optional 138 * useTicketCache="true" 139 * ticketCache="${user.home}${/}tickets"; 140 * }; 141 * </pre> 142 * 143 * <p> This {@code Configuration} specifies that an application named, 144 * "Login", requires users to first authenticate to the 145 * <i>com.sun.security.auth.module.UnixLoginModule</i>, which is 146 * required to succeed. Even if the <i>UnixLoginModule</i> 147 * authentication fails, the 148 * <i>com.sun.security.auth.module.Krb5LoginModule</i> 149 * still gets invoked. This helps hide the source of failure. 150 * Since the <i>Krb5LoginModule</i> is <i>Optional</i>, the overall 151 * authentication succeeds only if the <i>UnixLoginModule</i> 152 * (<i>Required</i>) succeeds. 153 * 154 * <p> Also note that the LoginModule-specific options, 155 * <i>useTicketCache="true"</i> and 156 * <i>ticketCache=${user.home}${/}tickets"</i>, 157 * are passed to the <i>Krb5LoginModule</i>. 158 * These options instruct the <i>Krb5LoginModule</i> to 159 * use the ticket cache at the specified location. 160 * The system properties, <i>user.home</i> and <i>/</i> 161 * (file.separator), are expanded to their respective values. 162 * 163 * <p> There is only one Configuration object installed in the runtime at any 164 * given time. A Configuration object can be installed by calling the 165 * {@code setConfiguration} method. The installed Configuration object 166 * can be obtained by calling the {@code getConfiguration} method. 167 * 168 * <p> If no Configuration object has been installed in the runtime, a call to 169 * {@code getConfiguration} installs an instance of the default 170 * Configuration implementation (a default subclass implementation of this 171 * abstract class). 172 * The default Configuration implementation can be changed by setting the value 173 * of the {@code login.configuration.provider} security property to the fully 174 * qualified name of the desired Configuration subclass implementation. 175 * 176 * <p> Application code can directly subclass Configuration to provide a custom 177 * implementation. In addition, an instance of a Configuration object can be 178 * constructed by invoking one of the {@code getInstance} factory methods 179 * with a standard type. The default policy type is "JavaLoginConfig". 180 * See the Configuration section in the <a href= 181 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration"> 182 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 183 * for a list of standard Configuration types. 184 * 185 * @see javax.security.auth.login.LoginContext 186 * @see java.security.Security security properties 187 */ 188 public abstract class Configuration { 189 190 private static Configuration configuration; 191 192 private final java.security.AccessControlContext acc = 193 java.security.AccessController.getContext(); 194 195 private static void checkPermission(String type) { 196 SecurityManager sm = System.getSecurityManager(); 197 if (sm != null) { 198 sm.checkPermission(new AuthPermission 199 ("createLoginConfiguration." + type)); 200 } 201 } 202 203 /** 204 * Sole constructor. (For invocation by subclass constructors, typically 205 * implicit.) 206 */ 207 protected Configuration() { } 208 209 /** 210 * Get the installed login Configuration. 211 * 212 * @return the login Configuration. If a Configuration object was set 213 * via the {@code Configuration.setConfiguration} method, 214 * then that object is returned. Otherwise, a default 215 * Configuration object is returned. 216 * 217 * @exception SecurityException if the caller does not have permission 218 * to retrieve the Configuration. 219 * 220 * @see #setConfiguration 221 */ 222 public static Configuration getConfiguration() { 223 224 SecurityManager sm = System.getSecurityManager(); 225 if (sm != null) 226 sm.checkPermission(new AuthPermission("getLoginConfiguration")); 227 228 synchronized (Configuration.class) { 229 if (configuration == null) { 230 String config_class = null; 231 config_class = AccessController.doPrivileged 232 (new PrivilegedAction<>() { 233 public String run() { 234 return java.security.Security.getProperty 235 ("login.configuration.provider"); 236 } 237 }); 238 if (config_class == null) { 239 config_class = "sun.security.provider.ConfigFile"; 240 } 241 242 try { 243 final String finalClass = config_class; 244 Configuration untrustedImpl = AccessController.doPrivileged( 245 new PrivilegedExceptionAction<>() { 246 public Configuration run() throws ClassNotFoundException, 247 InstantiationException, 248 IllegalAccessException { 249 Class<? extends Configuration> implClass = Class.forName( 250 finalClass, false, 251 Thread.currentThread().getContextClassLoader() 252 ).asSubclass(Configuration.class); 253 @SuppressWarnings("deprecation") 254 Configuration result = implClass.newInstance(); 255 return result; 256 } 257 }); 258 AccessController.doPrivileged( 259 new PrivilegedExceptionAction<>() { 260 public Void run() { 261 setConfiguration(untrustedImpl); 262 return null; 263 } 264 }, Objects.requireNonNull(untrustedImpl.acc) 265 ); 266 } catch (PrivilegedActionException e) { 267 Exception ee = e.getException(); 268 if (ee instanceof InstantiationException) { 269 throw (SecurityException) new 270 SecurityException 271 ("Configuration error:" + 272 ee.getCause().getMessage() + 273 "\n").initCause(ee.getCause()); 274 } else { 275 throw (SecurityException) new 276 SecurityException 277 ("Configuration error: " + 278 ee.toString() + 279 "\n").initCause(ee); 280 } 281 } 282 } 283 return configuration; 284 } 285 } 286 287 /** 288 * Set the login {@code Configuration}. 289 * 290 * @param configuration the new {@code Configuration} 291 * 292 * @exception SecurityException if the current thread does not have 293 * Permission to set the {@code Configuration}. 294 * 295 * @see #getConfiguration 296 */ 297 public static void setConfiguration(Configuration configuration) { 298 SecurityManager sm = System.getSecurityManager(); 299 if (sm != null) 300 sm.checkPermission(new AuthPermission("setLoginConfiguration")); 301 Configuration.configuration = configuration; 302 } 303 304 /** 305 * Returns a Configuration object of the specified type. 306 * 307 * <p> This method traverses the list of registered security providers, 308 * starting with the most preferred Provider. 309 * A new Configuration object encapsulating the 310 * ConfigurationSpi implementation from the first 311 * Provider that supports the specified type is returned. 312 * 313 * <p> Note that the list of registered providers may be retrieved via 314 * the {@link Security#getProviders() Security.getProviders()} method. 315 * 316 * @implNote 317 * The JDK Reference Implementation additionally uses the 318 * {@code jdk.security.provider.preferred} 319 * {@link Security#getProperty(String) Security} property to determine 320 * the preferred provider order for the specified algorithm. This 321 * may be different than the order of providers returned by 322 * {@link Security#getProviders() Security.getProviders()}. 323 * 324 * @param type the specified Configuration type. See the Configuration 325 * section in the <a href= 326 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration"> 327 * Java Cryptography Architecture Standard Algorithm Name 328 * Documentation</a> for a list of standard Configuration types. 329 * 330 * @param params parameters for the Configuration, which may be null. 331 * 332 * @return the new {@code Configuration} object 333 * 334 * @throws IllegalArgumentException if the specified parameters 335 * are not understood by the {@code ConfigurationSpi} 336 * implementation from the selected {@code Provider} 337 * 338 * @throws NoSuchAlgorithmException if no {@code Provider} supports a 339 * {@code ConfigurationSpi} implementation for the specified type 340 * 341 * @throws NullPointerException if {@code type} is {@code null} 342 * 343 * @throws SecurityException if the caller does not have permission 344 * to get a {@code Configuration} instance for the specified type 345 * 346 * @see Provider 347 * 348 * @since 1.6 349 */ 350 public static Configuration getInstance(String type, 351 Configuration.Parameters params) 352 throws NoSuchAlgorithmException { 353 354 Objects.requireNonNull(type, "null type name"); 355 checkPermission(type); 356 try { 357 GetInstance.Instance instance = GetInstance.getInstance 358 ("Configuration", 359 ConfigurationSpi.class, 360 type, 361 params); 362 return new ConfigDelegate((ConfigurationSpi)instance.impl, 363 instance.provider, 364 type, 365 params); 366 } catch (NoSuchAlgorithmException nsae) { 367 return handleException (nsae); 368 } 369 } 370 371 /** 372 * Returns a Configuration object of the specified type. 373 * 374 * <p> A new Configuration object encapsulating the 375 * ConfigurationSpi implementation from the specified provider 376 * is returned. The specified provider must be registered 377 * in the provider list. 378 * 379 * <p> Note that the list of registered providers may be retrieved via 380 * the {@link Security#getProviders() Security.getProviders()} method. 381 * 382 * @param type the specified Configuration type. See the Configuration 383 * section in the <a href= 384 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration"> 385 * Java Cryptography Architecture Standard Algorithm Name 386 * Documentation</a> for a list of standard Configuration types. 387 * 388 * @param params parameters for the Configuration, which may be null. 389 * 390 * @param provider the provider. 391 * 392 * @return the new {@code Configuration} object 393 * 394 * @throws IllegalArgumentException if the specified provider 395 * is {@code null} or empty, or if the specified parameters 396 * are not understood by the {@code ConfigurationSpi} 397 * implementation from the specified provider 398 * 399 * @throws NoSuchProviderException if the specified provider is not 400 * registered in the security provider list 401 * 402 * @throws NoSuchAlgorithmException if the specified provider does not 403 * support a {@code ConfigurationSpi} implementation for the 404 * specified type 405 * 406 * @throws NullPointerException if {@code type} is {@code null} 407 * 408 * @throws SecurityException if the caller does not have permission 409 * to get a {@code Configuration} instance for the specified type 410 * 411 * @see Provider 412 * @since 1.6 413 */ 414 public static Configuration getInstance(String type, 415 Configuration.Parameters params, 416 String provider) 417 throws NoSuchProviderException, NoSuchAlgorithmException { 418 419 Objects.requireNonNull(type, "null type name"); 420 if (provider == null || provider.length() == 0) { 421 throw new IllegalArgumentException("missing provider"); 422 } 423 424 checkPermission(type); 425 try { 426 GetInstance.Instance instance = GetInstance.getInstance 427 ("Configuration", 428 ConfigurationSpi.class, 429 type, 430 params, 431 provider); 432 return new ConfigDelegate((ConfigurationSpi)instance.impl, 433 instance.provider, 434 type, 435 params); 436 } catch (NoSuchAlgorithmException nsae) { 437 return handleException (nsae); 438 } 439 } 440 441 /** 442 * Returns a Configuration object of the specified type. 443 * 444 * <p> A new Configuration object encapsulating the 445 * ConfigurationSpi implementation from the specified Provider 446 * object is returned. Note that the specified Provider object 447 * does not have to be registered in the provider list. 448 * 449 * @param type the specified Configuration type. See the Configuration 450 * section in the <a href= 451 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration"> 452 * Java Cryptography Architecture Standard Algorithm Name 453 * Documentation</a> for a list of standard Configuration types. 454 * 455 * @param params parameters for the Configuration, which may be null. 456 * 457 * @param provider the Provider. 458 * 459 * @return the new {@code Configuration} object 460 * 461 * @throws IllegalArgumentException if the specified {@code Provider} 462 * is {@code null}, or if the specified parameters are not 463 * understood by the {@code ConfigurationSpi} implementation 464 * from the specified Provider 465 * 466 * @throws NoSuchAlgorithmException if the specified {@code Provider} 467 * does not support a {@code ConfigurationSpi} implementation 468 * for the specified type 469 * 470 * @throws NullPointerException if {@code type} is {@code null} 471 * 472 * @throws SecurityException if the caller does not have permission 473 * to get a {@code Configuration} instance for the specified type 474 * 475 * @see Provider 476 * @since 1.6 477 */ 478 public static Configuration getInstance(String type, 479 Configuration.Parameters params, 480 Provider provider) 481 throws NoSuchAlgorithmException { 482 483 Objects.requireNonNull(type, "null type name"); 484 if (provider == null) { 485 throw new IllegalArgumentException("missing provider"); 486 } 487 488 checkPermission(type); 489 try { 490 GetInstance.Instance instance = GetInstance.getInstance 491 ("Configuration", 492 ConfigurationSpi.class, 493 type, 494 params, 495 provider); 496 return new ConfigDelegate((ConfigurationSpi)instance.impl, 497 instance.provider, 498 type, 499 params); 500 } catch (NoSuchAlgorithmException nsae) { 501 return handleException (nsae); 502 } 503 } 504 505 private static Configuration handleException(NoSuchAlgorithmException nsae) 506 throws NoSuchAlgorithmException { 507 Throwable cause = nsae.getCause(); 508 if (cause instanceof IllegalArgumentException) { 509 throw (IllegalArgumentException)cause; 510 } 511 throw nsae; 512 } 513 514 /** 515 * Return the Provider of this Configuration. 516 * 517 * <p> This Configuration instance will only have a Provider if it 518 * was obtained via a call to {@code Configuration.getInstance}. 519 * Otherwise this method returns null. 520 * 521 * @return the Provider of this Configuration, or null. 522 * 523 * @since 1.6 524 */ 525 public Provider getProvider() { 526 return null; 527 } 528 529 /** 530 * Return the type of this Configuration. 531 * 532 * <p> This Configuration instance will only have a type if it 533 * was obtained via a call to {@code Configuration.getInstance}. 534 * Otherwise this method returns null. 535 * 536 * @return the type of this Configuration, or null. 537 * 538 * @since 1.6 539 */ 540 public String getType() { 541 return null; 542 } 543 544 /** 545 * Return Configuration parameters. 546 * 547 * <p> This Configuration instance will only have parameters if it 548 * was obtained via a call to {@code Configuration.getInstance}. 549 * Otherwise this method returns null. 550 * 551 * @return Configuration parameters, or null. 552 * 553 * @since 1.6 554 */ 555 public Configuration.Parameters getParameters() { 556 return null; 557 } 558 559 /** 560 * Retrieve the AppConfigurationEntries for the specified {@code name} 561 * from this Configuration. 562 * 563 * @param name the name used to index the Configuration. 564 * 565 * @return an array of AppConfigurationEntries for the specified {@code name} 566 * from this Configuration, or null if there are no entries 567 * for the specified {@code name} 568 */ 569 public abstract AppConfigurationEntry[] getAppConfigurationEntry 570 (String name); 571 572 /** 573 * Refresh and reload the Configuration. 574 * 575 * <p> This method causes this Configuration object to refresh/reload its 576 * contents in an implementation-dependent manner. 577 * For example, if this Configuration object stores its entries in a file, 578 * calling {@code refresh} may cause the file to be re-read. 579 * 580 * <p> The default implementation of this method does nothing. 581 * This method should be overridden if a refresh operation is supported 582 * by the implementation. 583 * 584 * @exception SecurityException if the caller does not have permission 585 * to refresh its Configuration. 586 */ 587 public void refresh() { } 588 589 /** 590 * This subclass is returned by the getInstance calls. All Configuration 591 * calls are delegated to the underlying ConfigurationSpi. 592 */ 593 private static class ConfigDelegate extends Configuration { 594 595 private ConfigurationSpi spi; 596 private Provider p; 597 private String type; 598 private Configuration.Parameters params; 599 600 private ConfigDelegate(ConfigurationSpi spi, Provider p, 601 String type, Configuration.Parameters params) { 602 this.spi = spi; 603 this.p = p; 604 this.type = type; 605 this.params = params; 606 } 607 608 public String getType() { return type; } 609 610 public Configuration.Parameters getParameters() { return params; } 611 612 public Provider getProvider() { return p; } 613 614 public AppConfigurationEntry[] getAppConfigurationEntry(String name) { 615 return spi.engineGetAppConfigurationEntry(name); 616 } 617 618 public void refresh() { 619 spi.engineRefresh(); 620 } 621 } 622 623 /** 624 * This represents a marker interface for Configuration parameters. 625 * 626 * @since 1.6 627 */ 628 public static interface Parameters { } 629 }