/* * Copyright 1999-2010 University of Chicago * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * * See the License for the specific language governing permissions and limitations under the License. */ package org.globus.gsi.stores; import org.globus.gsi.provider.SigningPolicyStore; import org.globus.gsi.provider.SigningPolicyStoreException; import org.globus.gsi.provider.SigningPolicyStoreParameters; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; import java.io.IOException; import java.net.URI; import java.security.InvalidAlgorithmParameterException; import java.util.Collection; import java.util.HashMap; import java.util.Map; import javax.security.auth.x500.X500Principal; import org.globus.gsi.SigningPolicy; import org.globus.gsi.util.CertificateIOUtil; import org.globus.util.GlobusResource; import org.globus.util.GlobusPathMatchingResourcePatternResolver; /** * FILL ME * * @author ranantha@mcs.anl.gov */ public class ResourceSigningPolicyStore implements SigningPolicyStore { private Map<URI, ResourceSigningPolicy> signingPolicyFileMap = new HashMap<URI, ResourceSigningPolicy>(); private Map<String, SigningPolicy> policyMap = new HashMap<String, SigningPolicy>(); private ResourceSigningPolicyStoreParameters parameters; private final static Log logger = LogFactory.getLog(ResourceSigningPolicyStore.class.getCanonicalName()); private final Map<String, Long> invalidPoliciesCache = new HashMap<String, Long>(); private final Map<String, Long> validPoliciesCache = new HashMap<String, Long>(); private final static long CACHE_TIME_MILLIS = 3600*1000; /** * Please use the {@link Stores} class to generate Key/Cert stores */ public ResourceSigningPolicyStore(SigningPolicyStoreParameters param) throws InvalidAlgorithmParameterException { if (param == null) { throw new IllegalArgumentException(); } if (!(param instanceof ResourceSigningPolicyStoreParameters)) { throw new InvalidAlgorithmParameterException(); } this.parameters = (ResourceSigningPolicyStoreParameters) param; } public synchronized SigningPolicy getSigningPolicy(X500Principal caPrincipal) throws SigningPolicyStoreException { if (caPrincipal == null) { return null; } String caPrincipalName = caPrincipal.getName(); long now = System.currentTimeMillis(); String hash = CertificateIOUtil.nameHash(caPrincipal); Long validCacheTime = validPoliciesCache.get(caPrincipalName); Long invalidCacheTime = invalidPoliciesCache.get(caPrincipalName); if ((invalidCacheTime != null) && (now - invalidCacheTime < 10*CACHE_TIME_MILLIS)) { return null; } if ((validCacheTime == null) || (now - validCacheTime >= CACHE_TIME_MILLIS) || !this.policyMap.containsKey(caPrincipalName)) { loadPolicy(hash, caPrincipalName); } return this.policyMap.get(caPrincipalName); } private synchronized void loadPolicy(String hash, String caPrincipalName) throws SigningPolicyStoreException { String locations = this.parameters.getTrustRootLocations(); GlobusResource[] resources = new GlobusPathMatchingResourcePatternResolver(). getResources(locations); long now = System.currentTimeMillis(); boolean found_policy = false; // Optimization: If we find a hash for this CA, only process that. // Otherwise, we will process all policies. for (GlobusResource resource : resources) { String filename = resource.getFilename(); if (!filename.startsWith(hash)) { continue; } if (loadSigningPolicy(resource, policyMap, signingPolicyFileMap, now)) { found_policy = true; } } if (!found_policy) { // Poor-man's implementation. Note it is much more expensive than a hashed directory for (GlobusResource resource : resources) { loadSigningPolicy(resource, policyMap, signingPolicyFileMap, now); } } if (!validPoliciesCache.containsKey(caPrincipalName)) { invalidPoliciesCache.put(caPrincipalName, now); } } private boolean loadSigningPolicy( GlobusResource policyResource, Map<String, SigningPolicy> policyMapToLoad, Map<URI, ResourceSigningPolicy> currentPolicyFileMap, long currentMillis) { String filename = policyResource.getFilename(); long now = currentMillis; boolean loaded = false; Long invalidCacheTime = invalidPoliciesCache.get(filename); if ((invalidCacheTime != null) && (now - invalidCacheTime < 10 * CACHE_TIME_MILLIS)) { return false; } try { URI uri; if (!policyResource.isReadable()) { throw new SigningPolicyStoreException("file is not readable"); } try { uri = policyResource.getURI(); } catch (IOException e) { throw new SigningPolicyStoreException(e); } ResourceSigningPolicy filePolicy = this.signingPolicyFileMap.get(uri); if (filePolicy == null) { try { filePolicy = new ResourceSigningPolicy(policyResource); } catch (ResourceStoreException e) { throw new SigningPolicyStoreException(e); } } Collection<SigningPolicy> policies = filePolicy.getSigningPolicies(); currentPolicyFileMap.put(uri, filePolicy); if (policies != null) { for (SigningPolicy policy : policies) { X500Principal caPrincipal = policy.getCASubjectDN(); policyMapToLoad.put(caPrincipal.getName(), policy); validPoliciesCache.put(caPrincipal.getName(), now); } } loaded = true; } catch (SigningPolicyStoreException e) { if ((invalidCacheTime == null) || (now - invalidCacheTime >= 10 * CACHE_TIME_MILLIS)) { logger.warn("Failed to load signing policy: " + filename + " : " + e.getMessage()); logger.debug("Failed to load signing policy: " + filename, e); invalidPoliciesCache.put(filename, now); } } return loaded; } }