Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/jca/ProviderConfig.java
41159 views
1
/*
2
* Copyright (c) 2003, 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 sun.security.jca;
27
28
import java.io.File;
29
import java.lang.reflect.*;
30
import java.util.*;
31
32
import java.security.*;
33
34
import sun.security.util.PropertyExpander;
35
36
/**
37
* Class representing a configured provider which encapsulates configuration
38
* (provider name + optional argument), the provider loading logic, and
39
* the loaded Provider object itself.
40
*
41
* @author Andreas Sterbenz
42
* @since 1.5
43
*/
44
final class ProviderConfig {
45
46
private static final sun.security.util.Debug debug =
47
sun.security.util.Debug.getInstance("jca", "ProviderConfig");
48
49
// suffix for identifying the SunPKCS11-Solaris provider
50
private static final String P11_SOL_NAME = "SunPKCS11";
51
52
// config file argument of the SunPKCS11-Solaris provider
53
private static final String P11_SOL_ARG =
54
"${java.home}/conf/security/sunpkcs11-solaris.cfg";
55
56
// maximum number of times to try loading a provider before giving up
57
private static final int MAX_LOAD_TRIES = 30;
58
59
// could be provider name (module) or provider class name (legacy)
60
private final String provName;
61
62
// argument to the Provider.configure() call, never null
63
private final String argument;
64
65
// number of times we have already tried to load this provider
66
private int tries;
67
68
// Provider object, if loaded
69
private volatile Provider provider;
70
71
// flag indicating if we are currently trying to load the provider
72
// used to detect recursion
73
private boolean isLoading;
74
75
ProviderConfig(String provName, String argument) {
76
if (provName.endsWith(P11_SOL_NAME) && argument.equals(P11_SOL_ARG)) {
77
checkSunPKCS11Solaris();
78
}
79
this.provName = provName;
80
this.argument = expand(argument);
81
}
82
83
ProviderConfig(String provName) {
84
this(provName, "");
85
}
86
87
ProviderConfig(Provider provider) {
88
this.provName = provider.getName();
89
this.argument = "";
90
this.provider = provider;
91
}
92
93
// check if we should try to load the SunPKCS11-Solaris provider
94
// avoid if not available (pre Solaris 10) to reduce startup time
95
// or if disabled via system property
96
private void checkSunPKCS11Solaris() {
97
@SuppressWarnings("removal")
98
Boolean o = AccessController.doPrivileged(
99
new PrivilegedAction<Boolean>() {
100
public Boolean run() {
101
File file = new File("/usr/lib/libpkcs11.so");
102
if (file.exists() == false) {
103
return Boolean.FALSE;
104
}
105
if ("false".equalsIgnoreCase(System.getProperty
106
("sun.security.pkcs11.enable-solaris"))) {
107
return Boolean.FALSE;
108
}
109
return Boolean.TRUE;
110
}
111
});
112
if (o == Boolean.FALSE) {
113
tries = MAX_LOAD_TRIES;
114
}
115
}
116
117
private boolean hasArgument() {
118
return !argument.isEmpty();
119
}
120
121
// should we try to load this provider?
122
private boolean shouldLoad() {
123
return (tries < MAX_LOAD_TRIES);
124
}
125
126
// do not try to load this provider again
127
private void disableLoad() {
128
tries = MAX_LOAD_TRIES;
129
}
130
131
boolean isLoaded() {
132
return (provider != null);
133
}
134
135
public boolean equals(Object obj) {
136
if (this == obj) {
137
return true;
138
}
139
if (obj instanceof ProviderConfig == false) {
140
return false;
141
}
142
ProviderConfig other = (ProviderConfig)obj;
143
return this.provName.equals(other.provName)
144
&& this.argument.equals(other.argument);
145
146
}
147
148
public int hashCode() {
149
return provName.hashCode() + argument.hashCode();
150
}
151
152
public String toString() {
153
if (hasArgument()) {
154
return provName + "('" + argument + "')";
155
} else {
156
return provName;
157
}
158
}
159
160
/**
161
* Get the provider object. Loads the provider if it is not already loaded.
162
*/
163
@SuppressWarnings("deprecation")
164
Provider getProvider() {
165
// volatile variable load
166
Provider p = provider;
167
if (p != null) {
168
return p;
169
}
170
// DCL
171
synchronized (this) {
172
p = provider;
173
if (p != null) {
174
return p;
175
}
176
if (shouldLoad() == false) {
177
return null;
178
}
179
180
// Create providers which are in java.base directly
181
if (provName.equals("SUN") || provName.equals("sun.security.provider.Sun")) {
182
p = new sun.security.provider.Sun();
183
} else if (provName.equals("SunRsaSign") || provName.equals("sun.security.rsa.SunRsaSign")) {
184
p = new sun.security.rsa.SunRsaSign();
185
} else if (provName.equals("SunJCE") || provName.equals("com.sun.crypto.provider.SunJCE")) {
186
p = new com.sun.crypto.provider.SunJCE();
187
} else if (provName.equals("SunJSSE")) {
188
p = new sun.security.ssl.SunJSSE();
189
} else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) {
190
// need to use reflection since this class only exists on MacOsx
191
@SuppressWarnings("removal")
192
var tmp = AccessController.doPrivileged(new PrivilegedAction<Provider>() {
193
public Provider run() {
194
try {
195
Class<?> c = Class.forName("apple.security.AppleProvider");
196
if (Provider.class.isAssignableFrom(c)) {
197
@SuppressWarnings("deprecation")
198
Object tmp = c.newInstance();
199
return (Provider) tmp;
200
} else {
201
return null;
202
}
203
} catch (Exception ex) {
204
if (debug != null) {
205
debug.println("Error loading provider Apple");
206
ex.printStackTrace();
207
}
208
return null;
209
}
210
}
211
});
212
p = tmp;
213
} else {
214
if (isLoading) {
215
// because this method is synchronized, this can only
216
// happen if there is recursion.
217
if (debug != null) {
218
debug.println("Recursion loading provider: " + this);
219
new Exception("Call trace").printStackTrace();
220
}
221
return null;
222
}
223
try {
224
isLoading = true;
225
tries++;
226
p = doLoadProvider();
227
} finally {
228
isLoading = false;
229
}
230
}
231
provider = p;
232
}
233
return p;
234
}
235
236
/**
237
* Load and instantiate the Provider described by this class.
238
*
239
* NOTE use of doPrivileged().
240
*
241
* @return null if the Provider could not be loaded
242
*
243
* @throws ProviderException if executing the Provider's constructor
244
* throws a ProviderException. All other Exceptions are ignored.
245
*/
246
@SuppressWarnings("removal")
247
private Provider doLoadProvider() {
248
return AccessController.doPrivileged(new PrivilegedAction<Provider>() {
249
public Provider run() {
250
if (debug != null) {
251
debug.println("Loading provider " + ProviderConfig.this);
252
}
253
try {
254
Provider p = ProviderLoader.INSTANCE.load(provName);
255
if (p != null) {
256
if (hasArgument()) {
257
p = p.configure(argument);
258
}
259
if (debug != null) {
260
debug.println("Loaded provider " + p.getName());
261
}
262
} else {
263
if (debug != null) {
264
debug.println("Error loading provider " +
265
ProviderConfig.this);
266
}
267
disableLoad();
268
}
269
return p;
270
} catch (Exception e) {
271
if (e instanceof ProviderException) {
272
// pass up
273
throw e;
274
} else {
275
if (debug != null) {
276
debug.println("Error loading provider " +
277
ProviderConfig.this);
278
e.printStackTrace();
279
}
280
disableLoad();
281
return null;
282
}
283
} catch (ExceptionInInitializerError err) {
284
// no sufficient permission to initialize provider class
285
if (debug != null) {
286
debug.println("Error loading provider " + ProviderConfig.this);
287
err.printStackTrace();
288
}
289
disableLoad();
290
return null;
291
}
292
}
293
});
294
}
295
296
/**
297
* Perform property expansion of the provider value.
298
*
299
* NOTE use of doPrivileged().
300
*/
301
@SuppressWarnings("removal")
302
private static String expand(final String value) {
303
// shortcut if value does not contain any properties
304
if (value.contains("${") == false) {
305
return value;
306
}
307
return AccessController.doPrivileged(new PrivilegedAction<String>() {
308
public String run() {
309
try {
310
return PropertyExpander.expand(value);
311
} catch (GeneralSecurityException e) {
312
throw new ProviderException(e);
313
}
314
}
315
});
316
}
317
318
// Inner class for loading security providers listed in java.security file
319
private static final class ProviderLoader {
320
static final ProviderLoader INSTANCE = new ProviderLoader();
321
322
private final ServiceLoader<Provider> services;
323
324
private ProviderLoader() {
325
// VM should already been booted at this point, if not
326
// - Only providers in java.base should be loaded, don't use
327
// ServiceLoader
328
// - ClassLoader.getSystemClassLoader() will throw InternalError
329
services = ServiceLoader.load(java.security.Provider.class,
330
ClassLoader.getSystemClassLoader());
331
}
332
333
/**
334
* Loads the provider with the specified class name.
335
*
336
* @param pn the name of the provider
337
* @return the Provider, or null if it cannot be found or loaded
338
* @throws ProviderException all other exceptions are ignored
339
*/
340
public Provider load(String pn) {
341
if (debug != null) {
342
debug.println("Attempt to load " + pn + " using SL");
343
}
344
Iterator<Provider> iter = services.iterator();
345
while (iter.hasNext()) {
346
try {
347
Provider p = iter.next();
348
String pName = p.getName();
349
if (debug != null) {
350
debug.println("Found SL Provider named " + pName);
351
}
352
if (pName.equals(pn)) {
353
return p;
354
}
355
} catch (SecurityException | ServiceConfigurationError |
356
InvalidParameterException ex) {
357
// if provider loading fail due to security permission,
358
// log it and move on to next provider
359
if (debug != null) {
360
debug.println("Encountered " + ex +
361
" while iterating through SL, ignore and move on");
362
ex.printStackTrace();
363
}
364
}
365
}
366
// No success with ServiceLoader. Try loading provider the legacy,
367
// i.e. pre-module, way via reflection
368
try {
369
return legacyLoad(pn);
370
} catch (ProviderException pe) {
371
// pass through
372
throw pe;
373
} catch (Exception ex) {
374
// logged and ignored
375
if (debug != null) {
376
debug.println("Encountered " + ex +
377
" during legacy load of " + pn);
378
ex.printStackTrace();
379
}
380
return null;
381
}
382
}
383
384
private Provider legacyLoad(String classname) {
385
386
if (debug != null) {
387
debug.println("Loading legacy provider: " + classname);
388
}
389
390
try {
391
Class<?> provClass =
392
ClassLoader.getSystemClassLoader().loadClass(classname);
393
394
// only continue if the specified class extends Provider
395
if (!Provider.class.isAssignableFrom(provClass)) {
396
if (debug != null) {
397
debug.println(classname + " is not a provider");
398
}
399
return null;
400
}
401
402
@SuppressWarnings("removal")
403
Provider p = AccessController.doPrivileged
404
(new PrivilegedExceptionAction<Provider>() {
405
@SuppressWarnings("deprecation") // Class.newInstance
406
public Provider run() throws Exception {
407
return (Provider) provClass.newInstance();
408
}
409
});
410
return p;
411
} catch (Exception e) {
412
Throwable t;
413
if (e instanceof InvocationTargetException) {
414
t = ((InvocationTargetException)e).getCause();
415
} else {
416
t = e;
417
}
418
if (debug != null) {
419
debug.println("Error loading legacy provider " + classname);
420
t.printStackTrace();
421
}
422
// provider indicates fatal error, pass through exception
423
if (t instanceof ProviderException) {
424
throw (ProviderException) t;
425
}
426
return null;
427
} catch (ExceptionInInitializerError | NoClassDefFoundError err) {
428
// no sufficient permission to access/initialize provider class
429
if (debug != null) {
430
debug.println("Error loading legacy provider " + classname);
431
err.printStackTrace();
432
}
433
return null;
434
}
435
}
436
}
437
}
438
439