// 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());
// 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) {
}
+ 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());
}
}
+ // 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,
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,
}
}
- 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 {
}
}
- // 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 {
}
}
- 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; }
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"); }
"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();
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
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());