KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > security > ACLSecurityImpl


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/security/ACLSecurityImpl.java,v 1.10.2.3 2004/12/03 23:14:43 masonjm Exp $
3  * $Revision: 1.10.2.3 $
4  * $Date: 2004/12/03 23:14:43 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23 package org.apache.slide.security;
24
25 import java.util.Enumeration JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Vector JavaDoc;
28 import org.apache.slide.common.Namespace;
29 import org.apache.slide.common.NamespaceConfig;
30 import org.apache.slide.common.ServiceAccessException;
31 import org.apache.slide.common.SlideToken;
32 import org.apache.slide.common.Uri;
33 import org.apache.slide.content.NodeProperty;
34 import org.apache.slide.content.NodeRevisionDescriptor;
35 import org.apache.slide.content.NodeRevisionNumber;
36 import org.apache.slide.content.RevisionDescriptorNotFoundException;
37 import org.apache.slide.structure.ActionNode;
38 import org.apache.slide.structure.ObjectNode;
39 import org.apache.slide.structure.ObjectNotFoundException;
40 import org.apache.slide.structure.SubjectNode;
41 import org.apache.slide.util.XMLValue;
42 import org.apache.slide.util.logger.Logger;
43 import org.jdom.JDOMException;
44
45 /**
46  * WebDAV/ACL compliant security helper implementation (draft-12)
47  *
48  * @version $Revision: 1.10.2.3 $
49  */

50 public class ACLSecurityImpl extends SecurityImpl {
51     
52     private static final String JavaDoc LOG_CHANNEL = ACLSecurityImpl.class.getName();
53     private static final Vector JavaDoc EMPTY_VECTOR = new Vector JavaDoc();
54     
55     /**
56      * Be sure to call init() before using an instance created with this
57      * constructor.
58      */

59     public ACLSecurityImpl() {
60         super();
61     }
62     
63     /**
64      * Constructor.
65      *
66      * @param namespace Namespace
67      * @param namespaceConfig Namespace configuration
68      */

69     public ACLSecurityImpl(Namespace namespace, NamespaceConfig namespaceConfig) {
70         super(namespace, namespaceConfig);
71     }
72     
73     /**
74      * Method init
75      *
76      * @param namespace a Namespace
77      * @param namespaceConfig a NamespaceConfig
78      */

79     public void init(Namespace namespace, NamespaceConfig namespaceConfig) {
80         super.init(namespace, namespaceConfig);
81     }
82     
83     /**
84      * Check whether or not an actor can perform the specified activity
85      * on a collection.
86      *
87      * @param object Object on which access is tested
88      * @param subject Subject who seeks to perform the action
89      * @param action Action which is to be performed
90      * @return true if the action can be performed
91      * @exception ServiceAccessException DataSource access error
92      * @exception ObjectNotFoundException Specified object was not found
93      * in the DataSource
94      */

95     public boolean hasPermission(ObjectNode object, SubjectNode subject,
96                                  ActionNode action)
97         throws ServiceAccessException, ObjectNotFoundException {
98         
99         throw new UnsupportedOperationException JavaDoc(
100             "Please use alternate signature: "
101                 +"hasPermission(SlideToken token, ObjectNode object, ActionNode action)");
102     }
103     
104     /**
105      * Check whether or not an actor (principal) can perform the specified activity
106      * on the specified resource.
107      *
108      * @param token a SlideToken
109      * @param objectNode Object on which access is tested
110      * @param actionNode Action which is to be performed
111      *
112      * @return true if the action can be performed
113      *
114      * @throws ServiceAccessException
115      * @throws ObjectNotFoundException
116      */

117     public boolean hasPermission(SlideToken token, ObjectNode objectNode, ActionNode actionNode)
118         throws ServiceAccessException, ObjectNotFoundException {
119         
120         // logging
121
if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
122             try {
123                 logger.log("@@@ check object="+objectNode+", subject="+getPrincipal(token)+", action="+actionNode, LOG_CHANNEL, Logger.DEBUG);
124             } catch (ObjectNotFoundException onfe) {
125                 // ignore as this is logging only
126
}
127         }
128         // no check for default action (server intitialization)
129
if (actionNode == namespaceConfig.getDefaultAction()) {
130             return true;
131         }
132         
133         Enumeration JavaDoc permissions = enumeratePermissions(token, objectNode, true);
134         return evaluateAcl(token, objectNode, actionNode, permissions);
135     }
136     
137     public boolean hasRole(SlideToken token, String JavaDoc role) throws ServiceAccessException, ObjectNotFoundException {
138         return hasRole(token, (SubjectNode)getPrincipal(token), role);
139     }
140     
141     // overwrites super
142
public boolean hasRole(SlideToken token, SubjectNode subjectNode, String JavaDoc role) throws ServiceAccessException, ObjectNotFoundException {
143         SubjectNode roleNode = null;
144         if (namespaceConfig.getRolesPath() != null && namespaceConfig.getRolesPath().length() != 0) {
145             roleNode = SubjectNode.getSubjectNode(namespaceConfig.getRolesPath()+"/"+role);
146         }
147         if (roleNode != null && matchPrincipal(token, subjectNode, roleNode)) {
148             return true;
149         }
150         else {
151             // check groups
152
SubjectNode groupNode = null;
153             if (namespaceConfig.getGroupsPath() != null && namespaceConfig.getGroupsPath().length() != 0) {
154                 groupNode = SubjectNode.getSubjectNode(namespaceConfig.getGroupsPath()+"/"+role);
155             }
156             return (groupNode != null && matchPrincipal(token, subjectNode, groupNode));
157         }
158     }
159     
160     // overwrites super
161
public boolean hasRole(ObjectNode object, String JavaDoc role) throws ServiceAccessException, ObjectNotFoundException {
162         throw new UnsupportedOperationException JavaDoc("Please use alternate signature: hasRole(SlideToken token, String role)");
163     }
164     
165     // overwrites super
166
public Enumeration JavaDoc getRoles(SlideToken token) throws ServiceAccessException, ObjectNotFoundException {
167         return getRoles(token, (SubjectNode)getPrincipal(token));
168     }
169     
170     /**
171      * Get the role names the specified subject has (deeply over nested roles, if there)
172      *
173      * @param token a SlideToken
174      * @param subjectNode a SubjectNode
175      * @return an Enumeration of role names
176      * @throws ServiceAccessException
177      * @throws ObjectNotFoundException
178      */

179     public Enumeration JavaDoc getRoles(SlideToken token, SubjectNode subjectNode) throws ServiceAccessException, ObjectNotFoundException {
180         // check the principal exists
181
Uri subjectUri = namespace.getUri(token, subjectNode.getUri());
182         subjectUri.getStore().retrieveObject(subjectUri);
183         
184         Vector JavaDoc result = new Vector JavaDoc();
185         Uri rolesUri = null;
186         ObjectNode rolesNode = null;
187         if (namespaceConfig.getRolesPath() != null && namespaceConfig.getRolesPath().length() != 0) {
188             rolesUri = namespace.getUri(token, namespaceConfig.getRolesPath());
189             try {
190                 rolesNode = rolesUri.getStore().retrieveObject(rolesUri);
191             } catch (ObjectNotFoundException e) {}
192             if (rolesNode != null) {
193                 Enumeration JavaDoc rolesEnum = rolesNode.enumerateBindings();
194                 while (rolesEnum.hasMoreElements()) {
195                     ObjectNode.Binding b = (ObjectNode.Binding)rolesEnum.nextElement();
196                     String JavaDoc role = b.getName();
197                     if (hasRole(token, subjectNode, role)) {
198                         result.add(role);
199                     }
200                 }
201             }
202         }
203         Uri groupsUri = null;
204         ObjectNode groupsNode = null;
205         if (namespaceConfig.getGroupsPath() != null && namespaceConfig.getGroupsPath().length() != 0) {
206             groupsUri = namespace.getUri(token, namespaceConfig.getGroupsPath());
207             groupsNode = groupsUri.getStore().retrieveObject(groupsUri);
208             if (groupsNode != null) {
209                 Enumeration JavaDoc groupsEnum = groupsNode.enumerateBindings();
210                 while (groupsEnum.hasMoreElements()) {
211                     ObjectNode.Binding b = (ObjectNode.Binding)groupsEnum.nextElement();
212                     String JavaDoc group = b.getName();
213                     if (hasRole(token, subjectNode, group)) {
214                         result.add(group);
215                     }
216                 }
217             }
218         }
219         return result.elements();
220     }
221     
222     /**
223      * Get enumeration of paths according to property DAV:group-membership
224      *
225      * @param token a SlideToken
226      * @param subjectNode a SubjectNode
227      * @return an Enumeration of paths (String)
228      * @throws ServiceAccessException
229      * @throws ObjectNotFoundException
230      */

231     public Enumeration JavaDoc getGroupMembership(SlideToken token, SubjectNode subjectNode) throws ServiceAccessException, ObjectNotFoundException {
232         // check the principal exists
233
Uri subjectUri = namespace.getUri(token, subjectNode.getUri());
234         subjectUri.getStore().retrieveObject(subjectUri);
235         
236         Vector JavaDoc result = new Vector JavaDoc();
237         Uri rolesUri = null;
238         ObjectNode rolesNode = null;
239         if (namespaceConfig.getRolesPath() != null && namespaceConfig.getRolesPath().length() != 0) {
240             rolesUri = namespace.getUri(token, namespaceConfig.getRolesPath());
241             try {
242                 rolesNode = rolesUri.getStore().retrieveObject(rolesUri);
243             } catch (ObjectNotFoundException e) {}
244             if (rolesNode != null) {
245                 Enumeration JavaDoc rolesEnum = rolesNode.enumerateBindings();
246                 while (rolesEnum.hasMoreElements()) {
247                     ObjectNode.Binding b = (ObjectNode.Binding)rolesEnum.nextElement();
248                     String JavaDoc role = b.getName();
249                     Uri roleUri = namespace.getUri(token, namespaceConfig.getRolesPath()+"/"+role);
250                     try {
251                         NodeRevisionDescriptor nrd =
252                             roleUri.getStore().retrieveRevisionDescriptor(roleUri, new NodeRevisionNumber());
253                         NodeProperty membersetProp = nrd.getProperty("group-member-set");
254                         if (membersetProp != null && membersetProp.getValue() != null) {
255                             XMLValue xmlVal = new XMLValue((String JavaDoc)membersetProp.getValue());
256                             List JavaDoc memberNodes = xmlVal.getHrefNodes();
257                             if (memberNodes.contains(subjectNode)) {
258                                 result.add(roleUri.toString());
259                             }
260                         }
261                     } catch (RevisionDescriptorNotFoundException e) {
262                     } catch (JDOMException e) {}
263                 }
264             }
265         }
266         Uri groupsUri = null;
267         ObjectNode groupsNode = null;
268         if (namespaceConfig.getGroupsPath() != null && namespaceConfig.getGroupsPath().length() != 0) {
269             groupsUri = namespace.getUri(token, namespaceConfig.getGroupsPath());
270             try {
271                 groupsNode = groupsUri.getStore().retrieveObject(groupsUri);
272             } catch (ObjectNotFoundException e) {}
273             if (groupsNode != null) {
274                 Enumeration JavaDoc rolesEnum = groupsNode.enumerateBindings();
275                 while (rolesEnum.hasMoreElements()) {
276                     ObjectNode.Binding b = (ObjectNode.Binding)rolesEnum.nextElement();
277                     String JavaDoc group = b.getName();
278                     Uri roleUri = namespace.getUri(token, namespaceConfig.getGroupsPath()+"/"+group);
279                     try {
280                         NodeRevisionDescriptor nrd =
281                             roleUri.getStore().retrieveRevisionDescriptor(roleUri, new NodeRevisionNumber());
282                         NodeProperty membersetProp = nrd.getProperty("group-member-set");
283                         if (membersetProp != null && membersetProp.getValue() != null) {
284                             XMLValue xmlVal = new XMLValue((String JavaDoc)membersetProp.getValue());
285                             List JavaDoc memberNodes = xmlVal.getHrefNodes();
286                             if (memberNodes.contains(subjectNode)) {
287                                 result.add(roleUri.toString());
288                             }
289                         }
290                     } catch (RevisionDescriptorNotFoundException e) {
291                     } catch (JDOMException e) {}
292                 }
293             }
294         }
295         return result.elements();
296     }
297     
298     // overwrites super
299
public Enumeration JavaDoc getRoles(ObjectNode object) {
300         return EMPTY_VECTOR.elements();
301     }
302     
303     /**
304      * Evaluates speified ACL by first-match principle
305      */

306     private boolean evaluateAcl(SlideToken token, ObjectNode objectNode, ActionNode actionNode, Enumeration JavaDoc permissions) throws ServiceAccessException, ObjectNotFoundException {
307         boolean result = false;
308         SubjectNode subjectNode = (SubjectNode)getPrincipal(token);
309         while (permissions.hasMoreElements()) {
310             NodePermission permission = (NodePermission)permissions.nextElement();
311             if (match(token, objectNode, subjectNode, actionNode, permission)) {
312                 result = !permission.isNegative();
313                 break;
314             }
315         }
316         return result;
317     }
318     
319     private boolean match(SlideToken token, ObjectNode objectNode, SubjectNode subjectNode, ActionNode actionNode, NodePermission permission) throws ServiceAccessException {
320         boolean result = true;
321         result = matchAction(token, actionNode, permission.getActionNode()) && matchSubject(token, objectNode, subjectNode, permission.getSubjectNode());
322         // logging
323
if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
324             logger.log(" permission="+permission+", match="+result, LOG_CHANNEL, Logger.DEBUG);
325         }
326         return result;
327     }
328     
329     private boolean matchSubject(SlideToken token, ObjectNode objectNode, SubjectNode checkSubject, SubjectNode permSubject) throws ServiceAccessException {
330         if (permSubject.equals(SubjectNode.ALL)) {
331             return true;
332         }
333         else if (permSubject.equals(SubjectNode.AUTHENTICATED)) {
334             return !checkSubject.equals(SubjectNode.UNAUTHENTICATED);
335         }
336         else if (permSubject.equals(SubjectNode.UNAUTHENTICATED)) {
337             return checkSubject.equals(SubjectNode.UNAUTHENTICATED);
338         }
339         else if (permSubject.equals(SubjectNode.OWNER)) {
340             return matchOwner(token, objectNode, checkSubject);
341         }
342         else if (permSubject.equals(SubjectNode.SELF)) {
343             return matchPrincipal(token, checkSubject, (SubjectNode)objectNode);
344         }
345         else {
346             return matchPrincipal(token, checkSubject, permSubject);
347         }
348     }
349     
350     private boolean matchOwner(SlideToken token, ObjectNode objectNode, SubjectNode checkSubject) throws ServiceAccessException {
351         Uri objectUri = namespace.getUri(token, objectNode.getUri());
352         try {
353             NodeRevisionDescriptor nrd =
354                 objectUri.getStore().retrieveRevisionDescriptor(objectUri, new NodeRevisionNumber());
355             NodeProperty ownerProp = nrd.getProperty("owner");
356             if (ownerProp != null && ownerProp.getValue() != null) {
357                 String JavaDoc usersPath = namespace.getConfig().getUsersPath();
358                 SubjectNode ownerSubject = SubjectNode.getSubjectNode(usersPath+"/"+ownerProp.getValue());
359                 return ownerSubject.equals(checkSubject);
360             }
361             else {
362                 return false;
363             }
364         }
365         catch (RevisionDescriptorNotFoundException e) {
366             return false;
367         }
368         catch (ServiceAccessException e) {
369             throw e;
370         }
371     }
372 }
373
374
375
376
377
Popular Tags