001/* 002 * $HeadURL: file:///opt/dev/not-yet-commons-ssl-SVN-repo/tags/commons-ssl-0.3.17/src/java/org/apache/commons/ssl/TrustChain.java $ 003 * $Revision: 138 $ 004 * $Date: 2008-03-03 23:50:07 -0800 (Mon, 03 Mar 2008) $ 005 * 006 * ==================================================================== 007 * Licensed to the Apache Software Foundation (ASF) under one 008 * or more contributor license agreements. See the NOTICE file 009 * distributed with this work for additional information 010 * regarding copyright ownership. The ASF licenses this file 011 * to you under the Apache License, Version 2.0 (the 012 * "License"); you may not use this file except in compliance 013 * with the License. You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, 018 * software distributed under the License is distributed on an 019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 020 * KIND, either express or implied. See the License for the 021 * specific language governing permissions and limitations 022 * under the License. 023 * ==================================================================== 024 * 025 * This software consists of voluntary contributions made by many 026 * individuals on behalf of the Apache Software Foundation. For more 027 * information on the Apache Software Foundation, please see 028 * <http://www.apache.org/>. 029 * 030 */ 031 032package org.apache.commons.ssl; 033 034import java.io.IOException; 035import java.security.KeyStore; 036import java.security.KeyStoreException; 037import java.security.NoSuchAlgorithmException; 038import java.security.cert.CertificateException; 039import java.security.cert.X509Certificate; 040import java.util.Collections; 041import java.util.Enumeration; 042import java.util.HashSet; 043import java.util.Iterator; 044import java.util.Set; 045import java.util.SortedSet; 046import java.util.TreeSet; 047 048/** 049 * @author Credit Union Central of British Columbia 050 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a> 051 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a> 052 * @since 27-Feb-2006 053 */ 054public class TrustChain { 055 private final Set trustMaterial = 056 Collections.synchronizedSet(new HashSet()); 057 private SortedSet x509Certificates = null; 058 private KeyStore unifiedKeyStore = null; 059 060 public TrustChain() { 061 } 062 063 public synchronized KeyStore getUnifiedKeyStore() 064 throws KeyStoreException, IOException, NoSuchAlgorithmException, 065 CertificateException { 066 067 // x509Certificates serves as our "cache available" indicator. 068 if (x509Certificates != null) { 069 return unifiedKeyStore; 070 } 071 072 // First, extract all the X509Certificates from this TrustChain. 073 this.x509Certificates = new TreeSet(Certificates.COMPARE_BY_EXPIRY); 074 Iterator it = trustMaterial.iterator(); 075 while (it.hasNext()) { 076 TrustMaterial tm = (TrustMaterial) it.next(); 077 KeyStore ks = tm.getKeyStore(); 078 if (ks != null) { 079 Enumeration en = ks.aliases(); 080 while (en.hasMoreElements()) { 081 String alias = (String) en.nextElement(); 082 if (ks.isCertificateEntry(alias)) { 083 X509Certificate cert; 084 cert = (X509Certificate) ks.getCertificate(alias); 085 if (!x509Certificates.contains(cert)) { 086 x509Certificates.add(cert); 087 } 088 } 089 } 090 } 091 } 092 093 // Now that the X509Certificates are extracted, create the unified 094 // keystore. 095 it = x509Certificates.iterator(); 096 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 097 ks.load(null, null); 098 int count = 0; 099 while (it.hasNext()) { 100 X509Certificate cert = (X509Certificate) it.next(); 101 // The "count" should keep the aliases unique (is that important?) 102 String alias = "commons-ssl-" + count; 103 ks.setCertificateEntry(alias, cert); 104 count++; 105 } 106 this.unifiedKeyStore = ks; 107 return unifiedKeyStore; 108 } 109 110 public synchronized void addTrustMaterial(TrustChain tc) { 111 this.x509Certificates = null; // invalidate cache 112 if (tc instanceof TrustMaterial) { 113 trustMaterial.add(tc); 114 } 115 // If duplicates are added, the Set will remove them. 116 trustMaterial.addAll(tc.trustMaterial); 117 } 118 119 public boolean contains(TrustChain tc) { 120 if (tc instanceof TrustMaterial) { 121 return trustMaterial.contains(tc); 122 } else { 123 return trustMaterial.containsAll(tc.trustMaterial); 124 } 125 } 126 127 public boolean contains(X509Certificate cert) 128 throws KeyStoreException, IOException, NoSuchAlgorithmException, 129 CertificateException { 130 return getCertificates().contains(cert); 131 } 132 133 public Object getTrustManagerFactory() 134 throws NoSuchAlgorithmException, KeyStoreException, IOException, 135 CertificateException { 136 KeyStore uks = getUnifiedKeyStore(); 137 if (uks != null) { 138 return JavaImpl.newTrustManagerFactory(uks); 139 } else { 140 return null; 141 } 142 } 143 144 /** 145 * @return Array of TrustManager[] - presumably these will be dropped into 146 * a call to SSLContext.init(). Note: returns null if this 147 * TrustChain doesn't contain anything to trust. 148 * @throws NoSuchAlgorithmException serious problems 149 * @throws KeyStoreException serious problems 150 * @throws IOException serious problems 151 * @throws CertificateException serious problems 152 */ 153 public Object[] getTrustManagers() 154 throws NoSuchAlgorithmException, KeyStoreException, IOException, 155 CertificateException { 156 Object tmf = getTrustManagerFactory(); 157 return tmf != null ? JavaImpl.getTrustManagers(tmf) : null; 158 } 159 160 /** 161 * @return All X509Certificates contained in this TrustChain as a SortedSet. 162 * The X509Certificates are sorted based on expiry date. 163 * <p/> 164 * See org.apache.commons.ssl.Certificates.COMPARE_BY_EXPIRY. 165 * @throws KeyStoreException serious problems 166 * @throws IOException serious problems 167 * @throws NoSuchAlgorithmException serious problems 168 * @throws CertificateException serious problems 169 */ 170 public synchronized SortedSet getCertificates() 171 throws KeyStoreException, IOException, NoSuchAlgorithmException, 172 CertificateException { 173 if (x509Certificates == null) { 174 getUnifiedKeyStore(); 175 } 176 return Collections.unmodifiableSortedSet(x509Certificates); 177 } 178 179 /** 180 * @return Count of all X509Certificates contained in this TrustChain. 181 * @throws KeyStoreException 182 * @throws IOException 183 * @throws NoSuchAlgorithmException 184 * @throws CertificateException 185 */ 186 public synchronized int getSize() 187 throws KeyStoreException, IOException, NoSuchAlgorithmException, 188 CertificateException { 189 return getCertificates().size(); 190 } 191 192 /** 193 * @return Count of all X509Certificates contained in this TrustChain. 194 * @throws KeyStoreException 195 * @throws IOException 196 * @throws NoSuchAlgorithmException 197 * @throws CertificateException 198 */ 199 public synchronized boolean isEmpty() 200 throws KeyStoreException, IOException, NoSuchAlgorithmException, 201 CertificateException { 202 return getCertificates().isEmpty(); 203 } 204 205 protected boolean containsTrustAll() { 206 Iterator it = trustMaterial.iterator(); 207 while (it.hasNext()) { 208 TrustChain tc = (TrustChain) it.next(); 209 if (tc == this) { 210 continue; 211 } 212 if (tc.containsTrustAll()) { 213 return true; 214 } 215 } 216 return false; 217 } 218 219}