1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.security.impl;
18
19 import java.lang.reflect.Constructor;
20 import java.security.AccessController;
21 import java.security.Permission;
22 import java.security.Permissions;
23 import java.security.Principal;
24 import java.security.PrivilegedAction;
25 import java.sql.Timestamp;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.LinkedList;
32
33 import javax.security.auth.Subject;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.jetspeed.i18n.KeyedMessage;
38 import org.apache.jetspeed.security.JSSubject;
39 import org.apache.jetspeed.security.PermissionManager;
40 import org.apache.jetspeed.security.RolePrincipal;
41 import org.apache.jetspeed.security.SecurityException;
42 import org.apache.jetspeed.security.SecurityHelper;
43 import org.apache.jetspeed.security.UserPrincipal;
44 import org.apache.jetspeed.security.om.InternalPermission;
45 import org.apache.jetspeed.security.om.InternalPrincipal;
46 import org.apache.jetspeed.security.om.impl.InternalPermissionImpl;
47 import org.apache.jetspeed.security.om.impl.InternalPrincipalImpl;
48 import org.apache.jetspeed.util.ArgUtil;
49 import org.apache.ojb.broker.query.Criteria;
50 import org.apache.ojb.broker.query.Query;
51 import org.apache.ojb.broker.query.QueryByCriteria;
52 import org.apache.ojb.broker.query.QueryFactory;
53 import org.springframework.orm.ojb.support.PersistenceBrokerDaoSupport;
54
55 /***
56 * <p>
57 * Implementation for managing {@link Permission}and permission association to
58 * {@link Principal}. Permissions are used to manage Principals access
59 * entitlement on specified resources.
60 * </p>
61 * <p>
62 * For instance:
63 * </p>
64 *
65 * <pre><code>
66 *
67 *
68 * grant principal o.a.j.security.UserPrincipal "theUserPrincipal"
69 * {
70 * permission o.a.j.security.PortletPermission "myportlet", "view,edit,minimize,maximize";
71 * };
72 *
73 *
74 * </code>
75 *
76 * <pre>
77 * @author <a href="mailto:dlestrat@apache.org">David Le Strat</a>
78 *
79 *
80 */
81 public class PermissionManagerImpl extends PersistenceBrokerDaoSupport implements PermissionManager
82 {
83 private static final Log log = LogFactory.getLog(PermissionManagerImpl.class);
84 private static ThreadLocal permissionsCache = new ThreadLocal();
85
86 /***
87 * @see org.apache.jetspeed.security.PermissionManager#getPermissions(java.security.Principal)
88 */
89 public Permissions getPermissions(Principal principal)
90 {
91 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
92 ArgUtil.notNull(new Object[] { fullPath }, new String[] { "fullPath" },
93 "removePermission(java.security.Principal)");
94
95 HashMap permissionsMap = (HashMap)permissionsCache.get();
96 if ( permissionsMap == null )
97 {
98 permissionsMap = new HashMap();
99 permissionsCache.set(permissionsMap);
100 }
101 HashSet principalPermissions = (HashSet)permissionsMap.get(fullPath);
102 if ( principalPermissions == null )
103 {
104 InternalPrincipal internalPrincipal = getInternalPrincipal(fullPath);
105 if (null != internalPrincipal)
106 {
107 principalPermissions = getSecurityPermissions(internalPrincipal.getPermissions());
108 }
109 if ( principalPermissions == null)
110 {
111 principalPermissions = new HashSet();
112 }
113 permissionsMap.put(fullPath, principalPermissions);
114 }
115
116 Permissions permissions = new Permissions();
117 Iterator iter =principalPermissions.iterator();
118 while (iter.hasNext())
119 {
120 permissions.add((Permission)iter.next());
121 }
122
123 return permissions;
124 }
125
126 /***
127 * @see org.apache.jetspeed.security.PermissionManager#getPermissions(java.util.Collection)
128 */
129 public Permissions getPermissions(Collection principals)
130 {
131 ArgUtil.notNull(new Object[] { principals }, new String[] { "principals" },
132 "getPermissions(java.util.Collection)");
133
134 Permissions permissions = new Permissions();
135 Collection principalsFullPath = getPrincipalsFullPath(principals);
136 if ((null != principalsFullPath) && principalsFullPath.size() > 0)
137 {
138 HashSet permissionsSet = new HashSet();
139 HashMap permissionsMap = (HashMap)permissionsCache.get();
140 if (permissionsMap == null)
141 {
142 permissionsMap = new HashMap();
143 permissionsCache.set(permissionsMap);
144 }
145
146 Iterator iter = principalsFullPath.iterator();
147 HashSet principalPermissions;
148 while ( iter.hasNext())
149 {
150 principalPermissions = (HashSet)permissionsMap.get(iter.next());
151 if ( principalPermissions != null )
152 {
153 iter.remove();
154 permissionsSet.addAll(principalPermissions);
155 }
156 }
157 if ( principalsFullPath.size() > 0)
158 {
159 Criteria filter = new Criteria();
160 filter.addIn("fullPath", principalsFullPath);
161 Query query = QueryFactory.newQuery(InternalPrincipalImpl.class, filter);
162 Collection internalPrincipals = getPersistenceBrokerTemplate().getCollectionByQuery(query);
163 Iterator internalPrincipalsIter = internalPrincipals.iterator();
164 while (internalPrincipalsIter.hasNext())
165 {
166 InternalPrincipal internalPrincipal = (InternalPrincipal) internalPrincipalsIter.next();
167 Collection internalPermissions = internalPrincipal.getPermissions();
168 if (null != internalPermissions)
169 {
170 principalPermissions = getSecurityPermissions(internalPermissions);
171 permissionsSet.addAll(principalPermissions);
172 }
173 else
174 {
175 principalPermissions = new HashSet();
176 }
177 permissionsMap.put(internalPrincipal.getFullPath(),principalPermissions);
178 }
179 }
180 iter = permissionsSet.iterator();
181 while (iter.hasNext())
182 {
183 permissions.add((Permission)iter.next());
184 }
185 }
186 return permissions;
187 }
188
189 /***
190 * <p>
191 * Get the full path for the {@link Principal}in the collection.
192 * </p>
193 *
194 * @param principals The collection of principals.
195 * @return The collection of principals names.
196 */
197 private Collection getPrincipalsFullPath(Collection principals)
198 {
199 Collection principalsFullPath = new ArrayList();
200 Iterator principalsIterator = principals.iterator();
201 while (principalsIterator.hasNext())
202 {
203 Principal principal = (Principal) principalsIterator.next();
204 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
205 if (null != fullPath)
206 {
207 principalsFullPath.add(fullPath);
208 }
209 }
210 return principalsFullPath;
211 }
212
213 /***
214 * <p>
215 * Iterate through a collection of {@link InternalPermission}and build a
216 * unique collection of {@link java.security.Permission}.
217 * </p>
218 *
219 * @param omPermissions The collection of {@link InternalPermission}.
220 */
221 private HashSet getSecurityPermissions(Collection omPermissions)
222 {
223 HashSet permissions = new HashSet();
224 Iterator internalPermissionsIter = omPermissions.iterator();
225 while (internalPermissionsIter.hasNext())
226 {
227 InternalPermission internalPermission = (InternalPermission) internalPermissionsIter.next();
228 Permission permission = null;
229 try
230 {
231 Class permissionClass = Class.forName(internalPermission.getClassname());
232 Class[] parameterTypes = { String.class, String.class };
233 Constructor permissionConstructor = permissionClass.getConstructor(parameterTypes);
234 Object[] initArgs = { internalPermission.getName(), internalPermission.getActions() };
235 permission = (Permission) permissionConstructor.newInstance(initArgs);
236 if(permissions.add(permission))
237 {
238 if (log.isDebugEnabled())
239 {
240 log.debug("Added permimssion: [class, " + permission.getClass().getName() + "], " + "[name, "
241 + permission.getName() + "], " + "[actions, " + permission.getActions() + "]");
242 }
243 }
244 }
245 catch (Exception e)
246 {
247 log.error("Internal error", e);
248 }
249 }
250 return permissions;
251 }
252
253 /***
254 * @see org.apache.jetspeed.security.PermissionManager#addPermission(java.security.Permission)
255 */
256 public void addPermission(Permission permission) throws SecurityException
257 {
258 ArgUtil.notNull(new Object[] { permission }, new String[] { "permission" },
259 "addPermission(java.security.Permission)");
260
261 InternalPermission internalPermission = new InternalPermissionImpl(permission.getClass().getName(), permission
262 .getName(), permission.getActions());
263 try
264 {
265 getPersistenceBrokerTemplate().store(internalPermission);
266 }
267 catch (Exception e)
268 {
269 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.addPermission",
270 "store", e.getMessage());
271 logger.error(msg, e);
272 throw new SecurityException(msg, e);
273 }
274 }
275
276 /***
277 * @see org.apache.jetspeed.security.PermissionManager#removePermission(java.security.Permission)
278 */
279 public void removePermission(Permission permission) throws SecurityException
280 {
281 ArgUtil.notNull(new Object[] { permission }, new String[] { "permission" },
282 "removePermission(java.security.Permission)");
283
284 InternalPermission internalPermission = getInternalPermission(permission);
285 if (null != internalPermission)
286 {
287
288 permissionsCache.set(null);
289 try
290 {
291
292 getPersistenceBrokerTemplate().delete(internalPermission);
293 }
294 catch (Exception e)
295 {
296 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.removePermission",
297 "delete", e.getMessage());
298 logger.error(msg, e);
299 throw new SecurityException(msg, e);
300 }
301 }
302 }
303
304 /***
305 * @see org.apache.jetspeed.security.PermissionManager#removePermissions(java.security.Principal)
306 */
307 public void removePermissions(Principal principal) throws SecurityException
308 {
309 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
310 ArgUtil.notNull(new Object[] { fullPath }, new String[] { "fullPath" },
311 "removePermission(java.security.Principal)");
312
313
314 InternalPrincipal internalPrincipal = getInternalPrincipal(fullPath);
315 if (null != internalPrincipal)
316 {
317 Collection internalPermissions = internalPrincipal.getPermissions();
318 if (null != internalPermissions)
319 {
320 internalPermissions.clear();
321 }
322
323 permissionsCache.set(null);
324 try
325 {
326 internalPrincipal.setModifiedDate(new Timestamp(System.currentTimeMillis()));
327 internalPrincipal.setPermissions(internalPermissions);
328
329 getPersistenceBrokerTemplate().store(internalPrincipal);
330 }
331 catch (Exception e)
332 {
333 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.removePermissions",
334 "store", e.getMessage());
335 logger.error(msg, e);
336 throw new SecurityException(msg, e);
337 }
338 }
339 }
340
341 /***
342 * @see org.apache.jetspeed.security.PermissionManager#grantPermission(java.security.Principal,
343 * java.security.Permission)
344 */
345 public void grantPermission(Principal principal, Permission permission) throws SecurityException
346 {
347 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
348 ArgUtil.notNull(new Object[] { fullPath, permission }, new String[] { "fullPath", "permission" },
349 "grantPermission(java.security.Principal, java.security.Permission)");
350
351 Collection internalPermissions = new ArrayList();
352
353 InternalPrincipal internalPrincipal = getInternalPrincipal(fullPath);
354 if (null == internalPrincipal)
355 {
356 if ( principal instanceof UserPrincipal )
357 {
358 throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(principal.getName()));
359 }
360 else if ( principal instanceof RolePrincipal )
361 {
362 throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(principal.getName()));
363 }
364
365 throw new SecurityException(SecurityException.GROUP_DOES_NOT_EXIST.create(principal.getName()));
366 }
367 InternalPermission internalPermission = getInternalPermission(permission);
368 if (null == internalPermission)
369 {
370 throw new SecurityException(SecurityException.PERMISSION_DOES_NOT_EXIST.create(permission.getName()));
371 }
372
373 if (null != internalPrincipal.getPermissions())
374 {
375 internalPermissions.addAll(internalPrincipal.getPermissions());
376 }
377 if (!internalPermissions.contains(internalPermission))
378 {
379 internalPermissions.add(internalPermission);
380 }
381
382 permissionsCache.set(null);
383 try
384 {
385 internalPrincipal.setModifiedDate(new Timestamp(System.currentTimeMillis()));
386 internalPrincipal.setPermissions(internalPermissions);
387
388 getPersistenceBrokerTemplate().store(internalPrincipal);
389 }
390 catch (Exception e)
391 {
392 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.grantPermission",
393 "store", e.getMessage());
394 logger.error(msg, e);
395 throw new SecurityException(msg, e);
396 }
397 }
398
399 /***
400 * @see org.apache.jetspeed.security.PermissionManager#permissionExists(java.security.Permission)
401 */
402 public boolean permissionExists(Permission permission)
403 {
404 boolean permissionExists = true;
405 InternalPermission internalPermission = getInternalPermission(permission);
406 if (null == internalPermission)
407 {
408 permissionExists = false;
409 }
410 return permissionExists;
411 }
412
413 /***
414 * @see org.apache.jetspeed.security.PermissionManager#revokePermission(java.security.Principal,
415 * java.security.Permission)
416 */
417 public void revokePermission(Principal principal, Permission permission) throws SecurityException
418 {
419 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
420 ArgUtil.notNull(new Object[] { fullPath, permission }, new String[] { "fullPath", "permission" },
421 "revokePermission(java.security.Principal, java.security.Permission)");
422
423
424 InternalPrincipal internalPrincipal = getInternalPrincipal(fullPath);
425 if (null != internalPrincipal)
426 {
427 Collection internalPermissions = internalPrincipal.getPermissions();
428 if (null != internalPermissions)
429 {
430 boolean revokePermission = false;
431 ArrayList newInternalPermissions = new ArrayList();
432 Iterator internalPermissionsIter = internalPermissions.iterator();
433 while (internalPermissionsIter.hasNext())
434 {
435 InternalPermission internalPermission = (InternalPermission) internalPermissionsIter.next();
436 if (!((internalPermission.getClassname().equals(permission.getClass().getName()))
437 && (internalPermission.getName().equals(permission.getName())) && (internalPermission.getActions()
438 .equals(permission.getActions()))))
439 {
440 newInternalPermissions.add(internalPermission);
441 }
442 else
443 {
444 revokePermission = true;
445 }
446 }
447 if (revokePermission)
448 {
449
450 permissionsCache.set(null);
451 try
452 {
453 internalPrincipal.setModifiedDate(new Timestamp(System.currentTimeMillis()));
454 internalPrincipal.setPermissions(newInternalPermissions);
455
456 getPersistenceBrokerTemplate().store(internalPrincipal);
457 }
458 catch (Exception e)
459 {
460 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.revokePermission",
461 "store", e.getMessage());
462 logger.error(msg, e);
463 throw new SecurityException(msg, e);
464 }
465 }
466 }
467 }
468 }
469
470 /***
471 * <p>
472 * Returns the {@link InternalPrincipal}from the full path.
473 * </p>
474 *
475 * @param fullPath The full path.
476 * @return The {@link InternalPrincipal}.
477 */
478 InternalPrincipal getInternalPrincipal(String fullPath)
479 {
480 Criteria filter = new Criteria();
481 filter.addEqualTo("fullPath", fullPath);
482 Query query = QueryFactory.newQuery(InternalPrincipalImpl.class, filter);
483 InternalPrincipal internalPrincipal = (InternalPrincipal) getPersistenceBrokerTemplate().getObjectByQuery(query);
484 return internalPrincipal;
485 }
486
487 /***
488 * <p>
489 * Returns the {@link InternalPermission} from a Permission.
490 * </p>
491 *
492 * @param permission The permission.
493 * @return The {@link InternalPermission}.
494 */
495 InternalPermission getInternalPermission(Permission permission)
496 {
497 Criteria filter = new Criteria();
498 filter.addEqualTo("classname", permission.getClass().getName());
499 filter.addEqualTo("name", permission.getName());
500 filter.addEqualTo("actions", permission.getActions());
501 Query query = QueryFactory.newQuery(InternalPermissionImpl.class, filter);
502 InternalPermission internalPermission = (InternalPermission) getPersistenceBrokerTemplate().getObjectByQuery(query);
503 return internalPermission;
504 }
505
506 public boolean checkPermission(Subject subject, final Permission permission)
507 {
508 try
509 {
510
511 JSSubject.doAsPrivileged(subject, new PrivilegedAction()
512 {
513 public Object run()
514 {
515 AccessController.checkPermission(permission);
516 return null;
517 }
518 }, null);
519 }
520 catch (Exception e)
521 {
522 return false;
523 }
524 return true;
525 }
526
527 public Collection getPermissions()
528 {
529 QueryByCriteria query = QueryFactory.newQuery(InternalPermissionImpl.class, new Criteria());
530 query.addOrderByAscending("classname");
531 query.addOrderByAscending("name");
532 Collection internalPermissions = getPersistenceBrokerTemplate().getCollectionByQuery(query);
533 return internalPermissions;
534 }
535
536 public Permissions getPermissions(String classname, String resource)
537 {
538 Criteria filter = new Criteria();
539 filter.addEqualTo("classname", classname);
540 filter.addEqualTo("name", resource);
541 Query query = QueryFactory.newQuery(InternalPermissionImpl.class, filter);
542 Collection internalPermissions = getPersistenceBrokerTemplate().getCollectionByQuery(query);
543 Permissions permissions = new Permissions();
544 Iterator iter = internalPermissions.iterator();
545 try
546 {
547 while (iter.hasNext())
548 {
549 InternalPermission internalPermission = (InternalPermission)iter.next();
550 Class permissionClass = Class.forName(internalPermission.getClassname());
551 Class[] parameterTypes = { String.class, String.class };
552 Constructor permissionConstructor = permissionClass.getConstructor(parameterTypes);
553 Object[] initArgs = { internalPermission.getName(), internalPermission.getActions() };
554 Permission permission = (Permission) permissionConstructor.newInstance(initArgs);
555 permissions.add(permission);
556 }
557 }
558 catch (Exception e)
559 {
560 logger.error("Failed to retrieve permissions", e);
561 }
562 return permissions;
563 }
564
565 public int updatePermission(Permission permission, Collection principals)
566 throws SecurityException
567 {
568 int count = 0;
569 InternalPermission internal = getInternalPermission(permission);
570 Iterator iter = principals.iterator();
571 Collection newPrincipals = new LinkedList();
572 while (iter.hasNext())
573 {
574 Principal principal = (Principal)iter.next();
575 String fullPath = SecurityHelper.getPreferencesFullPath(principal);
576 InternalPrincipal internalPrincipal = getInternalPrincipal(fullPath);
577 newPrincipals.add(internalPrincipal);
578 }
579 internal.setPrincipals(newPrincipals);
580 internal.setModifiedDate(new Timestamp(System.currentTimeMillis()));
581 try
582 {
583 getPersistenceBrokerTemplate().store(internal);
584 }
585 catch (Exception e)
586 {
587 KeyedMessage msg = SecurityException.UNEXPECTED.create("PermissionManager.updatePermission",
588 "store", e.getMessage());
589 logger.error(msg, e);
590 throw new SecurityException(msg, e);
591 }
592
593 return count;
594 }
595
596 public Collection getPrincipals(Permission permission)
597 {
598 Collection result = new LinkedList();
599 InternalPermission internalPermission = this.getInternalPermission(permission);
600 if (internalPermission == null)
601 {
602 return result;
603 }
604 Iterator principals = internalPermission.getPrincipals().iterator();
605 while (principals.hasNext())
606 {
607 InternalPrincipal internalPrincipal = (InternalPrincipal)principals.next();
608 Principal principal =
609 SecurityHelper.createPrincipalFromFullPath(internalPrincipal.getFullPath());
610 result.add(principal);
611 }
612 return result;
613 }
614
615
616 }