package at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Date; import java.util.List; import org.opensaml.Configuration; import org.opensaml.saml2.core.Assertion; import org.opensaml.xml.XMLObject; import org.opensaml.xml.io.Unmarshaller; import org.opensaml.xml.io.UnmarshallerFactory; import org.w3c.dom.Element; import org.xml.sax.SAXException; import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; import at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor; import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils; import at.gv.egovernment.moa.id.auth.exception.ValidateException; import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20eIDDataValidationException; import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants; import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator; import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureRequestBuilder; import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.sig.tsl.utils.MiscUtil; import at.gv.egovernment.moa.util.Base64Utils; public class QualifiedeIDVerifier { public static void verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException { // validates the identity link IdentityLinkValidator.getInstance().validate(idl); // builds a for a call of MOA-SP Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder() .build(idl, authConfig.getMoaSpIdentityLinkTrustProfileID(oaParam.isUseIDLTestTrustStore())); // invokes the call Element domVerifyXMLSignatureResponse = SignatureVerificationInvoker.getInstance() .verifyXMLSignature(domVerifyXMLSignatureRequest); // parses the IVerifiyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData(); // validates the VerifyXMLSignatureResponseValidator.getInstance().validate( verifyXMLSignatureResponse, authConfig.getIdentityLinkX509SubjectNames(), VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK, oaParam, authConfig); } public static IVerifiyXMLSignatureResponse verifyAuthBlock(String authBlockB64, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException, IOException { String trustProfileId = authConfig.getMoaSpAuthBlockTrustProfileID(oaParam.isUseAuthBlockTestTestStore()); List verifyTransformsInfoProfileID = KeyValueUtils.getListOfCSVValues( KeyValueUtils.normalizeCSVValueString( authConfig.getBasicConfiguration( at.gv.egovernment.moa.id.auth.modules.sl20_auth.Constants.CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID))); SignatureVerificationUtils sigVerify = new SignatureVerificationUtils(); IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(Base64Utils.decode(authBlockB64, false), trustProfileId , verifyTransformsInfoProfileID); // validates the VerifyXMLSignatureResponseValidator.getInstance().validate(sigVerifyResult, null, VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK, oaParam, authConfig); return sigVerifyResult; } public static boolean checkConsistencyOfeIDData(String sl20ReqId, IIdentityLink idl, AssertionAttributeExtractor authBlockExtractor, IVerifiyXMLSignatureResponse sigVerifyResult) throws SL20eIDDataValidationException { try { // compares the public keys from the identityLink with the AuthBlock VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(sigVerifyResult, idl); //compare requestId from SL20 qualifiedeID command to ID from SAML2 assertion String authBlockId = authBlockExtractor.getAssertionID(); if (MiscUtil.isEmpty(authBlockId)) { Logger.info("AuthBlock containts no ID, but ID MUST be included"); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "AuthBlock containts no ID, but ID MUST be included" }); } if (!authBlockId.equals(sl20ReqId)) { Logger.info("SL20 'requestId' does NOT match to AuthBlock Id." + " Expected : " + sl20ReqId + " Authblock: " + authBlockId); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "SL20 'requestId' does NOT match to AuthBlock Id." }); } // Compare AuthBlock Data with information stored in session, especially // date and time validateSigningDateTime(sigVerifyResult, authBlockExtractor); } catch ( ValidateException e) { Logger.warn("Validation of eID information FAILED. ", e); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, e.getMessage() }); } return false; } public static Assertion parseAuthBlockToSaml2Assertion(String authblockB64) throws SL20eIDDataValidationException { try { //parse authBlock into SAML2 Assertion byte[] authBlockBytes = Base64Utils.decode(authblockB64, false); Element authBlockDOM = DOMUtils.parseXmlValidating(new ByteArrayInputStream(authBlockBytes)); UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(authBlockDOM); XMLObject samlAssertion = unmarshaller.unmarshall(authBlockDOM); //validate SAML2 Assertion SAML2Utils.schemeValidation(samlAssertion); if (samlAssertion instanceof Assertion) return (Assertion) samlAssertion; else throw new SL20eIDDataValidationException( new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "AuthBlock is NOT of type SAML2 Assertion" }); } catch (SL20eIDDataValidationException e) { throw e; } catch (SAXException e) { Logger.info("Scheme validation of SAML2 AuthBlock FAILED. Reason: " + e.getMessage()); throw new SL20eIDDataValidationException( new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, e.getMessage() }, e); } catch (Exception e) { Logger.info("Can not parse AuthBlock. Reason: " + e.getMessage()); Logger.trace("FullAuthBlock: " + authblockB64); throw new SL20eIDDataValidationException( new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, e.getMessage() }, e); } } private static void validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult, AssertionAttributeExtractor authBlockExtractor) throws SL20eIDDataValidationException { Date signingDate = sigVerifyResult.getSigningDateTime(); Date notBefore = authBlockExtractor.getAssertionNotBefore(); Date notOrNotAfter = authBlockExtractor.getAssertionNotOnOrAfter(); if (signingDate == null) { Logger.info("AuthBlock signature contains NO signing data"); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "AuthBlock signature contains NO signing data" }); } Logger.debug("AuthBlock signing data: " + signingDate.toString()); if (notBefore == null || notOrNotAfter == null) { Logger.info("AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates"); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates" }); } Logger.debug("AuthBlock valid period." + " NotBefore:" + notBefore.toString() + " NotOrNotAfter:" + notOrNotAfter.toString()); if ((signingDate.after(notBefore) || signingDate.equals(notBefore)) && signingDate.before(notOrNotAfter)) Logger.debug("Signing date validation successfull"); else { Logger.info("AuthBlock signing date does NOT match to AuthBlock constrains"); throw new SL20eIDDataValidationException(new Object[] { SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, "AuthBlock signing date does NOT match to AuthBlock constrains" }); } } }