All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.modules.java.base.classes.sun.security.provider.certpath.URICertStore Maven / Gradle / Ivy

There is a newer version: 2024-05-10
Show newest version
/*
 * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider.certpath;

import java.io.InputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URLConnection;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertStoreParameters;
import java.security.cert.CertStoreSpi;
import java.security.cert.CRLException;
import java.security.cert.CRLSelector;
import java.security.cert.URICertStoreParameters;
import java.security.cert.X509Certificate;
import java.security.cert.X509CRL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import sun.security.action.GetIntegerAction;
import sun.security.x509.AccessDescription;
import sun.security.x509.GeneralNameInterface;
import sun.security.x509.URIName;
import sun.security.util.Cache;
import sun.security.util.Debug;

/**
 * A CertStore that retrieves Certificates or
 * CRLs from a URI, for example, as specified in an X.509
 * AuthorityInformationAccess or CRLDistributionPoint extension.
 * 

* For CRLs, this implementation retrieves a single DER encoded CRL per URI. * For Certificates, this implementation retrieves a single DER encoded CRL or * a collection of Certificates encoded as a PKCS#7 "certs-only" CMS message. *

* This CertStore also implements Certificate/CRL caching. * Currently, the cache is shared between all applications in the VM and uses a * hardcoded policy. The cache has a maximum size of 185 entries, which are held * by SoftReferences. A request will be satisfied from the cache if we last * checked for an update within CHECK_INTERVAL (last 30 seconds). Otherwise, * we open an URLConnection to download the Certificate(s)/CRL using an * If-Modified-Since request (HTTP) if possible. Note that both positive and * negative responses are cached, i.e. if we are unable to open the connection * or the Certificate(s)/CRL cannot be parsed, we remember this result and * additional calls during the CHECK_INTERVAL period do not try to open another * connection. *

* The URICertStore is not currently a standard CertStore type. We should * consider adding a standard "URI" CertStore type. * * @author Andreas Sterbenz * @author Sean Mullan * @since 1.7 */ class URICertStore extends CertStoreSpi { private static final Debug debug = Debug.getInstance("certpath"); // interval between checks for update of cached Certificates/CRLs // (30 seconds) private static final int CHECK_INTERVAL = 30 * 1000; // size of the cache (see Cache class for sizing recommendations) private static final int CACHE_SIZE = 185; // X.509 certificate factory instance private final CertificateFactory factory; // cached Collection of X509Certificates (may be empty, never null) private Collection certs = Collections.emptySet(); // cached X509CRL (may be null) private X509CRL crl; // time we last checked for an update private long lastChecked; // time server returned as last modified time stamp // or 0 if not available private long lastModified; // the URI of this CertStore private URI uri; // true if URI is ldap private boolean ldap = false; private CertStore ldapCertStore; // Default maximum connect timeout in milliseconds (15 seconds) // allowed when downloading CRLs private static final int DEFAULT_CRL_CONNECT_TIMEOUT = 15000; /** * Integer value indicating the connect timeout, in seconds, to be * used for the CRL download. A timeout of zero is interpreted as * an infinite timeout. */ private static final int CRL_CONNECT_TIMEOUT = initializeTimeout(); /** * Initialize the timeout length by getting the CRL timeout * system property. If the property has not been set, or if its * value is negative, set the timeout length to the default. */ private static int initializeTimeout() { Integer tmp = java.security.AccessController.doPrivileged( new GetIntegerAction("com.sun.security.crl.timeout")); if (tmp == null || tmp < 0) { return DEFAULT_CRL_CONNECT_TIMEOUT; } // Convert to milliseconds, as the system property will be // specified in seconds return tmp * 1000; } /** * Creates a URICertStore. * * @param parameters specifying the URI */ URICertStore(CertStoreParameters params) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { super(params); if (!(params instanceof URICertStoreParameters)) { throw new InvalidAlgorithmParameterException ("params must be instanceof URICertStoreParameters"); } this.uri = ((URICertStoreParameters) params).getURI(); // if ldap URI, use an LDAPCertStore to fetch certs and CRLs if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals("ldap")) { ldap = true; ldapCertStore = CertStore.getInstance("LDAP", params); } try { factory = CertificateFactory.getInstance("X.509"); } catch (CertificateException e) { throw new RuntimeException(); } } /** * Returns a URI CertStore. This method consults a cache of * CertStores (shared per JVM) using the URI as a key. */ private static final Cache certStoreCache = Cache.newSoftMemoryCache(CACHE_SIZE); static synchronized CertStore getInstance(URICertStoreParameters params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { if (debug != null) { debug.println("CertStore URI:" + params.getURI()); } CertStore ucs = certStoreCache.get(params); if (ucs == null) { ucs = new UCS(new URICertStore(params), null, "URI", params); certStoreCache.put(params, ucs); } else { if (debug != null) { debug.println("URICertStore.getInstance: cache hit"); } } return ucs; } /** * Creates a CertStore from information included in the AccessDescription * object of a certificate's Authority Information Access Extension. */ static CertStore getInstance(AccessDescription ad) { if (!ad.getAccessMethod().equals( AccessDescription.Ad_CAISSUERS_Id)) { return null; } GeneralNameInterface gn = ad.getAccessLocation().getName(); if (!(gn instanceof URIName)) { return null; } URI uri = ((URIName) gn).getURI(); try { return URICertStore.getInstance(new URICertStoreParameters(uri)); } catch (Exception ex) { if (debug != null) { debug.println("exception creating CertStore: " + ex); ex.printStackTrace(); } return null; } } /** * Returns a Collection of X509Certificates that * match the specified selector. If no X509Certificates * match the selector, an empty Collection will be returned. * * @param selector a CertSelector used to select which * X509Certificates should be returned. Specify * null to return all X509Certificates. * @return a Collection of X509Certificates that * match the specified selector * @throws CertStoreException if an exception occurs */ @Override @SuppressWarnings("unchecked") public synchronized Collection engineGetCertificates (CertSelector selector) throws CertStoreException { if (ldap) { // caching mechanism, see the class description for more info. return (Collection) ldapCertStore.getCertificates(selector); } // Return the Certificates for this entry. It returns the cached value // if it is still current and fetches the Certificates otherwise. // For the caching details, see the top of this class. long time = System.currentTimeMillis(); if (time - lastChecked < CHECK_INTERVAL) { if (debug != null) { debug.println("Returning certificates from cache"); } return getMatchingCerts(certs, selector); } lastChecked = time; try { URLConnection connection = uri.toURL().openConnection(); if (lastModified != 0) { connection.setIfModifiedSince(lastModified); } long oldLastModified = lastModified; try (InputStream in = connection.getInputStream()) { lastModified = connection.getLastModified(); if (oldLastModified != 0) { if (oldLastModified == lastModified) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCerts(certs, selector); } else if (connection instanceof HttpURLConnection) { // some proxy servers omit last modified HttpURLConnection hconn = (HttpURLConnection)connection; if (hconn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCerts(certs, selector); } } } if (debug != null) { debug.println("Downloading new certificates..."); } // Safe cast since factory is an X.509 certificate factory certs = (Collection) factory.generateCertificates(in); } return getMatchingCerts(certs, selector); } catch (IOException | CertificateException e) { if (debug != null) { debug.println("Exception fetching certificates:"); e.printStackTrace(); } } // exception, forget previous values lastModified = 0; certs = Collections.emptySet(); return certs; } /** * Iterates over the specified Collection of X509Certificates and * returns only those that match the criteria specified in the * CertSelector. */ private static Collection getMatchingCerts (Collection certs, CertSelector selector) { // if selector not specified, all certs match if (selector == null) { return certs; } List matchedCerts = new ArrayList<>(certs.size()); for (X509Certificate cert : certs) { if (selector.match(cert)) { matchedCerts.add(cert); } } return matchedCerts; } /** * Returns a Collection of X509CRLs that * match the specified selector. If no X509CRLs * match the selector, an empty Collection will be returned. * * @param selector A CRLSelector used to select which * X509CRLs should be returned. Specify null * to return all X509CRLs. * @return A Collection of X509CRLs that * match the specified selector * @throws CertStoreException if an exception occurs */ @Override @SuppressWarnings("unchecked") public synchronized Collection engineGetCRLs(CRLSelector selector) throws CertStoreException { if (ldap) { // Fetch the CRLs via LDAP. LDAPCertStore has its own // caching mechanism, see the class description for more info. try { return (Collection) ldapCertStore.getCRLs(selector); } catch (CertStoreException cse) { throw new PKIX.CertStoreTypeException("LDAP", cse); } } // Return the CRLs for this entry. It returns the cached value // if it is still current and fetches the CRLs otherwise. // For the caching details, see the top of this class. long time = System.currentTimeMillis(); if (time - lastChecked < CHECK_INTERVAL) { if (debug != null) { debug.println("Returning CRL from cache"); } return getMatchingCRLs(crl, selector); } lastChecked = time; try { URLConnection connection = uri.toURL().openConnection(); if (lastModified != 0) { connection.setIfModifiedSince(lastModified); } long oldLastModified = lastModified; connection.setConnectTimeout(CRL_CONNECT_TIMEOUT); try (InputStream in = connection.getInputStream()) { lastModified = connection.getLastModified(); if (oldLastModified != 0) { if (oldLastModified == lastModified) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCRLs(crl, selector); } else if (connection instanceof HttpURLConnection) { // some proxy servers omit last modified HttpURLConnection hconn = (HttpURLConnection)connection; if (hconn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCRLs(crl, selector); } } } if (debug != null) { debug.println("Downloading new CRL..."); } crl = (X509CRL) factory.generateCRL(in); } return getMatchingCRLs(crl, selector); } catch (IOException | CRLException e) { if (debug != null) { debug.println("Exception fetching CRL:"); e.printStackTrace(); } // exception, forget previous values lastModified = 0; crl = null; throw new PKIX.CertStoreTypeException("URI", new CertStoreException(e)); } } /** * Checks if the specified X509CRL matches the criteria specified in the * CRLSelector. */ private static Collection getMatchingCRLs (X509CRL crl, CRLSelector selector) { if (selector == null || (crl != null && selector.match(crl))) { return Collections.singletonList(crl); } else { return Collections.emptyList(); } } /** * This class allows the URICertStore to be accessed as a CertStore. */ private static class UCS extends CertStore { protected UCS(CertStoreSpi spi, Provider p, String type, CertStoreParameters params) { super(spi, p, type, params); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy