Port of new AAP plugin, and new algorithm that evals all policies.
authorcantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 8 Mar 2005 23:13:42 +0000 (23:13 +0000)
committercantor <cantor@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 8 Mar 2005 23:13:42 +0000 (23:13 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1274 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/serviceprovider/AttributeRequestor.java
src/edu/internet2/middleware/shibboleth/serviceprovider/FilterSupportImpl.java
src/edu/internet2/middleware/shibboleth/serviceprovider/ServiceProviderConfig.java
src/edu/internet2/middleware/shibboleth/serviceprovider/XMLAAPImpl.java

index ffaac04..42fa831 100644 (file)
@@ -169,20 +169,23 @@ public class AttributeRequestor {
                }
                
                // Check each assertion in the response.
+        int acount = 0;
                Iterator assertions = response.getAssertions();
                while (assertions.hasNext()) {
                        SAMLAssertion assertion = (SAMLAssertion) assertions.next();
-                       if (signedAssertions && 
-                      !assertion.isSigned()) {
+                       if (signedAssertions && !assertion.isSigned()) {
                                log.warn("AttributeRequestor has removed unsigned assertion from response from "+session.getEntityId());
-                               assertions.remove();
+                               response.removeAssertion(acount);
                                continue;
                        }
                        
-                       appinfo.applyAAP(entity,assertion); // apply each AAP to this assertion
-                       
-                       if (!assertion.getStatements().hasNext())
-                               assertions.remove(); // AAP rejected all statements for this assertion
+            try {
+                appinfo.applyAAP(assertion,aa); // apply each AAP to this assertion
+                acount++;
+            }
+                       catch (SAMLException ex) {
+                response.removeAssertion(acount); // AAP rejected all statements for this assertion
+            }
                }
 
                // A response may end up with no attributes, but that is not an error.
index 68ca323..9f0c283 100644 (file)
@@ -23,8 +23,8 @@ import org.opensaml.SAMLException;
 
 import x0.maceShibbolethTargetConfig1.SessionsDocument.Sessions;
 
-import edu.internet2.middleware.shibboleth.common.AAP;
-import edu.internet2.middleware.shibboleth.common.AttributeRule;
+import edu.internet2.middleware.shibboleth.aap.AAP;
+import edu.internet2.middleware.shibboleth.aap.AttributeRule;
 import edu.internet2.middleware.shibboleth.resource.FilterSupport;
 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig.ApplicationInfo;
 
index 9150267..3711943 100644 (file)
@@ -147,6 +147,7 @@ import org.apache.xmlbeans.XmlOptions;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAttribute;
 import org.opensaml.SAMLAttributeStatement;
+import org.opensaml.SAMLException;
 import org.opensaml.SAMLObject;
 import org.opensaml.artifact.Artifact;
 import org.w3c.dom.Document;
@@ -164,8 +165,8 @@ import x0.maceShibbolethTargetConfig1.HostDocument.Host;
 import x0.maceShibbolethTargetConfig1.PathDocument.Path;
 import x0.maceShibbolethTargetConfig1.SHIREDocument.SHIRE;
 import x0.maceShibbolethTargetConfig1.ShibbolethTargetConfigDocument.ShibbolethTargetConfig;
-import edu.internet2.middleware.shibboleth.common.AAP;
-import edu.internet2.middleware.shibboleth.common.AttributeRule;
+import edu.internet2.middleware.shibboleth.aap.AAP;
+import edu.internet2.middleware.shibboleth.aap.AttributeRule;
 import edu.internet2.middleware.shibboleth.common.Credentials;
 import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
 import edu.internet2.middleware.shibboleth.common.XML;
@@ -1007,59 +1008,76 @@ public class ServiceProviderConfig {
                 * Empty SAML elements get removed from the assertion.
                 * This can yield an AttributeAssertion with no attributes. 
                 * 
-                * @param entity     Origin site that sent the assertion
                 * @param assertion  SAML Attribute Assertion
+         * @param role     Role that issued the assertion
+                * @throws SAMLException  Raised if assertion is mangled beyond repair
                 */
-               void applyAAP(EntityDescriptor entity, SAMLAssertion assertion) {
+               void applyAAP(SAMLAssertion assertion, RoleDescriptor role) throws SAMLException {
                    
                    // Foreach AAP in the collection
                        AAP[] providers = getAAPProviders();
+            if (providers.length == 0) {
+                log.info("no filters specified, accepting entire assertion");
+                return;
+            }
                        for (int i=0;i<providers.length;i++) {
                                AAP aap = providers[i];
-                               if (aap.isAnyAttribute())
+                               if (aap.anyAttribute()) {
+                    log.info("any attribute enabled, accepting entire assertion");
                                        continue;
-                               
-                               // Foreach Statement in the Assertion
-                               Iterator statements = assertion.getStatements();
-                               int istatement=0;
-                               while (statements.hasNext()) {
-                                       Object statement = statements.next();
-                                       if (statement instanceof SAMLAttributeStatement) {
-                                               SAMLAttributeStatement attributeStatement = 
-                                                       (SAMLAttributeStatement) statement;
-                                               
-                                               // Foreach Attribute in the AttributeStatement
-                                               Iterator attributes = attributeStatement.getAttributes();
-                                               int iattribute=0;
-                                               while (attributes.hasNext()) {
-                                                       SAMLAttribute attribute = 
-                                                               (SAMLAttribute) attributes.next();
-                                                       String name = attribute.getName();
-                                                       String namespace = attribute.getNamespace();
-                                                       AttributeRule rule = aap.lookup(name,namespace);
-                                                       if (rule==null) {
-                                                               // TODO Not sure, but code appears to keep unknown attributes
-                                                               log.warn("No rule found for attribute "+name);
-                                                               iattribute++;
-                                                               continue;
-                                                       }
-                                                       rule.apply(entity,attribute);
-                                                       if (!attribute.getValues().hasNext())
-                                                               attributeStatement.removeAttribute(iattribute);
-                                                       else
-                                                               iattribute++;
-                                                               
-                                               }
-                                               if (!attributeStatement.getAttributes().hasNext())
-                                                       assertion.removeStatement(istatement);
-                                               else
-                                                       istatement++;
-                                       } else {
-                                               istatement++;
+                }
+            }
+            
+                       // Foreach Statement in the Assertion
+                       Iterator statements = assertion.getStatements();
+                       int istatement=0;
+                       while (statements.hasNext()) {
+                               Object statement = statements.next();
+                               if (statement instanceof SAMLAttributeStatement) {
+                                       SAMLAttributeStatement attributeStatement =     (SAMLAttributeStatement) statement;
+                                       
+                    // Check each attribute, applying any matching rules.
+                                       Iterator attributes = attributeStatement.getAttributes();
+                                       int iattribute=0;
+                                       while (attributes.hasNext()) {
+                                               SAMLAttribute attribute = (SAMLAttribute) attributes.next();
+                        boolean ruleFound = false;
+                        for (int i=0;i<providers.length;i++) {
+                                               AttributeRule rule = providers[i].lookup(attribute.getName(),attribute.getNamespace());
+                                               if (rule!=null) {
+                                                   ruleFound = true;
+                                try {
+                                    rule.apply(attribute,role);
+                                }
+                                catch (SAMLException ex) {
+                                    log.info("no values remain, removing attribute");
+                                                               attributeStatement.removeAttribute(iattribute--);
+                                    break;
+                                }
+                            }
+                        }
+                        if (!ruleFound) {
+                            log.warn("no rule found for attribute (" + attribute.getName() + "), filtering it out");
+                            attributeStatement.removeAttribute(iattribute--);
+                        }
+                        iattribute++;
+                                       }
+                    
+                    try {
+                        attributeStatement.checkValidity();
+                        istatement++;
+                                       }
+                    catch (SAMLException ex) {
+                        // The statement is now defunct.
+                        log.info("no attributes remain, removing statement");
+                                               assertion.removeStatement(istatement);
                                        }
                                }
                        }
-               }
+
+            // Now see if we trashed it irrevocably.
+            assertion.checkValidity();
+        }
                
                
                /**
index 61156d4..b41ca75 100644 (file)
  */
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
-import java.util.regex.Pattern;
 
 import org.apache.log4j.Logger;
-import org.apache.xmlbeans.XmlException;
-import org.opensaml.SAMLAttribute;
+import org.opensaml.SAMLException;
 
-import x0.maceShibboleth1.AttributeAcceptancePolicyDocument;
-import x0.maceShibboleth1.AttributeRuleType;
-import x0.maceShibboleth1.AttributeRuleValueType;
-import x0.maceShibboleth1.AttributeAcceptancePolicyDocument.AttributeAcceptancePolicy;
-import x0.maceShibboleth1.SiteRuleDocument.SiteRule;
-import x0.maceShibboleth1.SiteRuleType.Scope;
-import x0.maceShibboleth1.SiteRuleType;
-import edu.internet2.middleware.shibboleth.common.AAP;
-import edu.internet2.middleware.shibboleth.common.AttributeRule;
-import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
+import edu.internet2.middleware.shibboleth.aap.provider.XMLAAPProvider;
+import edu.internet2.middleware.shibboleth.aap.AAP;
+import edu.internet2.middleware.shibboleth.aap.AttributeRule;
+import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+
+import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
@@ -59,283 +51,38 @@ public class XMLAAPImpl
        PluggableConfigurationComponent {
        
        private static Logger log = Logger.getLogger(XMLAAPImpl.class);
+    XMLAAPProvider realObject = null;
        
-       private boolean anyAttribute=false;
-       private AttributeRule[] attributeRules;
-
-
-       public void initialize(Node dom) 
-               throws XmlException {
-           AttributeAcceptancePolicyDocument bean = AttributeAcceptancePolicyDocument.Factory.parse(dom);
-           AttributeAcceptancePolicy aapbean = bean.getAttributeAcceptancePolicy();
-               if  (null!=aapbean.getAnyAttribute())
-                       anyAttribute=true; // There is an anyAttribute element
-               
-               AttributeRuleType[] rulebeans = aapbean.getAttributeRuleArray();
-               attributeRules = new AttributeRule[rulebeans.length];
-               for (int i=0;i<rulebeans.length;i++) {
-                       attributeRules[i]=new XMLAttributeRuleImpl(rulebeans[i]);
-               }
-       }
-       
+    public void initialize(Node dom) throws ShibbolethConfigurationException {
+        try {
+            // Assuming this just gets a DOM tree containing the AAP,
+            // hopefully this will "just work".
+            realObject =
+                new edu.internet2.middleware.shibboleth.aap.provider.XMLAAPProvider(
+                        (dom instanceof Element) ? (Element)dom : ((dom instanceof Document) ? ((Document)dom).getDocumentElement() : null)
+                    );
+        }
+        catch (SAMLException e) {
+            throw new ShibbolethConfigurationException("Exception initializing AAP: " + e);
+        }
+    }
        
-       public boolean isAnyAttribute() {
-               return anyAttribute;
-       }
-
-       // The lookup could use a Map, but the array is not expected to
-       // be long, and there are three keys to process. We can add a
-       // Map later if needed.
+    public boolean anyAttribute() {
+        return realObject.anyAttribute();
+    }
        
-       public AttributeRule lookup(String attrName, String attrNamespace) {
-               for (int i=0;i<attributeRules.length;i++) {
-                       AttributeRule attributeRule = attributeRules[i];
-                       String name = attributeRule.getName();
-                       String namespace = attributeRule.getNamespace();
-                       if (name!=null && 
-                               name.equals(attrName)) {
-                               if (attrNamespace==null ||
-                                  (namespace!=null &&
-                                           namespace.equals(attrNamespace)))
-                                    return attributeRule;
-                       }
-               }
-               return null;
+       public AttributeRule lookup(String name, String namespace) {
+        return realObject.lookup(name,namespace);
        }
 
        public AttributeRule lookup(String alias) {
-               for (int i=0;i<attributeRules.length;i++) {
-                       AttributeRule attributeRule = attributeRules[i];
-                       if (attributeRule.getAlias().equals(alias))
-                               return attributeRule;
-               }
-               return null;
+               return realObject.lookup(alias);
        }
 
-       public AttributeRule[] getAttributeRules() {
-               return attributeRules;
+       public Iterator getAttributeRules() {
+               return realObject.getAttributeRules();
        }
        
-       
-       /**
-        * Implement the ...commmon.AttributeRules interface by wrapping the XMLBean
-        * 
-        * @author Howard Gilbert
-        */
-       public class XMLAttributeRuleImpl implements AttributeRule {
-               
-               AttributeRuleType bean;
-               Map /*<Entityname-String,SiteRule>*/ siteMap = new HashMap();
-               
-               XMLAttributeRuleImpl(AttributeRuleType bean) {
-                       this.bean=bean;
-                       SiteRule[] siteRules = bean.getSiteRuleArray();
-                       for (int i=0;i<siteRules.length;i++) {
-                               SiteRule siteRule = siteRules[i];
-                               String entityName = siteRule.getName();
-                               siteMap.put(entityName,siteRule);
-                       }
-               }
-
-               public String getName() {
-                       return bean.getName();
-               }
-
-               public String getNamespace() {
-                       return bean.getNamespace();
-               }
-
-               public String getAlias() {
-                       return bean.getAlias();
-               }
-
-               public String getHeader() {
-                       return bean.getHeader();
-               }
-
-               /**
-                * Apply this AttributeRule to values of a SAMLAttribute
-                */
-               public void apply(EntityDescriptor originSite, SAMLAttribute attribute) {
-                       Iterator values = attribute.getValues();
-                       int i=0;
-                       while(values.hasNext()) {
-                               Element valueElement = (Element) values.next();
-                               if (!acceptableValue(originSite,valueElement)|| 
-                                       !scopeCheck(originSite,valueElement)) {
-                                       attribute.removeValue(i);
-                               } else {
-                                       i++;
-                               }
-                       }
-               }
-               
-               
-               
-               /**
-                * Apply an array of Scope elements to a SAML scope attribute.
-                * 
-                * <p>Scope rules can accept or reject their matches.
-                * Any match to a rejection is immediately fatal. Otherwise,
-                * there must have been one accept by the end of the scan.</p>
-                * 
-                * <p>The return is a three state Boolean object. A Boolean(false)
-                * is a rejection. A Boolean(true) is a tentative approval. A 
-                * null is neutral (no rejection, but no match).
-                */
-               private Boolean applyScopeRules(Scope[] scopeArray, String scopeAttribute) {
-                       Boolean decision = null;
-                       
-                       for (int i=0;i<scopeArray.length;i++) {
-                               Scope scoperule = scopeArray[i];
-                               
-                               boolean accept = scoperule.getAccept();
-                               int type = scoperule.getType().intValue();
-                               String value = scoperule.getStringValue();
-                               
-                               switch (type) {
-                               case AttributeRuleValueType.INT_REGEXP:
-                                       if (Pattern.matches(scopeAttribute,value)) {
-                                               if (accept && decision==null)
-                                                       decision=Boolean.TRUE; // Tentative approval
-                                               else
-                                                       return Boolean.FALSE;  // Deny immediate
-                                       }
-                               break;
-                               case AttributeRuleValueType.INT_XPATH:
-                                       log.warn("implementation does not support XPath value rules");
-                               break;
-                               default:
-                                       if (scopeAttribute.equals(value)) {
-                                               if (accept && decision==null)
-                                                       decision=Boolean.TRUE; // Tentative approval
-                                               else
-                                                       return Boolean.FALSE;  // Deny immediate
-                                       }
-                               break;
-                               }
-                       }
-                       return decision;
-                       
-               }
-               
-               /**
-                * Apply AnySite scope rules, then rules for Origin site.
-                * 
-                * @param originSite Metadata for origin site
-                * @param ele        SAML attribute value
-                * @return           true if OK, false if failed test
-                */
-               private boolean scopeCheck(EntityDescriptor originSite, Element ele) {
-                       
-                       String scopeAttribute = ele.getAttributeNS(null,"Scope");
-                       if (scopeAttribute==null || 
-                               scopeAttribute.length()==0)
-                               return true;  // Nothing to verify, so its OK
-                       
-                       Boolean anypermit = null; // null is neutral on decision
-                       Boolean sitepermit = null;
-                       
-                       // AnySite scope test
-                       Scope[] scopeArray = bean.getAnySite().getScopeArray();
-                       anypermit = applyScopeRules(scopeArray,scopeAttribute);
-                       if (anypermit!=null && // if null (neutral) fall through
-                               !anypermit.booleanValue()) // if tentative true, fall through
-                               return false; // Boolean(false) is immediate deny
-                       
-                       // Now find origin site rule, if present
-                       String os = originSite.getId();
-                       SiteRule siteRule = (SiteRule) siteMap.get(os);
-                       
-                       if (siteRule!=null) {
-                               scopeArray = siteRule.getScopeArray();
-                               sitepermit = applyScopeRules(scopeArray,scopeAttribute);
-                               if (sitepermit!=null &&
-                                       !sitepermit.booleanValue()) 
-                                       return false;
-                       }
-
-                       // Now, since any Boolean(false) would have generated a 
-                       // rejection, any non-null value is a Boolean(true). 
-                       // Accept if either found an accept
-                       return anypermit!=null || sitepermit!=null;
-               }
-
-               /**
-                * Determine if SAML value matches any Value rule in list
-                * 
-                * @param values Value rules from AAP
-                * @param node   SAML value
-                * @return
-                */
-               private boolean checkForMatchingValue(SiteRuleType.Value[] values, Node node) {
-                       String nodeValue = node.getNodeValue();
-                       for (int i=0;i<values.length;i++) {
-                               SiteRuleType.Value value = values[i];
-                               String valueContents = value.getStringValue();
-                               switch (value.getType().intValue()) {
-                                       case AttributeRuleValueType.INT_REGEXP:
-                                               if (Pattern.matches(valueContents,nodeValue))
-                                                       return true;
-                                               break;
-                                       case AttributeRuleValueType.INT_XPATH:
-                                               //log.warn("implementation does not support XPath value rules");
-                                               break;
-                                       default:
-                                               if (nodeValue.equals(valueContents))
-                                                       return true;
-                                               break;
-                               }
-                       }
-                       return false;
-                       
-               }
-
-               
-               /**
-                * Apply AnySite Value rules, then rules for Origin site
-                * @param originSite Metadata for Origin site
-                * @param ele SAML Attribute value
-                * @return true to continue with scope check, false to reject now
-                */
-               private boolean acceptableValue(EntityDescriptor originSite, Element ele) {
-                       
-                       // any site, any value
-                       if (bean.getAnySite().getAnyValue()!=null) 
-                               return true;
-                       
-                       Node node = ele.getFirstChild();
-                       boolean simple = node.getNodeType()==Node.TEXT_NODE;
-                       
-                       // any site, specific value
-                       if (simple) {
-                               SiteRuleType.Value[] values = bean.getAnySite().getValueArray();
-                               if (checkForMatchingValue(values,node))
-                                       return true;
-                       }
-                       
-                       // Specific site
-                       String os = originSite.getId();
-                       SiteRule siteRule = (SiteRule) siteMap.get(os);
-                       if (siteRule==null) {
-                               log.warn("Site "+os+" not found in ruleset "+this.getName());
-                               return false;
-                       }
-                       if (siteRule.getAnyValue()!=null) {
-                               return true;
-                       }
-                       SiteRuleType.Value[] values = siteRule.getValueArray();
-                       if (checkForMatchingValue(values,node))
-                               return true;
-                       
-                       return false;
-               }
-       }
-
-
-    /**
-     * @return
-     */
     public String getSchemaPathname() {
        return null;
     }