/******************************************************************************* *******************************************************************************/ package at.asitplus.eidas.specific.connector.verification; import java.io.IOException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.opensaml.common.SignableSAMLObject; import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.security.SAMLSignatureProfileValidator; import org.opensaml.xml.security.x509.BasicX509Credential; import org.opensaml.xml.signature.SignatureValidator; import org.opensaml.xml.validation.ValidationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; import at.gv.egiz.eaaf.modules.pvp2.idp.exception.SAMLRequestNotSignedException; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.AbstractMetadataSignatureFilter; public class MetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter{ private static final Logger log = LoggerFactory.getLogger(MetadataSignatureVerificationFilter.class); private String metadataURL; private List trustedCredential = new ArrayList(); public MetadataSignatureVerificationFilter(String trustStorePath, String trustStorePassword, String metadataURL) throws PVP2MetadataException { this.metadataURL = metadataURL; log.trace("Initialize metadata signature-verification filter with truststore: " + trustStorePath + " ... "); try { KeyStore keyStore = KeyStoreUtils.loadKeyStore(trustStorePath, trustStorePassword); if (keyStore != null) { //load trusted certificates Enumeration aliases = keyStore.aliases(); while(aliases.hasMoreElements()) { String el = aliases.nextElement(); log.trace("Process TrustStoreEntry: " + el); if (keyStore.isCertificateEntry(el)) { Certificate cert = keyStore.getCertificate(el); if (cert != null && cert instanceof X509Certificate) { BasicX509Credential trustedCert = new BasicX509Credential(); trustedCert.setEntityCertificate((X509Certificate) cert); this.trustedCredential.add(trustedCert); log.debug("Add cert: " + ((X509Certificate) cert).getSubjectDN() + " as trusted for metadata: " + metadataURL); } else log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); } } } else throw new PVP2MetadataException("pvp2.26", new Object[] {"Can not open trustStore: " + trustStorePath + " for metadata: " + metadataURL}); } catch (KeyStoreException | IOException e) { log.warn("Can not open trustStore: " + trustStorePath + " for metadata: " + metadataURL + " Reason: " + e.getMessage(), e); throw new PVP2MetadataException("pvp2.26", new Object[] {"Can not open trustStore: " + trustStorePath + " for metadata"}, e); } } @Override protected void verify(EntityDescriptor desc) throws PVP2MetadataException { try { internalVerify(desc); } catch (EAAFException e) { log.info("Metadata verification FAILED for: " + metadataURL + " Reason: " +e.getMessage()); throw new PVP2MetadataException("pvp2.26", new Object[] {"Metadata verification FAILED for: " + metadataURL + " Reason: " +e.getMessage()}, e); } } @Override protected void verify(EntitiesDescriptor desc) throws PVP2MetadataException { throw new PVP2MetadataException("pvp2.26", new Object[] {"EntitiesDescritors are NOT supported"}); } @Override protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws PVP2MetadataException { throw new PVP2MetadataException("pvp2.26", new Object[] {"EntitiesDescritors are NOT supported"}); } private void internalVerify(SignableSAMLObject signedElement) throws EAAFException { if (signedElement.getSignature() == null) { throw new SAMLRequestNotSignedException(); } try { SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); sigValidator.validate(signedElement.getSignature()); } catch (ValidationException e) { log.error("Failed to validate Signature", e); throw new SAMLRequestNotSignedException(e); } boolean isTrusted = false; for (BasicX509Credential cred : trustedCredential) { SignatureValidator sigValidator = new SignatureValidator(cred); try { sigValidator.validate(signedElement.getSignature()); isTrusted = true; } catch (ValidationException e) { log.info("Failed to verfiy Signature with cert: " + cred.getEntityCertificate().getSubjectDN() + " Reason: " + e.getMessage()); } } if (!isTrusted) { log.warn("PVP2 metadata: " + metadataURL + " are NOT trusted!"); throw new SAMLRequestNotSignedException(); } } }