Checked for null format in wrong place
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / profile / saml2 / AbstractSAML2ProfileHandler.java
index e723d35..bfdcfdc 100644 (file)
@@ -30,7 +30,6 @@ import org.opensaml.common.SAMLObjectBuilder;
 import org.opensaml.common.SAMLVersion;
 import org.opensaml.common.impl.SAMLObjectContentReference;
 import org.opensaml.log.Level;
-import org.opensaml.saml2.core.Advice;
 import org.opensaml.saml2.core.Assertion;
 import org.opensaml.saml2.core.AttributeQuery;
 import org.opensaml.saml2.core.AttributeStatement;
@@ -67,6 +66,7 @@ import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestExce
 import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncoder;
 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncodingException;
+import edu.internet2.middleware.shibboleth.common.attribute.encoding.SAML2NameIDAttributeEncoder;
 import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML2AttributeAuthority;
 import edu.internet2.middleware.shibboleth.common.attribute.provider.ShibbolethSAMLAttributeRequestContext;
 import edu.internet2.middleware.shibboleth.common.log.AuditLogEntry;
@@ -123,9 +123,6 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     /** For building audience. */
     private SAMLObjectBuilder<Audience> audienceBuilder;
 
-    /** For building advice. */
-    private SAMLObjectBuilder<Advice> adviceBuilder;
-
     /** For building signature. */
     private XMLObjectBuilder<Signature> signatureBuilder;
 
@@ -153,137 +150,10 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         proxyRestrictionBuilder = (SAMLObjectBuilder<ProxyRestriction>) getBuilderFactory().getBuilder(
                 ProxyRestriction.DEFAULT_ELEMENT_NAME);
         audienceBuilder = (SAMLObjectBuilder<Audience>) getBuilderFactory().getBuilder(Audience.DEFAULT_ELEMENT_NAME);
-        adviceBuilder = (SAMLObjectBuilder<Advice>) getBuilderFactory().getBuilder(Advice.DEFAULT_ELEMENT_NAME);
         signatureBuilder = (XMLObjectBuilder<Signature>) getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME);
     }
 
     /**
-     * Convenience method for getting the SAML 2 advice builder.
-     * 
-     * @return SAML 2 advice builder
-     */
-    public SAMLObjectBuilder<Advice> getAdviceBuilder() {
-        return adviceBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 assertion builder.
-     * 
-     * @return SAML 2 assertion builder
-     */
-    public SAMLObjectBuilder<Assertion> getAssertionBuilder() {
-        return assertionBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 audience builder.
-     * 
-     * @return SAML 2 audience builder
-     */
-    public SAMLObjectBuilder<Audience> getAudienceBuilder() {
-        return audienceBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 audience restriction builder.
-     * 
-     * @return SAML 2 audience restriction builder
-     */
-    public SAMLObjectBuilder<AudienceRestriction> getAudienceRestrictionBuilder() {
-        return audienceRestrictionBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 conditions builder.
-     * 
-     * @return SAML 2 conditions builder
-     */
-    public SAMLObjectBuilder<Conditions> getConditionsBuilder() {
-        return conditionsBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 Issuer builder.
-     * 
-     * @return SAML 2 Issuer builder
-     */
-    public SAMLObjectBuilder<Issuer> getIssuerBuilder() {
-        return issuerBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 proxy restriction builder.
-     * 
-     * @return SAML 2 proxy restriction builder
-     */
-    public SAMLObjectBuilder<ProxyRestriction> getProxyRestrictionBuilder() {
-        return proxyRestrictionBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 response builder.
-     * 
-     * @return SAML 2 response builder
-     */
-    public SAMLObjectBuilder<Response> getResponseBuilder() {
-        return responseBuilder;
-    }
-
-    /**
-     * Convenience method for getting the Signature builder.
-     * 
-     * @return signature builder
-     */
-    public XMLObjectBuilder<Signature> getSignatureBuilder() {
-        return signatureBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 status builder.
-     * 
-     * @return SAML 2 status builder
-     */
-    public SAMLObjectBuilder<Status> getStatusBuilder() {
-        return statusBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 status code builder.
-     * 
-     * @return SAML 2 status code builder
-     */
-    public SAMLObjectBuilder<StatusCode> getStatusCodeBuilder() {
-        return statusCodeBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 status message builder.
-     * 
-     * @return SAML 2 status message builder
-     */
-    public SAMLObjectBuilder<StatusMessage> getStatusMessageBuilder() {
-        return statusMessageBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 subject builder.
-     * 
-     * @return SAML 2 subject builder
-     */
-    public SAMLObjectBuilder<Subject> getSubjectBuilder() {
-        return subjectBuilder;
-    }
-
-    /**
-     * Convenience method for getting the SAML 2 subject confirmation builder.
-     * 
-     * @return SAML 2 subject confirmation builder
-     */
-    public SAMLObjectBuilder<SubjectConfirmation> getSubjectConfirmationBuilder() {
-        return subjectConfirmationBuilder;
-    }
-
-    /**
      * Checks that the SAML major version for a request is 2.
      * 
      * @param requestContext current request context containing the SAML message
@@ -327,7 +197,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         }
 
         // create the SAML response and add the assertion
-        Response samlResponse = getResponseBuilder().buildObject();
+        Response samlResponse = responseBuilder.buildObject();
         samlResponse.setIssueInstant(issueInstant);
         populateStatusResponse(requestContext, samlResponse);
 
@@ -351,7 +221,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * @return the built assertion
      */
     protected Assertion buildAssertion(SAML2ProfileRequestContext requestContext, DateTime issueInstant) {
-        Assertion assertion = getAssertionBuilder().buildObject();
+        Assertion assertion = assertionBuilder.buildObject();
         assertion.setID(getIdGenerator().generateIdentifier());
         assertion.setIssueInstant(issueInstant);
         assertion.setVersion(SAMLVersion.VERSION_20);
@@ -371,9 +241,9 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * @return the built issuer
      */
     protected Issuer buildEntityIssuer(SAML2ProfileRequestContext requestContext) {
-        Issuer issuer = getIssuerBuilder().buildObject();
+        Issuer issuer = issuerBuilder.buildObject();
         issuer.setFormat(Issuer.ENTITY);
-        issuer.setValue(requestContext.getRelyingPartyId());
+        issuer.setValue(requestContext.getAssertingPartyId());
 
         return issuer;
     }
@@ -390,7 +260,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
     protected Conditions buildConditions(SAML2ProfileRequestContext requestContext, DateTime issueInstant) {
         AbstractSAML2ProfileConfiguration profileConfig = requestContext.getProfileConfiguration();
 
-        Conditions conditions = getConditionsBuilder().buildObject();
+        Conditions conditions = conditionsBuilder.buildObject();
         conditions.setNotBefore(issueInstant);
         conditions.setNotOnOrAfter(issueInstant.plus(profileConfig.getAssertionLifetime()));
 
@@ -399,9 +269,9 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         // add audience restrictions
         audiences = profileConfig.getAssertionAudiences();
         if (audiences != null && audiences.size() > 0) {
-            AudienceRestriction audienceRestriction = getAudienceRestrictionBuilder().buildObject();
+            AudienceRestriction audienceRestriction = audienceRestrictionBuilder.buildObject();
             for (String audienceUri : audiences) {
-                Audience audience = getAudienceBuilder().buildObject();
+                Audience audience = audienceBuilder.buildObject();
                 audience.setAudienceURI(audienceUri);
                 audienceRestriction.getAudiences().add(audience);
             }
@@ -411,10 +281,10 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         // add proxy restrictions
         audiences = profileConfig.getProxyAudiences();
         if (audiences != null && audiences.size() > 0) {
-            ProxyRestriction proxyRestriction = getProxyRestrictionBuilder().buildObject();
+            ProxyRestriction proxyRestriction = proxyRestrictionBuilder.buildObject();
             Audience audience;
             for (String audienceUri : audiences) {
-                audience = getAudienceBuilder().buildObject();
+                audience = audienceBuilder.buildObject();
                 audience.setAudienceURI(audienceUri);
                 proxyRestriction.getAudiences().add(audience);
             }
@@ -539,9 +409,14 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
             SAML2ProfileRequestContext requestContext) {
 
         ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery> queryContext;
-        
+
+        if(requestContext.getSamlRequest() instanceof AttributeQuery){
         queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
                 requestContext.getRelyingPartyConfiguration(), (AttributeQuery) requestContext.getSamlRequest());
+        }else{
+            queryContext = new ShibbolethSAMLAttributeRequestContext<NameID, AttributeQuery>(getMetadataProvider(),
+                    requestContext.getRelyingPartyConfiguration(), null);
+        }
         queryContext.setAttributeRequester(requestContext.getAssertingPartyId());
         queryContext.setPrincipalName(requestContext.getPrincipalName());
         queryContext.setProfileConfiguration(requestContext.getProfileConfiguration());
@@ -641,20 +516,20 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * @return a Status object.
      */
     protected Status buildStatus(String topLevelCode, String secondLevelCode, String failureMessage) {
-        Status status = getStatusBuilder().buildObject();
+        Status status = statusBuilder.buildObject();
 
-        StatusCode statusCode = getStatusCodeBuilder().buildObject();
+        StatusCode statusCode = statusCodeBuilder.buildObject();
         statusCode.setValue(DatatypeHelper.safeTrimOrNullString(topLevelCode));
         status.setStatusCode(statusCode);
 
         if (secondLevelCode != null) {
-            StatusCode secondLevelStatusCode = getStatusCodeBuilder().buildObject();
+            StatusCode secondLevelStatusCode = statusCodeBuilder.buildObject();
             secondLevelStatusCode.setValue(DatatypeHelper.safeTrimOrNullString(secondLevelCode));
             statusCode.setStatusCode(secondLevelStatusCode);
         }
 
         if (failureMessage != null) {
-            StatusMessage msg = getStatusMessageBuilder().buildObject();
+            StatusMessage msg = statusMessageBuilder.buildObject();
             msg.setMessage(failureMessage);
             status.setStatusMessage(msg);
         }
@@ -679,10 +554,10 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         requestContext.setSubjectNameID(nameID);
         // TODO handle encryption
 
-        SubjectConfirmation subjectConfirmation = getSubjectConfirmationBuilder().buildObject();
+        SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
         subjectConfirmation.setMethod(confirmationMethod);
 
-        Subject subject = getSubjectBuilder().buildObject();
+        Subject subject = subjectBuilder.buildObject();
         subject.setNameID(nameID);
         subject.getSubjectConfirmations().add(subjectConfirmation);
 
@@ -715,32 +590,37 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
             log.debug("Supported NameID formats: " + supportedNameFormats);
         }
 
-        if (principalAttributes != null && supportedNameFormats != null) {
-            try {
-                AttributeEncoder<NameID> nameIdEncoder = null;
-                for (BaseAttribute attribute : principalAttributes.values()) {
-                    for (String nameFormat : supportedNameFormats) {
-                        nameIdEncoder = attribute.getEncoderByCategory(nameFormat);
-                        if (nameIdEncoder != null) {
+        if (principalAttributes == null || supportedNameFormats == null) {
+            log.error("No attributes for principal " + requestContext.getPrincipalName() 
+                    + " support constructions of NameID");
+            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.INVALID_NAMEID_POLICY_URI,
+                    "Unable to construct NameID"));
+            throw new ProfileException("No principal attributes support NameID construction");
+        }
+
+        try {
+            SAML2NameIDAttributeEncoder nameIdEncoder;
+            for (BaseAttribute<?> attribute : principalAttributes.values()) {
+                for (AttributeEncoder encoder : attribute.getEncoders()) {
+                    if (encoder instanceof SAML2NameIDAttributeEncoder) {
+                        nameIdEncoder = (SAML2NameIDAttributeEncoder) encoder;
+                        if (supportedNameFormats.contains(nameIdEncoder.getNameFormat())) {
                             if (log.isDebugEnabled()) {
                                 log.debug("Using attribute " + attribute.getId() + " suppoting NameID format "
-                                        + nameFormat + " to create the NameID for principal "
+                                        + nameIdEncoder.getNameFormat() + " to create the NameID for principal "
                                         + requestContext.getPrincipalName());
                             }
                             return nameIdEncoder.encode(attribute);
                         }
                     }
                 }
-            } catch (AttributeEncodingException e) {
-                requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null,
-                        "Unable to construct NameID"));
-                throw new ProfileException("Unable to encode NameID attribute", e);
             }
+            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null, "Unable to construct NameID"));
+            throw new ProfileException("No principal attribute supported encoding into the a supported name ID format.");
+        } catch (AttributeEncodingException e) {
+            requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, null, "Unable to construct NameID"));
+            throw new ProfileException("Unable to encode NameID attribute", e);
         }
-
-        requestContext.setFailureStatus(buildStatus(StatusCode.RESPONDER_URI, StatusCode.INVALID_NAMEID_POLICY_URI,
-                "Unable to construct NameID"));
-        throw new ProfileException("No principal attributes support NameID construction");
     }
 
     /**
@@ -761,7 +641,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         String nameFormat = null;
         if (requestContext.getSamlRequest() instanceof AuthnRequest) {
             AuthnRequest authnRequest = (AuthnRequest) requestContext.getSamlRequest();
-            if (authnRequest.getNameIDPolicy() != null) {
+            if (authnRequest.getNameIDPolicy() != null && !DatatypeHelper.isEmpty(nameFormat)) {
                 nameFormat = authnRequest.getNameIDPolicy().getFormat();
                 if (assertingPartySupportedFormats.contains(nameFormat)) {
                     nameFormats.add(nameFormat);
@@ -825,7 +705,7 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
      * @return the constructed error response
      */
     protected Response buildErrorResponse(SAML2ProfileRequestContext requestContext) {
-        Response samlResponse = getResponseBuilder().buildObject();
+        Response samlResponse = responseBuilder.buildObject();
         samlResponse.setIssueInstant(new DateTime());
         populateStatusResponse(requestContext, samlResponse);
 
@@ -850,6 +730,9 @@ public abstract class AbstractSAML2ProfileHandler extends AbstractSAMLProfileHan
         auditLogEntry.setRequestId(context.getSamlRequest().getID());
         auditLogEntry.setResponseBinding(context.getMessageEncoder().getBindingURI());
         auditLogEntry.setResponseId(context.getSamlResponse().getID());
+        if(context.getPrincipalAttributes() != null){
+            auditLogEntry.getReleasedAttributes().addAll(context.getPrincipalAttributes().keySet());
+        }
         getAduitLog().log(Level.CRITICAL, auditLogEntry);
     }