/** * Verify the signature in <code>Response</code>. * * @param pepEntityID entity identifier of PEP. * @param pdpEntityID entity identifier of PDP. * @param response <code>Response</code> to be verified * @return true if signature is valid. * @throws <code>SAML2Exception</code> if error in verifying the signature. */ public static boolean verifySignedResponse( String pepEntityID, String pdpEntityID, Response response) throws SAML2Exception { String classMethod = "QueryClient:verifySignedResponse: "; String realm = "/"; XACMLAuthzDecisionQueryConfigElement pepConfig = getPEPConfig(realm, pepEntityID); String wantResponseSigned = getAttributeValueFromPEPConfig(pepConfig, "wantXACMLAuthzDecisionResponseSigned"); boolean valid = false; if (wantResponseSigned != null && wantResponseSigned.equalsIgnoreCase("true")) { XACMLPDPDescriptorElement pdpDescriptor = saml2MetaManager.getPolicyDecisionPointDescriptor(null, pdpEntityID); X509Certificate signingCert = KeyUtil.getPDPVerificationCert(pdpDescriptor, pdpEntityID); if (signingCert != null) { valid = response.isSignatureValid(signingCert); if (debug.messageEnabled()) { debug.message(classMethod + "Signature is valid :" + valid); } } else { debug.error(classMethod + "Incorrect configuration for Signing Certificate."); throw new SAML2Exception(SAML2SDKUtils.bundle.getString("metaDataError")); } } else { if (debug.messageEnabled()) { debug.message(classMethod + "Response doesn't need to be verified."); } valid = true; } return valid; }
/** * Returns the Policy Decision Point End Point (PDP) URL. * * @param pdpEntityID entity Identifier of the PDP. * @return the PDP endpoint URL. * @exception if there is an error retreiving the endpoint from the configuration. */ private static String getPDPEndPoint(String pdpEntityID) throws SAML2Exception { String endPoint = null; String classMethod = "QueryClient:getPDPEndPoint"; if (saml2MetaManager != null) { try { XACMLPDPDescriptorElement pdpDescriptor = saml2MetaManager.getPolicyDecisionPointDescriptor(null, pdpEntityID); if (pdpDescriptor != null) { List xacmlPDP = pdpDescriptor.getXACMLAuthzService(); if (xacmlPDP != null) { Iterator i = xacmlPDP.iterator(); while (i.hasNext()) { Object o = (Object) i.next(); if (o instanceof XACMLAuthzServiceElement) { XACMLAuthzServiceElement xType = (XACMLAuthzServiceElement) o; endPoint = xType.getLocation(); if (debug.messageEnabled()) { debug.message(classMethod + "EndPoint :" + endPoint); } } break; } } } } catch (SAML2MetaException sme) { if (debug.messageEnabled()) { debug.message(classMethod + "Error retreiving PDP Meta", sme); } String[] args = {pdpEntityID}; LogUtil.error(Level.INFO, LogUtil.PDP_METADATA_ERROR, args); throw new SAML2Exception(SAML2SDKUtils.BUNDLE_NAME, "pdpMetaRetreivalError", args); } } return endPoint; }
/** * Returns SAMLv2 <code>Response</code> after validation of the response. A new <code>Response * </code> object is created which contains decrypted assertion if the assertions were encrypted. * * @param realm the realm of the entity. * @param pepEntityID entity identifier of the PEP. * @param samlResponse the <code>Response</code>. * @exception <code>SAML2Exception</code> if there is an error. */ private static Response verifyResponse(String realm, String pepEntityID, Response samlResponse) throws SAML2Exception { Response response = samlResponse; String classMethod = "QueryClient:verifyResponse"; if (samlResponse != null) { // validate issuer trust. Issuer issuer = samlResponse.getIssuer(); String issuerID = null; if (issuer != null) { issuerID = issuer.getValue().trim(); } String pdpEntityID = issuerID; boolean isTrusted = verifyResponseIssuer(realm, pepEntityID, issuerID); if (!isTrusted) { if (debug.messageEnabled()) { debug.message(classMethod + "Issuer in Request is not valid."); } String[] args = {realm, pepEntityID, issuerID}; LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_IN_PEP_REQUEST, args); throw new SAML2Exception(SAML2SDKUtils.BUNDLE_NAME, "invalidIssuer", args); } // verify signed response verifySignedResponse(pepEntityID, pdpEntityID, samlResponse); try { // check if assertion needs to be encrypted,signed. XACMLAuthzDecisionQueryConfigElement pepConfig = saml2MetaManager.getPolicyEnforcementPointConfig(realm, pepEntityID); String assertionEncrypted = getAttributeValueFromPEPConfig(pepConfig, SAML2Constants.WANT_ASSERTION_ENCRYPTED); boolean wantAssertionEncrypted = (assertionEncrypted != null && assertionEncrypted.equalsIgnoreCase("true")) ? true : false; boolean wantAssertionSigned = wantAssertionSigned(realm, pepEntityID); String respID = samlResponse.getID(); List assertions = samlResponse.getAssertion(); if (wantAssertionEncrypted && (assertions != null && (assertions.size() != 0))) { String[] data = {issuerID, respID}; LogUtil.error(Level.INFO, LogUtil.ASSERTION_FROM_PDP_NOT_ENCRYPTED, data); throw new SAML2Exception(SAML2SDKUtils.bundle.getString("assertionNotEncrypted")); } PrivateKey decryptionKey = null; List encAssertions = samlResponse.getEncryptedAssertion(); List decAssertions = null; if (encAssertions != null) { Iterator encIter = encAssertions.iterator(); while (encIter.hasNext()) { if (decryptionKey == null) { decryptionKey = KeyUtil.getDecryptionKey(pepConfig); } Assertion assertion = ((EncryptedAssertion) encIter.next()).decrypt(decryptionKey); if (assertions == null) { assertions = new ArrayList(); } assertions.add(assertion); } } if (assertions == null || assertions.size() == 0) { if (debug.messageEnabled()) { debug.message(classMethod + "no assertion in the Response."); } String[] data = {issuerID, respID}; LogUtil.error(Level.INFO, LogUtil.MISSING_ASSERTION_IN_PDP_RESPONSE, data); throw new SAML2Exception(SAML2SDKUtils.bundle.getString("missingAssertion")); } // validate Issuer in Assertion Iterator assertionIter = assertions.iterator(); X509Certificate cert = null; XACMLPDPDescriptorElement pdpDesc = null; if (wantAssertionSigned) { pdpDesc = saml2MetaManager.getPolicyDecisionPointDescriptor(realm, pdpEntityID); cert = KeyUtil.getPDPVerificationCert(pdpDesc, pdpEntityID); } while (assertionIter.hasNext()) { Assertion assertion = (Assertion) assertionIter.next(); String assertionID = assertion.getID(); String assertionIssuer = assertion.getIssuer().getValue().trim(); isTrusted = verifyResponseIssuer(realm, pepEntityID, assertionIssuer); if (!isTrusted) { debug.error(classMethod + "Assertion's source site is not valid."); String[] data = {assertionIssuer, assertionID}; LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_IN_ASSERTION_FROM_PDP, data); throw new SAML2Exception(SAML2SDKUtils.bundle.getString("invalidIssuerInAssertion")); } String respIssuer = samlResponse.getIssuer().getValue().trim(); if (!respIssuer.equals(assertionIssuer)) { if (debug.messageEnabled()) { debug.message( classMethod + "Issuer in Assertion " + assertionIssuer + "doesn't match the Issuer in Response." + respIssuer); } String[] data = {pdpEntityID, assertionIssuer}; LogUtil.error(Level.INFO, LogUtil.MISMATCH_ISSUER_IN_ASSERTION_FROM_PDP, data); throw new SAML2Exception(SAML2SDKUtils.bundle.getString("mismatchIssuer")); } if (wantAssertionSigned) { if (debug.messageEnabled()) { debug.message(classMethod + "wantAssertionSigned " + wantAssertionSigned); } if (!assertion.isSigned() || !assertion.isSignatureValid(cert)) { debug.error(classMethod + "Assertion is not signed or signature " + "is not valid."); String[] data = {assertionIssuer, assertionID}; LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION_FROM_PDP, data); throw new SAML2Exception( SAML2SDKUtils.bundle.getString("invalidSignatureOnAssertion")); } } } // end while if (wantAssertionEncrypted) { response = createResponse(samlResponse, assertions); } if (debug.messageEnabled()) { debug.message(classMethod + " Response : " + response.toXMLString(true, true)); } } catch (SAML2MetaException sme) { if (debug.messageEnabled()) { debug.message(classMethod + "Error retreiving meta", sme); } throw new SAML2Exception(SAML2SDKUtils.bundle.getString("metaDataError")); } } return response; }