Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/javax/crypto/CryptoPermissions.java
41152 views
1
/*
2
* Copyright (c) 1999, 2019, 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.crypto;
27
28
import java.security.*;
29
import java.util.Enumeration;
30
import java.util.Hashtable;
31
import java.util.Vector;
32
import java.util.NoSuchElementException;
33
import java.util.concurrent.ConcurrentHashMap;
34
import java.io.Serializable;
35
import java.io.InputStream;
36
import java.io.InputStreamReader;
37
import java.io.BufferedReader;
38
import java.io.ObjectStreamField;
39
import java.io.ObjectInputStream;
40
import java.io.ObjectOutputStream;
41
import java.io.IOException;
42
43
import static java.nio.charset.StandardCharsets.UTF_8;
44
45
/**
46
* This class contains CryptoPermission objects, organized into
47
* PermissionCollections according to algorithm names.
48
*
49
* <p>When the <code>add</code> method is called to add a
50
* CryptoPermission, the CryptoPermission is stored in the
51
* appropriate PermissionCollection. If no such
52
* collection exists yet, the algorithm name associated with
53
* the CryptoPermission object is
54
* determined and the <code>newPermissionCollection</code> method
55
* is called on the CryptoPermission or CryptoAllPermission class to
56
* create the PermissionCollection and add it to the Permissions object.
57
*
58
* @see javax.crypto.CryptoPermission
59
* @see java.security.PermissionCollection
60
* @see java.security.Permissions
61
*
62
* @author Sharon Liu
63
* @since 1.4
64
*/
65
final class CryptoPermissions extends PermissionCollection
66
implements Serializable {
67
68
@java.io.Serial
69
private static final long serialVersionUID = 4946547168093391015L;
70
71
/**
72
* @serialField perms java.util.Hashtable
73
*/
74
@java.io.Serial
75
private static final ObjectStreamField[] serialPersistentFields = {
76
new ObjectStreamField("perms", Hashtable.class),
77
};
78
79
// Switched from Hashtable to ConcurrentHashMap to improve scalability.
80
// To maintain serialization compatibility, this field is made transient
81
// and custom readObject/writeObject methods are used.
82
private transient ConcurrentHashMap<String,PermissionCollection> perms;
83
84
/**
85
* Creates a new CryptoPermissions object containing
86
* no CryptoPermissionCollections.
87
*/
88
CryptoPermissions() {
89
perms = new ConcurrentHashMap<>(7);
90
}
91
92
/**
93
* Populates the crypto policy from the specified
94
* InputStream into this CryptoPermissions object.
95
*
96
* @param in the InputStream to load from.
97
*
98
* @exception SecurityException if cannot load
99
* successfully.
100
*/
101
void load(InputStream in)
102
throws IOException, CryptoPolicyParser.ParsingException {
103
CryptoPolicyParser parser = new CryptoPolicyParser();
104
parser.read(new BufferedReader(new InputStreamReader(in, UTF_8)));
105
106
CryptoPermission[] parsingResult = parser.getPermissions();
107
for (int i = 0; i < parsingResult.length; i++) {
108
this.add(parsingResult[i]);
109
}
110
}
111
112
/**
113
* Returns true if this CryptoPermissions object doesn't
114
* contain any CryptoPermission objects; otherwise, returns
115
* false.
116
*/
117
boolean isEmpty() {
118
return perms.isEmpty();
119
}
120
121
/**
122
* Adds a permission object to the PermissionCollection for the
123
* algorithm returned by
124
* <code>(CryptoPermission)permission.getAlgorithm()</code>.
125
*
126
* This method creates
127
* a new PermissionCollection object (and adds the permission to it)
128
* if an appropriate collection does not yet exist. <p>
129
*
130
* @param permission the Permission object to add.
131
*
132
* @exception SecurityException if this CryptoPermissions object is
133
* marked as readonly.
134
*
135
* @see isReadOnly
136
*/
137
@Override
138
public void add(Permission permission) {
139
140
if (isReadOnly()) {
141
throw new SecurityException("Attempt to add a Permission " +
142
"to a readonly CryptoPermissions " +
143
"object");
144
}
145
146
if (!(permission instanceof CryptoPermission)) {
147
return;
148
}
149
150
CryptoPermission cryptoPerm = (CryptoPermission)permission;
151
PermissionCollection pc =
152
getPermissionCollection(cryptoPerm);
153
pc.add(cryptoPerm);
154
String alg = cryptoPerm.getAlgorithm();
155
perms.putIfAbsent(alg, pc);
156
}
157
158
/**
159
* Checks if this object's PermissionCollection for permissons
160
* of the specified permission's algorithm implies the specified
161
* permission. Returns true if the checking succeeded.
162
*
163
* @param permission the Permission object to check.
164
*
165
* @return true if "permission" is implied by the permissions
166
* in the PermissionCollection it belongs to, false if not.
167
*
168
*/
169
@Override
170
public boolean implies(Permission permission) {
171
if (!(permission instanceof CryptoPermission)) {
172
return false;
173
}
174
175
CryptoPermission cryptoPerm = (CryptoPermission)permission;
176
177
PermissionCollection pc =
178
getPermissionCollection(cryptoPerm.getAlgorithm());
179
180
if (pc != null) {
181
return pc.implies(cryptoPerm);
182
} else {
183
// none found
184
return false;
185
}
186
}
187
188
/**
189
* Returns an enumeration of all the Permission objects in all the
190
* PermissionCollections in this CryptoPermissions object.
191
*
192
* @return an enumeration of all the Permissions.
193
*/
194
@Override
195
public Enumeration<Permission> elements() {
196
// go through each Permissions in the hash table
197
// and call their elements() function.
198
return new PermissionsEnumerator(perms.elements());
199
}
200
201
/**
202
* Returns a CryptoPermissions object which
203
* represents the minimum of the specified
204
* CryptoPermissions object and this
205
* CryptoPermissions object.
206
*
207
* @param other the CryptoPermission
208
* object to compare with this object.
209
*/
210
CryptoPermissions getMinimum(CryptoPermissions other) {
211
if (other == null) {
212
return null;
213
}
214
215
if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
216
return other;
217
}
218
219
if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
220
return this;
221
}
222
223
CryptoPermissions ret = new CryptoPermissions();
224
225
226
PermissionCollection thatWildcard =
227
other.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
228
int maxKeySize = 0;
229
if (thatWildcard != null) {
230
maxKeySize = ((CryptoPermission)
231
thatWildcard.elements().nextElement()).getMaxKeySize();
232
}
233
// For each algorithm in this CryptoPermissions,
234
// find out if there is anything we should add into
235
// ret.
236
Enumeration<String> thisKeys = this.perms.keys();
237
while (thisKeys.hasMoreElements()) {
238
String alg = thisKeys.nextElement();
239
240
PermissionCollection thisPc = this.perms.get(alg);
241
PermissionCollection thatPc = other.perms.get(alg);
242
243
CryptoPermission[] partialResult;
244
245
if (thatPc == null) {
246
if (thatWildcard == null) {
247
// The other CryptoPermissions
248
// doesn't allow this given
249
// algorithm at all. Just skip this
250
// algorithm.
251
continue;
252
}
253
partialResult = getMinimum(maxKeySize, thisPc);
254
} else {
255
partialResult = getMinimum(thisPc, thatPc);
256
}
257
258
for (int i = 0; i < partialResult.length; i++) {
259
ret.add(partialResult[i]);
260
}
261
}
262
263
PermissionCollection thisWildcard =
264
this.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
265
266
// If this CryptoPermissions doesn't
267
// have a wildcard, we are done.
268
if (thisWildcard == null) {
269
return ret;
270
}
271
272
// Deal with the algorithms only appear
273
// in the other CryptoPermissions.
274
maxKeySize =
275
((CryptoPermission)
276
thisWildcard.elements().nextElement()).getMaxKeySize();
277
Enumeration<String> thatKeys = other.perms.keys();
278
while (thatKeys.hasMoreElements()) {
279
String alg = thatKeys.nextElement();
280
281
if (this.perms.containsKey(alg)) {
282
continue;
283
}
284
285
PermissionCollection thatPc = other.perms.get(alg);
286
287
CryptoPermission[] partialResult;
288
289
partialResult = getMinimum(maxKeySize, thatPc);
290
291
for (int i = 0; i < partialResult.length; i++) {
292
ret.add(partialResult[i]);
293
}
294
}
295
return ret;
296
}
297
298
/**
299
* Get the minimum of the two given PermissionCollection
300
* <code>thisPc</code> and <code>thatPc</code>.
301
*
302
* @param thisPc the first given PermissionColloection
303
* object.
304
*
305
* @param thatPc the second given PermissionCollection
306
* object.
307
*/
308
private CryptoPermission[] getMinimum(PermissionCollection thisPc,
309
PermissionCollection thatPc) {
310
Vector<CryptoPermission> permVector = new Vector<>(2);
311
312
Enumeration<Permission> thisPcPermissions = thisPc.elements();
313
314
// For each CryptoPermission in
315
// thisPc object, do the following:
316
// 1) if this CryptoPermission is implied
317
// by thatPc, this CryptoPermission
318
// should be returned, and we can
319
// move on to check the next
320
// CryptoPermission in thisPc.
321
// 2) otherwise, we should return
322
// all CryptoPermissions in thatPc
323
// which
324
// are implied by this CryptoPermission.
325
// Then we can move on to the
326
// next CryptoPermission in thisPc.
327
while (thisPcPermissions.hasMoreElements()) {
328
CryptoPermission thisCp =
329
(CryptoPermission)thisPcPermissions.nextElement();
330
331
Enumeration<Permission> thatPcPermissions = thatPc.elements();
332
while (thatPcPermissions.hasMoreElements()) {
333
CryptoPermission thatCp =
334
(CryptoPermission)thatPcPermissions.nextElement();
335
336
if (thatCp.implies(thisCp)) {
337
permVector.addElement(thisCp);
338
break;
339
}
340
if (thisCp.implies(thatCp)) {
341
permVector.addElement(thatCp);
342
}
343
}
344
}
345
346
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
347
permVector.copyInto(ret);
348
return ret;
349
}
350
351
/**
352
* Returns all the CryptoPermission objects in the given
353
* PermissionCollection object
354
* whose maximum keysize no greater than <code>maxKeySize</code>.
355
* For all CryptoPermission objects with a maximum keysize greater
356
* than <code>maxKeySize</code>, this method constructs a
357
* corresponding CryptoPermission object whose maximum keysize is
358
* set to <code>maxKeySize</code>, and includes that in the result.
359
*
360
* @param maxKeySize the given maximum key size.
361
*
362
* @param pc the given PermissionCollection object.
363
*/
364
private CryptoPermission[] getMinimum(int maxKeySize,
365
PermissionCollection pc) {
366
Vector<CryptoPermission> permVector = new Vector<>(1);
367
368
Enumeration<Permission> enum_ = pc.elements();
369
370
while (enum_.hasMoreElements()) {
371
CryptoPermission cp =
372
(CryptoPermission)enum_.nextElement();
373
if (cp.getMaxKeySize() <= maxKeySize) {
374
permVector.addElement(cp);
375
} else {
376
if (cp.getCheckParam()) {
377
permVector.addElement(
378
new CryptoPermission(cp.getAlgorithm(),
379
maxKeySize,
380
cp.getAlgorithmParameterSpec(),
381
cp.getExemptionMechanism()));
382
} else {
383
permVector.addElement(
384
new CryptoPermission(cp.getAlgorithm(),
385
maxKeySize,
386
cp.getExemptionMechanism()));
387
}
388
}
389
}
390
391
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
392
permVector.copyInto(ret);
393
return ret;
394
}
395
396
/**
397
* Returns the PermissionCollection for the
398
* specified algorithm. Returns null if there
399
* isn't such a PermissionCollection.
400
*
401
* @param alg the algorithm name.
402
*/
403
PermissionCollection getPermissionCollection(String alg) {
404
// If this CryptoPermissions includes CryptoAllPermission,
405
// we should return CryptoAllPermission.
406
PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);
407
if (pc == null) {
408
pc = perms.get(alg);
409
410
// If there isn't a PermissionCollection for
411
// the given algorithm,we should return the
412
// PermissionCollection for the wildcard
413
// if there is one.
414
if (pc == null) {
415
pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);
416
}
417
}
418
return pc;
419
}
420
421
/**
422
* Returns the PermissionCollection for the algorithm
423
* associated with the specified CryptoPermission
424
* object. Creates such a PermissionCollection
425
* if such a PermissionCollection does not
426
* exist yet.
427
*
428
* @param cryptoPerm the CryptoPermission object.
429
*/
430
private PermissionCollection getPermissionCollection(
431
CryptoPermission cryptoPerm) {
432
433
String alg = cryptoPerm.getAlgorithm();
434
435
PermissionCollection pc = perms.get(alg);
436
437
if (pc == null) {
438
pc = cryptoPerm.newPermissionCollection();
439
}
440
return pc;
441
}
442
443
@java.io.Serial
444
private void readObject(ObjectInputStream s)
445
throws IOException, ClassNotFoundException {
446
ObjectInputStream.GetField fields = s.readFields();
447
@SuppressWarnings("unchecked")
448
Hashtable<String,PermissionCollection> permTable =
449
(Hashtable<String,PermissionCollection>)
450
(fields.get("perms", null));
451
if (permTable != null) {
452
perms = new ConcurrentHashMap<>(permTable);
453
} else {
454
perms = new ConcurrentHashMap<>();
455
}
456
}
457
458
@java.io.Serial
459
private void writeObject(ObjectOutputStream s) throws IOException {
460
Hashtable<String,PermissionCollection> permTable =
461
new Hashtable<>(perms);
462
ObjectOutputStream.PutField fields = s.putFields();
463
fields.put("perms", permTable);
464
s.writeFields();
465
}
466
}
467
468
final class PermissionsEnumerator implements Enumeration<Permission> {
469
470
// all the perms
471
private final Enumeration<PermissionCollection> perms;
472
// the current set
473
private Enumeration<Permission> permset;
474
475
PermissionsEnumerator(Enumeration<PermissionCollection> e) {
476
perms = e;
477
permset = getNextEnumWithMore();
478
}
479
480
@Override
481
public synchronized boolean hasMoreElements() {
482
// if we enter with permissionimpl null, we know
483
// there are no more left.
484
485
if (permset == null) {
486
return false;
487
}
488
489
// try to see if there are any left in the current one
490
491
if (permset.hasMoreElements()) {
492
return true;
493
}
494
495
// get the next one that has something in it...
496
permset = getNextEnumWithMore();
497
498
// if it is null, we are done!
499
return (permset != null);
500
}
501
502
@Override
503
public synchronized Permission nextElement() {
504
// hasMoreElements will update permset to the next permset
505
// with something in it...
506
507
if (hasMoreElements()) {
508
return permset.nextElement();
509
} else {
510
throw new NoSuchElementException("PermissionsEnumerator");
511
}
512
}
513
514
private Enumeration<Permission> getNextEnumWithMore() {
515
while (perms.hasMoreElements()) {
516
PermissionCollection pc = perms.nextElement();
517
Enumeration<Permission> next = pc.elements();
518
if (next.hasMoreElements()) {
519
return next;
520
}
521
}
522
return null;
523
}
524
}
525
526