History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/acl/AclImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/acl/AclImpl.java+408−0
@@ -0,0 +1,408 @@
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+}