Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/javax/security/auth/login/Configuration.java
67848 views
1
/*
2
* Copyright (c) 1998, 2021, 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}/../specs/security/standard-names.html#configuration-types">
182
* Java Security Standard Algorithm Names Specification</a>
183
* for a list of standard Configuration types.
184
*
185
* @since 1.4
186
* @see javax.security.auth.login.LoginContext
187
* @see java.security.Security security properties
188
*/
189
public abstract class Configuration {
190
191
private static Configuration configuration;
192
193
@SuppressWarnings("removal")
194
private final java.security.AccessControlContext acc =
195
java.security.AccessController.getContext();
196
197
private static void checkPermission(String type) {
198
@SuppressWarnings("removal")
199
SecurityManager sm = System.getSecurityManager();
200
if (sm != null) {
201
sm.checkPermission(new AuthPermission
202
("createLoginConfiguration." + type));
203
}
204
}
205
206
/**
207
* Sole constructor. (For invocation by subclass constructors, typically
208
* implicit.)
209
*/
210
protected Configuration() { }
211
212
/**
213
* Get the installed login Configuration.
214
*
215
* @return the login Configuration. If a Configuration object was set
216
* via the {@code Configuration.setConfiguration} method,
217
* then that object is returned. Otherwise, a default
218
* Configuration object is returned.
219
*
220
* @exception SecurityException if the caller does not have permission
221
* to retrieve the Configuration.
222
*
223
* @see #setConfiguration
224
*/
225
@SuppressWarnings("removal")
226
public static Configuration getConfiguration() {
227
228
SecurityManager sm = System.getSecurityManager();
229
if (sm != null)
230
sm.checkPermission(new AuthPermission("getLoginConfiguration"));
231
232
synchronized (Configuration.class) {
233
if (configuration == null) {
234
String config_class = null;
235
config_class = AccessController.doPrivileged
236
(new PrivilegedAction<>() {
237
public String run() {
238
return java.security.Security.getProperty
239
("login.configuration.provider");
240
}
241
});
242
if (config_class == null) {
243
config_class = "sun.security.provider.ConfigFile";
244
}
245
246
try {
247
final String finalClass = config_class;
248
Configuration untrustedImpl = AccessController.doPrivileged(
249
new PrivilegedExceptionAction<>() {
250
public Configuration run() throws ClassNotFoundException,
251
InstantiationException,
252
IllegalAccessException {
253
Class<? extends Configuration> implClass = Class.forName(
254
finalClass, false,
255
Thread.currentThread().getContextClassLoader()
256
).asSubclass(Configuration.class);
257
@SuppressWarnings("deprecation")
258
Configuration result = implClass.newInstance();
259
return result;
260
}
261
});
262
AccessController.doPrivileged(
263
new PrivilegedExceptionAction<>() {
264
public Void run() {
265
setConfiguration(untrustedImpl);
266
return null;
267
}
268
}, Objects.requireNonNull(untrustedImpl.acc)
269
);
270
} catch (PrivilegedActionException e) {
271
Exception ee = e.getException();
272
if (ee instanceof InstantiationException) {
273
throw (SecurityException) new
274
SecurityException
275
("Configuration error:" +
276
ee.getCause().getMessage() +
277
"\n").initCause(ee.getCause());
278
} else {
279
throw (SecurityException) new
280
SecurityException
281
("Configuration error: " +
282
ee.toString() +
283
"\n").initCause(ee);
284
}
285
}
286
}
287
return configuration;
288
}
289
}
290
291
/**
292
* Set the login {@code Configuration}.
293
*
294
* @param configuration the new {@code Configuration}
295
*
296
* @exception SecurityException if the current thread does not have
297
* Permission to set the {@code Configuration}.
298
*
299
* @see #getConfiguration
300
*/
301
public static void setConfiguration(Configuration configuration) {
302
@SuppressWarnings("removal")
303
SecurityManager sm = System.getSecurityManager();
304
if (sm != null)
305
sm.checkPermission(new AuthPermission("setLoginConfiguration"));
306
Configuration.configuration = configuration;
307
}
308
309
/**
310
* Returns a Configuration object of the specified type.
311
*
312
* <p> This method traverses the list of registered security providers,
313
* starting with the most preferred Provider.
314
* A new Configuration object encapsulating the
315
* ConfigurationSpi implementation from the first
316
* Provider that supports the specified type is returned.
317
*
318
* <p> Note that the list of registered providers may be retrieved via
319
* the {@link Security#getProviders() Security.getProviders()} method.
320
*
321
* @implNote
322
* The JDK Reference Implementation additionally uses the
323
* {@code jdk.security.provider.preferred}
324
* {@link Security#getProperty(String) Security} property to determine
325
* the preferred provider order for the specified algorithm. This
326
* may be different than the order of providers returned by
327
* {@link Security#getProviders() Security.getProviders()}.
328
*
329
* @param type the specified Configuration type. See the Configuration
330
* section in the <a href=
331
* "{@docRoot}/../specs/security/standard-names.html#configuration-types">
332
* Java Security Standard Algorithm Names Specification</a>
333
* for a list of standard Configuration types.
334
*
335
* @param params parameters for the Configuration, which may be null.
336
*
337
* @return the new {@code Configuration} object
338
*
339
* @throws IllegalArgumentException if the specified parameters
340
* are not understood by the {@code ConfigurationSpi}
341
* implementation from the selected {@code Provider}
342
*
343
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
344
* {@code ConfigurationSpi} implementation for the specified type
345
*
346
* @throws NullPointerException if {@code type} is {@code null}
347
*
348
* @throws SecurityException if the caller does not have permission
349
* to get a {@code Configuration} instance for the specified type
350
*
351
* @see Provider
352
*
353
* @since 1.6
354
*/
355
public static Configuration getInstance(String type,
356
Configuration.Parameters params)
357
throws NoSuchAlgorithmException {
358
359
Objects.requireNonNull(type, "null type name");
360
checkPermission(type);
361
try {
362
GetInstance.Instance instance = GetInstance.getInstance
363
("Configuration",
364
ConfigurationSpi.class,
365
type,
366
params);
367
return new ConfigDelegate((ConfigurationSpi)instance.impl,
368
instance.provider,
369
type,
370
params);
371
} catch (NoSuchAlgorithmException nsae) {
372
return handleException (nsae);
373
}
374
}
375
376
/**
377
* Returns a Configuration object of the specified type.
378
*
379
* <p> A new Configuration object encapsulating the
380
* ConfigurationSpi implementation from the specified provider
381
* is returned. The specified provider must be registered
382
* in the provider list.
383
*
384
* <p> Note that the list of registered providers may be retrieved via
385
* the {@link Security#getProviders() Security.getProviders()} method.
386
*
387
* @param type the specified Configuration type. See the Configuration
388
* section in the <a href=
389
* "{@docRoot}/../specs/security/standard-names.html#configuration-types">
390
* Java Security Standard Algorithm Names Specification</a>
391
* for a list of standard Configuration types.
392
*
393
* @param params parameters for the Configuration, which may be null.
394
*
395
* @param provider the provider.
396
*
397
* @return the new {@code Configuration} object
398
*
399
* @throws IllegalArgumentException if the specified provider
400
* is {@code null} or empty, or if the specified parameters
401
* are not understood by the {@code ConfigurationSpi}
402
* implementation from the specified provider
403
*
404
* @throws NoSuchProviderException if the specified provider is not
405
* registered in the security provider list
406
*
407
* @throws NoSuchAlgorithmException if the specified provider does not
408
* support a {@code ConfigurationSpi} implementation for the
409
* specified type
410
*
411
* @throws NullPointerException if {@code type} is {@code null}
412
*
413
* @throws SecurityException if the caller does not have permission
414
* to get a {@code Configuration} instance for the specified type
415
*
416
* @see Provider
417
* @since 1.6
418
*/
419
public static Configuration getInstance(String type,
420
Configuration.Parameters params,
421
String provider)
422
throws NoSuchProviderException, NoSuchAlgorithmException {
423
424
Objects.requireNonNull(type, "null type name");
425
if (provider == null || provider.isEmpty()) {
426
throw new IllegalArgumentException("missing provider");
427
}
428
429
checkPermission(type);
430
try {
431
GetInstance.Instance instance = GetInstance.getInstance
432
("Configuration",
433
ConfigurationSpi.class,
434
type,
435
params,
436
provider);
437
return new ConfigDelegate((ConfigurationSpi)instance.impl,
438
instance.provider,
439
type,
440
params);
441
} catch (NoSuchAlgorithmException nsae) {
442
return handleException (nsae);
443
}
444
}
445
446
/**
447
* Returns a Configuration object of the specified type.
448
*
449
* <p> A new Configuration object encapsulating the
450
* ConfigurationSpi implementation from the specified Provider
451
* object is returned. Note that the specified Provider object
452
* does not have to be registered in the provider list.
453
*
454
* @param type the specified Configuration type. See the Configuration
455
* section in the <a href=
456
* "{@docRoot}/../specs/security/standard-names.html#configuration-types">
457
* Java Security Standard Algorithm Names Specification</a>
458
* for a list of standard Configuration types.
459
*
460
* @param params parameters for the Configuration, which may be null.
461
*
462
* @param provider the Provider.
463
*
464
* @return the new {@code Configuration} object
465
*
466
* @throws IllegalArgumentException if the specified {@code Provider}
467
* is {@code null}, or if the specified parameters are not
468
* understood by the {@code ConfigurationSpi} implementation
469
* from the specified Provider
470
*
471
* @throws NoSuchAlgorithmException if the specified {@code Provider}
472
* does not support a {@code ConfigurationSpi} implementation
473
* for the specified type
474
*
475
* @throws NullPointerException if {@code type} is {@code null}
476
*
477
* @throws SecurityException if the caller does not have permission
478
* to get a {@code Configuration} instance for the specified type
479
*
480
* @see Provider
481
* @since 1.6
482
*/
483
public static Configuration getInstance(String type,
484
Configuration.Parameters params,
485
Provider provider)
486
throws NoSuchAlgorithmException {
487
488
Objects.requireNonNull(type, "null type name");
489
if (provider == null) {
490
throw new IllegalArgumentException("missing provider");
491
}
492
493
checkPermission(type);
494
try {
495
GetInstance.Instance instance = GetInstance.getInstance
496
("Configuration",
497
ConfigurationSpi.class,
498
type,
499
params,
500
provider);
501
return new ConfigDelegate((ConfigurationSpi)instance.impl,
502
instance.provider,
503
type,
504
params);
505
} catch (NoSuchAlgorithmException nsae) {
506
return handleException (nsae);
507
}
508
}
509
510
private static Configuration handleException(NoSuchAlgorithmException nsae)
511
throws NoSuchAlgorithmException {
512
Throwable cause = nsae.getCause();
513
if (cause instanceof IllegalArgumentException) {
514
throw (IllegalArgumentException)cause;
515
}
516
throw nsae;
517
}
518
519
/**
520
* Return the Provider of this Configuration.
521
*
522
* <p> This Configuration instance will only have a Provider if it
523
* was obtained via a call to {@code Configuration.getInstance}.
524
* Otherwise this method returns null.
525
*
526
* @return the Provider of this Configuration, or null.
527
*
528
* @since 1.6
529
*/
530
public Provider getProvider() {
531
return null;
532
}
533
534
/**
535
* Return the type of this Configuration.
536
*
537
* <p> This Configuration instance will only have a type if it
538
* was obtained via a call to {@code Configuration.getInstance}.
539
* Otherwise this method returns null.
540
*
541
* @return the type of this Configuration, or null.
542
*
543
* @since 1.6
544
*/
545
public String getType() {
546
return null;
547
}
548
549
/**
550
* Return Configuration parameters.
551
*
552
* <p> This Configuration instance will only have parameters if it
553
* was obtained via a call to {@code Configuration.getInstance}.
554
* Otherwise this method returns null.
555
*
556
* @return Configuration parameters, or null.
557
*
558
* @since 1.6
559
*/
560
public Configuration.Parameters getParameters() {
561
return null;
562
}
563
564
/**
565
* Retrieve the AppConfigurationEntries for the specified {@code name}
566
* from this Configuration.
567
*
568
* @param name the name used to index the Configuration.
569
*
570
* @return an array of AppConfigurationEntries for the specified {@code name}
571
* from this Configuration, or null if there are no entries
572
* for the specified {@code name}
573
*/
574
public abstract AppConfigurationEntry[] getAppConfigurationEntry
575
(String name);
576
577
/**
578
* Refresh and reload the Configuration.
579
*
580
* <p> This method causes this Configuration object to refresh/reload its
581
* contents in an implementation-dependent manner.
582
* For example, if this Configuration object stores its entries in a file,
583
* calling {@code refresh} may cause the file to be re-read.
584
*
585
* <p> The default implementation of this method does nothing.
586
* This method should be overridden if a refresh operation is supported
587
* by the implementation.
588
*
589
* @exception SecurityException if the caller does not have permission
590
* to refresh its Configuration.
591
*/
592
public void refresh() { }
593
594
/**
595
* This subclass is returned by the getInstance calls. All Configuration
596
* calls are delegated to the underlying ConfigurationSpi.
597
*/
598
private static class ConfigDelegate extends Configuration {
599
600
private ConfigurationSpi spi;
601
private Provider p;
602
private String type;
603
private Configuration.Parameters params;
604
605
private ConfigDelegate(ConfigurationSpi spi, Provider p,
606
String type, Configuration.Parameters params) {
607
this.spi = spi;
608
this.p = p;
609
this.type = type;
610
this.params = params;
611
}
612
613
public String getType() { return type; }
614
615
public Configuration.Parameters getParameters() { return params; }
616
617
public Provider getProvider() { return p; }
618
619
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
620
return spi.engineGetAppConfigurationEntry(name);
621
}
622
623
public void refresh() {
624
spi.engineRefresh();
625
}
626
}
627
628
/**
629
* This represents a marker interface for Configuration parameters.
630
*
631
* @since 1.6
632
*/
633
public static interface Parameters { }
634
}
635
636