]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
70e5f0b6254dd95f7fd8259a3f60061ff75633fc
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.authorization.spring;
25
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import org.collectionspace.services.authorization.CSpaceAction;
34 import org.collectionspace.services.authorization.spi.CSpacePermissionManager;
35 import org.collectionspace.services.authorization.CSpaceResource;
36 import org.collectionspace.services.authorization.PermissionException;
37 import org.collectionspace.services.authorization.PermissionNotFoundException;
38
39 import org.springframework.security.acls.model.AccessControlEntry;
40 import org.springframework.security.acls.model.AclDataAccessException;
41 import org.springframework.security.acls.model.AlreadyExistsException;
42 import org.springframework.security.acls.model.MutableAcl;
43 import org.springframework.security.acls.model.NotFoundException;
44 import org.springframework.security.acls.model.ObjectIdentity;
45 import org.springframework.security.acls.model.Permission;
46 import org.springframework.security.acls.model.Sid;
47
48 /**
49  * Manages permissions in Spring Security
50  * @author 
51  */
52 public class SpringPermissionManager implements CSpacePermissionManager {
53
54     final Log log = LogFactory.getLog(SpringPermissionManager.class);
55     private SpringAuthorizationProvider provider;
56
57     SpringPermissionManager(SpringAuthorizationProvider provider) {
58         this.provider = provider;
59     }
60
61     /**
62      * addPermissions adds permissions according to the given grant for given
63      * resource#action for each given principal
64      * @param res
65      * @param action
66      * @param principals
67      * @param grant
68      * @throws PermissionException
69      */
70     @Override
71     public void addPermissionsToRoles(CSpaceResource res, CSpaceAction action, String[] principals, boolean grant)
72             throws PermissionException {
73         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
74         Sid[] sids = SpringAuthorizationProvider.getSids(principals);
75         Permission p = SpringAuthorizationProvider.getPermission(action);
76
77         //add permission for each sid
78         for (Sid sid : sids) {
79             try {
80                 addPermissionToRole(oid, p, sid, grant);
81                 if (log.isDebugEnabled()) {
82                     log.debug("addpermissions(res,action,prin[], grant), success for "
83                             + " res=" + res.toString()
84                             + " action=" + action.toString()
85                             + " grant=" + grant
86                             + " oid=" + oid.toString()
87                             + " perm=" + p.toString()
88                             + " sid=" + sid.toString());
89                 }
90
91             } catch (AlreadyExistsException aex) {
92                 if (log.isWarnEnabled()) {
93                     log.warn("addpermissions(res,action,prin[], grant) failed,"
94                             + " oid=" + oid.toString()
95                             + " res=" + res.toString()
96                             + " grant=" + grant
97                             + " action=" + action.toString()
98                             + " oid=" + oid.toString()
99                             + " perm=" + p.toString(), aex);
100                 }
101                 throw new PermissionException("Permission already exists", aex);
102             } catch (Exception ex) {
103                 String msg = "addpermissions(res,action,prin[], grant) failed,"
104                         + " oid=" + oid.toString()
105                         + " res=" + res.toString()
106                         + " action=" + action.toString()
107                         + " oid=" + oid.toString()
108                         + " perm=" + p.toString()
109                         + " grant=" + grant;
110                 if (log.isDebugEnabled()) {
111                     log.debug(msg, ex);
112                 }
113                 //don't know what might be wrong...stop
114                 if (ex instanceof PermissionException) {
115                     throw (PermissionException) ex;
116                 }
117                 throw new PermissionException(msg, ex);
118             }
119         }//rof
120         if (log.isDebugEnabled()) {
121             log.debug("addpermissions(res,action,prin[], grant), success for "
122                     + " res=" + res.toString()
123                     + " action=" + action.toString()
124                     + " grant=" + grant
125                     + " oid=" + oid.toString()
126                     + " perm=" + p.toString()
127                     + " sids=" + sids.toString());
128         }
129     }
130
131     /**
132      * deletePermissions removes permisions for given resource#action for each given principal
133      * @param res
134      * @param action
135      * @param principals
136      * @throws PermissionNotFoundException
137      * @throws PermissionException
138      */
139     @Override
140     public void deletePermissionsFromRoles(CSpaceResource res, CSpaceAction action, String[] principals)
141             throws PermissionNotFoundException, PermissionException {
142         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
143         Sid[] sids = SpringAuthorizationProvider.getSids(principals);
144         Permission p = SpringAuthorizationProvider.getPermission(action);
145         //delete permission for each sid
146         for (Sid sid : sids) {
147             try {
148                 deletePermissionFromRole(oid, p, sid);
149                 if (log.isDebugEnabled()) {
150                     log.debug("deletedpermissions(res,action,prin[]), success for "
151                             + " res=" + res.toString()
152                             + " action=" + action.toString()
153                             + " oid=" + oid.toString()
154                             + " perm=" + p.toString()
155                             + " sid=" + sid.toString());
156                 }
157             } catch (AclDataAccessException aex) {
158                 if (log.isWarnEnabled()) {
159                     log.debug("deletepermissions(res,action,prin[]) failed, "
160                             + " oid=" + oid.toString()
161                             + " res=" + res.toString()
162                             + " action=" + action.toString()
163                             + " oid=" + oid.toString()
164                             + " perm=" + p.toString(), aex);
165                 }
166                 //keep going
167             } catch (Exception ex) {
168                 String msg = "deletepermissions(res,action,prin[]) failed,"
169                         + " oid=" + oid.toString()
170                         + " res=" + res.toString()
171                         + " action=" + action.toString()
172                         + " oid=" + oid.toString()
173                         + " perm=" + p.toString();
174                 if (log.isDebugEnabled()) {
175                     log.debug(msg, ex);
176                 }
177                 //don't know what might be wrong...stop
178                 if (ex instanceof PermissionException) {
179                     throw (PermissionException) ex;
180                 }
181                 throw new PermissionException(msg, ex);
182             }
183         }
184         if (log.isDebugEnabled()) {
185             log.debug("deletedpermissions(res,action,prin[]), success for "
186                     + " res=" + res.toString()
187                     + " action=" + action.toString()
188                     + " oid=" + oid.toString()
189                     + " perm=" + p.toString()
190                     + " sids=" + sids.toString());
191         }
192     }
193
194     /**
195      * deletePermissions
196      * @param res
197      * @param action
198      * @throws PermissionNotFoundException
199      * @throws PermissionException
200      */
201     //non-javadoc NOTE: this is a very destructive operation. it would remove all permissions
202     //to access given resource#action for ANY role including administrators
203     @Override
204     public void deletePermissions(CSpaceResource res, CSpaceAction action)
205             throws PermissionNotFoundException, PermissionException {
206         
207         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
208         Permission p = SpringAuthorizationProvider.getPermission(action);
209         try {
210             deletePermissionFromRole(oid, p, null);
211             if (log.isDebugEnabled()) {
212                 log.debug("deletepermissions(res,action) success, "
213                         + " res=" + res.toString()
214                         + " action=" + action.toString()
215                         + " oid=" + oid.toString()
216                         + " perm=" + p.toString());
217             }
218         } catch (AclDataAccessException aex) {
219             log.debug("deletepermissions(res,action) failed,"
220                     + " oid=" + oid.toString()
221                     + " res=" + res.toString()
222                     + " action=" + action.toString()
223                     + " oid=" + oid.toString()
224                     + " perm=" + p.toString(), aex);
225             throw new PermissionException(aex);
226         } catch (Exception ex) {
227             String msg = "deletepermissions(res,action,prin[]) failed,"
228                     + " oid=" + oid.toString()
229                     + " res=" + res.toString()
230                     + " action=" + action.toString()
231                     + " oid=" + oid.toString()
232                     + " perm=" + p.toString();
233             if (log.isDebugEnabled()) {
234                 log.debug(msg, ex);
235             }
236             if (ex instanceof PermissionException) {
237                 throw (PermissionException) ex;
238             }
239             throw new PermissionException(msg, ex);
240         }
241
242     }
243
244     /**
245      * deletePermissions
246      * @param res
247      * @throws PermissionNotFoundException
248      * @throws PermissionException
249      */
250     //non-javadoc NOTE: this is a very very destructive operation. it would remove all permissions
251     //to access given resource for ANY action for ANY role including administrators
252     @Override
253     public void deletePermissions(CSpaceResource res)
254             throws PermissionNotFoundException, PermissionException {
255         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
256         try {
257             provider.getProviderAclService().deleteAcl(oid, true);
258             if (log.isDebugEnabled()) {
259                 log.debug("deletepermissions(res) success, "
260                         + " res=" + res.toString()
261                         + " oid=" + oid.toString());
262             }
263         } catch (AclDataAccessException aex) {
264             log.debug("deletepermissions(res) failed,"
265                     + " oid=" + oid.toString()
266                     + " res=" + res.toString()
267                     + " oid=" + oid.toString(), aex);
268             throw new PermissionException(aex);
269         } catch (Exception ex) {
270             String msg = "deletepermissions(res) failed,"
271                     + " oid=" + oid.toString()
272                     + " res=" + res.toString()
273                     + " oid=" + oid.toString();
274             if (log.isDebugEnabled()) {
275                 log.debug(msg, ex);
276             }
277             if (ex instanceof PermissionException) {
278                 throw (PermissionException) ex;
279             }
280             throw new PermissionException(msg, ex);
281         }
282     }
283
284     /**
285      * addPermission adds permission grant for given object identity for given permission
286      * for given sid
287      * @param oid
288      * @param permission
289      * @param sid
290      * @param grant
291      * @throws PermissionException
292      */
293     private void addPermissionToRole(ObjectIdentity oid, Permission permission,
294             Sid sid, boolean grant) throws PermissionException {
295         MutableAcl acl;
296
297         try {
298             acl = getAcl(oid);
299         } catch (NotFoundException nfe) {
300             if (log.isDebugEnabled()) {
301                 log.debug("addPermission: acl not found for oid=" + oid.toString()
302                         + " perm=" + permission.toString()
303                         + " sid=" + sid.toString()
304                         + " grant=" + grant
305                         + " adding...");
306             }
307             acl = provider.getProviderAclService().createAcl(oid);
308         }
309         // Need to see if there is already an entry, so we do not duplicate (e.g., 
310         // when we run our permission-roles init more than once.
311         List<AccessControlEntry> aceEntries = acl.getEntries();
312         if (aceListHasEntry(aceEntries, permission, sid, grant)) {
313             if (log.isDebugEnabled()) {
314                 log.debug("addPermission: Pre-existing acl for oid=" + oid.toString()
315                         + " perm=" + permission.toString()
316                         + " sid=" + sid.toString()
317                         + " grant=" + grant);
318             }
319                 
320         } else {
321             acl.insertAce(acl.getEntries().size(), permission, sid, grant);
322             provider.getProviderAclService().updateAcl(acl);
323
324             if (log.isDebugEnabled()) {
325                 log.debug("addPermission: added acl for oid=" + oid.toString()
326                         + " perm=" + permission.toString()
327                         + " sid=" + sid.toString()
328                         + " grant=" + grant);
329             }
330         }
331     }
332     
333     private boolean aceListHasEntry(List<AccessControlEntry> aceEntries, Permission permission,
334             Sid sid, boolean grant) {
335         for(AccessControlEntry entry : aceEntries) {
336                 if(permission.equals(entry.getPermission())
337                         && sid.equals(entry.getSid())
338                         && grant == entry.isGranting()) {
339                         return true;
340                 }
341         }
342         return false;
343     }
344
345     /**
346      * deletePermissions deletes given permission on given object id for given sid
347      * @param oid
348      * @param permission
349      * @param sid
350      */
351     //non-javadoc NOTE: if sid is null it would remove ACEs for all sid(s)
352     private void deletePermissionFromRole(ObjectIdentity oid, Permission permission, Sid sid) /** throws AclDataAccessException */
353     {
354         int i = 0;
355         MutableAcl acl = getAcl(oid);
356         List<AccessControlEntry> acel = acl.getEntries();
357         int aces = acel.size();
358         if (log.isDebugEnabled()) {
359             log.debug("deletePermissions: for acl oid=" + oid.toString()
360                     + " found " + aces + " aces");
361         }
362         ArrayList<Integer> foundAces = new ArrayList<Integer>();
363         Iterator iter = acel.listIterator();
364         //not possible to delete while iterating
365         while (iter.hasNext()) {
366             AccessControlEntry ace = (AccessControlEntry) iter.next();
367             if (sid != null) {
368                 if (ace.getSid().equals(sid)
369                         && ace.getPermission().equals(permission)) {
370                     foundAces.add(i);
371                 }
372             } else {
373                 if (ace.getPermission().equals(permission)) {
374                     foundAces.add(i);
375                 }
376             }
377             i++;
378         }
379         for (int j = foundAces.size() - 1; j >= 0; j--) {
380             //the following operation does not work while iterating in the while loop
381             acl.deleteAce(foundAces.get(j)); //autobox
382         }
383         provider.getProviderAclService().updateAcl(acl);
384
385         if (log.isDebugEnabled()) {
386             log.debug("deletePermissions: for acl oid=" + oid.toString()
387                     + " deleted " + i + " aces");
388         }
389     }
390
391     private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
392         MutableAcl acl = null;
393         acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
394         if (log.isDebugEnabled()) {
395             log.debug("found acl for oid=" + oid.toString());
396         }
397         return acl;
398     }
399 }