30
30
import java .util .*;
31
31
import java .util .concurrent .ConcurrentHashMap ;
32
32
import java .util .concurrent .ConcurrentMap ;
33
+ import java .lang .StackWalker .*;
33
34
34
35
/**
35
36
* The JCE security manager.
39
40
* algorithm, by consulting the configured jurisdiction policy files and
40
41
* the cryptographic permissions bundled with the applet/application.
41
42
*
42
- * <p>Note that this security manager is never installed, only instantiated.
43
- *
44
43
* @author Jan Luehe
45
44
*
46
45
* @since 1.4
47
46
*/
48
-
49
- @ SuppressWarnings ("removal" )
50
- final class JceSecurityManager extends SecurityManager {
47
+ final class JceSecurityManager {
51
48
52
49
private static final CryptoPermissions defaultPolicy ;
53
50
private static final CryptoPermissions exemptPolicy ;
@@ -61,17 +58,25 @@ final class JceSecurityManager extends SecurityManager {
61
58
62
59
// singleton instance
63
60
static final JceSecurityManager INSTANCE ;
61
+ static final StackWalker WALKER ;
64
62
65
63
static {
66
64
defaultPolicy = JceSecurity .getDefaultPolicy ();
67
65
exemptPolicy = JceSecurity .getExemptPolicy ();
68
66
allPerm = CryptoAllPermission .INSTANCE ;
69
- INSTANCE = AccessController .doPrivileged (
70
- new PrivilegedAction <>() {
71
- public JceSecurityManager run () {
72
- return new JceSecurityManager ();
73
- }
74
- });
67
+
68
+ PrivilegedAction <JceSecurityManager > paSM = JceSecurityManager ::new ;
69
+ @ SuppressWarnings ("removal" )
70
+ JceSecurityManager dummySecurityManager =
71
+ AccessController .doPrivileged (paSM );
72
+ INSTANCE = dummySecurityManager ;
73
+
74
+ PrivilegedAction <StackWalker > paWalker =
75
+ () -> StackWalker .getInstance (Option .RETAIN_CLASS_REFERENCE );
76
+ @ SuppressWarnings ("removal" )
77
+ StackWalker dummyWalker = AccessController .doPrivileged (paWalker );
78
+
79
+ WALKER = dummyWalker ;
75
80
}
76
81
77
82
private JceSecurityManager () {
@@ -82,10 +87,11 @@ private JceSecurityManager() {
82
87
* Returns the maximum allowable crypto strength for the given
83
88
* applet/application, for the given algorithm.
84
89
*/
85
- CryptoPermission getCryptoPermission (String alg ) {
90
+ CryptoPermission getCryptoPermission (String theAlg ) {
91
+
86
92
// Need to convert to uppercase since the crypto perm
87
93
// lookup is case sensitive.
88
- alg = alg .toUpperCase (Locale .ENGLISH );
94
+ final String alg = theAlg .toUpperCase (Locale .ENGLISH );
89
95
90
96
// If CryptoAllPermission is granted by default, we return that.
91
97
// Otherwise, this will be the permission we return if anything goes
@@ -100,28 +106,19 @@ CryptoPermission getCryptoPermission(String alg) {
100
106
// javax.crypto.* packages.
101
107
// NOTE: javax.crypto.* package maybe subject to package
102
108
// insertion, so need to check its classloader as well.
103
- Class <?>[] context = getClassContext ();
104
- URL callerCodeBase = null ;
105
- int i ;
106
- for (i =0 ; i <context .length ; i ++) {
107
- Class <?> cls = context [i ];
108
- callerCodeBase = JceSecurity .getCodeBase (cls );
109
- if (callerCodeBase != null ) {
110
- break ;
111
- } else {
112
- if (cls .getName ().startsWith ("javax.crypto." )) {
113
- // skip jce classes since they aren't the callers
114
- continue ;
115
- }
116
- // use default permission when the caller is system classes
117
- return defaultPerm ;
118
- }
119
- }
120
-
121
- if (i == context .length ) {
122
- return defaultPerm ;
123
- }
109
+ return WALKER .walk (s -> s .map (StackFrame ::getDeclaringClass )
110
+ .filter (c -> !c .getPackageName ().equals ("javax.crypto" ))
111
+ .map (cls -> {
112
+ URL callerCodeBase = JceSecurity .getCodeBase (cls );
113
+ return (callerCodeBase != null ) ?
114
+ getCryptoPermissionFromURL (callerCodeBase ,
115
+ alg , defaultPerm ) : defaultPerm ;})
116
+ .findFirst ().get () // nulls not possible for Optional
117
+ );
118
+ }
124
119
120
+ CryptoPermission getCryptoPermissionFromURL (URL callerCodeBase ,
121
+ String alg , CryptoPermission defaultPerm ) {
125
122
CryptoPermissions appPerms = exemptCache .get (callerCodeBase );
126
123
if (appPerms == null ) {
127
124
// no match found in cache
@@ -231,14 +228,9 @@ private CryptoPermission getDefaultPermission(String alg) {
231
228
// Only used by javax.crypto.Cipher constructor to disallow Cipher
232
229
// objects being constructed by untrusted code (See bug 4341369 &
233
230
// 4334690 for more info).
234
- boolean isCallerTrusted (Provider provider ) {
231
+ boolean isCallerTrusted (Class <?> caller , Provider provider ) {
235
232
// Get the caller and its codebase.
236
- Class <?>[] context = getClassContext ();
237
- if (context .length >= 3 ) {
238
- // context[0]: class javax.crypto.JceSecurityManager
239
- // context[1]: class javax.crypto.Cipher (or other JCE API class)
240
- // context[2]: this is what we are gonna check
241
- Class <?> caller = context [2 ];
233
+ if (caller != null ) {
242
234
URL callerCodeBase = JceSecurity .getCodeBase (caller );
243
235
if (callerCodeBase == null ) {
244
236
return true ;
0 commit comments