Example usage for java.security.cert X509Certificate getIssuerDN

List of usage examples for java.security.cert X509Certificate getIssuerDN

Introduction

In this page you can find the example usage for java.security.cert X509Certificate getIssuerDN.

Prototype

public abstract Principal getIssuerDN();

Source Link

Document

Denigrated, replaced by #getIssuerX500Principal() .

Usage

From source file:org.ejbca.core.protocol.ws.CommonEjbcaWS.java

protected void checkRevokeStatus() throws Exception {

    final P12TestUser p12TestUser = new P12TestUser();
    final X509Certificate cert = p12TestUser.getCertificate("12345678");

    String issuerdn = cert.getIssuerDN().toString();
    String serno = cert.getSerialNumber().toString(16);

    RevokeStatus revokestatus = ejbcaraws.checkRevokationStatus(issuerdn, serno);
    assertNotNull(revokestatus);/*from   www.  j  ava 2 s  . c  o m*/
    assertTrue(revokestatus.getReason() == RevokedCertInfo.NOT_REVOKED);

    ejbcaraws.revokeCert(issuerdn, serno, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);

    revokestatus = ejbcaraws.checkRevokationStatus(issuerdn, serno);
    assertNotNull(revokestatus);
    assertTrue(revokestatus.getReason() == RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);
    assertTrue(revokestatus.getCertificateSN().equals(serno));
    assertTrue(revokestatus.getIssuerDN().equals(issuerdn));
    assertNotNull(revokestatus.getRevocationDate());
}

From source file:org.ejbca.core.protocol.ws.CommonEjbcaWS.java

protected void revokeCertBackdated() throws Exception {

    final P12TestUser p12TestUser = new P12TestUser();
    final X509Certificate cert = p12TestUser.getCertificate(null);

    final String issuerdn = cert.getIssuerDN().toString();
    final String serno = cert.getSerialNumber().toString(16);
    final String sDate = "2012-06-07T23:55:59+02:00";

    final CertificateProfile certProfile = this.certificateProfileSession.getCertificateProfile(WS_CERTPROF_EI);
    certProfile.setAllowBackdatedRevocation(false);
    this.certificateProfileSession.changeCertificateProfile(intAdmin, WS_CERTPROF_EI, certProfile);
    try {/*from  w  w w . j a v a2 s .  co  m*/
        this.ejbcaraws.revokeCertBackdated(issuerdn, serno, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE,
                sDate);
        assertTrue(false);
    } catch (RevokeBackDateNotAllowedForProfileException_Exception e) {
        // do nothing
    }
    certProfile.setAllowBackdatedRevocation(true);
    this.certificateProfileSession.changeCertificateProfile(intAdmin, WS_CERTPROF_EI, certProfile);
    this.ejbcaraws.revokeCertBackdated(issuerdn, serno, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE, sDate);
    final RevokeStatus revokestatus = this.ejbcaraws.checkRevokationStatus(issuerdn, serno);
    assertNotNull(revokestatus);
    final Date realRevokeDate = revokestatus.getRevocationDate().toGregorianCalendar().getTime();
    final Date expectedRevokeDate;
    try {
        expectedRevokeDate = DatatypeConverter.parseDateTime(sDate).getTime();
    } catch (IllegalArgumentException e) {
        assertTrue("Not a valid ISO8601 date revocation date", false);
        return;
    }
    assertEquals("Revocation date not the expected.", expectedRevokeDate, realRevokeDate);
}

From source file:org.ejbca.core.protocol.ws.CommonEjbcaWS.java

protected void revokeCert() throws Exception {

    final P12TestUser p12TestUser = new P12TestUser();
    final X509Certificate cert = p12TestUser.getCertificate(null);

    final String issuerdn = cert.getIssuerDN().toString();
    final String serno = cert.getSerialNumber().toString(16);

    this.ejbcaraws.revokeCert(issuerdn, serno, RevokedCertInfo.REVOCATION_REASON_CERTIFICATEHOLD);

    {//  w ww .  ja  v a  2  s  .com
        final RevokeStatus revokestatus = this.ejbcaraws.checkRevokationStatus(issuerdn, serno);
        assertNotNull(revokestatus);
        assertTrue(revokestatus.getReason() == RevokedCertInfo.REVOCATION_REASON_CERTIFICATEHOLD);

        assertTrue(revokestatus.getCertificateSN().equals(serno));
        assertTrue(revokestatus.getIssuerDN().equals(issuerdn));
        assertNotNull(revokestatus.getRevocationDate());
    }
    this.ejbcaraws.revokeCert(issuerdn, serno, RevokedCertInfo.NOT_REVOKED);
    {
        final RevokeStatus revokestatus = this.ejbcaraws.checkRevokationStatus(issuerdn, serno);
        assertNotNull(revokestatus);
        assertTrue(revokestatus.getReason() == RevokedCertInfo.NOT_REVOKED);
    }
    {
        //final long beforeTimeMilliseconds = new Date().getTime();
        final Date beforeRevoke = new Date();
        this.ejbcaraws.revokeCert(issuerdn, serno, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);
        final Date afterRevoke = new Date();
        //final Date beforeRevoke = new Date(beforeTimeMilliseconds-beforeTimeMilliseconds%1000);
        final RevokeStatus revokestatus = this.ejbcaraws.checkRevokationStatus(issuerdn, serno);
        assertNotNull(revokestatus);
        assertTrue(revokestatus.getReason() == RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE);
        final Date revokeDate = revokestatus.getRevocationDate().toGregorianCalendar().getTime();
        assertTrue("Too early revocation date. Before time '" + beforeRevoke + "'. Revoke time '" + revokeDate
                + "'.", !revokeDate.before(beforeRevoke));
        assertTrue(
                "Too late revocation date. After time '" + afterRevoke + "'. Revoke time '" + revokeDate + "'.",
                !revokeDate.after(afterRevoke));
    }
    try {
        this.ejbcaraws.revokeCert(issuerdn, serno, RevokedCertInfo.NOT_REVOKED);
        assertTrue(false);
    } catch (AlreadyRevokedException_Exception e) {
    }

}

From source file:org.cesecore.util.CertTools.java

/**
 * Gets subject or issuer DN in the format we are sure about (BouncyCastle),supporting UTF8.
 * /*from w ww. j a  v  a 2 s .  c o m*/
 * @param cert X509Certificate
 * @param which 1 = subjectDN, anything else = issuerDN
 * 
 * @return String containing the DN.
 */
private static String getDN(final Certificate cert, final int which) {
    String ret = null;
    if (cert == null) {
        return null;
    }
    if (cert instanceof X509Certificate) {
        // cert.getType=X.509
        try {
            final CertificateFactory cf = CertTools.getCertificateFactory();
            final X509Certificate x509cert = (X509Certificate) cf
                    .generateCertificate(new ByteArrayInputStream(cert.getEncoded()));
            String dn = null;
            if (which == 1) {
                dn = x509cert.getSubjectDN().toString();
            } else {
                dn = x509cert.getIssuerDN().toString();
            }
            ret = stringToBCDNString(dn);
        } catch (CertificateException ce) {
            log.info("Could not get DN from X509Certificate. " + ce.getMessage());
            log.debug("", ce);
            return null;
        }
    } else if (StringUtils.equals(cert.getType(), "CVC")) {
        final CardVerifiableCertificate cvccert = (CardVerifiableCertificate) cert;
        try {
            ReferenceField rf = null;
            if (which == 1) {
                rf = cvccert.getCVCertificate().getCertificateBody().getHolderReference();
            } else {
                rf = cvccert.getCVCertificate().getCertificateBody().getAuthorityReference();
            }
            if (rf != null) {
                // Construct a "fake" DN which can be used in EJBCA
                // Use only mnemonic and country, since sequence is more of a serialnumber than a DN part
                String dn = "";
                if (rf.getMnemonic() != null) {
                    if (StringUtils.isNotEmpty(dn)) {
                        dn += ", ";
                    }
                    dn += "CN=" + rf.getMnemonic();
                }
                if (rf.getCountry() != null) {
                    if (StringUtils.isNotEmpty(dn)) {
                        dn += ", ";
                    }
                    dn += "C=" + rf.getCountry();
                }
                ret = stringToBCDNString(dn);
            }
        } catch (NoSuchFieldException e) {
            log.error("NoSuchFieldException: ", e);
            return null;
        }
    }
    return ret;
}

From source file:org.ejbca.core.protocol.ws.CommonEjbcaWS.java

protected void revokeToken() throws Exception {

    final P12TestUser p12TestUser = new P12TestUser();
    final X509Certificate cert1 = p12TestUser.getCertificate("12345678");
    final X509Certificate cert2 = p12TestUser.getCertificate("12345678");

    ejbcaraws.revokeToken("12345678", RevokeStatus.REVOKATION_REASON_KEYCOMPROMISE);

    String issuerdn1 = cert1.getIssuerDN().toString();
    String serno1 = cert1.getSerialNumber().toString(16);

    RevokeStatus revokestatus = ejbcaraws.checkRevokationStatus(issuerdn1, serno1);
    assertNotNull(revokestatus);// w w  w  . j av a  2s.co m
    assertTrue(revokestatus.getReason() == RevokeStatus.REVOKATION_REASON_KEYCOMPROMISE);

    String issuerdn2 = cert2.getIssuerDN().toString();
    String serno2 = cert2.getSerialNumber().toString(16);

    revokestatus = ejbcaraws.checkRevokationStatus(issuerdn2, serno2);
    assertNotNull(revokestatus);
    assertTrue(revokestatus.getReason() == RevokeStatus.REVOKATION_REASON_KEYCOMPROMISE);

}

From source file:org.ejbca.core.protocol.ws.EjbcaWS.java

private void logAdminName(final AuthenticationToken admin, final IPatternLogger logger) {
    // Log certificate info
    final X509Certificate cert = ((X509CertificateAuthenticationToken) admin).getCertificate();
    logger.paramPut(TransactionTags.ADMIN_DN.toString(), cert.getSubjectDN().toString());
    logger.paramPut(TransactionTags.ADMIN_ISSUER_DN.toString(), cert.getIssuerDN().toString());

    // Log IP address
    MessageContext msgctx = wsContext.getMessageContext();
    HttpServletRequest request = (HttpServletRequest) msgctx.get(MessageContext.SERVLET_REQUEST);
    logger.paramPut(TransactionTags.ADMIN_REMOTE_IP.toString(), request.getRemoteAddr());
    String addr = request.getHeader("X-Forwarded-For");
    if (addr != null)
        addr = addr.replaceAll("[^a-zA-Z0-9.:-_]", "?");
    logger.paramPut(TransactionTags.ADMIN_FORWARDED_IP.toString(), addr);
}

From source file:org.ejbca.core.protocol.ws.CommonEjbcaWS.java

protected void keyRecoverAny() throws Exception {
    log.trace(">keyRecoverAny");
    GlobalConfiguration gc = (GlobalConfiguration) globalConfigurationSession
            .getCachedConfiguration(GlobalConfiguration.GLOBAL_CONFIGURATION_ID);
    boolean krenabled = gc.getEnableKeyRecovery();
    if (!krenabled == true) {
        gc.setEnableKeyRecovery(true);//from   w  w w.ja  v a  2  s .c om
        globalConfigurationSession.saveConfiguration(intAdmin, gc);
    }

    // Add a new user, set token to P12, status to new and end entity
    // profile to key recovery
    UserDataVOWS user1 = new UserDataVOWS();
    user1.setKeyRecoverable(true);
    user1.setUsername("WSTESTUSERKEYREC2");
    user1.setPassword("foo456");
    user1.setClearPwd(true);
    user1.setSubjectDN("CN=WSTESTUSERKEYREC2");
    user1.setCaName(getAdminCAName());
    user1.setEmail(null);
    user1.setSubjectAltName(null);
    user1.setStatus(UserDataVOWS.STATUS_NEW);
    user1.setTokenType(UserDataVOWS.TOKEN_TYPE_P12);
    user1.setEndEntityProfileName("KEYRECOVERY");
    user1.setCertificateProfileName("ENDUSER");
    ejbcaraws.editUser(user1);

    UserMatch usermatch = new UserMatch();
    usermatch.setMatchwith(UserMatch.MATCH_WITH_USERNAME);
    usermatch.setMatchtype(UserMatch.MATCH_TYPE_EQUALS);
    usermatch.setMatchvalue("WSTESTUSERKEYREC2");

    List<java.security.KeyStore> keyStores = new ArrayList<java.security.KeyStore>();

    // generate 4 certificates
    for (int i = 0; i < 4; i++) {
        List<UserDataVOWS> userdatas = ejbcaraws.findUser(usermatch);
        assertTrue(userdatas != null);
        assertTrue(userdatas.size() == 1);
        user1 = userdatas.get(0);
        // Surely not all of these properties need to be set again?
        user1.setKeyRecoverable(true);
        user1.setUsername("WSTESTUSERKEYREC2");
        user1.setPassword("foo456");
        user1.setClearPwd(true);
        user1.setSubjectDN("CN=WSTESTUSERKEYREC2");
        user1.setCaName(getAdminCAName());
        user1.setEmail(null);
        user1.setSubjectAltName(null);
        user1.setStatus(UserDataVOWS.STATUS_NEW);
        user1.setTokenType(UserDataVOWS.TOKEN_TYPE_P12);
        user1.setEndEntityProfileName("KEYRECOVERY");
        user1.setCertificateProfileName("ENDUSER");
        ejbcaraws.editUser(user1);

        KeyStore ksenv = ejbcaraws.pkcs12Req("WSTESTUSERKEYREC2", "foo456", null, "1024",
                AlgorithmConstants.KEYALGORITHM_RSA);
        java.security.KeyStore ks = KeyStoreHelper.getKeyStore(ksenv.getKeystoreData(), "PKCS12", "foo456");
        assertNotNull(ks);
        keyStores.add(ks);
    }

    // user should have 4 certificates
    assertTrue(keyStores.size() == 4);

    // recover all keys
    for (java.security.KeyStore ks : keyStores) {
        Enumeration<String> en = ks.aliases();
        String alias = (String) en.nextElement();
        // You never know in which order the certificates in the KS are returned, it's different between java 6 and 7 for ex 
        if (!ks.isKeyEntry(alias)) {
            alias = (String) en.nextElement();
        }
        X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
        assertEquals(cert.getSubjectDN().toString(), "CN=WSTESTUSERKEYREC2");
        PrivateKey privK = (PrivateKey) ks.getKey(alias, "foo456".toCharArray());
        log.info("recovering key. sn " + cert.getSerialNumber().toString(16) + " issuer "
                + cert.getIssuerDN().toString());

        // recover key
        ejbcaraws.keyRecover("WSTESTUSERKEYREC2", cert.getSerialNumber().toString(16),
                cert.getIssuerDN().toString());

        // A new PK12 request now should return the same key and certificate
        KeyStore ksenv = ejbcaraws.pkcs12Req("WSTESTUSERKEYREC2", "foo456", null, "1024",
                AlgorithmConstants.KEYALGORITHM_RSA);
        java.security.KeyStore ks2 = KeyStoreHelper.getKeyStore(ksenv.getKeystoreData(), "PKCS12", "foo456");
        assertNotNull(ks2);
        en = ks2.aliases();
        alias = (String) en.nextElement();
        // You never know in which order the certificates in the KS are returned, it's different between java 6 and 7 for ex 
        if (!ks.isKeyEntry(alias)) {
            alias = (String) en.nextElement();
        }
        X509Certificate cert2 = (X509Certificate) ks2.getCertificate(alias);
        assertEquals(cert2.getSubjectDN().toString(), "CN=WSTESTUSERKEYREC2");
        PrivateKey privK2 = (PrivateKey) ks2.getKey(alias, "foo456".toCharArray());

        // Compare certificates
        assertEquals(cert.getSerialNumber().toString(16), cert2.getSerialNumber().toString(16));
        // Compare keys
        String key1 = new String(Hex.encode(privK.getEncoded()));
        String key2 = new String(Hex.encode(privK2.getEncoded()));
        assertEquals(key1, key2);

    }
    log.trace("<keyRecoverAny");
}

From source file:eu.stork.peps.auth.engine.STORKSAMLEngine.java

/**
 * Gets the alias from X.509 Certificate at keystore.
 * /* w  w w .  j a va 2  s.  c  o m*/
 * @param keyInfo the key info
 * @param storkOwnKeyStore 
 * @param storkOwnKeyStore 
 * 
 * @return the alias
 */
private String getAlias(final KeyInfo keyInfo, KeyStore storkOwnKeyStore) {

    LOG.debug("Recover alias information");

    String alias = null;
    try {
        final org.opensaml.xml.signature.X509Certificate xmlCert = keyInfo.getX509Datas().get(0)
                .getX509Certificates().get(0);

        // Transform the KeyInfo to X509Certificate.
        CertificateFactory certFact;
        certFact = CertificateFactory.getInstance("X.509");

        final ByteArrayInputStream bis = new ByteArrayInputStream(Base64.decode(xmlCert.getValue()));

        final X509Certificate cert = (X509Certificate) certFact.generateCertificate(bis);

        final String tokenSerialNumber = cert.getSerialNumber().toString(16);
        final X509Principal tokenIssuerDN = new X509Principal(cert.getIssuerDN().getName());

        String aliasCert;
        X509Certificate certificate;
        boolean find = false;

        for (final Enumeration<String> e = storkOwnKeyStore.aliases(); e.hasMoreElements() && !find;) {
            aliasCert = e.nextElement();
            certificate = (X509Certificate) storkOwnKeyStore.getCertificate(aliasCert);

            final String serialNum = certificate.getSerialNumber().toString(16);

            X509Principal issuerDN = new X509Principal(certificate.getIssuerDN().getName());

            if (serialNum.equalsIgnoreCase(tokenSerialNumber)
                    && X509PrincipalUtil.equals2(issuerDN, tokenIssuerDN)) {
                alias = aliasCert;
                find = true;
            }

        }

    } catch (KeyStoreException e) {
        LOG.error("Procces getAlias from certificate associated into the signing keystore..", e);
    } catch (CertificateException e) {
        LOG.error("Procces getAlias from certificate associated into the signing keystore..", e);
    } catch (RuntimeException e) {
        LOG.error("Procces getAlias from certificate associated into the signing keystore..", e);
    }
    return alias;
}

From source file:com.vmware.identity.idm.server.config.directory.DirectoryConfigStore.java

private boolean isIssuedByCert(List<Certificate> certChain, X509Certificate certToCheck) {
    if (certChain == null || certChain.isEmpty())
        return false;

    for (Certificate cert : certChain) {
        X509Certificate x509Cert = (X509Certificate) cert;
        if (x509Cert.getSubjectDN().getName().compareToIgnoreCase(certToCheck.getIssuerDN().getName()) == 0) {
            return true;
        }/*  w  ww  . j  ava 2 s.  c  o  m*/
    }

    return false;
}

From source file:net.java.sip.communicator.impl.certificate.CertificateServiceImpl.java

public X509TrustManager getTrustManager(final Iterable<String> identitiesToTest,
        final CertificateMatcher clientVerifier, final CertificateMatcher serverVerifier)
        throws GeneralSecurityException {
    // obtain the default X509 trust manager
    X509TrustManager defaultTm = null;
    TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

    //workaround for https://bugs.openjdk.java.net/browse/JDK-6672015
    KeyStore ks = null;/*from   ww w  . ja  va2s.c  o m*/
    String tsType = System.getProperty("javax.net.ssl.trustStoreType", null);
    if ("Windows-ROOT".equals(tsType)) {
        try {
            ks = KeyStore.getInstance(tsType);
            ks.load(null, null);
            int numEntries = keyStoreAppendIndex(ks);
            logger.info(
                    "Using Windows-ROOT. Aliases sucessfully renamed on " + numEntries + " root certificates.");
        } catch (Exception e) {
            logger.error("Could not rename Windows-ROOT aliases", e);
        }
    }

    tmFactory.init(ks);
    for (TrustManager m : tmFactory.getTrustManagers()) {
        if (m instanceof X509TrustManager) {
            defaultTm = (X509TrustManager) m;
            break;
        }
    }
    if (defaultTm == null)
        throw new GeneralSecurityException("No default X509 trust manager found");

    final X509TrustManager tm = defaultTm;

    return new X509TrustManager() {
        private boolean serverCheck;

        public X509Certificate[] getAcceptedIssuers() {
            return tm.getAcceptedIssuers();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            serverCheck = true;
            checkCertTrusted(chain, authType);
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            serverCheck = false;
            checkCertTrusted(chain, authType);
        }

        private void checkCertTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // check and default configurations for property
            // if missing default is null - false
            String defaultAlwaysTrustMode = CertificateVerificationActivator.getResources()
                    .getSettingsString(CertificateService.PNAME_ALWAYS_TRUST);

            if (config.getBoolean(PNAME_ALWAYS_TRUST, Boolean.parseBoolean(defaultAlwaysTrustMode)))
                return;

            try {
                // check the certificate itself (issuer, validity)
                try {
                    chain = tryBuildChain(chain);
                } catch (Exception e) {
                } // don't care and take the chain as is

                if (serverCheck)
                    tm.checkServerTrusted(chain, authType);
                else
                    tm.checkClientTrusted(chain, authType);

                if (identitiesToTest == null || !identitiesToTest.iterator().hasNext())
                    return;
                else if (serverCheck)
                    serverVerifier.verify(identitiesToTest, chain[0]);
                else
                    clientVerifier.verify(identitiesToTest, chain[0]);

                // ok, globally valid cert
            } catch (CertificateException e) {
                String thumbprint = getThumbprint(chain[0], THUMBPRINT_HASH_ALGORITHM);
                String message = null;
                List<String> propNames = new LinkedList<String>();
                List<String> storedCerts = new LinkedList<String>();
                String appName = R.getSettingsString("service.gui.APPLICATION_NAME");

                if (identitiesToTest == null || !identitiesToTest.iterator().hasNext()) {
                    String propName = PNAME_CERT_TRUST_PREFIX + ".server." + thumbprint;
                    propNames.add(propName);

                    message = R.getI18NString("service.gui." + "CERT_DIALOG_DESCRIPTION_TXT_NOHOST",
                            new String[] { appName });

                    // get the thumbprints from the permanent allowances
                    String hashes = config.getString(propName);
                    if (hashes != null)
                        for (String h : hashes.split(","))
                            storedCerts.add(h);

                    // get the thumbprints from the session allowances
                    List<String> sessionCerts = sessionAllowedCertificates.get(propName);
                    if (sessionCerts != null)
                        storedCerts.addAll(sessionCerts);
                } else {
                    if (serverCheck) {
                        message = R.getI18NString("service.gui." + "CERT_DIALOG_DESCRIPTION_TXT",
                                new String[] { appName, identitiesToTest.toString() });
                    } else {
                        message = R.getI18NString("service.gui." + "CERT_DIALOG_PEER_DESCRIPTION_TXT",
                                new String[] { appName, identitiesToTest.toString() });
                    }
                    for (String identity : identitiesToTest) {
                        String propName = PNAME_CERT_TRUST_PREFIX + ".param." + identity;
                        propNames.add(propName);

                        // get the thumbprints from the permanent allowances
                        String hashes = config.getString(propName);
                        if (hashes != null)
                            for (String h : hashes.split(","))
                                storedCerts.add(h);

                        // get the thumbprints from the session allowances
                        List<String> sessionCerts = sessionAllowedCertificates.get(propName);
                        if (sessionCerts != null)
                            storedCerts.addAll(sessionCerts);
                    }
                }

                if (!storedCerts.contains(thumbprint)) {
                    switch (verify(chain, message)) {
                    case DO_NOT_TRUST:
                        logger.info("Untrusted certificate", e);
                        throw new CertificateException("The peer provided certificate with Subject <"
                                + chain[0].getSubjectDN() + "> is not trusted", e);
                    case TRUST_ALWAYS:
                        for (String propName : propNames) {
                            String current = config.getString(propName);
                            String newValue = thumbprint;
                            if (current != null)
                                newValue += "," + current;
                            config.setProperty(propName, newValue);
                        }
                        break;
                    case TRUST_THIS_SESSION_ONLY:
                        for (String propName : propNames)
                            getSessionCertEntry(propName).add(thumbprint);
                        break;
                    }
                }
                // ok, we've seen this certificate before
            }
        }

        private X509Certificate[] tryBuildChain(X509Certificate[] chain)
                throws IOException, URISyntaxException, CertificateException {
            // Only try to build chains for servers that send only their
            // own cert, but no issuer. This also matches self signed (will
            // be ignored later) and Root-CA signed certs. In this case we
            // throw the Root-CA away after the lookup
            if (chain.length != 1)
                return chain;

            // ignore self signed certs
            if (chain[0].getIssuerDN().equals(chain[0].getSubjectDN()))
                return chain;

            // prepare for the newly created chain
            List<X509Certificate> newChain = new ArrayList<X509Certificate>(chain.length + 4);
            for (X509Certificate cert : chain) {
                newChain.add(cert);
            }

            // search from the topmost certificate upwards
            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            X509Certificate current = chain[chain.length - 1];
            boolean foundParent;
            int chainLookupCount = 0;
            do {
                foundParent = false;
                // extract the url(s) where the parent certificate can be
                // found
                byte[] aiaBytes = current.getExtensionValue(Extension.authorityInfoAccess.getId());
                if (aiaBytes == null)
                    break;

                AuthorityInformationAccess aia = AuthorityInformationAccess
                        .getInstance(X509ExtensionUtil.fromExtensionValue(aiaBytes));

                // the AIA may contain different URLs and types, try all
                // of them
                for (AccessDescription ad : aia.getAccessDescriptions()) {
                    // we are only interested in the issuer certificate,
                    // not in OCSP urls the like
                    if (!ad.getAccessMethod().equals(AccessDescription.id_ad_caIssuers))
                        continue;

                    GeneralName gn = ad.getAccessLocation();
                    if (!(gn.getTagNo() == GeneralName.uniformResourceIdentifier
                            && gn.getName() instanceof DERIA5String))
                        continue;

                    URI uri = new URI(((DERIA5String) gn.getName()).getString());
                    // only http(s) urls; LDAP is taken care of in the
                    // default implementation
                    if (!(uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equals("https")))
                        continue;

                    X509Certificate cert = null;

                    // try to get cert from cache first to avoid consecutive
                    // (slow) http lookups
                    AiaCacheEntry cache = aiaCache.get(uri);
                    if (cache != null && cache.cacheDate.after(new Date())) {
                        cert = cache.cert;
                    } else {
                        // download if no cache entry or if it is expired
                        if (logger.isDebugEnabled())
                            logger.debug("Downloading parent certificate for <" + current.getSubjectDN()
                                    + "> from <" + uri + ">");
                        try {
                            InputStream is = HttpUtils.openURLConnection(uri.toString()).getContent();
                            cert = (X509Certificate) certFactory.generateCertificate(is);
                        } catch (Exception e) {
                            logger.debug("Could not download from <" + uri + ">");
                        }
                        // cache for 10mins
                        aiaCache.put(uri,
                                new AiaCacheEntry(new Date(new Date().getTime() + 10 * 60 * 1000), cert));
                    }
                    if (cert != null) {
                        if (!cert.getIssuerDN().equals(cert.getSubjectDN())) {
                            newChain.add(cert);
                            foundParent = true;
                            current = cert;
                            break; // an AD was valid, ignore others
                        } else
                            logger.debug("Parent is self-signed, ignoring");
                    }
                }
                chainLookupCount++;
            } while (foundParent && chainLookupCount < 10);
            chain = newChain.toArray(chain);
            return chain;
        }
    };
}