More IdP cleanups. Beginning the move to new naming scheme in configs.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 1 Mar 2005 23:38:37 +0000 (23:38 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 1 Mar 2005 23:38:37 +0000 (23:38 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1255 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/idp/IdPConfig.java
src/edu/internet2/middleware/shibboleth/idp/IdPResponder.java
src/schemas/shibboleth-idpconfig-1.0.xsd [moved from src/schemas/origin.xsd with 86% similarity]

index f1a8611..6c92185 100644 (file)
@@ -42,7 +42,7 @@ public class IdPConfig {
 
        private String defaultRelyingPartyName;
        private String providerId;
-       public static final String originConfigNamespace = "urn:mace:shibboleth:origin:1.0";
+       public static final String originConfigNamespace = "urn:mace:shibboleth:idp:config:1.0";
        private String resolverConfig = "/conf/resolver.xml";
        private boolean passThruErrors = false;
        private int maxThreads = 5;
@@ -55,21 +55,21 @@ public class IdPConfig {
        public IdPConfig(Element config) throws ShibbolethConfigurationException {
 
                if (!config.getTagName().equals("IdPConfig")) { throw new ShibbolethConfigurationException(
-                               "Unexpected configuration data.  <IdPConfig> is needed."); }
+                               "Unexpected configuration data.  <IdPConfig/> is needed."); }
 
                log.debug("Loading global configuration properties.");
 
                // Global providerId
                providerId = ((Element) config).getAttribute("providerId");
                if (providerId == null || providerId.equals("")) {
-                       log.error("Global providerId not set.  Add a (providerId) attribute to <IdPConfig>.");
+                       log.error("Global providerId not set.  Add a (providerId) attribute to <IdPConfig/>.");
                        throw new ShibbolethConfigurationException("Required configuration not specified.");
                }
 
                // Default Relying Party
                defaultRelyingPartyName = ((Element) config).getAttribute("defaultRelyingParty");
                if (defaultRelyingPartyName == null || defaultRelyingPartyName.equals("")) {
-                       log.error("Default Relying Party not set.  Add a (defaultRelyingParty) attribute to <IdPConfig>.");
+                       log.error("Default Relying Party not set.  Add a (defaultRelyingParty) attribute to <IdPConfig/>.");
                        throw new ShibbolethConfigurationException("Required configuration not specified.");
                }
 
@@ -87,7 +87,7 @@ public class IdPConfig {
 
                attribute = ((Element) config).getAttribute("AAUrl");
                if (attribute == null || attribute.equals("")) {
-                       log.error("Global Attribute Authority URL not set.  Add an (AAUrl) attribute to <IdPConfig>.");
+                       log.error("Global Attribute Authority URL not set.  Add an (AAUrl) attribute to <IdPConfig/>.");
                        throw new ShibbolethConfigurationException("Required configuration not specified.");
                }
                try {
index e85732c..bc1fd28 100644 (file)
@@ -115,6 +115,8 @@ public class IdPResponder extends TargetFederationComponent {
 
        // TODO Maybe should rethink the inheritance here, since there is only one
        // servlet
+       
+       //TODO idp config should accept new or old element <ShibbolethOriginConfiguration/> or <IdPConfig/>
 
        private static Logger transactionLog = Logger.getLogger("Shibboleth-TRANSACTION");
        private static Logger log = Logger.getLogger(IdPResponder.class.getName());
@@ -143,6 +145,12 @@ public class IdPResponder extends TargetFederationComponent {
                        // TODO this needs to be pluggable
                        artifactMapper = new MemoryArtifactMapper();
                        loadConfiguration();
+                       
+                       //TODO what should we do with the throttle now!!!  default???
+                       
+                       //Load a semaphore that throttles how many requests the IdP will handle at once
+                       throttle = new Semaphore(configuration.getMaxThreads());
+                       
                        log.info("Identity Provider initialization complete.");
 
                } catch (ShibbolethConfigurationException ae) {
@@ -245,6 +253,174 @@ public class IdPResponder extends TargetFederationComponent {
 
        }
 
+       public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
+               MDC.put("remoteAddr", request.getRemoteAddr());
+               log.debug("Recieved a request via GET.");
+               log.info("Handling authN request.");
+
+               try {
+                       throttle.enter();
+
+                       // Ensure that we have the required data from the servlet container
+                       validateEngineData(request);
+
+                       // Determine which profile of SAML we are responding to (at this point, Shib vs. EAuth)
+                       SSOProfileHandler activeHandler = null;
+                       for (int i = 0; i < profileHandlers.length; i++) {
+                               if (profileHandlers[i].validForRequest(request)) {
+                                       activeHandler = profileHandlers[i];
+                                       break;
+                               }
+                       }
+                       if (activeHandler == null) { throw new InvalidClientDataException(
+                                       "The request did not contain sufficient parameter data to determine the protocol."); }
+
+                       // Run profile specific preprocessing
+                       if (activeHandler.preProcessHook(request, response)) { return; }
+
+                       // Get the authN info
+                       String username = configuration.getAuthHeaderName().equalsIgnoreCase("REMOTE_USER") ? request
+                                       .getRemoteUser() : request.getHeader(configuration.getAuthHeaderName());
+
+                       // Select the appropriate Relying Party configuration for the request
+                       RelyingParty relyingParty = null;
+                       String remoteProviderId = activeHandler.getRemoteProviderId(request);
+                       // If the target did not send a Provider Id, then assume it is a Shib
+                       // 1.1 or older target
+                       if (remoteProviderId == null) {
+                               relyingParty = spMapper.getLegacyRelyingParty();
+                       } else if (remoteProviderId.equals("")) {
+                               throw new InvalidClientDataException("Invalid service provider id.");
+                       } else {
+                               log.debug("Remote provider has identified itself as: (" + remoteProviderId + ").");
+                               relyingParty = spMapper.getRelyingParty(remoteProviderId);
+                       }
+
+                       // Grab the metadata for the provider
+                       Provider provider = lookup(relyingParty.getProviderId());
+
+                       // Use profile-specific method for determining the acceptance URL
+                       String acceptanceURL = activeHandler.getAcceptanceURL(request, relyingParty, provider);
+
+                       // Make sure that the selected relying party configuration is appropriate for this
+                       // acceptance URL
+                       if (!relyingParty.isLegacyProvider()) {
+
+                               if (provider == null) {
+                                       log.info("No metadata found for provider: (" + relyingParty.getProviderId() + ").");
+                                       relyingParty = spMapper.getRelyingParty(null);
+
+                               } else {
+
+                                       if (isValidAssertionConsumerURL(provider, acceptanceURL)) {
+                                               log.info("Supplied consumer URL validated for this provider.");
+                                       } else {
+                                               log.error("Assertion consumer service URL (" + acceptanceURL + ") is NOT valid for provider ("
+                                                               + relyingParty.getProviderId() + ").");
+                                               throw new InvalidClientDataException("Invalid assertion consumer service URL.");
+                                       }
+                               }
+                       }
+
+                       // Create SAML Name Identifier
+                       SAMLNameIdentifier nameId = nameMapper.getNameIdentifierName(relyingParty.getHSNameFormatId(),
+                                       new AuthNPrincipal(username), relyingParty, relyingParty.getIdentityProvider());
+
+                       String authenticationMethod = request.getHeader("SAMLAuthenticationMethod");
+                       if (authenticationMethod == null || authenticationMethod.equals("")) {
+                               authenticationMethod = relyingParty.getDefaultAuthMethod().toString();
+                               log.debug("User was authenticated via the default method for this relying party ("
+                                               + authenticationMethod + ").");
+                       } else {
+                               log.debug("User was authenticated via the method (" + authenticationMethod + ").");
+                       }
+
+                       // We might someday want to provide a mechanism for the authenticator to specify the auth time
+                       SAMLAssertion[] assertions = activeHandler.processHook(request, relyingParty, provider, nameId,
+                                       authenticationMethod, new Date(System.currentTimeMillis()));
+
+                       // TODO do assertion signing here
+
+                       // SAML Artifact profile
+                       if (useArtifactProfile(provider, acceptanceURL)) {
+                               log.debug("Responding with Artifact profile.");
+
+                               // Create artifacts for each assertion
+                               ArrayList artifacts = new ArrayList();
+                               for (int i = 0; i < assertions.length; i++) {
+                                       artifacts.add(artifactMapper.generateArtifact(assertions[i], relyingParty));
+                               }
+
+                               // Assemble the query string
+                               StringBuffer destination = new StringBuffer(acceptanceURL);
+                               destination.append("?TARGET=");
+                               destination.append(URLEncoder.encode(activeHandler.getSAMLTargetParameter(request, relyingParty,
+                                               provider), "UTF-8"));
+                               Iterator iterator = artifacts.iterator();
+                               StringBuffer artifactBuffer = new StringBuffer(); // Buffer for the transaction log
+                               while (iterator.hasNext()) {
+                                       destination.append("&SAMLart=");
+                                       String artifact = (String) iterator.next();
+                                       destination.append(URLEncoder.encode(artifact, "UTF-8"));
+                                       artifactBuffer.append("(" + artifact + ")");
+                               }
+                               log.debug("Redirecting to (" + destination.toString() + ").");
+                               response.sendRedirect(destination.toString()); // Redirect to the artifact receiver
+
+                               transactionLog.info("Assertion artifact(s) (" + artifactBuffer.toString() + ") issued to provider ("
+                                               + relyingParty.getIdentityProvider().getProviderId() + ") on behalf of principal (" + username
+                                               + "). Name Identifier: (" + nameId.getName() + "). Name Identifier Format: ("
+                                               + nameId.getFormat() + ").");
+
+                               // SAML POST profile
+                       } else {
+                               log.debug("Responding with POST profile.");
+                               request.setAttribute("acceptanceURL", acceptanceURL);
+                               request.setAttribute("target", activeHandler.getSAMLTargetParameter(request, relyingParty, provider));
+
+                               SAMLResponse samlResponse = new SAMLResponse(null, acceptanceURL, Arrays.asList(assertions), null);
+                               addSignatures(samlResponse, relyingParty, provider, true);
+                               createPOSTForm(request, response, samlResponse.toBase64());
+
+                               // Make transaction log entry
+                               if (relyingParty.isLegacyProvider()) {
+                                       transactionLog.info("Authentication assertion issued to legacy provider (SHIRE: "
+                                                       + request.getParameter("shire") + ") on behalf of principal (" + username
+                                                       + ") for resource (" + request.getParameter("target") + "). Name Identifier: ("
+                                                       + nameId.getName() + "). Name Identifier Format: (" + nameId.getFormat() + ").");
+                               } else {
+                                       transactionLog.info("Authentication assertion issued to provider ("
+                                                       + relyingParty.getIdentityProvider().getProviderId() + ") on behalf of principal ("
+                                                       + username + "). Name Identifier: (" + nameId.getName() + "). Name Identifier Format: ("
+                                                       + nameId.getFormat() + ").");
+                               }
+                       }
+
+                       // TODO profile specific error handling
+               } catch (NameIdentifierMappingException ex) {
+                       log.error(ex);
+                       handleSSOError(request, response, ex);
+                       return;
+               } catch (InvalidClientDataException ex) {
+                       log.error(ex);
+                       handleSSOError(request, response, ex);
+                       return;
+               } catch (SAMLException ex) {
+                       log.error(ex);
+                       handleSSOError(request, response, ex);
+                       return;
+               } catch (InterruptedException ex) {
+                       log.error(ex);
+                       handleSSOError(request, response, ex);
+                       return;
+               } finally {
+                       throttle.exit();
+               }
+
+       }
+
        public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
                MDC.put("serviceId", "[IdP] " + idgen.nextInt());
@@ -336,6 +512,85 @@ public class IdPResponder extends TargetFederationComponent {
                }
        }
 
+       // TODO this should be renamed, since it is now only one type of response
+       // that we can send
+       public void sendSAMLResponse(HttpServletResponse resp, SAMLAttribute[] attrs, SAMLRequest samlRequest,
+                       RelyingParty relyingParty, SAMLException exception) throws IOException {
+
+               SAMLException ourSE = null;
+               SAMLResponse samlResponse = null;
+
+               try {
+                       if (attrs == null || attrs.length == 0) {
+                               // No attribute found
+                               samlResponse = new SAMLResponse(samlRequest.getId(), null, null, exception);
+                       } else {
+
+                               SAMLAttributeQuery attributeQuery = (SAMLAttributeQuery) samlRequest.getQuery();
+
+                               // Reference requested subject
+                               SAMLSubject rSubject = (SAMLSubject) attributeQuery.getSubject().clone();
+
+                               // Set appropriate audience
+                               ArrayList audiences = new ArrayList();
+                               if (relyingParty.getProviderId() != null) {
+                                       audiences.add(relyingParty.getProviderId());
+                               }
+                               if (relyingParty.getName() != null && !relyingParty.getName().equals(relyingParty.getProviderId())) {
+                                       audiences.add(relyingParty.getName());
+                               }
+                               SAMLCondition condition = new SAMLAudienceRestrictionCondition(audiences);
+
+                               // Put all attributes into an assertion
+                               SAMLStatement statement = new SAMLAttributeStatement(rSubject, Arrays.asList(attrs));
+
+                               // Set assertion expiration to longest attribute expiration
+                               long max = 0;
+                               for (int i = 0; i < attrs.length; i++) {
+                                       if (max < attrs[i].getLifetime()) {
+                                               max = attrs[i].getLifetime();
+                                       }
+                               }
+                               Date now = new Date();
+                               Date then = new Date(now.getTime() + (max * 1000)); // max is in
+                               // seconds
+
+                               SAMLAssertion sAssertion = new SAMLAssertion(relyingParty.getIdentityProvider().getProviderId(), now,
+                                               then, Collections.singleton(condition), null, Collections.singleton(statement));
+
+                               samlResponse = new SAMLResponse(samlRequest.getId(), null, Collections.singleton(sAssertion), exception);
+                               addSignatures(samlResponse, relyingParty, lookup(relyingParty.getProviderId()), false);
+                       }
+               } catch (SAMLException se) {
+                       ourSE = se;
+               } catch (CloneNotSupportedException ex) {
+                       ourSE = new SAMLException(SAMLException.RESPONDER, ex);
+
+               } finally {
+
+                       if (log.isDebugEnabled()) { // This takes some processing, so only do it if we need to
+                               try {
+                                       log.debug("Dumping generated SAML Response:"
+                                                       + System.getProperty("line.separator")
+                                                       + new String(
+                                                                       new BASE64Decoder().decodeBuffer(new String(samlResponse.toBase64(), "ASCII")),
+                                                                       "UTF8"));
+                               } catch (SAMLException e) {
+                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
+                               } catch (IOException e) {
+                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
+                               }
+                       }
+
+                       try {
+                               binding.respond(resp, samlResponse, ourSE);
+                       } catch (SAMLException e) {
+                               log.error("Caught exception while responding to requester: " + e.getMessage());
+                               resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
+                       }
+               }
+       }
+
        // TODO get rid of this AAException thing
        private void processAttributeQuery(SAMLRequest samlRequest, HttpServletRequest request, HttpServletResponse response)
                        throws SAMLException, IOException, ServletException, AAException, InvalidNameIdentifierException,
@@ -525,258 +780,8 @@ public class IdPResponder extends TargetFederationComponent {
                transactionLog.info("Succesfully dereferenced the following artifacts: " + dereferencedArtifacts.toString());
        }
 
-       public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
-               MDC.put("serviceId", "[IdP] " + idgen.nextInt());
-               MDC.put("remoteAddr", request.getRemoteAddr());
-               log.debug("Recieved a request via GET.");
-               log.info("Handling authN request.");
-
-               try {
-                       throttle.enter();
-
-                       // Ensure that we have the required data from the servlet container
-                       validateEngineData(request);
-
-                       // Determine which profile of SAML we are responding to (at this point, Shib vs. EAuth)
-                       SSOProfileHandler activeHandler = null;
-                       for (int i = 0; i < profileHandlers.length; i++) {
-                               if (profileHandlers[i].validForRequest(request)) {
-                                       activeHandler = profileHandlers[i];
-                                       break;
-                               }
-                       }
-                       if (activeHandler == null) { throw new InvalidClientDataException(
-                                       "The request did not contain sufficient parameter data to determine the protocol."); }
-
-                       // Run profile specific preprocessing
-                       if (activeHandler.preProcessHook(request, response)) { return; }
-
-                       // Get the authN info
-                       String username = configuration.getAuthHeaderName().equalsIgnoreCase("REMOTE_USER") ? request
-                                       .getRemoteUser() : request.getHeader(configuration.getAuthHeaderName());
-
-                       // Select the appropriate Relying Party configuration for the request
-                       RelyingParty relyingParty = null;
-                       String remoteProviderId = activeHandler.getRemoteProviderId(request);
-                       // If the target did not send a Provider Id, then assume it is a Shib
-                       // 1.1 or older target
-                       if (remoteProviderId == null) {
-                               relyingParty = spMapper.getLegacyRelyingParty();
-                       } else if (remoteProviderId.equals("")) {
-                               throw new InvalidClientDataException("Invalid service provider id.");
-                       } else {
-                               log.debug("Remote provider has identified itself as: (" + remoteProviderId + ").");
-                               relyingParty = spMapper.getRelyingParty(remoteProviderId);
-                       }
-
-                       // Grab the metadata for the provider
-                       Provider provider = lookup(relyingParty.getProviderId());
-
-                       // Use profile-specific method for determining the acceptance URL
-                       String acceptanceURL = activeHandler.getAcceptanceURL(request, relyingParty, provider);
-
-                       // Make sure that the selected relying party configuration is appropriate for this
-                       // acceptance URL
-                       if (!relyingParty.isLegacyProvider()) {
-
-                               if (provider == null) {
-                                       log.info("No metadata found for provider: (" + relyingParty.getProviderId() + ").");
-                                       relyingParty = spMapper.getRelyingParty(null);
-
-                               } else {
-
-                                       if (isValidAssertionConsumerURL(provider, acceptanceURL)) {
-                                               log.info("Supplied consumer URL validated for this provider.");
-                                       } else {
-                                               log.error("Assertion consumer service URL (" + acceptanceURL + ") is NOT valid for provider ("
-                                                               + relyingParty.getProviderId() + ").");
-                                               throw new InvalidClientDataException("Invalid assertion consumer service URL.");
-                                       }
-                               }
-                       }
-
-                       // Create SAML Name Identifier
-                       SAMLNameIdentifier nameId = nameMapper.getNameIdentifierName(relyingParty.getHSNameFormatId(),
-                                       new AuthNPrincipal(username), relyingParty, relyingParty.getIdentityProvider());
-
-                       String authenticationMethod = request.getHeader("SAMLAuthenticationMethod");
-                       if (authenticationMethod == null || authenticationMethod.equals("")) {
-                               authenticationMethod = relyingParty.getDefaultAuthMethod().toString();
-                               log.debug("User was authenticated via the default method for this relying party ("
-                                               + authenticationMethod + ").");
-                       } else {
-                               log.debug("User was authenticated via the method (" + authenticationMethod + ").");
-                       }
-
-                       // We might someday want to provide a mechanism for the authenticator to specify the auth time
-                       SAMLAssertion[] assertions = activeHandler.processHook(request, relyingParty, provider, nameId,
-                                       authenticationMethod, new Date(System.currentTimeMillis()));
-
-                       //TODO do assertion signing here
-
-                       // SAML Artifact profile
-                       if (useArtifactProfile(provider, acceptanceURL)) {
-                               log.debug("Responding with Artifact profile.");
-
-                               // Create artifacts for each assertion
-                               ArrayList artifacts = new ArrayList();
-                               for (int i = 0; i < assertions.length; i++) {
-                                       artifacts.add(artifactMapper.generateArtifact(assertions[i], relyingParty));
-                               }
-
-                               // Assemble the query string
-                               StringBuffer destination = new StringBuffer(acceptanceURL);
-                               destination.append("?TARGET=");
-                               destination.append(URLEncoder.encode(activeHandler.getSAMLTargetParameter(request, relyingParty,
-                                               provider), "UTF-8"));
-                               Iterator iterator = artifacts.iterator();
-                               StringBuffer artifactBuffer = new StringBuffer(); // Buffer for the transaction log
-                               while (iterator.hasNext()) {
-                                       destination.append("&SAMLart=");
-                                       String artifact = (String) iterator.next();
-                                       destination.append(URLEncoder.encode(artifact, "UTF-8"));
-                                       artifactBuffer.append("(" + artifact + ")");
-                               }
-                               log.debug("Redirecting to (" + destination.toString() + ").");
-                               response.sendRedirect(destination.toString()); // Redirect to the artifact receiver
-
-                               transactionLog.info("Assertion artifact(s) (" + artifactBuffer.toString() + ") issued to provider ("
-                                               + relyingParty.getIdentityProvider().getProviderId() + ") on behalf of principal (" + username
-                                               + "). Name Identifier: (" + nameId.getName() + "). Name Identifier Format: ("
-                                               + nameId.getFormat() + ").");
-
-                               // SAML POST profile
-                       } else {
-                               log.debug("Responding with POST profile.");
-                               request.setAttribute("acceptanceURL", acceptanceURL);
-                               request.setAttribute("target", activeHandler.getSAMLTargetParameter(request, relyingParty, provider));
-
-                               SAMLResponse samlResponse = new SAMLResponse(null, acceptanceURL, Arrays.asList(assertions), null);
-                               addSignatures(samlResponse, relyingParty, provider, true);
-                               createPOSTForm(request, response, samlResponse.toBase64());
-
-                               // Make transaction log entry
-                               if (relyingParty.isLegacyProvider()) {
-                                       transactionLog.info("Authentication assertion issued to legacy provider (SHIRE: "
-                                                       + request.getParameter("shire") + ") on behalf of principal (" + username
-                                                       + ") for resource (" + request.getParameter("target") + "). Name Identifier: ("
-                                                       + nameId.getName() + "). Name Identifier Format: (" + nameId.getFormat() + ").");
-                               } else {
-                                       transactionLog.info("Authentication assertion issued to provider ("
-                                                       + relyingParty.getIdentityProvider().getProviderId() + ") on behalf of principal ("
-                                                       + username + "). Name Identifier: (" + nameId.getName() + "). Name Identifier Format: ("
-                                                       + nameId.getFormat() + ").");
-                               }
-                       }
-
-                       // TODO profile specific error handling
-               } catch (NameIdentifierMappingException ex) {
-                       log.error(ex);
-                       handleSSOError(request, response, ex);
-                       return;
-               } catch (InvalidClientDataException ex) {
-                       log.error(ex);
-                       handleSSOError(request, response, ex);
-                       return;
-               } catch (SAMLException ex) {
-                       log.error(ex);
-                       handleSSOError(request, response, ex);
-                       return;
-               } catch (InterruptedException ex) {
-                       log.error(ex);
-                       handleSSOError(request, response, ex);
-                       return;
-               } finally {
-                       throttle.exit();
-               }
-
-       }
-
-       private static X509Certificate getCredentialFromProvider(HttpServletRequest req) {
-
-               X509Certificate[] certArray = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
-               if (certArray != null && certArray.length > 0) { return certArray[0]; }
-               return null;
-       }
-
-       private static boolean isValidCredential(Provider provider, X509Certificate certificate) {
-
-               ProviderRole[] roles = provider.getRoles();
-               if (roles.length == 0) {
-                       log.info("Inappropriate metadata for provider.");
-                       return false;
-               }
-               // TODO figure out what to do about this role business here
-               for (int i = 0; roles.length > i; i++) {
-                       if (roles[i] instanceof AttributeConsumerRole) {
-                               KeyDescriptor[] descriptors = roles[i].getKeyDescriptors();
-                               for (int j = 0; descriptors.length > j; j++) {
-                                       KeyInfo[] keyInfo = descriptors[j].getKeyInfo();
-                                       for (int k = 0; keyInfo.length > k; k++) {
-                                               for (int l = 0; keyInfo[k].lengthKeyName() > l; l++) {
-                                                       try {
-
-                                                               // First, try to match DN against metadata
-                                                               try {
-                                                                       if (certificate.getSubjectX500Principal().getName(X500Principal.RFC2253).equals(
-                                                                                       new X500Principal(keyInfo[k].itemKeyName(l).getKeyName())
-                                                                                                       .getName(X500Principal.RFC2253))) {
-                                                                               log.debug("Matched against DN.");
-                                                                               return true;
-                                                                       }
-                                                               } catch (IllegalArgumentException iae) {
-                                                                       // squelch this runtime exception, since
-                                                                       // this might be a valid case
-                                                               }
-
-                                                               // If that doesn't work, we try matching against
-                                                               // some Subject Alt Names
-                                                               try {
-                                                                       Collection altNames = certificate.getSubjectAlternativeNames();
-                                                                       if (altNames != null) {
-                                                                               for (Iterator nameIterator = altNames.iterator(); nameIterator.hasNext();) {
-                                                                                       List altName = (List) nameIterator.next();
-                                                                                       if (altName.get(0).equals(new Integer(2))
-                                                                                                       || altName.get(0).equals(new Integer(6))) { // 2 is
-                                                                                               // DNS,
-                                                                                               // 6 is
-                                                                                               // URI
-                                                                                               if (altName.get(1).equals(keyInfo[k].itemKeyName(l).getKeyName())) {
-                                                                                                       log.debug("Matched against SubjectAltName.");
-                                                                                                       return true;
-                                                                                               }
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               } catch (CertificateParsingException e1) {
-                                                                       log
-                                                                                       .error("Encountered an problem trying to extract Subject Alternate Name from supplied certificate: "
-                                                                                                       + e1);
-                                                               }
-
-                                                               // If that doesn't work, try to match using
-                                                               // SSL-style hostname matching
-                                                               if (ShibBrowserProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
-                                                                               keyInfo[k].itemKeyName(l).getKeyName())) {
-                                                                       log.debug("Matched against hostname.");
-                                                                       return true;
-                                                               }
-
-                                                       } catch (XMLSecurityException e) {
-                                                               log.error("Encountered an error reading federation metadata: " + e);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-               log.info("Supplied credential not found in metadata.");
-               return false;
-       }
-
-       private void sendSAMLFailureResponse(HttpServletResponse httpResponse, SAMLRequest samlRequest,
-                       SAMLException exception) throws IOException {
+       private void sendSAMLFailureResponse(HttpServletResponse httpResponse, SAMLRequest samlRequest,
+                       SAMLException exception) throws IOException {
 
                try {
                        SAMLResponse samlResponse = new SAMLResponse((samlRequest != null) ? samlRequest.getId() : null, null,
@@ -805,17 +810,6 @@ public class IdPResponder extends TargetFederationComponent {
                }
        }
 
-       private static boolean fromLegacyProvider(HttpServletRequest request) {
-
-               String version = request.getHeader("Shibboleth");
-               if (version != null) {
-                       log.debug("Request from Shibboleth version: " + version);
-                       return false;
-               }
-               log.debug("No version header found.");
-               return true;
-       }
-
        private String getEffectiveName(HttpServletRequest req, RelyingParty relyingParty)
                        throws InvalidProviderCredentialException {
 
@@ -865,85 +859,6 @@ public class IdPResponder extends TargetFederationComponent {
                }
        }
 
-       // TODO this should be renamed, since it is now only one type of response
-       // that we can send
-       public void sendSAMLResponse(HttpServletResponse resp, SAMLAttribute[] attrs, SAMLRequest samlRequest,
-                       RelyingParty relyingParty, SAMLException exception) throws IOException {
-
-               SAMLException ourSE = null;
-               SAMLResponse samlResponse = null;
-
-               try {
-                       if (attrs == null || attrs.length == 0) {
-                               // No attribute found
-                               samlResponse = new SAMLResponse(samlRequest.getId(), null, null, exception);
-                       } else {
-
-                               SAMLAttributeQuery attributeQuery = (SAMLAttributeQuery) samlRequest.getQuery();
-
-                               // Reference requested subject
-                               SAMLSubject rSubject = (SAMLSubject) attributeQuery.getSubject().clone();
-
-                               // Set appropriate audience
-                               ArrayList audiences = new ArrayList();
-                               if (relyingParty.getProviderId() != null) {
-                                       audiences.add(relyingParty.getProviderId());
-                               }
-                               if (relyingParty.getName() != null && !relyingParty.getName().equals(relyingParty.getProviderId())) {
-                                       audiences.add(relyingParty.getName());
-                               }
-                               SAMLCondition condition = new SAMLAudienceRestrictionCondition(audiences);
-
-                               // Put all attributes into an assertion
-                               SAMLStatement statement = new SAMLAttributeStatement(rSubject, Arrays.asList(attrs));
-
-                               // Set assertion expiration to longest attribute expiration
-                               long max = 0;
-                               for (int i = 0; i < attrs.length; i++) {
-                                       if (max < attrs[i].getLifetime()) {
-                                               max = attrs[i].getLifetime();
-                                       }
-                               }
-                               Date now = new Date();
-                               Date then = new Date(now.getTime() + (max * 1000)); // max is in
-                               // seconds
-
-                               SAMLAssertion sAssertion = new SAMLAssertion(relyingParty.getIdentityProvider().getProviderId(), now,
-                                               then, Collections.singleton(condition), null, Collections.singleton(statement));
-
-                               samlResponse = new SAMLResponse(samlRequest.getId(), null, Collections.singleton(sAssertion), exception);
-                               addSignatures(samlResponse, relyingParty, lookup(relyingParty.getProviderId()), false);
-                       }
-               } catch (SAMLException se) {
-                       ourSE = se;
-               } catch (CloneNotSupportedException ex) {
-                       ourSE = new SAMLException(SAMLException.RESPONDER, ex);
-
-               } finally {
-
-                       if (log.isDebugEnabled()) { // This takes some processing, so only do it if we need to
-                               try {
-                                       log.debug("Dumping generated SAML Response:"
-                                                       + System.getProperty("line.separator")
-                                                       + new String(
-                                                                       new BASE64Decoder().decodeBuffer(new String(samlResponse.toBase64(), "ASCII")),
-                                                                       "UTF8"));
-                               } catch (SAMLException e) {
-                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
-                               } catch (IOException e) {
-                                       log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
-                               }
-                       }
-
-                       try {
-                               binding.respond(resp, samlResponse, ourSE);
-                       } catch (SAMLException e) {
-                               log.error("Caught exception while responding to requester: " + e.getMessage());
-                               resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while responding.");
-                       }
-               }
-       }
-
        private static void addSignatures(SAMLResponse response, RelyingParty relyingParty, Provider provider,
                        boolean signResponse) throws SAMLException {
 
@@ -1005,7 +920,7 @@ public class IdPResponder extends TargetFederationComponent {
                }
        }
 
-       private boolean useArtifactProfile(Provider provider, String acceptanceURL) {
+       private static boolean useArtifactProfile(Provider provider, String acceptanceURL) {
 
                // Default to POST if we have no metadata
                if (provider == null) { return false; }
@@ -1028,7 +943,7 @@ public class IdPResponder extends TargetFederationComponent {
                return false;
        }
 
-       protected static void validateEngineData(HttpServletRequest req) throws InvalidClientDataException {
+       private static void validateEngineData(HttpServletRequest req) throws InvalidClientDataException {
 
                if ((req.getRemoteUser() == null) || (req.getRemoteUser().equals(""))) { throw new InvalidClientDataException(
                                "Unable to authenticate remote user"); }
@@ -1036,7 +951,7 @@ public class IdPResponder extends TargetFederationComponent {
                                "Unable to obtain client address."); }
        }
 
-       protected static boolean isValidAssertionConsumerURL(Provider provider, String shireURL)
+       private static boolean isValidAssertionConsumerURL(Provider provider, String shireURL)
                        throws InvalidClientDataException {
 
                ProviderRole[] roles = provider.getRoles();
@@ -1057,7 +972,100 @@ public class IdPResponder extends TargetFederationComponent {
                return false;
        }
 
-       protected void createPOSTForm(HttpServletRequest req, HttpServletResponse res, byte[] buf) throws IOException,
+       private static X509Certificate getCredentialFromProvider(HttpServletRequest req) {
+
+               X509Certificate[] certArray = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
+               if (certArray != null && certArray.length > 0) { return certArray[0]; }
+               return null;
+       }
+
+       private static boolean isValidCredential(Provider provider, X509Certificate certificate) {
+
+               ProviderRole[] roles = provider.getRoles();
+               if (roles.length == 0) {
+                       log.info("Inappropriate metadata for provider.");
+                       return false;
+               }
+               // TODO figure out what to do about this role business here
+               for (int i = 0; roles.length > i; i++) {
+                       if (roles[i] instanceof AttributeConsumerRole) {
+                               KeyDescriptor[] descriptors = roles[i].getKeyDescriptors();
+                               for (int j = 0; descriptors.length > j; j++) {
+                                       KeyInfo[] keyInfo = descriptors[j].getKeyInfo();
+                                       for (int k = 0; keyInfo.length > k; k++) {
+                                               for (int l = 0; keyInfo[k].lengthKeyName() > l; l++) {
+                                                       try {
+
+                                                               // First, try to match DN against metadata
+                                                               try {
+                                                                       if (certificate.getSubjectX500Principal().getName(X500Principal.RFC2253).equals(
+                                                                                       new X500Principal(keyInfo[k].itemKeyName(l).getKeyName())
+                                                                                                       .getName(X500Principal.RFC2253))) {
+                                                                               log.debug("Matched against DN.");
+                                                                               return true;
+                                                                       }
+                                                               } catch (IllegalArgumentException iae) {
+                                                                       // squelch this runtime exception, since
+                                                                       // this might be a valid case
+                                                               }
+
+                                                               // If that doesn't work, we try matching against
+                                                               // some Subject Alt Names
+                                                               try {
+                                                                       Collection altNames = certificate.getSubjectAlternativeNames();
+                                                                       if (altNames != null) {
+                                                                               for (Iterator nameIterator = altNames.iterator(); nameIterator.hasNext();) {
+                                                                                       List altName = (List) nameIterator.next();
+                                                                                       if (altName.get(0).equals(new Integer(2))
+                                                                                                       || altName.get(0).equals(new Integer(6))) { // 2 is
+                                                                                               // DNS,
+                                                                                               // 6 is
+                                                                                               // URI
+                                                                                               if (altName.get(1).equals(keyInfo[k].itemKeyName(l).getKeyName())) {
+                                                                                                       log.debug("Matched against SubjectAltName.");
+                                                                                                       return true;
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               } catch (CertificateParsingException e1) {
+                                                                       log
+                                                                                       .error("Encountered an problem trying to extract Subject Alternate Name from supplied certificate: "
+                                                                                                       + e1);
+                                                               }
+
+                                                               // If that doesn't work, try to match using
+                                                               // SSL-style hostname matching
+                                                               if (ShibBrowserProfile.getHostNameFromDN(certificate.getSubjectX500Principal()).equals(
+                                                                               keyInfo[k].itemKeyName(l).getKeyName())) {
+                                                                       log.debug("Matched against hostname.");
+                                                                       return true;
+                                                               }
+
+                                                       } catch (XMLSecurityException e) {
+                                                               log.error("Encountered an error reading federation metadata: " + e);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               log.info("Supplied credential not found in metadata.");
+               return false;
+       }
+
+       private static boolean fromLegacyProvider(HttpServletRequest request) {
+
+               String version = request.getHeader("Shibboleth");
+               if (version != null) {
+                       log.debug("Request from Shibboleth version: " + version);
+                       return false;
+               }
+               log.debug("No version header found.");
+               return true;
+       }
+
+       private static void createPOSTForm(HttpServletRequest req, HttpServletResponse res, byte[] buf) throws IOException,
                        ServletException {
 
                // Hardcoded to ASCII to ensure Base64 encoding compatibility
@@ -1077,7 +1085,7 @@ public class IdPResponder extends TargetFederationComponent {
                rd.forward(req, res);
        }
 
-       protected void handleSSOError(HttpServletRequest req, HttpServletResponse res, Exception e)
+       private static void handleSSOError(HttpServletRequest req, HttpServletResponse res, Exception e)
                        throws ServletException, IOException {
 
                req.setAttribute("errorText", e.toString());
similarity index 86%
rename from src/schemas/origin.xsd
rename to src/schemas/shibboleth-idpconfig-1.0.xsd
index 428ef63..8d65337 100644 (file)
@@ -1,16 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xs:schema 
-       targetNamespace="urn:mace:shibboleth:origin:1.0" 
+       targetNamespace="urn:mace:shibboleth:idp:config:1.0" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        xmlns:credentials="urn:mace:shibboleth:credentials:1.0" 
        xmlns:namemapper="urn:mace:shibboleth:namemapper:1.0" 
-       xmlns:origin="urn:mace:shibboleth:origin:1.0" 
+       xmlns:idp="urn:mace:shibboleth:idp:config:1.0" 
        elementFormDefault="qualified" 
        attributeFormDefault="unqualified">
 
        <xs:import namespace="urn:mace:shibboleth:credentials:1.0" schemaLocation="credentials.xsd"/>
        <xs:import namespace="urn:mace:shibboleth:namemapper:1.0" schemaLocation="namemapper.xsd"/>
 
+       <xs:element name="IdPConfig" type="idp:ShibbolethOriginConfig"/>
+
        <xs:simpleType name="LevelType">
                <xs:restriction base="xs:string">
                        <xs:enumeration value="OFF"/>
@@ -24,7 +26,7 @@
 
        <xs:complexType name="LogWithLevels">
                <xs:attribute name="location" type="xs:anyURI" use="required" />
-               <xs:attribute name="level" type="origin:LevelType" use="optional" default="WARN" />
+               <xs:attribute name="level" type="idp:LevelType" use="optional" default="WARN" />
        </xs:complexType>
 
        <xs:complexType name="Log">
                </xs:restriction>
        </xs:simpleType>
 
-       <xs:element name="ShibbolethOriginConfig">
-               <xs:annotation>
-                       <xs:documentation>Configures the Shibboleth Origin software.</xs:documentation>
-               </xs:annotation>
-               <xs:complexType>
+               <xs:complexType name="ShibbolethOriginConfig">
                        <xs:sequence>
                                <xs:sequence>
                                        <xs:element name="RelyingParty" maxOccurs="unbounded">
                                        <xs:complexType>
                                                <xs:choice>
                                                        <xs:sequence>
-                                                               <xs:element name="ErrorLog" type="origin:LogWithLevels" minOccurs="0" maxOccurs="1" />
-                                                               <xs:element name="TransactionLog" type="origin:Log" minOccurs="0" maxOccurs="1" />
+                                                               <xs:element name="ErrorLog" type="idp:LogWithLevels" minOccurs="0" maxOccurs="1" />
+                                                               <xs:element name="TransactionLog" type="idp:Log" minOccurs="0" maxOccurs="1" />
                                                        </xs:sequence>
                                                        <xs:element name="Log4JConfig">
                                                                <xs:complexType>
-                                                                       <xs:attribute name="type" type="origin:Log4JConfigType" use="optional" default="properties" />
+                                                                       <xs:attribute name="type" type="idp:Log4JConfigType" use="optional" default="properties" />
                                                                        <xs:attribute name="location" type="xs:anyURI" use="required" />
                                                                </xs:complexType>
                                                        </xs:element>
                        <xs:attribute name="authHeaderName" type="xs:string" use="optional"/>
                        <xs:attribute name="maxHSThreads" type="xs:integer" use="optional"/>
                </xs:complexType>
-       </xs:element>
 
 </xs:schema>