Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/acl/AclImpl.java
38830 views
1
/*
2
* Copyright (c) 1996, 2011, 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.acl;
27
28
import java.io.*;
29
import java.util.*;
30
import java.security.Principal;
31
import java.security.acl.*;
32
33
/**
34
* An Access Control List (ACL) is encapsulated by this class.
35
* @author Satish Dharmaraj
36
*/
37
public class AclImpl extends OwnerImpl implements Acl {
38
//
39
// Maintain four tables. one each for positive and negative
40
// ACLs. One each depending on whether the entity is a group
41
// or principal.
42
//
43
private Hashtable<Principal, AclEntry> allowedUsersTable =
44
new Hashtable<>(23);
45
private Hashtable<Principal, AclEntry> allowedGroupsTable =
46
new Hashtable<>(23);
47
private Hashtable<Principal, AclEntry> deniedUsersTable =
48
new Hashtable<>(23);
49
private Hashtable<Principal, AclEntry> deniedGroupsTable =
50
new Hashtable<>(23);
51
private String aclName = null;
52
private Vector<Permission> zeroSet = new Vector<>(1,1);
53
54
55
/**
56
* Constructor for creating an empty ACL.
57
*/
58
public AclImpl(Principal owner, String name) {
59
super(owner);
60
try {
61
setName(owner, name);
62
} catch (Exception e) {}
63
}
64
65
/**
66
* Sets the name of the ACL.
67
* @param caller the principal who is invoking this method.
68
* @param name the name of the ACL.
69
* @exception NotOwnerException if the caller principal is
70
* not on the owners list of the Acl.
71
*/
72
public void setName(Principal caller, String name)
73
throws NotOwnerException
74
{
75
if (!isOwner(caller))
76
throw new NotOwnerException();
77
78
aclName = name;
79
}
80
81
/**
82
* Returns the name of the ACL.
83
* @return the name of the ACL.
84
*/
85
public String getName() {
86
return aclName;
87
}
88
89
/**
90
* Adds an ACL entry to this ACL. An entry associates a
91
* group or a principal with a set of permissions. Each
92
* user or group can have one positive ACL entry and one
93
* negative ACL entry. If there is one of the type (negative
94
* or positive) already in the table, a false value is returned.
95
* The caller principal must be a part of the owners list of
96
* the ACL in order to invoke this method.
97
* @param caller the principal who is invoking this method.
98
* @param entry the ACL entry that must be added to the ACL.
99
* @return true on success, false if the entry is already present.
100
* @exception NotOwnerException if the caller principal
101
* is not on the owners list of the Acl.
102
*/
103
public synchronized boolean addEntry(Principal caller, AclEntry entry)
104
throws NotOwnerException
105
{
106
if (!isOwner(caller))
107
throw new NotOwnerException();
108
109
Hashtable<Principal, AclEntry> aclTable = findTable(entry);
110
Principal key = entry.getPrincipal();
111
112
if (aclTable.get(key) != null)
113
return false;
114
115
aclTable.put(key, entry);
116
return true;
117
}
118
119
/**
120
* Removes an ACL entry from this ACL.
121
* The caller principal must be a part of the owners list of the ACL
122
* in order to invoke this method.
123
* @param caller the principal who is invoking this method.
124
* @param entry the ACL entry that must be removed from the ACL.
125
* @return true on success, false if the entry is not part of the ACL.
126
* @exception NotOwnerException if the caller principal is not
127
* the owners list of the Acl.
128
*/
129
public synchronized boolean removeEntry(Principal caller, AclEntry entry)
130
throws NotOwnerException
131
{
132
if (!isOwner(caller))
133
throw new NotOwnerException();
134
135
Hashtable<Principal, AclEntry> aclTable = findTable(entry);
136
Principal key = entry.getPrincipal();
137
138
AclEntry o = aclTable.remove(key);
139
return (o != null);
140
}
141
142
/**
143
* This method returns the set of allowed permissions for the
144
* specified principal. This set of allowed permissions is calculated
145
* as follows:
146
*
147
* If there is no entry for a group or a principal an empty permission
148
* set is assumed.
149
*
150
* The group positive permission set is the union of all
151
* the positive permissions of each group that the individual belongs to.
152
* The group negative permission set is the union of all
153
* the negative permissions of each group that the individual belongs to.
154
* If there is a specific permission that occurs in both
155
* the postive permission set and the negative permission set,
156
* it is removed from both. The group positive and negatoive permission
157
* sets are calculated.
158
*
159
* The individial positive permission set and the individual negative
160
* permission set is then calculated. Again abscence of an entry means
161
* the empty set.
162
*
163
* The set of permissions granted to the principal is then calculated using
164
* the simple rule: Individual permissions always override the Group permissions.
165
* Specifically, individual negative permission set (specific
166
* denial of permissions) overrides the group positive permission set.
167
* And the individual positive permission set override the group negative
168
* permission set.
169
*
170
* @param user the principal for which the ACL entry is returned.
171
* @return The resulting permission set that the principal is allowed.
172
*/
173
public synchronized Enumeration<Permission> getPermissions(Principal user) {
174
175
Enumeration<Permission> individualPositive;
176
Enumeration<Permission> individualNegative;
177
Enumeration<Permission> groupPositive;
178
Enumeration<Permission> groupNegative;
179
180
//
181
// canonicalize the sets. That is remove common permissions from
182
// positive and negative sets.
183
//
184
groupPositive =
185
subtract(getGroupPositive(user), getGroupNegative(user));
186
groupNegative =
187
subtract(getGroupNegative(user), getGroupPositive(user));
188
individualPositive =
189
subtract(getIndividualPositive(user), getIndividualNegative(user));
190
individualNegative =
191
subtract(getIndividualNegative(user), getIndividualPositive(user));
192
193
//
194
// net positive permissions is individual positive permissions
195
// plus (group positive - individual negative).
196
//
197
Enumeration<Permission> temp1 =
198
subtract(groupPositive, individualNegative);
199
Enumeration<Permission> netPositive =
200
union(individualPositive, temp1);
201
202
// recalculate the enumeration since we lost it in performing the
203
// subtraction
204
//
205
individualPositive =
206
subtract(getIndividualPositive(user), getIndividualNegative(user));
207
individualNegative =
208
subtract(getIndividualNegative(user), getIndividualPositive(user));
209
210
//
211
// net negative permissions is individual negative permissions
212
// plus (group negative - individual positive).
213
//
214
temp1 = subtract(groupNegative, individualPositive);
215
Enumeration<Permission> netNegative = union(individualNegative, temp1);
216
217
return subtract(netPositive, netNegative);
218
}
219
220
/**
221
* This method checks whether or not the specified principal
222
* has the required permission. If permission is denied
223
* permission false is returned, a true value is returned otherwise.
224
* This method does not authenticate the principal. It presumes that
225
* the principal is a valid authenticated principal.
226
* @param principal the name of the authenticated principal
227
* @param permission the permission that the principal must have.
228
* @return true of the principal has the permission desired, false
229
* otherwise.
230
*/
231
public boolean checkPermission(Principal principal, Permission permission)
232
{
233
Enumeration<Permission> permSet = getPermissions(principal);
234
while (permSet.hasMoreElements()) {
235
Permission p = permSet.nextElement();
236
if (p.equals(permission))
237
return true;
238
}
239
return false;
240
}
241
242
/**
243
* returns an enumeration of the entries in this ACL.
244
*/
245
public synchronized Enumeration<AclEntry> entries() {
246
return new AclEnumerator(this,
247
allowedUsersTable, allowedGroupsTable,
248
deniedUsersTable, deniedGroupsTable);
249
}
250
251
/**
252
* return a stringified version of the
253
* ACL.
254
*/
255
public String toString() {
256
StringBuffer sb = new StringBuffer();
257
Enumeration<AclEntry> entries = entries();
258
while (entries.hasMoreElements()) {
259
AclEntry entry = entries.nextElement();
260
sb.append(entry.toString().trim());
261
sb.append("\n");
262
}
263
264
return sb.toString();
265
}
266
267
//
268
// Find the table that this entry belongs to. There are 4
269
// tables that are maintained. One each for postive and
270
// negative ACLs and one each for groups and users.
271
// This method figures out which
272
// table is the one that this AclEntry belongs to.
273
//
274
private Hashtable<Principal, AclEntry> findTable(AclEntry entry) {
275
Hashtable<Principal, AclEntry> aclTable = null;
276
277
Principal p = entry.getPrincipal();
278
if (p instanceof Group) {
279
if (entry.isNegative())
280
aclTable = deniedGroupsTable;
281
else
282
aclTable = allowedGroupsTable;
283
} else {
284
if (entry.isNegative())
285
aclTable = deniedUsersTable;
286
else
287
aclTable = allowedUsersTable;
288
}
289
return aclTable;
290
}
291
292
//
293
// returns the set e1 U e2.
294
//
295
private static Enumeration<Permission> union(Enumeration<Permission> e1,
296
Enumeration<Permission> e2) {
297
Vector<Permission> v = new Vector<>(20, 20);
298
299
while (e1.hasMoreElements())
300
v.addElement(e1.nextElement());
301
302
while (e2.hasMoreElements()) {
303
Permission o = e2.nextElement();
304
if (!v.contains(o))
305
v.addElement(o);
306
}
307
308
return v.elements();
309
}
310
311
//
312
// returns the set e1 - e2.
313
//
314
private Enumeration<Permission> subtract(Enumeration<Permission> e1,
315
Enumeration<Permission> e2) {
316
Vector<Permission> v = new Vector<>(20, 20);
317
318
while (e1.hasMoreElements())
319
v.addElement(e1.nextElement());
320
321
while (e2.hasMoreElements()) {
322
Permission o = e2.nextElement();
323
if (v.contains(o))
324
v.removeElement(o);
325
}
326
327
return v.elements();
328
}
329
330
private Enumeration<Permission> getGroupPositive(Principal user) {
331
Enumeration<Permission> groupPositive = zeroSet.elements();
332
Enumeration<Principal> e = allowedGroupsTable.keys();
333
while (e.hasMoreElements()) {
334
Group g = (Group)e.nextElement();
335
if (g.isMember(user)) {
336
AclEntry ae = allowedGroupsTable.get(g);
337
groupPositive = union(ae.permissions(), groupPositive);
338
}
339
}
340
return groupPositive;
341
}
342
343
private Enumeration<Permission> getGroupNegative(Principal user) {
344
Enumeration<Permission> groupNegative = zeroSet.elements();
345
Enumeration<Principal> e = deniedGroupsTable.keys();
346
while (e.hasMoreElements()) {
347
Group g = (Group)e.nextElement();
348
if (g.isMember(user)) {
349
AclEntry ae = deniedGroupsTable.get(g);
350
groupNegative = union(ae.permissions(), groupNegative);
351
}
352
}
353
return groupNegative;
354
}
355
356
private Enumeration<Permission> getIndividualPositive(Principal user) {
357
Enumeration<Permission> individualPositive = zeroSet.elements();
358
AclEntry ae = allowedUsersTable.get(user);
359
if (ae != null)
360
individualPositive = ae.permissions();
361
return individualPositive;
362
}
363
364
private Enumeration<Permission> getIndividualNegative(Principal user) {
365
Enumeration<Permission> individualNegative = zeroSet.elements();
366
AclEntry ae = deniedUsersTable.get(user);
367
if (ae != null)
368
individualNegative = ae.permissions();
369
return individualNegative;
370
}
371
}
372
373
final class AclEnumerator implements Enumeration<AclEntry> {
374
Acl acl;
375
Enumeration<AclEntry> u1, u2, g1, g2;
376
377
AclEnumerator(Acl acl, Hashtable<?,AclEntry> u1, Hashtable<?,AclEntry> g1,
378
Hashtable<?,AclEntry> u2, Hashtable<?,AclEntry> g2) {
379
this.acl = acl;
380
this.u1 = u1.elements();
381
this.u2 = u2.elements();
382
this.g1 = g1.elements();
383
this.g2 = g2.elements();
384
}
385
386
public boolean hasMoreElements() {
387
return (u1.hasMoreElements() ||
388
u2.hasMoreElements() ||
389
g1.hasMoreElements() ||
390
g2.hasMoreElements());
391
}
392
393
public AclEntry nextElement()
394
{
395
AclEntry o;
396
synchronized (acl) {
397
if (u1.hasMoreElements())
398
return u1.nextElement();
399
if (u2.hasMoreElements())
400
return u2.nextElement();
401
if (g1.hasMoreElements())
402
return g1.nextElement();
403
if (g2.hasMoreElements())
404
return g2.nextElement();
405
}
406
throw new NoSuchElementException("Acl Enumerator");
407
}
408
}
409
410