diff options
Diffstat (limited to 'eaaf_modules')
2 files changed, 121 insertions, 11 deletions
| diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java index 5a97924f..f4b008af 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java @@ -25,17 +25,24 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata;  import java.security.KeyStore;  import java.security.KeyStoreException; +import java.security.MessageDigest; +import java.security.cert.CertificateEncodingException;  import java.security.cert.X509Certificate;  import java.util.ArrayList;  import java.util.List;  import javax.annotation.Nonnull; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.xml.security.keys.KeyInfo; +import org.apache.xml.security.keys.keyresolver.KeyResolverException;  import org.opensaml.saml.common.SignableSAMLObject;  import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;  import org.opensaml.saml.saml2.metadata.EntityDescriptor;  import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;  import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.impl.SignatureImpl;  import org.opensaml.xmlsec.signature.support.SignatureException;  import org.opensaml.xmlsec.signature.support.SignatureValidator; @@ -124,28 +131,78 @@ public class SimpleMetadataSignatureVerificationFilter extends AbstractMetadataS      }      // perform cryptographic signature verification -    boolean isTrusted = false; -    for (final BasicX509Credential cred : getTrustedCertificates()) { -      log.trace("Validating signature with credential: {} ... ", -          cred.getEntityCertificate().getSubjectDN()); +    if (!performCryptographicCheck(signedElement.getSignature())) { +      log.info("PVP2 metadata: " + metadataUrl + " are NOT trusted!"); +      throw new SamlMetadataSignatureException(metadataUrl, ERROR_MSG_SIGNOTVALID); + +    } +  } + +  private boolean performCryptographicCheck(Signature signature) throws EaafConfigurationException { + +    // extract trusted signer certificate from signature +    BasicX509Credential x509FromSig = extractTrustedX509FromSignature(signature); +    if (x509FromSig != null) {        try { -        SignatureValidator.validate(signedElement.getSignature(), cred); -        isTrusted = true; +        SignatureValidator.validate(signature, x509FromSig); +        return true;        } catch (final SignatureException e) {          log.debug("Failed to verfiy Signature with cert: {} Reason: {}", -            cred.getEntityCertificate().getSubjectDN(), e.getMessage()); +            x509FromSig.getEntityCertificate().getSubjectDN(), e.getMessage()); + +      } +    } else { +      for (final BasicX509Credential cred : getTrustedCertificates()) { +        log.trace("Validating signature with credential: {} ... ", +            cred.getEntityCertificate().getSubjectDN()); +        try { +          SignatureValidator.validate(signature, cred); +          return true; + +        } catch (final SignatureException e) { +          log.debug("Failed to verfiy Signature with cert: {} Reason: {}", +              cred.getEntityCertificate().getSubjectDN(), e.getMessage()); + +        }        }      } -    if (!isTrusted) { -      log.info("PVP2 metadata: " + metadataUrl + " are NOT trusted!"); -      throw new SamlMetadataSignatureException(metadataUrl, ERROR_MSG_SIGNOTVALID); +    return false; + +  } + +  private BasicX509Credential extractTrustedX509FromSignature(Signature signature) { +    try { +      KeyInfo keyInfo = ((SignatureImpl) signature).getXMLSignature().getKeyInfo(); + +      byte[] encSigCert = keyInfo.getX509Certificate() != null +          ? keyInfo.getX509Certificate().getEncoded() +          : ArrayUtils.EMPTY_BYTE_ARRAY; + +      return getTrustedCertificates().stream() +          .filter(el -> { +            try { +              return MessageDigest.isEqual(el.getEntityCertificate().getEncoded(), encSigCert); + +            } catch (CertificateEncodingException e) { +              log.warn("Can not match certificates.", e); +              return false; + +            } +          }) +          .findFirst() +          .orElse(null); + +    } catch (KeyResolverException | EaafConfigurationException | CertificateEncodingException e) { +      log.info("Can not extract X509 certificate from XML signature. Reason: {}", e.getMessage());      } +    return null; +    } -   +    private List<BasicX509Credential> getTrustedCertificates() throws EaafConfigurationException {      try {        final List<X509Certificate> certs = diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java index 036d682b..511b7283 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java @@ -337,6 +337,59 @@ public class MetadataResolverTest {    }    @Test +  public void metadataSignatureValidCredentialsNoX509() throws CertificateException, Pvp2MetadataException, +      ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, +      CredentialsNotAvailableException, MarshallingException, TransformerException, IOException, +      KeyStoreException, NoSuchAlgorithmException { + +    mockWebServer.shutdown(); +    mockWebServer = new MockWebServer(); +    mockServerUrl = mockWebServer.url("/sp/metadata"); + +    final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( +        XMLObjectProviderRegistrySupport.getParserPool(), +        MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_moaid_test.xml")); +    metadata.setValidUntil(Instant.now().plus(Duration.ofDays(1))); +    metadata.setSignature(null); +    metadata.setEntityID(RandomStringUtils.randomAlphabetic(10)); +    final EntityDescriptor signedMatadata = +        Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), false); +    final Element metadataElement = XMLObjectSupport.marshall(signedMatadata); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(SerializeSupport.nodeToString(metadataElement)) +        .setHeader("Content-Type", "text/html;charset=utf-8")); + +    final KeyStore keystore = KeyStore.getInstance("JKS"); +    keystore.load(null, "junit".toCharArray()); +    final CertificateFactory fact = CertificateFactory.getInstance("X.509"); +    keystore.setCertificateEntry("1", fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt"))); +    keystore.setCertificateEntry("2", fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))); +    keystore.setCertificateEntry("3", fact.generateCertificate( +        MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))); + +    final List<MetadataFilter> filterList = new ArrayList<>(); +    filterList.add(new SchemaValidationFilter(true)); +    filterList.add(new SimpleMetadataSignatureVerificationFilter( +        keystore, +        mockServerUrl.url().toString())); +    filterList.add(new PvpEntityCategoryFilter(true)); + +    final MetadataFilterChain filterChain = new MetadataFilterChain(); +    filterChain.setFilters(filterList); + +    final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( +        mockServerUrl.url().toString(), +        filterChain, "jUnit test", httpClientFactory.getHttpClient()); + +    final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( +        metadata.getEntityID()); +    Assert.assertNotNull("No EntityDescripter", entityIdNotExists); + +  } + +  @Test    public void metadataSignatureValidCredentialsSecond() throws CertificateException, Pvp2MetadataException,        ResolverException, XMLParserException, UnmarshallingException, SamlSigningException,        CredentialsNotAvailableException, MarshallingException, TransformerException, IOException, | 
