1 18 package org.apache.geronimo.security.ca; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.IOException ; 22 import java.math.BigInteger ; 23 import java.security.PrivateKey ; 24 import java.security.PublicKey ; 25 import java.security.Signature ; 26 import java.security.cert.Certificate ; 27 import java.security.cert.CertificateFactory ; 28 import java.util.Date ; 29 30 import javax.security.auth.x500.X500Principal ; 31 32 import org.apache.commons.logging.Log; 33 import org.apache.commons.logging.LogFactory; 34 import org.apache.geronimo.gbean.AbstractName; 35 import org.apache.geronimo.gbean.GBeanInfo; 36 import org.apache.geronimo.gbean.GBeanInfoBuilder; 37 import org.apache.geronimo.gbean.GBeanLifecycle; 38 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 39 import org.apache.geronimo.kernel.Kernel; 40 import org.apache.geronimo.management.geronimo.CertificateRequestStore; 41 import org.apache.geronimo.management.geronimo.CertificateStore; 42 import org.apache.geronimo.management.geronimo.CertificateStoreException; 43 import org.apache.geronimo.management.geronimo.CertificationAuthority; 44 import org.apache.geronimo.management.geronimo.CertificationAuthorityException; 45 import org.apache.geronimo.management.geronimo.KeystoreException; 46 import org.apache.geronimo.management.geronimo.KeystoreInstance; 47 import org.apache.geronimo.system.serverinfo.ServerInfo; 48 import org.apache.geronimo.util.CaUtils; 49 import org.apache.geronimo.util.asn1.ASN1InputStream; 50 import org.apache.geronimo.util.asn1.DERBitString; 51 import org.apache.geronimo.util.asn1.DEREncodableVector; 52 import org.apache.geronimo.util.asn1.DERInteger; 53 import org.apache.geronimo.util.asn1.DERObject; 54 import org.apache.geronimo.util.asn1.DERSequence; 55 import org.apache.geronimo.util.asn1.pkcs.PKCSObjectIdentifiers; 56 import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier; 57 import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo; 58 import org.apache.geronimo.util.asn1.x509.TBSCertificateStructure; 59 import org.apache.geronimo.util.asn1.x509.Time; 60 import org.apache.geronimo.util.asn1.x509.V3TBSCertificateGenerator; 61 import org.apache.geronimo.util.asn1.x509.X509Name; 62 63 69 public class GeronimoCertificationAuthority implements CertificationAuthority, GBeanLifecycle { 70 private final static Log log = LogFactory.getLog(GeronimoCertificationAuthority.class); 71 72 private ServerInfo serverInfo; 73 private Kernel kernel; 74 private AbstractName abstractName; 75 76 private KeystoreInstance caKeystore = null; 78 private CertificateStore certStore = null; 80 private char[] password; 82 private CertificateRequestStore certReqStore = null; 84 85 private String alias; 88 private PrivateKey caPrivateKey; 90 private PublicKey caPublicKey; 92 private Certificate caCert; 94 private X509Name caName; 96 97 104 public GeronimoCertificationAuthority(ServerInfo serverInfo, KeystoreInstance caKeystore, CertificateStore certStore, CertificateRequestStore certReqStore, Kernel kernel, AbstractName abstractName) { 105 if(caKeystore == null) throw new IllegalArgumentException ("caKeystore is null."); 106 if(certStore == null) throw new IllegalArgumentException ("certStore is null"); 107 if(certReqStore == null) throw new IllegalArgumentException ("certReqStore is null"); 108 this.serverInfo = serverInfo; 109 this.kernel = kernel; 110 this.abstractName = abstractName; 111 this.caKeystore = caKeystore; 112 this.certStore = certStore; 113 this.certReqStore = certReqStore; 114 } 115 116 120 public boolean isLocked() { 121 return password == null; 122 } 123 124 127 public void lock() { 128 try { 129 caKeystore.lockKeystore(password); 130 } catch (KeystoreException e) { 131 log.error("Error locking CA.", e); 132 } 133 password = null; 134 caName = null; 135 caCert = null; 136 caPrivateKey = null; 137 alias = null; 138 } 139 140 144 public void unlock(char[] password) throws CertificationAuthorityException{ 145 try { 146 this.password = password; 147 caKeystore.unlockKeystore(password); 148 alias = caKeystore.listPrivateKeys(password)[0]; 149 caKeystore.unlockPrivateKey(alias, password, password); 150 caCert = caKeystore.getCertificate(alias, password); 151 caName = CaUtils.getSubjectX509Name(caCert); 152 caPrivateKey = caKeystore.getPrivateKey(alias, password, password); 153 caPublicKey = caCert.getPublicKey(); 154 } catch(Exception e) { 155 throw new CertificationAuthorityException("Errors in unlocking CA.", e); 156 } 157 } 158 159 163 public X500Principal getName() throws CertificationAuthorityException { 164 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 165 try { 166 return new X500Principal (caName.getEncoded()); 167 } catch (IOException e) { 168 throw new CertificationAuthorityException("Error in getting CA name.", e); 169 } 170 } 171 172 176 public Certificate getCertificate() throws CertificationAuthorityException { 177 if(caCert == null) throw new CertificationAuthorityException("CA Certificate is null. CA may be locked."); 178 try { 179 return caCert = caKeystore.getCertificate(alias, password); 180 } catch (KeystoreException e) { 181 log.error("Error getting CA's certificate.", e); 182 } 183 return null; 184 } 185 186 195 public void issueOwnCertificate(BigInteger sNo, Date validFromDate, Date validToDate, String algorithm) throws CertificationAuthorityException{ 196 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 197 try { 198 PublicKey publicKey = caCert.getPublicKey(); 199 Certificate cert = issueCertificate(getName(), publicKey, sNo, validFromDate, validToDate, algorithm); 200 caKeystore.importPKCS7Certificate(alias, CaUtils.base64Certificate(cert), password); 201 caCert = cert; 202 } catch(Exception e) { 203 throw new CertificationAuthorityException("Error in issuing own certificate.", e); 204 } 205 } 206 207 218 public Certificate issueCertificate(X500Principal subject, PublicKey publicKey, BigInteger sNo, Date validFromDate, Date validToDate, String algorithm) throws CertificationAuthorityException{ 219 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 220 try { 221 X509Name subName = CaUtils.getX509Name(subject); 222 Certificate cert = issueCertificate(subName, caName, sNo, publicKey, caPrivateKey, validFromDate, validToDate, algorithm); 223 cert.verify(caPublicKey); 224 certStore.storeCertificate(cert); 225 return cert; 226 } catch(Exception e) { 227 throw new CertificationAuthorityException("Error in issuing certificate.", e); 228 } 229 } 230 231 234 public BigInteger getHighestSerialNumber() throws CertificationAuthorityException { 235 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 236 try { 237 return certStore.getHighestSerialNumber(); 238 } catch (CertificateStoreException e) { 239 throw new CertificationAuthorityException("Error in getting highest serial number for CA.", e); 240 } 241 } 242 243 248 public boolean isCertificateIssued(BigInteger sNo) throws CertificationAuthorityException { 249 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 250 return certStore.containsCertificate(sNo); 251 } 252 253 257 public BigInteger getNextSerialNumber() throws CertificationAuthorityException { 258 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 259 try { 260 return certStore.getNextSerialNumber(); 261 } catch (CertificateStoreException e) { 262 throw new CertificationAuthorityException("Error in getting next serial number for CA.", e); 263 } 264 } 265 266 271 public Certificate getCertificate(BigInteger sNo) throws CertificationAuthorityException { 272 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 273 try { 274 return certStore.getCertificate(sNo); 275 } catch (CertificateStoreException e) { 276 throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e); 277 } 278 } 279 280 285 public String getCertificateBase64Text(BigInteger sNo) throws CertificationAuthorityException { 286 if(isLocked()) throw new CertificationAuthorityException("CA is locked."); 287 try { 288 return certStore.getCertificateBase64Text(sNo); 289 } catch (CertificateStoreException e) { 290 throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e); 291 } 292 } 293 294 306 private Certificate issueCertificate(X509Name subName, X509Name caName, BigInteger serialNum, PublicKey subPubKey, PrivateKey caPriKey, Date validFromDate, Date validToDate, String algorithm) throws Exception { 307 AlgorithmIdentifier algId = null; 308 if("MD2withRSA".equalsIgnoreCase(algorithm)) 309 algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md2WithRSAEncryption); 310 else if("MD5withRSA".equalsIgnoreCase(algorithm)) 311 algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption); 312 else if("SHA1withRSA".equalsIgnoreCase(algorithm)) 313 algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption); 314 else 315 throw new CertificationAuthorityException("Signature algorithm "+algorithm+" is not supported."); 316 317 ASN1InputStream ais = new ASN1InputStream(subPubKey.getEncoded()); 318 DERObject subPubkeyDerObj = ais.readObject(); 319 SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(subPubkeyDerObj); 320 321 V3TBSCertificateGenerator v3certGen = new V3TBSCertificateGenerator(); 324 v3certGen.setSubject(subName); 326 v3certGen.setSubjectPublicKeyInfo(subPubKeyInfo); 327 v3certGen.setIssuer(caName); 329 v3certGen.setSerialNumber(new DERInteger(serialNum)); 331 v3certGen.setStartDate(new Time(validFromDate)); 333 v3certGen.setEndDate(new Time(validToDate)); 334 v3certGen.setSignature(algId); 336 337 TBSCertificateStructure tbsCert = v3certGen.generateTBSCertificate(); 339 byte[] tobesigned = tbsCert.getEncoded(); 340 341 Signature signatureObj = Signature.getInstance(algorithm); 343 signatureObj.initSign(caPriKey); 344 signatureObj.update(tobesigned); 345 byte[] signature = signatureObj.sign(); 346 347 DEREncodableVector certDerVec = new DEREncodableVector(); 350 certDerVec.add(tbsCert); 351 certDerVec.add(algId); 352 certDerVec.add(new DERBitString(signature)); 353 DERSequence certDerSeq = new DERSequence(certDerVec); 354 byte[] certData = certDerSeq.getEncoded(); 355 356 Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream (certData)); 358 359 return certificate; 360 } 361 362 public void doFail() { 363 } 364 365 public void doStart() throws Exception { 366 if(caKeystore.isKeystoreLocked()) { 367 lock(); 368 } 369 } 370 371 public void doStop() throws Exception { 372 } 373 public static final GBeanInfo GBEAN_INFO; 374 375 static { 376 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(GeronimoCertificationAuthority.class, "CertificationAuthority"); 377 infoFactory.addAttribute("kernel", Kernel.class, false); 378 infoFactory.addAttribute("abstractName", AbstractName.class, false); 379 infoFactory.addReference("ServerInfo", ServerInfo.class, NameFactory.GERONIMO_SERVICE); 380 infoFactory.addReference("KeystoreInstance", KeystoreInstance.class, NameFactory.KEYSTORE_INSTANCE); 381 infoFactory.addReference("CertificateStore", CertificateStore.class, "CertificateStore"); 382 infoFactory.addReference("CertificateRequestStore", CertificateRequestStore.class, "CertificateRequestStore"); 383 infoFactory.addInterface(CertificationAuthority.class); 384 infoFactory.setConstructor(new String []{"ServerInfo", "KeystoreInstance", "CertificateStore", "CertificateRequestStore", "kernel", "abstractName"}); 385 386 GBEAN_INFO = infoFactory.getBeanInfo(); 387 } 388 public static GBeanInfo getGBeanInfo() { 389 return GBEAN_INFO; 390 } 391 } 392 | Popular Tags |