1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.components.crypto;
21
22 import org.apache.ws.security.WSPasswordCallback;
23 import org.apache.ws.security.WSSecurityException;
24 import org.apache.ws.security.util.Loader;
25
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.math.BigInteger;
30 import java.security.GeneralSecurityException;
31 import java.security.Key;
32 import java.security.KeyStore;
33 import java.security.KeyStoreException;
34 import java.security.MessageDigest;
35 import java.security.NoSuchAlgorithmException;
36 import java.security.NoSuchProviderException;
37 import java.security.PrivateKey;
38 import java.security.PublicKey;
39 import java.security.UnrecoverableKeyException;
40 import java.security.cert.CertPath;
41 import java.security.cert.CertPathValidator;
42 import java.security.cert.CertStore;
43 import java.security.cert.Certificate;
44 import java.security.cert.CertificateEncodingException;
45 import java.security.cert.CertificateException;
46 import java.security.cert.CertificateFactory;
47 import java.security.cert.CollectionCertStoreParameters;
48 import java.security.cert.PKIXParameters;
49 import java.security.cert.TrustAnchor;
50 import java.security.cert.X509CRL;
51 import java.security.cert.X509Certificate;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.Enumeration;
55 import java.util.HashSet;
56 import java.util.List;
57 import java.util.Properties;
58 import java.util.Set;
59
60 import javax.security.auth.callback.Callback;
61 import javax.security.auth.callback.CallbackHandler;
62 import javax.security.auth.callback.UnsupportedCallbackException;
63 import javax.security.auth.x500.X500Principal;
64
65
66
67
68
69 public class Merlin extends CryptoBase {
70
71
72
73
74 public static final String OLD_KEYSTORE_FILE =
75 "org.apache.ws.security.crypto.merlin.file";
76
77
78
79
80 public static final String CRYPTO_KEYSTORE_PROVIDER =
81 "org.apache.ws.security.crypto.merlin.keystore.provider";
82 public static final String CRYPTO_CERT_PROVIDER =
83 "org.apache.ws.security.crypto.merlin.cert.provider";
84
85
86
87
88 public static final String KEYSTORE_FILE =
89 "org.apache.ws.security.crypto.merlin.keystore.file";
90 public static final String KEYSTORE_PASSWORD =
91 "org.apache.ws.security.crypto.merlin.keystore.password";
92 public static final String KEYSTORE_TYPE =
93 "org.apache.ws.security.crypto.merlin.keystore.type";
94 public static final String KEYSTORE_ALIAS =
95 "org.apache.ws.security.crypto.merlin.keystore.alias";
96 public static final String KEYSTORE_PRIVATE_PASSWORD =
97 "org.apache.ws.security.crypto.merlin.keystore.private.password";
98
99
100
101
102 public static final String LOAD_CA_CERTS =
103 "org.apache.ws.security.crypto.merlin.load.cacerts";
104 public static final String TRUSTSTORE_FILE =
105 "org.apache.ws.security.crypto.merlin.truststore.file";
106 public static final String TRUSTSTORE_PASSWORD =
107 "org.apache.ws.security.crypto.merlin.truststore.password";
108 public static final String TRUSTSTORE_TYPE =
109 "org.apache.ws.security.crypto.merlin.truststore.type";
110
111
112
113
114 public static final String X509_CRL_FILE =
115 "org.apache.ws.security.crypto.merlin.x509crl.file";
116
117 private static final org.apache.commons.logging.Log LOG =
118 org.apache.commons.logging.LogFactory.getLog(Merlin.class);
119 private static final boolean DO_DEBUG = LOG.isDebugEnabled();
120
121 protected static CertificateFactory certFact;
122 protected Properties properties = null;
123 protected KeyStore keystore = null;
124 protected KeyStore truststore = null;
125 protected CertStore crlCertStore = null;
126 protected boolean loadCACerts = false;
127 protected boolean privatePasswordSet = false;
128
129 public Merlin() {
130
131 }
132
133 public Merlin(Properties properties)
134 throws CredentialException, IOException {
135 this(properties, Loader.getClassLoader(Merlin.class));
136 }
137
138 public Merlin(Properties properties, ClassLoader loader)
139 throws CredentialException, IOException {
140 loadProperties(properties, loader);
141 }
142
143 public void loadProperties(Properties properties)
144 throws CredentialException, IOException {
145 loadProperties(properties, Loader.getClassLoader(Merlin.class));
146 }
147
148 public void loadProperties(Properties properties, ClassLoader loader)
149 throws CredentialException, IOException {
150 if (properties == null) {
151 return;
152 }
153 this.properties = properties;
154
155
156
157 String provider = properties.getProperty(CRYPTO_KEYSTORE_PROVIDER);
158 if (provider != null) {
159 provider = provider.trim();
160 }
161 String certProvider = properties.getProperty(CRYPTO_CERT_PROVIDER);
162 if (certProvider != null) {
163 setCryptoProvider(certProvider);
164 }
165
166
167
168 String alias = properties.getProperty(KEYSTORE_ALIAS);
169 if (alias != null) {
170 alias = alias.trim();
171 defaultAlias = alias;
172 }
173 String keyStoreLocation = properties.getProperty(KEYSTORE_FILE);
174 if (keyStoreLocation == null) {
175 keyStoreLocation = properties.getProperty(OLD_KEYSTORE_FILE);
176 }
177 if (keyStoreLocation != null) {
178 keyStoreLocation = keyStoreLocation.trim();
179 InputStream is = loadInputStream(loader, keyStoreLocation);
180
181 try {
182 String passwd = properties.getProperty(KEYSTORE_PASSWORD, "security");
183 if (passwd != null) {
184 passwd = passwd.trim();
185 }
186 String type = properties.getProperty(KEYSTORE_TYPE, KeyStore.getDefaultType());
187 if (type != null) {
188 type = type.trim();
189 }
190 keystore = load(is, passwd, provider, type);
191 if (DO_DEBUG) {
192 LOG.debug(
193 "The KeyStore " + keyStoreLocation + " of type " + type
194 + " has been loaded"
195 );
196 }
197 String privatePasswd = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
198 if (privatePasswd != null) {
199 privatePasswordSet = true;
200 }
201 } finally {
202 if (is != null) {
203 is.close();
204 }
205 }
206 } else {
207 if (DO_DEBUG) {
208 LOG.debug("The KeyStore is not loaded as KEYSTORE_FILE is null");
209 }
210 }
211
212
213
214
215 String trustStoreLocation = properties.getProperty(TRUSTSTORE_FILE);
216 if (trustStoreLocation != null) {
217 trustStoreLocation = trustStoreLocation.trim();
218 InputStream is = loadInputStream(loader, trustStoreLocation);
219
220 try {
221 String passwd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit");
222 if (passwd != null) {
223 passwd = passwd.trim();
224 }
225 String type = properties.getProperty(TRUSTSTORE_TYPE, KeyStore.getDefaultType());
226 if (type != null) {
227 type = type.trim();
228 }
229 truststore = load(is, passwd, provider, type);
230 if (DO_DEBUG) {
231 LOG.debug(
232 "The TrustStore " + trustStoreLocation + " of type " + type
233 + " has been loaded"
234 );
235 }
236 loadCACerts = false;
237 } finally {
238 if (is != null) {
239 is.close();
240 }
241 }
242 } else {
243 String loadCacerts = properties.getProperty(LOAD_CA_CERTS, "false");
244 if (loadCacerts != null) {
245 loadCacerts = loadCacerts.trim();
246 }
247 if (Boolean.valueOf(loadCacerts).booleanValue()) {
248 String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
249 if (cacertsPath != null) {
250 cacertsPath = cacertsPath.trim();
251 }
252 InputStream is = new FileInputStream(cacertsPath);
253 try {
254 String cacertsPasswd = properties.getProperty(TRUSTSTORE_PASSWORD, "changeit");
255 if (cacertsPasswd != null) {
256 cacertsPasswd = cacertsPasswd.trim();
257 }
258 truststore = load(is, cacertsPasswd, null, KeyStore.getDefaultType());
259 if (DO_DEBUG) {
260 LOG.debug("CA certs have been loaded");
261 }
262 loadCACerts = true;
263 } finally {
264 if (is != null) {
265 is.close();
266 }
267 }
268 }
269 }
270
271
272
273 String crlLocation = properties.getProperty(X509_CRL_FILE);
274 if (crlLocation != null) {
275 crlLocation = crlLocation.trim();
276 InputStream is = loadInputStream(loader, crlLocation);
277
278 try {
279 CertificateFactory cf = getCertificateFactory();
280 X509CRL crl = (X509CRL)cf.generateCRL(is);
281
282 if (provider == null || provider.length() == 0) {
283 crlCertStore =
284 CertStore.getInstance(
285 "Collection",
286 new CollectionCertStoreParameters(Collections.singletonList(crl))
287 );
288 } else {
289 crlCertStore =
290 CertStore.getInstance(
291 "Collection",
292 new CollectionCertStoreParameters(Collections.singletonList(crl)),
293 provider
294 );
295 }
296 if (DO_DEBUG) {
297 LOG.debug(
298 "The CRL " + crlLocation + " has been loaded"
299 );
300 }
301 } catch (Exception e) {
302 if (DO_DEBUG) {
303 LOG.debug(e.getMessage(), e);
304 }
305 throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e);
306 } finally {
307 if (is != null) {
308 is.close();
309 }
310 }
311 }
312 }
313
314
315
316
317
318 public static InputStream loadInputStream(ClassLoader loader, String location)
319 throws CredentialException, IOException {
320 InputStream is = null;
321 if (location != null) {
322 java.net.URL url = Loader.getResource(loader, location);
323 if (url != null) {
324 is = url.openStream();
325 }
326
327
328
329
330 if (is == null) {
331 try {
332 is = new FileInputStream(location);
333 } catch (Exception e) {
334 if (DO_DEBUG) {
335 LOG.debug(e.getMessage(), e);
336 }
337 throw new CredentialException(
338 CredentialException.IO_ERROR, "proxyNotFound", new Object[]{location}, e
339 );
340 }
341 }
342 }
343 return is;
344 }
345
346
347
348
349
350
351
352
353
354 public KeyStore load(InputStream input, String storepass, String provider, String type)
355 throws CredentialException {
356 KeyStore ks = null;
357
358 try {
359 if (provider == null || provider.length() == 0) {
360 ks = KeyStore.getInstance(type);
361 } else {
362 ks = KeyStore.getInstance(type, provider);
363 }
364
365 ks.load(input, (storepass == null || storepass.length() == 0)
366 ? new char[0] : storepass.toCharArray());
367 } catch (IOException e) {
368 if (DO_DEBUG) {
369 LOG.debug(e.getMessage(), e);
370 }
371 throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e);
372 } catch (GeneralSecurityException e) {
373 if (DO_DEBUG) {
374 LOG.debug(e.getMessage(), e);
375 }
376 throw new CredentialException(CredentialException.SEC_ERROR, "secError00", e);
377 } catch (Exception e) {
378 if (DO_DEBUG) {
379 LOG.debug(e.getMessage(), e);
380 }
381 throw new CredentialException(CredentialException.FAILURE, "error00", e);
382 }
383 return ks;
384 }
385
386
387
388
389
390
391
392
393
394
395 public KeyStore getKeyStore() {
396 return keystore;
397 }
398
399
400
401
402
403
404 public void setKeyStore(KeyStore keyStore) {
405 keystore = keyStore;
406 }
407
408
409
410
411
412
413 public KeyStore getTrustStore() {
414 return truststore;
415 }
416
417
418
419
420
421
422 public void setTrustStore(KeyStore trustStore) {
423 truststore = trustStore;
424 }
425
426
427
428
429
430
431
432 public void setCRLCertStore(CertStore crlCertStore) {
433 this.crlCertStore = crlCertStore;
434 }
435
436
437
438
439
440
441
442 public CertStore getCRLCertStore() {
443 return crlCertStore;
444 }
445
446
447
448
449
450
451
452
453
454 @Override
455 public CertificateFactory getCertificateFactory() throws WSSecurityException {
456 String provider = getCryptoProvider();
457 String keyStoreProvider = null;
458 if (keystore != null) {
459 keyStoreProvider = keystore.getProvider().getName();
460 }
461
462
463
464 CertificateFactory factory = null;
465 if (provider != null) {
466 factory = certFactMap.get(provider);
467 } else if (keyStoreProvider != null) {
468 factory =
469 certFactMap.get(mapKeystoreProviderToCertProvider(keyStoreProvider));
470 if (factory == null) {
471 factory = certFactMap.get(keyStoreProvider);
472 }
473 } else {
474 factory = certFactMap.get("DEFAULT");
475 }
476 if (factory == null) {
477 try {
478 if (provider == null || provider.length() == 0) {
479 if (keyStoreProvider != null && keyStoreProvider.length() != 0) {
480 try {
481 factory =
482 CertificateFactory.getInstance(
483 "X.509", mapKeystoreProviderToCertProvider(keyStoreProvider)
484 );
485 certFactMap.put(keyStoreProvider, factory);
486 certFactMap.put(
487 mapKeystoreProviderToCertProvider(keyStoreProvider), factory
488 );
489 } catch (Exception ex) {
490 LOG.debug(ex);
491
492
493 }
494 }
495 if (factory == null) {
496 factory = CertificateFactory.getInstance("X.509");
497 certFactMap.put("DEFAULT", factory);
498 }
499 } else {
500 factory = CertificateFactory.getInstance("X.509", provider);
501 certFactMap.put(provider, factory);
502 }
503 certFactMap.put(factory.getProvider().getName(), factory);
504 } catch (CertificateException e) {
505 throw new WSSecurityException(
506 WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "unsupportedCertType",
507 null, e
508 );
509 } catch (NoSuchProviderException e) {
510 throw new WSSecurityException(
511 WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "noSecProvider",
512 null, e
513 );
514 }
515 }
516 return factory;
517 }
518
519 private String mapKeystoreProviderToCertProvider(String s) {
520 if ("SunJSSE".equals(s)) {
521 return "SUN";
522 }
523 return s;
524 }
525
526
527
528
529
530
531
532
533
534
535 @Override
536 public String getDefaultX509Identifier() throws WSSecurityException {
537 if (defaultAlias != null) {
538 return defaultAlias;
539 }
540
541 if (keystore != null) {
542 try {
543 Enumeration<String> as = keystore.aliases();
544 if (as.hasMoreElements()) {
545 String alias = as.nextElement();
546 if (!as.hasMoreElements()) {
547 defaultAlias = alias;
548 return alias;
549 }
550 }
551 } catch (KeyStoreException ex) {
552 throw new WSSecurityException(
553 WSSecurityException.FAILURE, "keystore", null, ex
554 );
555 }
556 }
557 return null;
558 }
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575 public X509Certificate[] getX509Certificates(CryptoType cryptoType) throws WSSecurityException {
576 if (cryptoType == null) {
577 return null;
578 }
579 CryptoType.TYPE type = cryptoType.getType();
580 X509Certificate[] certs = null;
581 switch (type) {
582 case ISSUER_SERIAL: {
583 certs = getX509Certificates(cryptoType.getIssuer(), cryptoType.getSerial());
584 break;
585 }
586 case THUMBPRINT_SHA1: {
587 certs = getX509Certificates(cryptoType.getBytes());
588 break;
589 }
590 case SKI_BYTES: {
591 certs = getX509CertificatesSKI(cryptoType.getBytes());
592 break;
593 }
594 case SUBJECT_DN: {
595 certs = getX509CertificatesSubjectDN(cryptoType.getSubjectDN());
596 break;
597 }
598 case ALIAS: {
599 certs = getX509Certificates(cryptoType.getAlias());
600 break;
601 }
602 }
603 return certs;
604 }
605
606
607
608
609
610
611
612
613 public String getX509Identifier(X509Certificate cert) throws WSSecurityException {
614 String identifier = null;
615
616 if (keystore != null) {
617 identifier = getIdentifier(cert, keystore);
618 }
619
620 if (identifier == null && truststore != null) {
621 identifier = getIdentifier(cert, truststore);
622 }
623
624 return identifier;
625 }
626
627
628
629
630
631
632
633
634 public PrivateKey getPrivateKey(
635 X509Certificate certificate,
636 CallbackHandler callbackHandler
637 ) throws WSSecurityException {
638 if (keystore == null) {
639 throw new WSSecurityException("The keystore is null");
640 }
641 if (callbackHandler == null) {
642 throw new WSSecurityException("The CallbackHandler is null");
643 }
644
645 String identifier = getIdentifier(certificate, keystore);
646 try {
647 if (identifier == null || !keystore.isKeyEntry(identifier)) {
648 String msg = "Cannot find key for alias: [" + identifier + "]";
649 String logMsg = createKeyStoreErrorMessage(keystore);
650 LOG.error(msg + logMsg);
651 throw new WSSecurityException(msg);
652 }
653 String password = getPassword(identifier, callbackHandler);
654 if (password == null && privatePasswordSet) {
655 password = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
656 if (password != null) {
657 password = password.trim();
658 }
659 }
660 Key keyTmp = keystore.getKey(identifier, password == null
661 ? new char[]{} : password.toCharArray());
662 if (!(keyTmp instanceof PrivateKey)) {
663 String msg = "Key is not a private key, alias: [" + identifier + "]";
664 String logMsg = createKeyStoreErrorMessage(keystore);
665 LOG.error(msg + logMsg);
666 throw new WSSecurityException(msg);
667 }
668 return (PrivateKey) keyTmp;
669 } catch (KeyStoreException ex) {
670 throw new WSSecurityException(
671 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
672 );
673 } catch (UnrecoverableKeyException ex) {
674 throw new WSSecurityException(
675 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
676 );
677 } catch (NoSuchAlgorithmException ex) {
678 throw new WSSecurityException(
679 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
680 );
681 }
682 }
683
684
685
686
687
688
689
690
691 public PrivateKey getPrivateKey(
692 String identifier,
693 String password
694 ) throws WSSecurityException {
695 if (keystore == null) {
696 throw new WSSecurityException("The keystore is null");
697 }
698 try {
699 if (identifier == null || !keystore.isKeyEntry(identifier)) {
700 String msg = "Cannot find key for alias: [" + identifier + "]";
701 String logMsg = createKeyStoreErrorMessage(keystore);
702 LOG.error(msg + logMsg);
703 throw new WSSecurityException(msg);
704 }
705 if (password == null && privatePasswordSet) {
706 password = properties.getProperty(KEYSTORE_PRIVATE_PASSWORD);
707 if (password != null) {
708 password = password.trim();
709 }
710 }
711 Key keyTmp = keystore.getKey(identifier, password == null
712 ? new char[]{} : password.toCharArray());
713 if (!(keyTmp instanceof PrivateKey)) {
714 String msg = "Key is not a private key, alias: [" + identifier + "]";
715 String logMsg = createKeyStoreErrorMessage(keystore);
716 LOG.error(msg + logMsg);
717 throw new WSSecurityException(msg);
718 }
719 return (PrivateKey) keyTmp;
720 } catch (KeyStoreException ex) {
721 throw new WSSecurityException(
722 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
723 );
724 } catch (UnrecoverableKeyException ex) {
725 throw new WSSecurityException(
726 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
727 );
728 } catch (NoSuchAlgorithmException ex) {
729 throw new WSSecurityException(
730 WSSecurityException.FAILURE, "noPrivateKey", new Object[]{ex.getMessage()}, ex
731 );
732 }
733 }
734
735
736
737
738
739
740
741
742
743 @Deprecated
744 public boolean verifyTrust(X509Certificate[] certs) throws WSSecurityException {
745 return verifyTrust(certs, false);
746 }
747
748
749
750
751
752
753
754
755
756
757 public boolean verifyTrust(
758 X509Certificate[] certs,
759 boolean enableRevocation
760 ) throws WSSecurityException {
761 try {
762
763 List<X509Certificate> certList = Arrays.asList(certs);
764 CertPath path = getCertificateFactory().generateCertPath(certList);
765
766 Set<TrustAnchor> set = new HashSet<TrustAnchor>();
767 if (truststore != null) {
768 Enumeration<String> truststoreAliases = truststore.aliases();
769 while (truststoreAliases.hasMoreElements()) {
770 String alias = truststoreAliases.nextElement();
771 X509Certificate cert =
772 (X509Certificate) truststore.getCertificate(alias);
773 if (cert != null) {
774 TrustAnchor anchor =
775 new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
776 set.add(anchor);
777 }
778 }
779 }
780
781
782
783
784
785
786 if (keystore != null && (truststore == null || loadCACerts)) {
787 Enumeration<String> aliases = keystore.aliases();
788 while (aliases.hasMoreElements()) {
789 String alias = aliases.nextElement();
790 X509Certificate cert =
791 (X509Certificate) keystore.getCertificate(alias);
792 if (cert != null) {
793 TrustAnchor anchor =
794 new TrustAnchor(cert, cert.getExtensionValue(NAME_CONSTRAINTS_OID));
795 set.add(anchor);
796 }
797 }
798 }
799
800 PKIXParameters param = new PKIXParameters(set);
801 param.setRevocationEnabled(enableRevocation);
802 if (enableRevocation && crlCertStore != null) {
803 param.addCertStore(crlCertStore);
804 }
805
806
807 String provider = getCryptoProvider();
808 CertPathValidator validator = null;
809 if (provider == null || provider.length() == 0) {
810 validator = CertPathValidator.getInstance("PKIX");
811 } else {
812 validator = CertPathValidator.getInstance("PKIX", provider);
813 }
814 validator.validate(path, param);
815 return true;
816 } catch (java.security.NoSuchProviderException e) {
817 throw new WSSecurityException(
818 WSSecurityException.FAILURE, "certpath",
819 new Object[] { e.getMessage() }, e
820 );
821 } catch (java.security.NoSuchAlgorithmException e) {
822 throw new WSSecurityException(
823 WSSecurityException.FAILURE,
824 "certpath", new Object[] { e.getMessage() },
825 e
826 );
827 } catch (java.security.cert.CertificateException e) {
828 throw new WSSecurityException(
829 WSSecurityException.FAILURE, "certpath",
830 new Object[] { e.getMessage() }, e
831 );
832 } catch (java.security.InvalidAlgorithmParameterException e) {
833 throw new WSSecurityException(
834 WSSecurityException.FAILURE, "certpath",
835 new Object[] { e.getMessage() }, e
836 );
837 } catch (java.security.cert.CertPathValidatorException e) {
838 throw new WSSecurityException(
839 WSSecurityException.FAILURE, "certpath",
840 new Object[] { e.getMessage() }, e
841 );
842 } catch (java.security.KeyStoreException e) {
843 throw new WSSecurityException(
844 WSSecurityException.FAILURE, "certpath",
845 new Object[] { e.getMessage() }, e
846 );
847 } catch (NullPointerException e) {
848
849 throw new WSSecurityException(
850 WSSecurityException.FAILURE, "certpath",
851 new Object[] { e.getMessage() }, e
852 );
853 }
854 }
855
856
857
858
859
860
861
862 public boolean verifyTrust(PublicKey publicKey) throws WSSecurityException {
863
864
865
866 if (publicKey == null) {
867 return false;
868 }
869
870
871
872
873 boolean trust = findPublicKeyInKeyStore(publicKey, keystore);
874 if (trust) {
875 return true;
876 } else {
877
878
879
880 trust = findPublicKeyInKeyStore(publicKey, truststore);
881 if (trust) {
882 return true;
883 }
884 }
885 return false;
886 }
887
888
889
890
891
892
893
894
895
896 private X509Certificate[] getX509Certificates(
897 String issuer,
898 BigInteger serialNumber
899 ) throws WSSecurityException {
900
901
902
903
904
905
906
907
908 Object issuerName = null;
909 try {
910 X500Principal issuerRDN = new X500Principal(issuer);
911 issuerName = createBCX509Name(issuerRDN.getName());
912 } catch (java.lang.IllegalArgumentException ex) {
913 issuerName = createBCX509Name(issuer);
914 }
915 Certificate[] certs = null;
916 if (keystore != null) {
917 certs = getCertificates(issuerName, serialNumber, keystore);
918 }
919
920
921 if ((certs == null || certs.length == 0) && truststore != null) {
922 certs = getCertificates(issuerName, serialNumber, truststore);
923 }
924
925 if ((certs == null || certs.length == 0)) {
926 return null;
927 }
928
929 X509Certificate[] x509certs = new X509Certificate[certs.length];
930 for (int i = 0; i < certs.length; i++) {
931 x509certs[i] = (X509Certificate) certs[i];
932 }
933 return x509certs;
934 }
935
936
937
938
939
940
941
942
943 private Certificate[] getCertificates(
944 Object issuerRDN,
945 BigInteger serialNumber,
946 KeyStore store
947 ) throws WSSecurityException {
948 try {
949 for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
950 String alias = e.nextElement();
951 Certificate cert = null;
952 Certificate[] certs = store.getCertificateChain(alias);
953 if (certs == null || certs.length == 0) {
954
955 cert = store.getCertificate(alias);
956 if (cert == null) {
957 continue;
958 }
959 certs = new Certificate[]{cert};
960 } else {
961 cert = certs[0];
962 }
963 if (cert instanceof X509Certificate) {
964 X509Certificate x509cert = (X509Certificate) cert;
965 if (x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
966 Object certName =
967 createBCX509Name(x509cert.getIssuerX500Principal().getName());
968 if (certName.equals(issuerRDN)) {
969 return certs;
970 }
971 }
972 }
973 }
974 } catch (KeyStoreException e) {
975 throw new WSSecurityException(
976 WSSecurityException.FAILURE, "keystore", null, e
977 );
978 }
979 return new Certificate[]{};
980 }
981
982
983
984
985
986
987
988
989 private X509Certificate[] getX509Certificates(byte[] thumbprint) throws WSSecurityException {
990 MessageDigest sha = null;
991
992 try {
993 sha = MessageDigest.getInstance("SHA1");
994 } catch (NoSuchAlgorithmException e) {
995 throw new WSSecurityException(
996 WSSecurityException.FAILURE, "noSHA1availabe", null, e
997 );
998 }
999 Certificate[] certs = null;
1000 if (keystore != null) {
1001 certs = getCertificates(thumbprint, keystore, sha);
1002 }
1003
1004
1005 if ((certs == null || certs.length == 0) && truststore != null) {
1006 certs = getCertificates(thumbprint, truststore, sha);
1007 }
1008
1009 if ((certs == null || certs.length == 0)) {
1010 return null;
1011 }
1012
1013 X509Certificate[] x509certs = new X509Certificate[certs.length];
1014 for (int i = 0; i < certs.length; i++) {
1015 x509certs[i] = (X509Certificate) certs[i];
1016 }
1017 return x509certs;
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027 private Certificate[] getCertificates(
1028 byte[] thumbprint,
1029 KeyStore store,
1030 MessageDigest sha
1031 ) throws WSSecurityException {
1032 try {
1033 for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1034 String alias = e.nextElement();
1035 Certificate cert = null;
1036 Certificate[] certs = store.getCertificateChain(alias);
1037 if (certs == null || certs.length == 0) {
1038
1039 cert = store.getCertificate(alias);
1040 if (cert == null) {
1041 continue;
1042 }
1043 certs = new Certificate[]{cert};
1044 } else {
1045 cert = certs[0];
1046 }
1047 if (cert instanceof X509Certificate) {
1048 X509Certificate x509cert = (X509Certificate) cert;
1049 try {
1050 sha.update(x509cert.getEncoded());
1051 } catch (CertificateEncodingException ex) {
1052 throw new WSSecurityException(
1053 WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError",
1054 null, ex
1055 );
1056 }
1057 byte[] data = sha.digest();
1058
1059 if (Arrays.equals(data, thumbprint)) {
1060 return certs;
1061 }
1062 }
1063 }
1064 } catch (KeyStoreException e) {
1065 throw new WSSecurityException(
1066 WSSecurityException.FAILURE, "keystore", null, e
1067 );
1068 }
1069 return new Certificate[]{};
1070 }
1071
1072
1073
1074
1075
1076
1077
1078 private X509Certificate[] getX509CertificatesSKI(byte[] skiBytes) throws WSSecurityException {
1079 Certificate[] certs = null;
1080 if (keystore != null) {
1081 certs = getCertificates(skiBytes, keystore);
1082 }
1083
1084
1085 if ((certs == null || certs.length == 0) && truststore != null) {
1086 certs = getCertificates(skiBytes, truststore);
1087 }
1088
1089 if ((certs == null || certs.length == 0)) {
1090 return null;
1091 }
1092
1093 X509Certificate[] x509certs = new X509Certificate[certs.length];
1094 for (int i = 0; i < certs.length; i++) {
1095 x509certs[i] = (X509Certificate) certs[i];
1096 }
1097 return x509certs;
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107 private Certificate[] getCertificates(
1108 byte[] skiBytes,
1109 KeyStore store
1110 ) throws WSSecurityException {
1111 try {
1112 for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1113 String alias = e.nextElement();
1114 Certificate cert = null;
1115 Certificate[] certs = store.getCertificateChain(alias);
1116 if (certs == null || certs.length == 0) {
1117
1118 cert = store.getCertificate(alias);
1119 if (cert == null) {
1120 continue;
1121 }
1122 certs = new Certificate[]{cert};
1123 } else {
1124 cert = certs[0];
1125 }
1126 if (cert instanceof X509Certificate) {
1127 X509Certificate x509cert = (X509Certificate) cert;
1128 byte[] data = getSKIBytesFromCert(x509cert);
1129 if (data.length == skiBytes.length && Arrays.equals(data, skiBytes)) {
1130 return certs;
1131 }
1132 }
1133 }
1134 } catch (KeyStoreException e) {
1135 throw new WSSecurityException(
1136 WSSecurityException.FAILURE, "keystore", null, e
1137 );
1138 }
1139 return new Certificate[]{};
1140 }
1141
1142
1143
1144
1145
1146
1147
1148
1149 private X509Certificate[] getX509CertificatesSubjectDN(String subjectDN) throws WSSecurityException {
1150
1151
1152
1153
1154
1155
1156
1157
1158 Object subject;
1159 try {
1160 X500Principal subjectRDN = new X500Principal(subjectDN);
1161 subject = createBCX509Name(subjectRDN.getName());
1162 } catch (java.lang.IllegalArgumentException ex) {
1163 subject = createBCX509Name(subjectDN);
1164 }
1165
1166 Certificate[] certs = null;
1167 if (keystore != null) {
1168 certs = getCertificates(subject, keystore);
1169 }
1170
1171
1172 if ((certs == null || certs.length == 0) && truststore != null) {
1173 certs = getCertificates(subject, truststore);
1174 }
1175
1176 if ((certs == null || certs.length == 0)) {
1177 return null;
1178 }
1179
1180 X509Certificate[] x509certs = new X509Certificate[certs.length];
1181 for (int i = 0; i < certs.length; i++) {
1182 x509certs[i] = (X509Certificate) certs[i];
1183 }
1184 return x509certs;
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194 private X509Certificate[] getX509Certificates(String identifier) throws WSSecurityException {
1195 Certificate[] certs = null;
1196 try {
1197 if (keystore != null) {
1198
1199 certs = keystore.getCertificateChain(identifier);
1200 if (certs == null || certs.length == 0) {
1201
1202 Certificate cert = keystore.getCertificate(identifier);
1203 if (cert != null) {
1204 certs = new Certificate[]{cert};
1205 }
1206 }
1207 }
1208
1209 if (certs == null && truststore != null) {
1210
1211 certs = truststore.getCertificateChain(identifier);
1212 if (certs == null) {
1213 Certificate cert = truststore.getCertificate(identifier);
1214 if (cert != null) {
1215 certs = new Certificate[]{cert};
1216 }
1217 }
1218 }
1219
1220 if (certs == null) {
1221 return null;
1222 }
1223 } catch (KeyStoreException e) {
1224 throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
1225 }
1226
1227 X509Certificate[] x509certs = new X509Certificate[certs.length];
1228 for (int i = 0; i < certs.length; i++) {
1229 x509certs[i] = (X509Certificate) certs[i];
1230 }
1231 return x509certs;
1232 }
1233
1234
1235
1236
1237 private boolean findPublicKeyInKeyStore(PublicKey publicKey, KeyStore keyStoreToSearch) {
1238 if (keyStoreToSearch == null) {
1239 return false;
1240 }
1241 try {
1242 for (Enumeration<String> e = keyStoreToSearch.aliases(); e.hasMoreElements();) {
1243 String alias = e.nextElement();
1244 Certificate[] certs = keyStoreToSearch.getCertificateChain(alias);
1245 Certificate cert;
1246 if (certs == null || certs.length == 0) {
1247
1248 cert = keyStoreToSearch.getCertificate(alias);
1249 if (cert == null) {
1250 continue;
1251 }
1252 } else {
1253 cert = certs[0];
1254 }
1255 if (!(cert instanceof X509Certificate)) {
1256 continue;
1257 }
1258 X509Certificate x509cert = (X509Certificate) cert;
1259 if (publicKey.equals(x509cert.getPublicKey())) {
1260 return true;
1261 }
1262 }
1263 } catch (KeyStoreException e) {
1264 return false;
1265 }
1266 return false;
1267 }
1268
1269
1270
1271
1272
1273
1274
1275
1276 private Certificate[] getCertificates(Object subjectRDN, KeyStore store)
1277 throws WSSecurityException {
1278 try {
1279 for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1280 String alias = e.nextElement();
1281 Certificate cert = null;
1282 Certificate[] certs = store.getCertificateChain(alias);
1283 if (certs == null || certs.length == 0) {
1284
1285 cert = store.getCertificate(alias);
1286 if (cert == null) {
1287 continue;
1288 }
1289 certs = new Certificate[]{cert};
1290 } else {
1291 cert = certs[0];
1292 }
1293 if (cert instanceof X509Certificate) {
1294 X500Principal foundRDN = ((X509Certificate) cert).getSubjectX500Principal();
1295 Object certName = createBCX509Name(foundRDN.getName());
1296
1297 if (subjectRDN.equals(certName)) {
1298 return certs;
1299 }
1300 }
1301 }
1302 } catch (KeyStoreException e) {
1303 throw new WSSecurityException(
1304 WSSecurityException.FAILURE, "keystore", null, e
1305 );
1306 }
1307 return new Certificate[]{};
1308 }
1309
1310 private static String createKeyStoreErrorMessage(KeyStore keystore) throws KeyStoreException {
1311 Enumeration<String> aliases = keystore.aliases();
1312 StringBuilder sb = new StringBuilder(keystore.size() * 7);
1313 boolean firstAlias = true;
1314 while (aliases.hasMoreElements()) {
1315 if (!firstAlias) {
1316 sb.append(", ");
1317 }
1318 sb.append(aliases.nextElement());
1319 firstAlias = false;
1320 }
1321 String msg = " in keystore of type [" + keystore.getType()
1322 + "] from provider [" + keystore.getProvider()
1323 + "] with size [" + keystore.size() + "] and aliases: {"
1324 + sb.toString() + "}";
1325 return msg;
1326 }
1327
1328
1329
1330
1331
1332
1333
1334
1335 private String getIdentifier(X509Certificate cert, KeyStore store)
1336 throws WSSecurityException {
1337 try {
1338 for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
1339 String alias = e.nextElement();
1340
1341 Certificate[] certs = store.getCertificateChain(alias);
1342 Certificate retrievedCert = null;
1343 if (certs == null || certs.length == 0) {
1344
1345 retrievedCert = store.getCertificate(alias);
1346 if (retrievedCert == null) {
1347 continue;
1348 }
1349 } else {
1350 retrievedCert = certs[0];
1351 }
1352 if (!(retrievedCert instanceof X509Certificate)) {
1353 continue;
1354 }
1355 if (retrievedCert.equals(cert)) {
1356 return alias;
1357 }
1358 }
1359 } catch (KeyStoreException e) {
1360 throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
1361 }
1362 return null;
1363 }
1364
1365
1366
1367
1368
1369
1370
1371
1372 private String getPassword(
1373 String identifier,
1374 CallbackHandler cb
1375 ) throws WSSecurityException {
1376 WSPasswordCallback pwCb =
1377 new WSPasswordCallback(identifier, WSPasswordCallback.DECRYPT);
1378 try {
1379 Callback[] callbacks = new Callback[]{pwCb};
1380 cb.handle(callbacks);
1381 } catch (IOException e) {
1382 throw new WSSecurityException(
1383 WSSecurityException.FAILURE,
1384 "noPassword",
1385 new Object[]{identifier},
1386 e
1387 );
1388 } catch (UnsupportedCallbackException e) {
1389 throw new WSSecurityException(
1390 WSSecurityException.FAILURE,
1391 "noPassword",
1392 new Object[]{identifier},
1393 e
1394 );
1395 }
1396
1397 return pwCb.getPassword();
1398 }
1399
1400
1401 }