]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
ef2b1074f1ae94a2330ba17f47b978ec99efe3c3
[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 deletePermissionFromRoles(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     }
185
186     /**
187      * deletePermissions
188      * @param res
189      * @param action
190      * @throws PermissionNotFoundException
191      * @throws PermissionException
192      */
193     //non-javadoc NOTE: this is a very destructive operation. it would remove all permissions
194     //to access given resource#action for ANY role including administrators
195     @Override
196     public void deletePermissions(CSpaceResource res, CSpaceAction action)
197             throws PermissionNotFoundException, PermissionException {
198         
199         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
200         Permission p = SpringAuthorizationProvider.getPermission(action);
201         try {
202             deletePermissionFromRole(oid, p, null);
203             if (log.isDebugEnabled()) {
204                 log.debug("deletepermissions(res,action) success, "
205                         + " res=" + res.toString()
206                         + " action=" + action.toString()
207                         + " oid=" + oid.toString()
208                         + " perm=" + p.toString());
209             }
210         } catch (AclDataAccessException aex) {
211             log.debug("deletepermissions(res,action) failed,"
212                     + " oid=" + oid.toString()
213                     + " res=" + res.toString()
214                     + " action=" + action.toString()
215                     + " oid=" + oid.toString()
216                     + " perm=" + p.toString(), aex);
217             throw new PermissionException(aex);
218         } catch (Exception ex) {
219             String msg = "deletepermissions(res,action,prin[]) failed,"
220                     + " oid=" + oid.toString()
221                     + " res=" + res.toString()
222                     + " action=" + action.toString()
223                     + " oid=" + oid.toString()
224                     + " perm=" + p.toString();
225             if (log.isDebugEnabled()) {
226                 log.debug(msg, ex);
227             }
228             if (ex instanceof PermissionException) {
229                 throw (PermissionException) ex;
230             }
231             throw new PermissionException(msg, ex);
232         }
233
234     }
235
236     /**
237      * deletePermissions
238      * @param res
239      * @throws PermissionNotFoundException
240      * @throws PermissionException
241      */
242     //non-javadoc NOTE: this is a very very destructive operation. it would remove all permissions
243     //to access given resource for ANY action for ANY role including administrators
244     @Override
245     public void deletePermissions(CSpaceResource res)
246             throws PermissionNotFoundException, PermissionException {
247         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
248         try {
249             provider.getProviderAclService().deleteAcl(oid, true);
250             if (log.isDebugEnabled()) {
251                 log.debug("deletepermissions(res) success, "
252                         + " res=" + res.toString()
253                         + " oid=" + oid.toString());
254             }
255         } catch (AclDataAccessException aex) {
256             log.debug("deletepermissions(res) failed,"
257                     + " oid=" + oid.toString()
258                     + " res=" + res.toString()
259                     + " oid=" + oid.toString(), aex);
260             throw new PermissionException(aex);
261         } catch (Exception ex) {
262             String msg = "deletepermissions(res) failed,"
263                     + " oid=" + oid.toString()
264                     + " res=" + res.toString()
265                     + " oid=" + oid.toString();
266             if (log.isDebugEnabled()) {
267                 log.debug(msg, ex);
268             }
269             if (ex instanceof PermissionException) {
270                 throw (PermissionException) ex;
271             }
272             throw new PermissionException(msg, ex);
273         }
274     }
275
276     /**
277      * addPermission adds permission grant for given object identity for given permission
278      * for given sid
279      * @param oid
280      * @param permission
281      * @param sid
282      * @param grant
283      * @throws PermissionException
284      */
285     private void addPermissionToRole(ObjectIdentity oid, Permission permission,
286             Sid sid, boolean grant) throws PermissionException {
287         MutableAcl acl;
288
289         try {
290             acl = getAcl(oid);
291         } catch (NotFoundException nfe) {
292             if (log.isDebugEnabled()) {
293                 log.debug("addPermission: acl not found for oid=" + oid.toString()
294                         + " perm=" + permission.toString()
295                         + " sid=" + sid.toString()
296                         + " grant=" + grant
297                         + " adding...");
298             }
299             acl = provider.getProviderAclService().createAcl(oid);
300         }
301         // Need to see if there is already an entry, so we do not duplicate (e.g., 
302         // when we run our permission-roles init more than once.
303         List<AccessControlEntry> aceEntries = acl.getEntries();
304         if (aceListHasEntry(aceEntries, permission, sid, grant)) {
305             if (log.isDebugEnabled()) {
306                 log.debug("addPermission: Pre-existing acl for oid=" + oid.toString()
307                         + " perm=" + permission.toString()
308                         + " sid=" + sid.toString()
309                         + " grant=" + grant);
310             }
311                 
312         } else {
313             acl.insertAce(acl.getEntries().size(), permission, sid, grant);
314             provider.getProviderAclService().updateAcl(acl);
315
316             if (log.isDebugEnabled()) {
317                 log.debug("addPermission: added acl for oid=" + oid.toString()
318                         + " perm=" + permission.toString()
319                         + " sid=" + sid.toString()
320                         + " grant=" + grant);
321             }
322         }
323     }
324     
325     private boolean aceListHasEntry(List<AccessControlEntry> aceEntries, Permission permission,
326             Sid sid, boolean grant) {
327         for(AccessControlEntry entry : aceEntries) {
328                 if(permission.equals(entry.getPermission())
329                         && sid.equals(entry.getSid())
330                         && grant == entry.isGranting()) {
331                         return true;
332                 }
333         }
334         return false;
335     }
336
337     /**
338      * deletePermissions deletes given permission on given object id for given sid
339      * @param oid
340      * @param permission
341      * @param sid
342      */
343     //non-javadoc NOTE: if sid is null it would remove ACEs for all sid(s)
344     private void deletePermissionFromRole(ObjectIdentity oid, Permission permission, Sid sid) /** throws AclDataAccessException */
345     {
346         int i = 0;
347         MutableAcl acl = getAcl(oid);
348         List<AccessControlEntry> acel = acl.getEntries();
349         int aces = acel.size();
350         if (log.isDebugEnabled()) {
351             log.debug("deletePermissions: for acl oid=" + oid.toString()
352                     + " found " + aces + " aces");
353         }
354         ArrayList<Integer> foundAces = new ArrayList<Integer>();
355         Iterator<AccessControlEntry> iter = acel.listIterator();
356         //not possible to delete while iterating
357         while (iter.hasNext()) {
358             AccessControlEntry ace = (AccessControlEntry) iter.next();
359             if (sid != null) {
360                 if (ace.getSid().equals(sid)
361                         && ace.getPermission().equals(permission)) {
362                     foundAces.add(i);
363                 }
364             } else {
365                 if (ace.getPermission().equals(permission)) {
366                     foundAces.add(i);
367                 }
368             }
369             i++;
370         }
371         
372         boolean updateNeeded = false;
373         for (int j = foundAces.size() - 1; j >= 0; j--) {
374             //the following operation does not work while iterating in the while loop
375             acl.deleteAce(foundAces.get(j)); //autobox
376             updateNeeded = true;
377         }
378         
379         if (updateNeeded) {
380                 provider.getProviderAclService().updateAcl(acl);
381         }
382
383         if (log.isDebugEnabled()) {
384             log.debug("deletePermissions: for acl oid=" + oid.toString()
385                     + " deleted " + i + " aces");
386         }
387     }
388
389     private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
390         MutableAcl acl = null;
391         acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
392         if (log.isDebugEnabled()) {
393             log.debug("found acl for oid=" + oid.toString());
394         }
395         return acl;
396     }
397 }