39
39
import java .security .cert .X509Certificate ;
40
40
import java .security .spec .DSAParameterSpec ;
41
41
import java .util .HashMap ;
42
+ import java .util .Map ;
42
43
import java .util .logging .Level ;
43
44
import java .util .logging .Logger ;
44
45
45
46
import javax .crypto .spec .DHParameterSpec ;
46
47
47
48
/**
48
49
* This is the main entry point into the Cybervillains CA.
49
- *
50
+ *
50
51
* This class handles generation, storage and the persistent mapping of input to duplicated
51
52
* certificates and mapped public keys.
52
- *
53
+ *
53
54
* Default setting is to immediately persist changes to the store by writing out the keystore and
54
55
* mapping file every time a new certificate is added. This behavior can be disabled if desired, to
55
56
* enhance performance or allow temporary testing without modifying the certificate store.
56
- *
57
- ***************************************************************************************
57
+ *
58
+ ***************************************************************************************
58
59
* Copyright (c) 2007, Information Security Partners, LLC All rights reserved.
59
- *
60
+ *
60
61
* In a special exception, Selenium/OpenQA is allowed to use this code under the Apache License 2.0.
61
- *
62
+ *
62
63
* @author Brad Hill
63
- *
64
+ *
64
65
*/
65
66
public class KeyStoreManager {
66
67
@@ -384,7 +385,7 @@ protected void createKeystore() {
384
385
385
386
/**
386
387
* Stores a new certificate and its associated private key in the keystore.
387
- *
388
+ *
388
389
* @throws KeyStoreException
389
390
* @throws CertificateException
390
391
* @throws NoSuchAlgorithmException
@@ -409,32 +410,39 @@ public synchronized void addCertAndPrivateKey(String hostname, final X509Certifi
409
410
410
411
/**
411
412
* Writes the keystore and certificate/keypair mappings to disk.
412
- *
413
+ *
413
414
* @throws KeyStoreException
414
415
* @throws NoSuchAlgorithmException
415
416
* @throws CertificateException
416
417
*/
417
418
public synchronized void persist () throws KeyStoreException , NoSuchAlgorithmException ,
418
419
CertificateException {
419
- try
420
- {
421
- FileOutputStream kso = new FileOutputStream (new File (root , _caPrivateKeystore ));
420
+ FileOutputStream kso = null ;
421
+ try {
422
+ kso = new FileOutputStream (new File (root , _caPrivateKeystore ));
422
423
_ks .store (kso , _keystorepass );
423
424
kso .flush ();
424
425
kso .close ();
425
426
persistCertMap ();
426
427
persistSubjectMap ();
427
428
persistKeyPairMap ();
428
429
persistPublicKeyMap ();
429
- } catch (IOException ioe )
430
- {
430
+ } catch (IOException ioe ) {
431
431
ioe .printStackTrace ();
432
+ } finally {
433
+ if (kso != null ) {
434
+ try {
435
+ kso .close ();
436
+ } catch (IOException e ) {
437
+ log .log (Level .WARNING , "Unable to close " + _caPrivateKeystore , e );
438
+ }
439
+ }
432
440
}
433
441
}
434
442
435
443
/**
436
444
* Returns the aliased certificate. Certificates are aliased by their SHA1 digest.
437
- *
445
+ *
438
446
* @see ThumbprintUtil
439
447
* @throws KeyStoreException
440
448
*/
@@ -445,7 +453,7 @@ public synchronized X509Certificate getCertificateByAlias(final String alias)
445
453
446
454
/**
447
455
* Returns the aliased certificate. Certificates are aliased by their hostname.
448
- *
456
+ *
449
457
* @see ThumbprintUtil
450
458
* @throws KeyStoreException
451
459
* @throws UnrecoverableKeyException
@@ -472,7 +480,7 @@ public synchronized X509Certificate getCertificateByHostname(final String hostna
472
480
473
481
/**
474
482
* Gets the authority root signing cert.
475
- *
483
+ *
476
484
* @throws KeyStoreException
477
485
*/
478
486
public synchronized X509Certificate getSigningCert () throws KeyStoreException {
@@ -481,7 +489,7 @@ public synchronized X509Certificate getSigningCert() throws KeyStoreException {
481
489
482
490
/**
483
491
* Gets the authority private signing key.
484
- *
492
+ *
485
493
* @throws KeyStoreException
486
494
* @throws NoSuchAlgorithmException
487
495
* @throws UnrecoverableKeyException
@@ -495,7 +503,7 @@ public synchronized PrivateKey getSigningPrivateKey() throws KeyStoreException,
495
503
* This method returns the mapped certificate for a hostname, or generates a "standard" SSL server
496
504
* certificate issued by the CA to the supplied subject if no mapping has been created. This is
497
505
* not a true duplication, just a shortcut method that is adequate for web browsers.
498
- *
506
+ *
499
507
* @throws CertificateParsingException
500
508
* @throws InvalidKeyException
501
509
* @throws CertificateExpiredException
@@ -544,39 +552,13 @@ private String getSubjectForHostname(String hostname) {
544
552
}
545
553
546
554
private synchronized void persistCertMap () {
547
- try {
548
- ObjectOutput out =
549
- new ObjectOutputStream (new FileOutputStream (new File (root , CERTMAP_SER_FILE )));
550
- out .writeObject (_certMap );
551
- out .flush ();
552
- out .close ();
553
- } catch (FileNotFoundException e ) {
554
- // writing, this shouldn't happen...
555
- e .printStackTrace ();
556
- } catch (IOException e ) {
557
- // big problem!
558
- e .printStackTrace ();
559
- throw new Error (e );
560
- }
555
+ persistMap (new File (root , CERTMAP_SER_FILE ), _certMap );
561
556
}
562
557
563
558
564
559
565
560
private synchronized void persistSubjectMap () {
566
- try {
567
- ObjectOutput out =
568
- new ObjectOutputStream (new FileOutputStream (new File (root , SUBJMAP_SER_FILE )));
569
- out .writeObject (_subjectMap );
570
- out .flush ();
571
- out .close ();
572
- } catch (FileNotFoundException e ) {
573
- // writing, this shouldn't happen...
574
- e .printStackTrace ();
575
- } catch (IOException e ) {
576
- // big problem!
577
- e .printStackTrace ();
578
- throw new Error (e );
579
- }
561
+ persistMap (new File (root , SUBJMAP_SER_FILE ), _subjectMap );
580
562
}
581
563
582
564
/**
@@ -591,36 +573,35 @@ public KeyPair getRSAKeyPair()
591
573
}
592
574
593
575
private synchronized void persistPublicKeyMap () {
594
- try {
595
- ObjectOutput out =
596
- new ObjectOutputStream (new FileOutputStream (new File (root , PUB_KEYMAP_SER_FILE )));
597
- out .writeObject (_mappedPublicKeys );
598
- out .flush ();
599
- out .close ();
600
- } catch (FileNotFoundException e ) {
601
- // writing, won't happen
602
- e .printStackTrace ();
603
- } catch (IOException e ) {
604
- // very bad
605
- e .printStackTrace ();
606
- throw new Error (e );
607
- }
576
+ persistMap (new File (root , PUB_KEYMAP_SER_FILE ), _mappedPublicKeys );
608
577
}
609
578
610
579
private synchronized void persistKeyPairMap () {
580
+ persistMap (new File (root , KEYMAP_SER_FILE ), _rememberedPrivateKeys );
581
+ }
582
+
583
+ private void persistMap (File outputFile , Map <?, ?> toPersist ) {
584
+ ObjectOutput out = null ;
611
585
try {
612
- ObjectOutput out =
613
- new ObjectOutputStream (new FileOutputStream (new File (root , KEYMAP_SER_FILE )));
614
- out .writeObject (_rememberedPrivateKeys );
586
+ out = new ObjectOutputStream (new FileOutputStream (outputFile ));
587
+ out .writeObject (toPersist );
615
588
out .flush ();
616
- out .close ();
617
589
} catch (FileNotFoundException e ) {
618
590
// writing, won't happen.
619
591
e .printStackTrace ();
620
592
} catch (IOException e ) {
621
593
// very bad
622
594
e .printStackTrace ();
623
595
throw new Error (e );
596
+ } finally {
597
+ if (out != null ) {
598
+ try {
599
+ out .close ();
600
+ } catch (IOException e ) {
601
+ // Nothing sane to do.
602
+ log .log (Level .WARNING , "Unable to close " + outputFile .getName (), e );
603
+ }
604
+ }
624
605
}
625
606
}
626
607
0 commit comments