1 23 24 package org.apache.slide.security; 25 26 import java.lang.reflect.Constructor; 27 import java.lang.reflect.InvocationTargetException; 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.Enumeration; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Hashtable; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Set; 38 import java.util.Vector; 39 import org.apache.slide.common.Namespace; 40 import org.apache.slide.common.NamespaceConfig; 41 import org.apache.slide.common.ServiceAccessException; 42 import org.apache.slide.common.SlideException; 43 import org.apache.slide.common.SlideToken; 44 import org.apache.slide.common.Uri; 45 import org.apache.slide.content.NodeProperty; 46 import org.apache.slide.content.NodeRevisionDescriptor; 47 import org.apache.slide.content.NodeRevisionDescriptors; 48 import org.apache.slide.content.NodeRevisionNumber; 49 import org.apache.slide.content.RevisionDescriptorNotFoundException; 50 import org.apache.slide.store.Store; 51 import org.apache.slide.structure.ActionNode; 52 import org.apache.slide.structure.LinkNode; 53 import org.apache.slide.structure.ObjectAlreadyExistsException; 54 import org.apache.slide.structure.ObjectNode; 55 import org.apache.slide.structure.ObjectNotFoundException; 56 import org.apache.slide.structure.SubjectNode; 57 import org.apache.slide.util.Configuration; 58 import org.apache.slide.util.XMLValue; 59 import org.apache.slide.util.logger.Logger; 60 import org.apache.slide.event.VetoException; 61 import org.apache.slide.event.EventDispatcher; 62 import org.apache.slide.event.SecurityEvent; 63 import org.jdom.JDOMException; 64 65 70 public class SecurityImpl implements Security { 71 72 private static final String LOG_CHANNEL = SecurityImpl.class.getName(); 73 private static final String PRIVILEGE_MEMBER_SET = "privilege-member-set"; 74 private static final String PRIVILEGE_NAMESPACE = "privilege-namespace"; 75 protected Logger logger; 76 77 78 81 public SecurityImpl() {} 82 83 89 public SecurityImpl(Namespace namespace, NamespaceConfig namespaceConfig) { 90 init(namespace, namespaceConfig); 91 } 92 93 public void init(Namespace namespace, NamespaceConfig namespaceConfig) { 94 this.namespace = namespace; 95 this.namespaceConfig = namespaceConfig; 96 this.rolesCache = new Hashtable(); 97 aclInheritanceType = namespaceConfig.getAclInheritanceType(); 98 logger = namespace.getLogger(); 99 } 100 101 103 104 107 protected Namespace namespace; 108 109 110 113 protected NamespaceConfig namespaceConfig; 114 115 116 120 protected Hashtable rolesCache; 121 122 protected int aclInheritanceType; 123 124 128 private Set modificationActions; 129 130 132 133 143 public void setPermissions(SlideToken token, String object, 144 Enumeration permissions) 145 throws ServiceAccessException, ObjectNotFoundException, 146 AccessDeniedException { 147 148 Uri objectUri = namespace.getUri(token, object); 149 ObjectNode objectNode = objectUri.getStore().retrieveObject(objectUri); 150 151 checkCredentials(token, objectNode, 152 namespaceConfig.getGrantPermissionAction()); 153 checkCredentials(token, objectNode, 154 namespaceConfig.getRevokePermissionAction()); 155 156 objectUri.getStore().revokePermissions(objectUri); 157 158 while (permissions.hasMoreElements()) { 159 NodePermission permission = 160 (NodePermission) permissions.nextElement(); 161 objectUri.getStore().grantPermission(objectUri, permission); 162 } 163 164 } 165 166 167 179 public void grantPermission(SlideToken token, ObjectNode object, 180 SubjectNode subject, ActionNode action) 181 throws ServiceAccessException, ObjectNotFoundException, 182 AccessDeniedException, VetoException { 183 grantPermission(token, object, subject, action, true); 184 } 185 186 187 200 public void grantPermission(SlideToken token, ObjectNode object, 201 SubjectNode subject, ActionNode action, 202 boolean inheritable) 203 throws ServiceAccessException, ObjectNotFoundException, 204 AccessDeniedException, VetoException { 205 NodePermission permission = new NodePermission(object, subject, action, 206 inheritable); 207 grantPermission(token, permission); 208 } 209 210 211 221 public void grantPermission(SlideToken token, 222 NodePermission permission) 223 throws ServiceAccessException, ObjectNotFoundException, 224 AccessDeniedException, VetoException { 225 Uri objectUri = namespace.getUri(token, permission.getObjectUri()); 226 ObjectNode object = objectUri.getStore() 227 .retrieveObject(objectUri); 228 229 Enumeration permissions = enumeratePermissions(token, object); 231 boolean alreadyPresent = false; 232 while (permissions.hasMoreElements() && !alreadyPresent) { 233 if (permission.equals(permissions.nextElement())) { 234 alreadyPresent = true; 235 } 236 } 237 238 if (!alreadyPresent) { 239 checkCredentials(token, object, 240 namespaceConfig.getGrantPermissionAction()); 241 objectUri.getStore().grantPermission(objectUri, permission); 242 } 243 244 if ( permission.isNegative() ) { 246 if ( SecurityEvent.DENY_PERMISSION.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(SecurityEvent.DENY_PERMISSION, new SecurityEvent(this, token, namespace, objectUri, permission)); 247 } else { 248 if ( SecurityEvent.GRANT_PERMISSION.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(SecurityEvent.GRANT_PERMISSION, new SecurityEvent(this, token, namespace, objectUri, permission)); 249 } 250 } 251 252 253 265 public void denyPermission(SlideToken token, ObjectNode object, 266 SubjectNode subject, ActionNode action) 267 throws ServiceAccessException, ObjectNotFoundException, 268 AccessDeniedException, VetoException { 269 denyPermission(token, object, subject, action, true); 270 } 271 272 273 286 public void denyPermission(SlideToken token, ObjectNode object, 287 SubjectNode subject, ActionNode action, 288 boolean inheritable) 289 throws ServiceAccessException, ObjectNotFoundException, 290 AccessDeniedException, VetoException { 291 NodePermission permission = new NodePermission(object, subject, action, 292 inheritable, true); 293 denyPermission(token, permission); 294 } 295 296 297 307 public void denyPermission(SlideToken token, 308 NodePermission permission) 309 throws ServiceAccessException, ObjectNotFoundException, 310 AccessDeniedException, VetoException { 311 if (!permission.isNegative()) 314 permission.setNegative(true); 315 grantPermission(token, permission); 316 } 317 318 319 331 public void revokePermission(SlideToken token, ObjectNode object, 332 SubjectNode subject, ActionNode action) 333 throws ServiceAccessException, ObjectNotFoundException, 334 AccessDeniedException, VetoException { 335 checkCredentials(token, object, namespaceConfig 337 .getRevokePermissionAction()); 338 NodePermission permission = new NodePermission(object, subject, 339 action); 340 Uri objectUri = namespace.getUri(token, object.getUri()); 341 objectUri.getStore() 342 .revokePermission(objectUri, permission); 343 344 if ( SecurityEvent.REVOKE_PERMISSION.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(SecurityEvent.REVOKE_PERMISSION, new SecurityEvent(this, token, namespace, objectUri, permission)); 346 } 347 348 349 350 360 public void revokePermission(SlideToken token, NodePermission permission) 361 throws ServiceAccessException, ObjectNotFoundException, 362 AccessDeniedException, VetoException { 363 364 Uri objectUri = namespace.getUri(token, permission.getObjectUri()); 365 ObjectNode object = objectUri.getStore().retrieveObject(objectUri); 366 367 checkCredentials(token, object, 368 namespaceConfig.getRevokePermissionAction()); 369 objectUri.getStore().revokePermission(objectUri, permission); 370 371 if ( SecurityEvent.REVOKE_PERMISSION.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(SecurityEvent.REVOKE_PERMISSION, new SecurityEvent(this, token, namespace, objectUri, permission)); 373 } 374 375 376 387 public void checkCredentials(SlideToken token, ObjectNode object, 388 ActionNode action) 389 throws ServiceAccessException, AccessDeniedException { 390 391 if (!token.isForceSecurity()) { 392 return; 393 } 394 395 try { 396 if (Configuration.useIntegratedSecurity()) { 397 Boolean permission = token.checkPermissionCache(object, action); 399 if (permission == null) { 400 try { 402 Uri objectUri = namespace.getUri(token, object.getUri()); 403 ObjectNode realObject = objectUri.getStore() 404 .retrieveObject(objectUri); 405 checkPermission(token, realObject, action); 406 token.cachePermission(object, action, true); 407 } catch (AccessDeniedException ade) { 408 token.cachePermission(object, action, false); 409 ade.fillInStackTrace(); 410 throw ade; 411 } 412 } 413 else { 414 if (!(permission.booleanValue())) { 415 throw new AccessDeniedException 416 (object.getUri(), 417 getPrincipal(token).getPath().toString(), 418 action.getUri()); 419 } 420 } 421 } 422 } catch (ObjectNotFoundException e) { 423 String subjectUri = "*** Could not determine principal ***"; 424 try { 425 subjectUri = getPrincipal(token).getPath().toString(); 426 } catch (Exception x) {} 427 throw new AccessDeniedException 428 (object.getUri(), 429 subjectUri, 430 action.getUri()); 431 } 432 } 433 434 435 447 public void checkPermission(ObjectNode object, SubjectNode subject, 448 ActionNode action) 449 throws ServiceAccessException, AccessDeniedException, 450 ObjectNotFoundException { 451 if (!hasPermission(object, subject, action)) { 452 throw new AccessDeniedException(object.getUri(), subject.getUri(), 453 action.getUri()); 454 } 455 456 determineActionsCacheInvalidation(object, action); 457 } 458 459 471 public void checkPermission(SlideToken token, ObjectNode object, ActionNode action) throws ServiceAccessException, AccessDeniedException, ObjectNotFoundException { 472 if (!hasPermission(token, object, action)) { 473 throw new AccessDeniedException(object.getUri(), getPrincipal(token).getUri(), 474 action.getUri()); 475 } 476 477 determineActionsCacheInvalidation(object, action); 478 } 479 480 481 493 public boolean hasPermission(ObjectNode object, SubjectNode subject, 494 ActionNode action) 495 throws ServiceAccessException, ObjectNotFoundException { 496 497 if (action.equals(ActionNode.DEFAULT)) { 499 return true; 500 } 501 502 boolean granted = false; 503 boolean denied = false; 504 boolean rootObjectReached = false; 505 506 ObjectNode courObject = object; 507 508 Uri subjectUri = namespace.getUri(subject.getUri()); 509 Uri actionUri = namespace.getUri(action.getUri()); 510 511 513 while (!granted && !denied && !rootObjectReached) { 514 515 Uri courUri = namespace.getUri(courObject.getUri()); 516 Enumeration permissions = courUri.getStore() 517 .enumeratePermissions(courUri); 518 519 while (permissions.hasMoreElements()) { 520 521 boolean oldGranted = granted; 522 boolean oldDenied = denied; 523 524 NodePermission permission = 525 (NodePermission) permissions.nextElement(); 526 String permissionSubject = permission.getSubjectUri(); 527 528 if (permissionSubject.equals(SubjectNode.SELF_URI)) { 529 530 boolean check; 531 check = object.getUri().equals(subjectUri.toString()); 532 if (permission.isInheritable()) { 533 String subjectUriString = subjectUri.toString(); 534 if(!subjectUriString.endsWith("/")) 535 subjectUriString = subjectUriString + "/"; 536 537 check |= object.getUri().startsWith(subjectUriString); 538 } 539 540 granted = (!permission.isNegative()) 542 && (check) 543 && (actionUri.toString() 544 .startsWith(permission.getActionUri())); 545 denied = (permission.isNegative()) 546 && (check) 547 && (actionUri.toString() 548 .startsWith(permission.getActionUri())); 549 550 } else if (permission.isInheritable() 551 || permission.getObjectUri().equals(object.getUri())) { 552 553 if (permissionSubject.startsWith("/")) { 554 555 557 String permSubj = permission.getSubjectUri(); 558 if(!permSubj.endsWith("/")) 559 permSubj = permSubj + "/"; 560 boolean match = subjectUri.toString(). 561 equals(permission.getSubjectUri()) || 562 subjectUri.toString().startsWith(permSubj); 563 match &= actionUri.toString(). 564 startsWith(permission.getActionUri()); 565 566 granted = (!permission.isNegative()) && match; 567 denied = permission.isNegative() && match; 568 569 } else if (permissionSubject.startsWith("+")) { 570 571 Uri permissionSubjectUri = 573 namespace.getUri(permissionSubject.substring(1)); 574 ObjectNode group = 575 permissionSubjectUri.getStore().retrieveObject 576 (permissionSubjectUri); 577 if (group instanceof 580 org.apache.slide.structure.GroupNode ) { 581 if (group.hasChildren()) { 582 Enumeration groupMembers = 583 group.enumerateChildren(); 584 while (groupMembers.hasMoreElements()) { 587 588 oldGranted = granted; 589 oldDenied = denied; 590 591 Uri childUri = 592 namespace.getUri 593 ((String) groupMembers.nextElement()); 594 ObjectNode childNode = 595 childUri.getStore().retrieveObject 596 (childUri); 597 String childSubjectUri = childNode 598 instanceof LinkNode ? 599 ((LinkNode) childNode) 600 .getLinkedUri() : 601 childNode.getUri() ; 602 603 String testUri; 604 if(!childSubjectUri.endsWith("/")) 605 testUri = childSubjectUri+"/"; 606 else 607 testUri = childSubjectUri; 608 609 boolean match = subjectUri.toString(). 610 equals(childSubjectUri) || 611 subjectUri.toString(). 612 startsWith(testUri); 613 match &= actionUri.toString(). 614 startsWith(permission.getActionUri()); 615 616 granted = (!permission.isNegative()) && 617 match; 618 denied = permission.isNegative() && match; 619 620 granted = granted | oldGranted; 621 denied = denied | oldDenied; 622 623 } 624 } 625 } 626 627 } else { 628 629 granted = (!permission.isNegative()) 631 && (hasRole(subject, permissionSubject)) 632 && (actionUri.toString() 633 .startsWith(permission.getActionUri())); 634 denied = (permission.isNegative()) 635 && (hasRole(subject, permissionSubject)) 636 && (actionUri.toString() 637 .startsWith(permission.getActionUri())); 638 639 } 640 641 } 642 643 granted = granted | oldGranted; 644 denied = denied | oldDenied; 645 646 } 647 648 Uri parentUri = courUri.getParentUri(); 649 650 if (parentUri != null) { 651 courObject = parentUri.getStore() 652 .retrieveObject(parentUri); 653 } else { 654 rootObjectReached = true; 655 } 656 } 657 658 if (denied) { 661 return false; 662 } 663 664 if (!granted) { 665 return false; 666 } 667 668 return true; 669 670 } 671 672 685 public boolean hasPermission(SlideToken token, ObjectNode object, ActionNode action) throws ServiceAccessException, ObjectNotFoundException { 686 Boolean cachedPermission = token.checkPermissionCache(object, action); 687 if (cachedPermission != null) { 688 return cachedPermission.booleanValue(); 689 } 690 else { 691 return hasPermission(object, (SubjectNode)getPrincipal(token), action); 692 } 693 } 694 695 696 706 public Enumeration enumeratePermissions(SlideToken token, 707 ObjectNode object) 708 throws ServiceAccessException, ObjectNotFoundException, 709 AccessDeniedException { 710 711 return enumeratePermissions(token, object, false); 712 } 713 714 715 725 public Enumeration enumeratePermissions(SlideToken token, 726 ObjectNode object, 727 boolean includeInherited) 728 throws ServiceAccessException, ObjectNotFoundException { 729 return enumeratePermissions(token, object.getUri(), includeInherited); 730 } 731 732 733 743 public Enumeration enumeratePermissions(SlideToken token, 744 String object) 745 throws ServiceAccessException, ObjectNotFoundException, 746 AccessDeniedException { 747 748 return enumeratePermissions(token, object, false); 749 } 750 751 752 762 public Enumeration enumeratePermissions(SlideToken token, 763 String object, 764 boolean includeInherited) 765 throws ServiceAccessException, ObjectNotFoundException { 766 767 Uri objectUri = namespace.getUri(token, object); 768 if (!includeInherited) { 769 return objectUri.getStore().enumeratePermissions(objectUri); 770 } 771 else { 772 ObjectNode objectNode = objectUri.getStore().retrieveObject(objectUri); 773 Iterator i = retrieveAclSourceNodes(token, objectNode).iterator(); 774 Vector permissions = new Vector(); 775 while (i.hasNext()) { 776 ObjectNode oNode = (ObjectNode)i.next(); 777 Uri oUri = namespace.getUri(token, oNode.getUri()); 778 Enumeration permEnum = oUri.getStore().enumeratePermissions(oUri); 779 while (permEnum.hasMoreElements()) { 780 NodePermission perm = (NodePermission)permEnum.nextElement(); 781 if (object.equals(oNode.getUri())) { 782 perm.setInheritedFrom(null); 785 permissions.add(perm); 786 } 787 else if (perm.isInheritable()) { 788 perm.setInheritedFrom(oNode.getUri()); 789 permissions.add(perm); 790 } 791 } 792 } 793 return permissions.elements(); 794 } 795 } 796 797 798 810 public List retrieveAclSourceNodes(SlideToken token, ObjectNode object) 811 throws ServiceAccessException, ObjectNotFoundException { 812 813 List result = new ArrayList(); 814 815 Uri uri; 816 switch (aclInheritanceType) { 817 case NamespaceConfig.ACL_INHERIT_TYPE_NONE: 818 uri = namespace.getUri(token, object.getUri()); 819 result.add( uri.getStore().retrieveObject(uri) ); 820 break; 821 case NamespaceConfig.ACL_INHERIT_TYPE_ROOT: 822 uri = namespace.getUri(token, object.getUri()); 823 Uri rootUri = namespace.getUri(token, uri.getScope().toString()); 824 result.add( uri.getStore().retrieveObject(uri) ); 825 result.add( rootUri.getStore().retrieveObject(rootUri) ); 826 break; 827 case NamespaceConfig.ACL_INHERIT_TYPE_PATH: 828 uri = namespace.getUri(token, object.getUri()); 829 Enumeration enum = uri.getScopes(); 830 while (enum.hasMoreElements()) { 831 Uri element = namespace.getUri(token, (String)enum.nextElement()); 832 ObjectNode objectNode = element.getStore().retrieveObject(element); 833 result.add(objectNode); 834 } 835 break; 836 case NamespaceConfig.ACL_INHERIT_TYPE_FULL: 837 break; 839 default: 840 break; 841 } 842 843 return result; 844 } 845 846 855 public boolean hasRole(SlideToken token, String role) 856 throws ServiceAccessException, ObjectNotFoundException { 857 858 ObjectNode subject = getPrincipal(token); 859 860 return hasRole(subject, role); 861 862 } 863 864 865 874 public boolean hasRole(ObjectNode object, String role) 875 throws ServiceAccessException, ObjectNotFoundException { 876 877 if (role.equals(NamespaceConfig.NOBODY)) 878 return true; 879 String associatedRole = namespaceConfig.getRoleMapping(role); 880 if ((associatedRole != null) 881 && (associatedRole.equals(NamespaceConfig.NOBODY))) 882 return true; 883 884 Class roleClass = (Class) rolesCache.get(role); 885 if ((roleClass == null) && (associatedRole != null)) { 886 roleClass = (Class) rolesCache.get(associatedRole); 887 if (roleClass == null) { 888 try { 889 roleClass = Class.forName(associatedRole); 890 rolesCache.put(role, roleClass); 891 rolesCache.put(associatedRole, roleClass); 892 } catch (ClassNotFoundException ex) { 893 } 894 } 895 } 896 if (roleClass == null) { 897 try { 898 roleClass = Class.forName(role); 899 rolesCache.put(role, roleClass); 900 } catch (ClassNotFoundException e) { 901 } 902 } 903 if (roleClass == null) { 904 return false; 905 } 906 907 if (roleClass.isInstance(object)) 908 return true; 909 910 return false; 911 912 } 913 914 915 920 public Enumeration getRoles(ObjectNode object) { 921 922 Vector result = new Vector(); 923 result.addElement(NamespaceConfig.NOBODY); 924 925 Class currentObjectClass = object.getClass(); 926 927 while (!currentObjectClass.equals(ObjectNode.class)) { 928 929 Class[] interfaces = currentObjectClass.getInterfaces(); 930 for (int i = 0; i < interfaces.length; i++) { 931 String className = interfaces[i].getName(); 932 String associatedName = 933 namespaceConfig.getRoleMapping(className); 934 if (associatedName != null) 935 result.addElement(associatedName); 936 else 937 result.addElement(className); 938 } 939 940 currentObjectClass = currentObjectClass.getSuperclass(); 941 if (currentObjectClass == null) { 942 throw new IllegalStateException("Invalid node"); 944 } 945 946 } 947 948 return result.elements(); 949 950 } 951 952 953 958 public Enumeration getRoles(SlideToken token) 959 throws ServiceAccessException, ObjectNotFoundException { 960 return getRoles(getPrincipal(token)); 961 } 962 963 public Enumeration getRoles(SlideToken token, SubjectNode subjectNode) 964 throws ServiceAccessException, ObjectNotFoundException { 965 return getRoles(subjectNode); 966 } 967 968 976 public ObjectNode getPrincipal(SlideToken token) 977 throws ServiceAccessException, ObjectNotFoundException { 978 979 String user = 980 token.getCredentialsToken().getPublicCredentials(); 981 if ((user == null) || user.equals("") || user.equals("/")) { 982 return SubjectNode.UNAUTHENTICATED; 983 } 984 985 Uri subjectUri = namespace.getUri 986 (token, namespaceConfig.getUsersPath()+"/"+user); 987 988 try { 989 return subjectUri.getStore().retrieveObject(subjectUri); 990 } catch (ObjectNotFoundException e) { 991 if (!namespaceConfig.isAutoCreateUsers()) { 992 throw e; 993 } 994 else { 995 try { 996 Uri parentUri = subjectUri.getParentUri(); 997 ObjectNode parent = 998 subjectUri.getStore().retrieveObject(parentUri); 999 Enumeration childrenEnum = parent.enumerateChildren(); 1000 Enumeration linksEnum = parent.enumerateLinks(); 1001 Vector children = new Vector(); 1002 while (childrenEnum.hasMoreElements()) { 1003 children.addElement(childrenEnum.nextElement()); 1004 } 1005 children.addElement(subjectUri.toString()); 1006 Vector links = new Vector(); 1007 while (linksEnum.hasMoreElements()) { 1008 links.addElement(linksEnum.nextElement()); 1009 } 1010 1011 Class objectClass = Class.forName 1013 (namespaceConfig.getAutoCreateUsersRole()); 1014 Class[] types = { String.class }; 1015 Object[] args = { subjectUri.toString() }; 1016 Constructor constructor = 1017 objectClass.getConstructor(types); 1018 ObjectNode object = 1019 (ObjectNode) constructor.newInstance(args); 1020 subjectUri.getStore().createObject(subjectUri, object); 1021 1022 Class[] types2 = 1023 { String.class, Vector.class, Vector.class }; 1024 Object[] args2 = { parentUri.toString(), children, links }; 1025 constructor = parent.getClass().getConstructor(types2); 1026 object = (ObjectNode) constructor.newInstance(args2); 1027 parentUri.getStore().storeObject(parentUri, object); 1028 1029 NodeRevisionNumber initialRevision = new NodeRevisionNumber(1, 0); Hashtable workingRevisions = new Hashtable(); 1031 workingRevisions.put(NodeRevisionDescriptors.MAIN_BRANCH, initialRevision); 1032 Hashtable latestRevisionNumbers = new Hashtable(); 1033 latestRevisionNumbers.put(NodeRevisionDescriptors.MAIN_BRANCH, initialRevision); 1034 Hashtable branches = new Hashtable(); 1035 branches.put(initialRevision, new Vector()); 1036 boolean isVersioned = false; 1037 1038 NodeRevisionDescriptors revisionDescriptors = new NodeRevisionDescriptors(subjectUri.toString(), 1039 initialRevision, workingRevisions, latestRevisionNumbers, branches, isVersioned); 1040 1041 NodeRevisionDescriptor revisionDescriptor = new NodeRevisionDescriptor(initialRevision, 1042 NodeRevisionDescriptors.MAIN_BRANCH, new Vector(), new Hashtable()); 1043 1044 subjectUri.getStore().createRevisionDescriptors(subjectUri, revisionDescriptors); 1045 subjectUri.getStore().createRevisionDescriptor(subjectUri, revisionDescriptor); 1046 1047 } catch (ClassNotFoundException ex) { 1048 throw new ObjectNotFoundException(subjectUri); 1050 } catch (NoSuchMethodException ex) { 1051 throw new ObjectNotFoundException(subjectUri); 1053 } catch (InstantiationException ex) { 1054 throw new ObjectNotFoundException(subjectUri); 1056 } catch (InvocationTargetException ex) { 1057 throw new ObjectNotFoundException(subjectUri); 1059 } catch (IllegalAccessException ex) { 1060 throw new ObjectNotFoundException(subjectUri); 1062 } catch (ObjectAlreadyExistsException ex) { 1063 ex.printStackTrace(); 1065 throw new ObjectNotFoundException(subjectUri); 1066 } 1067 return subjectUri.getStore().retrieveObject(subjectUri); 1068 } 1069 } 1070 } 1071 1072 1080 private static synchronized Set getActionAggregates(SecurityImpl security, SlideToken token, ActionNode aNode) throws SlideException, JDOMException { 1081 Set result = new HashSet(); 1082 Uri aNodeUri = security.namespace.getUri(token, aNode.getUri()); 1083 NodeRevisionDescriptor aNrd = aNodeUri.getStore().retrieveRevisionDescriptor(aNodeUri, new NodeRevisionNumber()); 1084 NodeProperty membersProp = aNrd.getProperty(PRIVILEGE_MEMBER_SET); 1085 if (membersProp != null && membersProp.getValue() != null) { 1086 XMLValue membersVal; 1087 if (membersProp.getValue() instanceof XMLValue) { 1088 membersVal = (XMLValue)membersProp.getValue(); 1089 } 1090 else { 1091 membersVal = new XMLValue((String)membersProp.getValue()); 1092 } 1093 security.logger.log(membersVal.getHrefStrings(), LOG_CHANNEL, Logger.DEBUG); 1094 Iterator mUris = membersVal.getHrefStrings().iterator(); 1095 while (mUris.hasNext()) { 1096 String uriAsString = (String)mUris.next(); 1097 Uri uri = security.namespace.getUri(token, uriAsString); 1098 NodeRevisionNumber latestRevisionNumber = aNodeUri.getStore().retrieveRevisionDescriptors(uri).getLatestRevision(); 1099 if (latestRevisionNumber != null) { 1100 NodeProperty privilegeNamespace = aNodeUri.getStore().retrieveRevisionDescriptor(uri, latestRevisionNumber).getProperty(PRIVILEGE_NAMESPACE, "DAV:"); 1101 org.jdom.Namespace namespace = null; 1102 if (privilegeNamespace != null && privilegeNamespace.getValue() instanceof String) { 1103 namespace = org.jdom.Namespace.getNamespace((String) privilegeNamespace.getValue()); 1104 } else { 1105 namespace = org.jdom.Namespace.getNamespace("DAV:"); 1106 } 1107 result.add(ActionNode.getActionNode(uriAsString, namespace)); 1108 } 1109 } 1110 } 1111 return result; 1112 } 1113 1114 1124 public boolean matchAction(SlideToken token, ActionNode checkAction, ActionNode permAction) throws ServiceAccessException { 1125 if (permAction.equals(ActionNode.ALL)) { 1126 return true; 1127 } 1128 Map actionAggregationClosure = getActionAggregationClosureImpl(this, token, checkAction.getUri()); 1129 Set permActionSet = (Set)actionAggregationClosure.get(permAction); 1130 if (permActionSet == null) { 1131 logger.log("Unknown action " + permAction.getUri() , LOG_CHANNEL, Logger.WARNING); 1132 return false; 1133 } 1134 return permActionSet.contains(checkAction); 1135 } 1136 1137 1150 public boolean matchPrincipal(SlideToken token, SubjectNode checkSubject, SubjectNode matchSubject) throws ServiceAccessException { 1151 Boolean b = token.checkMatchPrincipalCache(checkSubject, matchSubject); 1152 if (b != null) { 1153 return b.booleanValue(); 1154 } 1155 else { 1156 boolean match = matchPrincipal(token, checkSubject, matchSubject, namespaceConfig.getNestedRolesMaxDepth()); 1157 token.cacheMatchPrincipal(checkSubject, matchSubject, match); 1158 return match; 1159 } 1160 } 1161 1162 1175 public boolean matchPrincipal(SlideToken token, SubjectNode checkSubject, SubjectNode matchSubject, int level) throws ServiceAccessException { 1176 if (matchSubject.equals(checkSubject)) { 1177 return true; 1178 } 1179 else { 1180 Uri groupUri = namespace.getUri(token, matchSubject.getUri()); 1181 try { 1182 NodeRevisionDescriptor nrd = 1183 groupUri.getStore().retrieveRevisionDescriptor(groupUri, new NodeRevisionNumber()); 1184 NodeProperty membersetProp = nrd.getProperty("group-member-set"); 1185 if (membersetProp != null && membersetProp.getValue() != null) { 1186 XMLValue xmlVal = new XMLValue((String)membersetProp.getValue()); 1187 List memberNodes = xmlVal.getHrefNodes(); 1188 if (memberNodes.contains(checkSubject)) { 1189 return true; 1190 } 1191 else if (level > 0) { 1192 int nextLevel = level - 1; 1193 boolean match = false; 1194 Iterator i = memberNodes.iterator(); 1195 while (!match && i.hasNext()) { 1196 SubjectNode nextMatchNode = (SubjectNode)i.next(); 1197 if (namespaceConfig.isRole(nextMatchNode.getUri()) 1198 || namespaceConfig.isGroup(nextMatchNode.getUri())) { 1199 1200 match = matchPrincipal(token, checkSubject, nextMatchNode, nextLevel); 1201 } 1202 } 1203 return match; 1204 } 1205 else { 1206 return false; 1207 } 1208 } 1209 else { 1210 return false; 1211 } 1212 } 1213 catch (RevisionDescriptorNotFoundException e) { 1214 return false; 1215 } 1216 catch (ServiceAccessException e) { 1217 throw e; 1218 } 1219 catch (JDOMException e) { 1220 e.printStackTrace(); 1221 return false; 1222 } 1223 } 1224 } 1225 1226 1230 public Map getActionAggregation(SlideToken token) { 1231 logger.log("Action aggregation being retrieved", LOG_CHANNEL, Logger.DEBUG); 1232 return Collections.unmodifiableMap(getActionAggregationImpl(this, token)); 1233 } 1234 1235 1241 private synchronized Set getModificationActions() { 1242 if (this.modificationActions == null) { 1243 Set modificationActions = new HashSet(); 1244 modificationActions.add(namespaceConfig.getBindMemberAction()); 1245 modificationActions.add(namespaceConfig.getCreateObjectAction()); 1246 modificationActions.add(namespaceConfig.getCreateRevisionContentAction()); 1247 modificationActions.add(namespaceConfig.getCreateRevisionMetadataAction()); 1248 modificationActions.add(namespaceConfig.getModifyRevisionContentAction()); 1249 modificationActions.add(namespaceConfig.getModifyRevisionMetadataAction()); 1250 modificationActions.add(namespaceConfig.getRemoveObjectAction()); 1251 modificationActions.add(namespaceConfig.getRemoveRevisionContentAction()); 1252 modificationActions.add(namespaceConfig.getRemoveRevisionMetadataAction()); 1253 modificationActions.add(namespaceConfig.getUnbindMemberAction()); 1254 1255 modificationActions.remove(namespaceConfig.getDefaultAction()); 1256 1257 this.modificationActions = Collections.unmodifiableSet(modificationActions); 1258 } 1259 return this.modificationActions; 1260 } 1261 1262 1270 private boolean isModificationAction(ActionNode action) { 1271 return getModificationActions().contains(action); 1272 } 1273 1274 1281 private void determineActionsCacheInvalidation(ObjectNode object, ActionNode action) { 1282 if (object.getUri().startsWith(namespaceConfig.getActionsPath())) { 1283 if (isModificationAction(action)) { 1284 if (logger.isEnabled(Logger.DEBUG)) { 1285 logger.log("Actions cache invalidated for operation " + action.getUri() 1286 + " on action " + object.getUri(), LOG_CHANNEL, Logger.DEBUG); 1287 } 1288 invalidateActionsCache(this); 1289 } 1290 } 1291 } 1292 1293 1297 private static synchronized void invalidateActionsCache(SecurityImpl security) { 1298 ActionsCache cache = getActionsCache(security); 1299 cache.invalidate(); 1300 } 1301 1302 private static synchronized ActionsCache getActionsCache(SecurityImpl security) { 1303 String namespaceName = security.namespace.getName(); 1304 ActionsCache result = (ActionsCache)caches.get(namespaceName); 1305 if (result == null) 1306 { 1307 result = new ActionsCache(); 1308 caches.put(namespaceName, result); 1309 } 1310 return result; 1311 } 1312 1313 private static final Map caches = new HashMap(); 1314 1315 1321 private static synchronized void loadActionsCache(SecurityImpl security, SlideToken token) { 1322 ActionsCache cache = getActionsCache(security); 1323 try { 1324 cache.aggregation = new HashMap(); 1325 cache.aggregationClosure = new HashMap(); 1326 String actionsPath = security.namespaceConfig.getActionsPath(); 1327 Uri actionsPathUri = security.namespace.getUri(token, actionsPath); 1328 ObjectNode actionsPathNode = actionsPathUri.getStore().retrieveObject(actionsPathUri); 1329 Enumeration actions = actionsPathNode.enumerateChildren(); 1330 addActionLeafsToActionAggregation(security, token, cache, actions); 1331 1332 Iterator keys = cache.aggregationClosure.keySet().iterator(); 1333 while (keys.hasNext()) { 1334 ActionNode aNode = (ActionNode)keys.next(); 1335 Set aClosure = (Set)cache.aggregationClosure.get(aNode); 1336 cache.aggregationClosure.put(aNode, buildClosure(cache, aClosure)); 1337 } 1338 if (security.logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) { 1340 security.logger.log("Action aggregations loaded successfully", LOG_CHANNEL, Logger.DEBUG); 1341 } 1342 if (security.logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) { 1343 security.logger.log("\n@@@ Actions aggregations", LOG_CHANNEL, Logger.DEBUG); 1344 Iterator i = cache.aggregation.entrySet().iterator(); 1345 while (i.hasNext()) { 1346 security.logger.log(" "+i.next(), LOG_CHANNEL, Logger.DEBUG); 1347 } 1348 security.logger.log("\n@@@ Action aggregations (transitive closure)", LOG_CHANNEL, Logger.DEBUG); 1349 i = cache.aggregationClosure.entrySet().iterator(); 1350 while (i.hasNext()) { 1351 security.logger.log(" "+i.next(), LOG_CHANNEL, Logger.DEBUG); 1352 } 1353 } 1354 } 1355 catch (Throwable e) { 1356 security.logger.log(e, LOG_CHANNEL, Logger.ERROR); 1357 cache.fail(); 1358 } 1359 } 1360 1361 1370 private static synchronized void addActionLeafsToActionAggregation(SecurityImpl security, SlideToken token, ActionsCache cache, Enumeration actions) throws SlideException, JDOMException { 1371 while (actions.hasMoreElements()) { 1372 Uri aNodeUri = security.namespace.getUri(token, (String)actions.nextElement()); 1373 ObjectNode oNode = security.namespace.getStore(aNodeUri.getScope()).retrieveObject(aNodeUri); 1374 if (oNode.hasChildren()) { 1375 if (security.logger.isEnabled(Logger.DEBUG)) { 1376 security.logger.log("Adding children of action " + oNode.getUri() + " to action aggregation", LOG_CHANNEL, Logger.DEBUG); 1377 } 1378 addActionLeafsToActionAggregation(security, token, cache, oNode.enumerateChildren()); 1379 } else { 1380 if (security.logger.isEnabled(Logger.DEBUG)) { 1381 security.logger.log("Adding action " + oNode.getUri() + " to action aggregation", LOG_CHANNEL, Logger.DEBUG); 1382 } 1383 NodeRevisionNumber latestRevisionNumber = security.namespace.getStore(aNodeUri.getScope()).retrieveRevisionDescriptors(aNodeUri).getLatestRevision(); 1384 NodeProperty privilegeNamespace = security.namespace.getStore(aNodeUri.getScope()).retrieveRevisionDescriptor(aNodeUri, latestRevisionNumber).getProperty(PRIVILEGE_NAMESPACE, "DAV:"); 1385 ActionNode aNode; 1386 org.jdom.Namespace actionNamespace; 1387 if (privilegeNamespace != null && privilegeNamespace.getValue() instanceof String) { 1388 actionNamespace = org.jdom.Namespace.getNamespace((String) privilegeNamespace.getValue()); 1389 } else { 1390 actionNamespace = org.jdom.Namespace.getNamespace("DAV:"); 1391 } 1392 aNode = ActionNode.getActionNode(oNode.getUri(), actionNamespace); 1393 Set directAggregates = getActionAggregates(security, token, aNode); 1394 cache.aggregation.put(aNode, directAggregates); 1395 Set aClosure = new HashSet(); 1396 aClosure.add(aNode); 1397 aClosure.addAll(directAggregates); 1398 cache.aggregationClosure.put(aNode, aClosure); 1399 } 1400 } 1401 } 1402 1403 1413 private static synchronized Set buildClosure(ActionsCache cache, Set aClosure) { 1414 Set result = new HashSet(aClosure); 1415 int size = 0; 1416 while (result.size() > size) { 1417 size = result.size(); 1418 Set newResult = new HashSet(); 1419 Iterator i = result.iterator(); 1420 while (i.hasNext()) { 1421 Object member = i.next(); 1422 Set membersOfMember = (Set)cache.aggregationClosure.get(member); 1423 if (membersOfMember != null) { 1424 newResult.addAll(membersOfMember); 1425 } 1426 } 1427 result = newResult; 1428 } 1429 return result; 1430 } 1431 1432 1441 private static synchronized Map getActionAggregationImpl(SecurityImpl security, SlideToken token) { 1442 ActionsCache cache = getActionsCache(security); 1443 if (!cache.hasBeenLoaded()) { 1444 loadActionsCache(security, token); 1445 } 1446 if (cache.hasLoadingFailed) { 1447 security.logger.log("actionAggregation retrieved but cache didn't load successfully" , LOG_CHANNEL, Logger.WARNING); 1448 return new HashMap(); 1449 } 1450 return cache.aggregation; 1451 } 1452 1453 1463 private static synchronized Map getActionAggregationClosureImpl(SecurityImpl security, SlideToken token, String uri) throws ServiceAccessException { 1464 ActionsCache cache = getActionsCache(security); 1465 if (!cache.hasBeenLoaded()) { 1466 loadActionsCache(security, token); 1467 } 1468 if (cache.hasLoadingFailed()) { 1469 Uri u = security.namespace.getUri(token, uri); 1470 Store s = u.getStore(); 1471 throw new ServiceAccessException(s, "Actions cache not loaded"); 1472 } 1473 return cache.aggregationClosure; 1474 } 1475} 1476
| Popular Tags
|