001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: /*
037: * $Id: PolicyCallbackHandler1.java,v 1.6 2007/05/29 22:12:22 ofung Exp $
038: *
039: * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
040: * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
041: */
042:
043: package com.sun.xml.wss.callback;
044:
045: import java.io.IOException;
046: import java.io.FileInputStream;
047:
048: import com.sun.org.apache.xml.internal.security.utils.Base64;
049: import java.util.Enumeration;
050: import java.util.Properties;
051: import java.util.Arrays;
052: import java.util.Date;
053: import java.util.Calendar;
054: import java.util.GregorianCalendar;
055:
056: import java.text.SimpleDateFormat;
057:
058: import java.math.BigInteger;
059:
060: import java.security.KeyStore;
061: import java.security.PrivateKey;
062: import java.security.cert.CertPathBuilder;
063: import java.security.cert.Certificate;
064: import java.security.cert.CertificateExpiredException;
065: import java.security.cert.CertificateNotYetValidException;
066: import java.security.cert.PKIXBuilderParameters;
067: import java.security.cert.PKIXCertPathBuilderResult;
068: import java.security.cert.X509CertSelector;
069: import java.security.cert.X509Certificate;
070:
071: import javax.crypto.SecretKey;
072:
073: import javax.security.auth.callback.Callback;
074: import javax.security.auth.callback.CallbackHandler;
075: import javax.security.auth.callback.UnsupportedCallbackException;
076:
077: import com.sun.xml.wss.impl.callback.*;
078: import com.sun.xml.wss.impl.policy.mls.AuthenticationTokenPolicy;
079: import com.sun.xml.wss.impl.policy.SecurityPolicy;
080: import com.sun.org.apache.xml.internal.security.utils.RFC2253Parser;
081:
082: import java.security.MessageDigest;
083: import java.security.NoSuchAlgorithmException;
084: import java.security.cert.CertificateEncodingException;
085:
086: /**
087: * A sample implementation of a CallbackHandler.
088: */
089: public class PolicyCallbackHandler1 implements CallbackHandler {
090:
091: private String keyStoreURL;
092: private String keyStorePassword;
093: private String keyStoreType;
094:
095: private String trustStoreURL;
096: private String trustStorePassword;
097: private String trustStoreType;
098:
099: private String symmKeyStoreURL;
100: private String symmKeyStorePassword;
101: private String symmKeyStoreType;
102:
103: private KeyStore keyStore;
104: private KeyStore trustStore;
105: private KeyStore symmKeyStore;
106:
107: private static final String fileSeparator = System
108: .getProperty("file.separator");
109:
110: private static final UnsupportedCallbackException unsupported = new UnsupportedCallbackException(
111: null, "Unsupported Callback Type Encountered");
112:
113: public PolicyCallbackHandler1(String side) throws Exception {
114:
115: Properties properties = new Properties();
116:
117: if (side.equals("server")) {
118: String serverPropsFile = "./test/unit/data/security/keystore/server-security-env.properties";
119: properties.load(new FileInputStream(serverPropsFile));
120:
121: } else {
122: // we are on the client side
123: String clientPropsFile = "./test/unit/data/security/keystore/client-security-env.properties";
124: properties.load(new FileInputStream(clientPropsFile));
125: }
126:
127: this .keyStoreURL = properties.getProperty("keystore.url");
128: this .keyStoreType = properties.getProperty("keystore.type");
129: this .keyStorePassword = properties
130: .getProperty("keystore.password");
131:
132: this .trustStoreURL = properties.getProperty("truststore.url");
133: this .trustStoreType = properties.getProperty("truststore.type");
134: this .trustStorePassword = properties
135: .getProperty("truststore.password");
136:
137: initTrustStore();
138: initKeyStore();
139: }
140:
141: public void handle(Callback[] callbacks) throws IOException,
142: UnsupportedCallbackException {
143:
144: for (int i = 0; i < callbacks.length; i++) {
145:
146: if (callbacks[i] instanceof PasswordValidationCallback) {
147: PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];
148: if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
149: cb.setValidator(new PlainTextPasswordValidator());
150:
151: } else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
152: PasswordValidationCallback.DigestPasswordRequest request = (PasswordValidationCallback.DigestPasswordRequest) cb
153: .getRequest();
154: String username = request.getUsername();
155: if ("Ron".equals(username)) {
156: request.setPassword("noR");
157: cb
158: .setValidator(new PasswordValidationCallback.DigestPasswordValidator());
159: }
160: } else {
161: throw unsupported;
162: }
163:
164: } else if (callbacks[i] instanceof TimestampValidationCallback) {
165: TimestampValidationCallback cb = (TimestampValidationCallback) callbacks[i];
166: cb.setValidator(new DefaultTimestampValidator());
167:
168: } else if (callbacks[i] instanceof SignatureVerificationKeyCallback) {
169: SignatureVerificationKeyCallback cb = (SignatureVerificationKeyCallback) callbacks[i];
170:
171: if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
172: // subject keyid request
173: SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request = (SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
174: .getRequest();
175: if (trustStore == null)
176: initTrustStore();
177: X509Certificate cert = getCertificateFromTrustStore(request
178: .getSubjectKeyIdentifier());
179: request.setX509Certificate(cert);
180:
181: } else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) {
182: // issuer serial request
183: SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request = (SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) cb
184: .getRequest();
185: if (trustStore == null)
186: initTrustStore();
187: X509Certificate cert = getCertificateFromTrustStore(
188: request.getIssuerName(), request
189: .getSerialNumber());
190: request.setX509Certificate(cert);
191:
192: } else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.ThumbprintBasedRequest) {
193: SignatureVerificationKeyCallback.ThumbprintBasedRequest request = (SignatureVerificationKeyCallback.ThumbprintBasedRequest) cb
194: .getRequest();
195: if (trustStore == null)
196: initTrustStore();
197: X509Certificate cert = getCertificateFromTrustStoreForThumbprint(request
198: .getThumbprintIdentifier());
199: request.setX509Certificate(cert);
200:
201: } else {
202: throw unsupported;
203: }
204:
205: } else if (callbacks[i] instanceof SignatureKeyCallback) {
206: SignatureKeyCallback cb = (SignatureKeyCallback) callbacks[i];
207:
208: if (cb.getRequest() instanceof SignatureKeyCallback.DefaultPrivKeyCertRequest) {
209: // default priv key cert req
210: SignatureKeyCallback.DefaultPrivKeyCertRequest request = (SignatureKeyCallback.DefaultPrivKeyCertRequest) cb
211: .getRequest();
212: if (keyStore == null)
213: initKeyStore();
214: getDefaultPrivKeyCert(request);
215:
216: } else if (cb.getRequest() instanceof SignatureKeyCallback.AliasPrivKeyCertRequest) {
217: SignatureKeyCallback.AliasPrivKeyCertRequest request = (SignatureKeyCallback.AliasPrivKeyCertRequest) cb
218: .getRequest();
219: String alias = request.getAlias();
220: if (keyStore == null)
221: initKeyStore();
222: try {
223: X509Certificate cert = (X509Certificate) keyStore
224: .getCertificate(alias);
225: request.setX509Certificate(cert);
226: // Assuming key passwords same as the keystore password
227: PrivateKey privKey = (PrivateKey) keyStore
228: .getKey(alias, keyStorePassword
229: .toCharArray());
230: request.setPrivateKey(privKey);
231: } catch (Exception e) {
232: throw new IOException(e.getMessage());
233: }
234:
235: } else {
236: throw unsupported;
237: }
238:
239: } else if (callbacks[i] instanceof DecryptionKeyCallback) {
240: DecryptionKeyCallback cb = (DecryptionKeyCallback) callbacks[i];
241:
242: if (cb.getRequest() instanceof DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
243: DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request = (DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
244: .getRequest();
245: byte[] ski = request.getSubjectKeyIdentifier();
246: if (keyStore == null)
247: initKeyStore();
248: PrivateKey privKey = getPrivateKey(ski);
249: request.setPrivateKey(privKey);
250:
251: } else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBasedRequest) {
252: DecryptionKeyCallback.X509IssuerSerialBasedRequest request = (DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb
253: .getRequest();
254: String issuerName = request.getIssuerName();
255: BigInteger serialNumber = request.getSerialNumber();
256: if (keyStore == null)
257: initKeyStore();
258: PrivateKey privKey = getPrivateKey(issuerName,
259: serialNumber);
260: request.setPrivateKey(privKey);
261:
262: } else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBasedRequest) {
263: DecryptionKeyCallback.X509CertificateBasedRequest request = (DecryptionKeyCallback.X509CertificateBasedRequest) cb
264: .getRequest();
265: X509Certificate cert = request.getX509Certificate();
266: if (keyStore == null)
267: initKeyStore();
268: PrivateKey privKey = getPrivateKey(cert);
269: request.setPrivateKey(privKey);
270:
271: } else if (cb.getRequest() instanceof DecryptionKeyCallback.AliasSymmetricKeyRequest) {
272: DecryptionKeyCallback.AliasSymmetricKeyRequest request = (DecryptionKeyCallback.AliasSymmetricKeyRequest) cb
273: .getRequest();
274: if (symmKeyStore == null)
275: initSymmKeyStore();
276: String alias = request.getAlias();
277: try {
278: // Assuming key password same as key store password
279: SecretKey symmKey = (SecretKey) symmKeyStore
280: .getKey(alias, symmKeyStorePassword
281: .toCharArray());
282: request.setSymmetricKey(symmKey);
283: } catch (Exception e) {
284: throw new IOException(e.getMessage());
285: }
286:
287: } else if (cb.getRequest() instanceof DecryptionKeyCallback.ThumbprintBasedRequest) {
288: DecryptionKeyCallback.ThumbprintBasedRequest request = (DecryptionKeyCallback.ThumbprintBasedRequest) cb
289: .getRequest();
290: byte[] ski = request.getThumbprintIdentifier();
291: if (keyStore == null)
292: initKeyStore();
293: PrivateKey privKey = getPrivateKeyForThumbprint(ski);
294: request.setPrivateKey(privKey);
295: } else {
296: throw unsupported;
297: }
298:
299: } else if (callbacks[i] instanceof EncryptionKeyCallback) {
300: EncryptionKeyCallback cb = (EncryptionKeyCallback) callbacks[i];
301:
302: if (cb.getRequest() instanceof EncryptionKeyCallback.AliasX509CertificateRequest) {
303: EncryptionKeyCallback.AliasX509CertificateRequest request = (EncryptionKeyCallback.AliasX509CertificateRequest) cb
304: .getRequest();
305: if (trustStore == null)
306: initTrustStore();
307: String alias = request.getAlias();
308:
309: if ("".equals(alias) || (alias == null)) {
310: getDefaultCertificateFromTrustStore(request);
311: } else {
312:
313: try {
314: X509Certificate cert = (X509Certificate) trustStore
315: .getCertificate(alias);
316: request.setX509Certificate(cert);
317: } catch (Exception e) {
318: throw new IOException(e.getMessage());
319: }
320: }
321:
322: } else if (cb.getRequest() instanceof EncryptionKeyCallback.AliasSymmetricKeyRequest) {
323: EncryptionKeyCallback.AliasSymmetricKeyRequest request = (EncryptionKeyCallback.AliasSymmetricKeyRequest) cb
324: .getRequest();
325: if (symmKeyStore == null)
326: initSymmKeyStore();
327: String alias = request.getAlias();
328: try {
329: // Assuming key password same as key store password
330: SecretKey symmKey = (SecretKey) symmKeyStore
331: .getKey(alias, symmKeyStorePassword
332: .toCharArray());
333: request.setSymmetricKey(symmKey);
334: } catch (Exception e) {
335: throw new IOException(e.getMessage());
336: }
337:
338: } else {
339: throw unsupported;
340: }
341:
342: } else if (callbacks[i] instanceof CertificateValidationCallback) {
343: CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];
344: cb.setValidator(new X509CertificateValidatorImpl());
345:
346: } else if (callbacks[i] instanceof DynamicPolicyCallback) {
347: DynamicPolicyCallback dp = (DynamicPolicyCallback) callbacks[i];
348: SecurityPolicy policy = dp.getSecurityPolicy();
349: // This simplistic callback will simply set a Dummy Assertion
350: // An actual implementation can locate the saml assertion and set it
351: if (policy instanceof AuthenticationTokenPolicy.SAMLAssertionBinding) {
352:
353: AuthenticationTokenPolicy.SAMLAssertionBinding samlBinding = (AuthenticationTokenPolicy.SAMLAssertionBinding) ((AuthenticationTokenPolicy.SAMLAssertionBinding) policy)
354: .clone();
355: if ((samlBinding.getAssertion() == null)
356: && (samlBinding.getAuthorityBinding() == null)) {
357: //populateAssertion(samlBinding, dp);
358: } else if (samlBinding.getAssertion() != null) {
359: //validateSAMLAssertion(samlBinding);
360: } else if ((samlBinding.getAuthorityBinding() != null)
361: && (samlBinding.getAssertionId() != null)) {
362: //locateSAMLAssertion(samlBinding);
363: } else {
364: throw new UnsupportedCallbackException(null,
365: "Missing information from SAML Policy");
366: }
367:
368: } else {
369: throw unsupported;
370: }
371:
372: } else {
373: throw unsupported;
374: }
375: }
376: }
377:
378: private void initTrustStore() throws IOException {
379: try {
380: trustStore = KeyStore.getInstance(trustStoreType);
381: trustStore.load(new FileInputStream(trustStoreURL),
382: trustStorePassword.toCharArray());
383: } catch (Exception e) {
384: throw new IOException(e.getMessage());
385: }
386: }
387:
388: private void initKeyStore() throws IOException {
389: try {
390: keyStore = KeyStore.getInstance(keyStoreType);
391: keyStore.load(new FileInputStream(keyStoreURL),
392: keyStorePassword.toCharArray());
393: } catch (Exception e) {
394: throw new IOException(e.getMessage());
395: }
396: }
397:
398: private void initSymmKeyStore() throws IOException {
399: try {
400: symmKeyStore = KeyStore.getInstance(symmKeyStoreType);
401: symmKeyStore.load(new FileInputStream(symmKeyStoreURL),
402: symmKeyStorePassword.toCharArray());
403: } catch (Exception e) {
404: throw new IOException(e.getMessage());
405: }
406: }
407:
408: private X509Certificate getCertificateFromTrustStore(byte[] ski)
409: throws IOException {
410:
411: try {
412: Enumeration aliases = trustStore.aliases();
413: while (aliases.hasMoreElements()) {
414: String alias = (String) aliases.nextElement();
415: Certificate cert = trustStore.getCertificate(alias);
416: if (cert == null || !"X.509".equals(cert.getType())) {
417: continue;
418: }
419: X509Certificate x509Cert = (X509Certificate) cert;
420: byte[] keyId = getSubjectKeyIdentifier(x509Cert);
421: if (keyId == null) {
422: // Cert does not contain a key identifier
423: continue;
424: }
425: if (Arrays.equals(ski, keyId)) {
426: return x509Cert;
427: }
428: }
429: } catch (Exception e) {
430: throw new IOException(e.getMessage());
431: }
432: return null;
433: }
434:
435: private X509Certificate getCertificateFromTrustStore(
436: String issuerName, BigInteger serialNumber)
437: throws IOException {
438:
439: try {
440: Enumeration aliases = trustStore.aliases();
441: while (aliases.hasMoreElements()) {
442: String alias = (String) aliases.nextElement();
443: Certificate cert = trustStore.getCertificate(alias);
444: if (cert == null || !"X.509".equals(cert.getType())) {
445: continue;
446: }
447: X509Certificate x509Cert = (X509Certificate) cert;
448: String this IssuerName = RFC2253Parser
449: .normalize(x509Cert.getIssuerDN().getName());
450: BigInteger this SerialNumber = x509Cert
451: .getSerialNumber();
452: if (this IssuerName.equals(issuerName)
453: && this SerialNumber.equals(serialNumber)) {
454: return x509Cert;
455: }
456: }
457: } catch (Exception e) {
458: throw new IOException(e.getMessage());
459: }
460: return null;
461: }
462:
463: public PrivateKey getPrivateKey(byte[] ski) throws IOException {
464:
465: try {
466: Enumeration aliases = keyStore.aliases();
467: while (aliases.hasMoreElements()) {
468: String alias = (String) aliases.nextElement();
469: if (!keyStore.isKeyEntry(alias))
470: continue;
471: Certificate cert = keyStore.getCertificate(alias);
472: if (cert == null || !"X.509".equals(cert.getType())) {
473: continue;
474: }
475: X509Certificate x509Cert = (X509Certificate) cert;
476: byte[] keyId = getSubjectKeyIdentifier(x509Cert);
477: if (keyId == null) {
478: // Cert does not contain a key identifier
479: continue;
480: }
481: if (Arrays.equals(ski, keyId)) {
482: // Asuumed key password same as the keystore password
483: return (PrivateKey) keyStore.getKey(alias,
484: keyStorePassword.toCharArray());
485: }
486: }
487: } catch (Exception e) {
488: throw new IOException(e.getMessage());
489: }
490: return null;
491: }
492:
493: public PrivateKey getPrivateKey(String issuerName,
494: BigInteger serialNumber) throws IOException {
495:
496: try {
497: Enumeration aliases = keyStore.aliases();
498: while (aliases.hasMoreElements()) {
499: String alias = (String) aliases.nextElement();
500: if (!keyStore.isKeyEntry(alias))
501: continue;
502: Certificate cert = keyStore.getCertificate(alias);
503: if (cert == null || !"X.509".equals(cert.getType())) {
504: continue;
505: }
506: X509Certificate x509Cert = (X509Certificate) cert;
507: String this IssuerName = RFC2253Parser
508: .normalize(x509Cert.getIssuerDN().getName());
509: BigInteger this SerialNumber = x509Cert
510: .getSerialNumber();
511: if (this IssuerName.equals(issuerName)
512: && this SerialNumber.equals(serialNumber)) {
513: return (PrivateKey) keyStore.getKey(alias,
514: keyStorePassword.toCharArray());
515: }
516: }
517: } catch (Exception e) {
518: throw new IOException(e.getMessage());
519: }
520: return null;
521: }
522:
523: public PrivateKey getPrivateKey(X509Certificate certificate)
524: throws IOException {
525:
526: try {
527: Enumeration aliases = keyStore.aliases();
528: while (aliases.hasMoreElements()) {
529: String alias = (String) aliases.nextElement();
530: if (!keyStore.isKeyEntry(alias))
531: continue;
532: Certificate cert = keyStore.getCertificate(alias);
533: if (cert != null && cert.equals(certificate))
534: return (PrivateKey) keyStore.getKey(alias,
535: keyStorePassword.toCharArray());
536: }
537: } catch (Exception e) {
538: throw new IOException(e.getMessage());
539: }
540: return null;
541: }
542:
543: private void getDefaultCertificateFromTrustStore(
544: EncryptionKeyCallback.AliasX509CertificateRequest req)
545: throws IOException {
546:
547: try {
548: Enumeration aliases = trustStore.aliases();
549: while (aliases.hasMoreElements()) {
550: String currentAlias = (String) aliases.nextElement();
551: if (!"certificate-authority".equals(currentAlias)) {
552: X509Certificate this Certificate = (X509Certificate) trustStore
553: .getCertificate(currentAlias);
554: req.setX509Certificate(this Certificate);
555: return;
556: }
557: }
558: } catch (Exception e) {
559: throw new RuntimeException(e);
560: }
561: }
562:
563: private void getDefaultPrivKeyCert(
564: SignatureKeyCallback.DefaultPrivKeyCertRequest request)
565: throws IOException {
566:
567: String uniqueAlias = null;
568: try {
569: Enumeration aliases = keyStore.aliases();
570: while (aliases.hasMoreElements()) {
571: String currentAlias = (String) aliases.nextElement();
572: if (keyStore.isKeyEntry(currentAlias)) {
573: Certificate this Certificate = keyStore
574: .getCertificate(currentAlias);
575: if (this Certificate != null) {
576: if (this Certificate instanceof X509Certificate) {
577: if (uniqueAlias == null) {
578: uniqueAlias = currentAlias;
579: } else {
580: // Not unique!
581: uniqueAlias = null;
582: break;
583: }
584: }
585: }
586: }
587: }
588: if (uniqueAlias != null) {
589: request.setX509Certificate((X509Certificate) keyStore
590: .getCertificate(uniqueAlias));
591: request.setPrivateKey((PrivateKey) keyStore.getKey(
592: uniqueAlias, keyStorePassword.toCharArray()));
593: }
594: } catch (Exception e) {
595: throw new IOException(e.getMessage());
596: }
597: }
598:
599: private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {
600: String SUBJECT_KEY_IDENTIFIER_OID = "2.5.29.14";
601: byte[] subjectKeyIdentifier = cert
602: .getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);
603: if (subjectKeyIdentifier == null)
604: return null;
605:
606: try {
607: sun.security.x509.KeyIdentifier keyId = null;
608:
609: sun.security.util.DerValue derVal = new sun.security.util.DerValue(
610: new sun.security.util.DerInputStream(
611: subjectKeyIdentifier).getOctetString());
612:
613: keyId = new sun.security.x509.KeyIdentifier(derVal
614: .getOctetString());
615: return keyId.getIdentifier();
616: } catch (NoClassDefFoundError ncde) {
617: if (subjectKeyIdentifier == null)
618: return null;
619: byte[] dest = new byte[subjectKeyIdentifier.length - 4];
620: System.arraycopy(subjectKeyIdentifier, 4, dest, 0,
621: subjectKeyIdentifier.length - 4);
622: return dest;
623: } catch (java.io.IOException ex) {
624: //ignore
625: return null;
626: }
627: }
628:
629: private class PlainTextPasswordValidator implements
630: PasswordValidationCallback.PasswordValidator {
631:
632: public boolean validate(
633: PasswordValidationCallback.Request request)
634: throws PasswordValidationCallback.PasswordValidationException {
635:
636: PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest = (PasswordValidationCallback.PlainTextPasswordRequest) request;
637: if ("Ron".equals(plainTextRequest.getUsername())
638: && "noR".equals(plainTextRequest.getPassword())) {
639: return true;
640: }
641: return false;
642: }
643: }
644:
645: private class DefaultTimestampValidator implements
646: TimestampValidationCallback.TimestampValidator {
647:
648: public void validate(TimestampValidationCallback.Request request)
649: throws TimestampValidationCallback.TimestampValidationException {
650:
651: // validate timestamp creation and expiration time.
652: TimestampValidationCallback.UTCTimestampRequest utcTimestampRequest = (TimestampValidationCallback.UTCTimestampRequest) request;
653:
654: SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(
655: "yyyy-MM-dd'T'HH:mm:ss'Z'");
656: SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(
657: "yyyy-MM-dd'T'HH:mm:ss'.'sss'Z'");
658: Date created = null;
659: Date expired = null;
660:
661: try {
662: try {
663: created = calendarFormatter1
664: .parse(utcTimestampRequest.getCreated());
665: if (utcTimestampRequest.getExpired() != null)
666: expired = calendarFormatter1
667: .parse(utcTimestampRequest.getExpired());
668: } catch (java.text.ParseException pe) {
669: created = calendarFormatter2
670: .parse(utcTimestampRequest.getCreated());
671: if (utcTimestampRequest.getExpired() != null)
672: expired = calendarFormatter2
673: .parse(utcTimestampRequest.getExpired());
674: }
675: } catch (java.text.ParseException pe) {
676: throw new TimestampValidationCallback.TimestampValidationException(
677: pe.getMessage());
678: }
679:
680: long maxClockSkew = utcTimestampRequest.getMaxClockSkew();
681: long timestampFreshnessLimit = utcTimestampRequest
682: .getTimestampFreshnessLimit();
683:
684: // validate creation time
685: validateCreationTime(created, maxClockSkew,
686: timestampFreshnessLimit);
687:
688: // validate expiration time
689: if (expired != null)
690: validateExpirationTime(expired, maxClockSkew,
691: timestampFreshnessLimit);
692: }
693: }
694:
695: public void validateExpirationTime(Date expires, long maxClockSkew,
696: long timestampFreshnessLimit)
697: throws TimestampValidationCallback.TimestampValidationException {
698:
699: //System.out.println("Validate Expiration time called");
700: Date currentTime = getGMTDateWithSkewAdjusted(
701: new GregorianCalendar(), maxClockSkew, false);
702: if (expires.before(currentTime)) {
703: throw new TimestampValidationCallback.TimestampValidationException(
704: "The current time is ahead of the expiration time in Timestamp");
705: }
706: }
707:
708: public void validateCreationTime(Date created, long maxClockSkew,
709: long timestampFreshnessLimit)
710: throws TimestampValidationCallback.TimestampValidationException {
711:
712: //System.out.println("Validate Creation time called");
713: Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,
714: timestampFreshnessLimit);
715:
716: if (created.before(current)) {
717: throw new TimestampValidationCallback.TimestampValidationException(
718: "The creation time is older than "
719: + " currenttime - timestamp-freshness-limit - max-clock-skew");
720: }
721:
722: Date currentTime = getGMTDateWithSkewAdjusted(
723: new GregorianCalendar(), maxClockSkew, true);
724: if (currentTime.before(created)) {
725: throw new TimestampValidationCallback.TimestampValidationException(
726: "The creation time is ahead of the current time.");
727: }
728: }
729:
730: private static Date getFreshnessAndSkewAdjustedDate(
731: long maxClockSkew, long timestampFreshnessLimit) {
732: Calendar c = new GregorianCalendar();
733: long offset = c.get(Calendar.ZONE_OFFSET);
734: if (c.getTimeZone().inDaylightTime(c.getTime())) {
735: offset += c.getTimeZone().getDSTSavings();
736: }
737: long beforeTime = c.getTimeInMillis();
738: long currentTime = beforeTime - offset;
739:
740: long adjustedTime = currentTime - maxClockSkew
741: - timestampFreshnessLimit;
742: c.setTimeInMillis(adjustedTime);
743:
744: return c.getTime();
745: }
746:
747: private static Date getGMTDateWithSkewAdjusted(Calendar c,
748: long maxClockSkew, boolean addSkew) {
749: long offset = c.get(Calendar.ZONE_OFFSET);
750: if (c.getTimeZone().inDaylightTime(c.getTime())) {
751: offset += c.getTimeZone().getDSTSavings();
752: }
753: long beforeTime = c.getTimeInMillis();
754: long currentTime = beforeTime - offset;
755:
756: if (addSkew)
757: currentTime = currentTime + maxClockSkew;
758: else
759: currentTime = currentTime - maxClockSkew;
760:
761: c.setTimeInMillis(currentTime);
762: return c.getTime();
763: }
764:
765: private class X509CertificateValidatorImpl implements
766: CertificateValidationCallback.CertificateValidator {
767:
768: public boolean validate(X509Certificate certificate)
769: throws CertificateValidationCallback.CertificateValidationException {
770:
771: if (isSelfCert(certificate)) {
772: return true;
773: }
774:
775: try {
776: certificate.checkValidity();
777: } catch (CertificateExpiredException e) {
778: e.printStackTrace();
779: throw new CertificateValidationCallback.CertificateValidationException(
780: "X509Certificate Expired", e);
781: } catch (CertificateNotYetValidException e) {
782: e.printStackTrace();
783: throw new CertificateValidationCallback.CertificateValidationException(
784: "X509Certificate not yet valid", e);
785: }
786:
787: X509CertSelector certSelector = new X509CertSelector();
788: certSelector.setCertificate(certificate);
789:
790: PKIXBuilderParameters parameters;
791: CertPathBuilder builder;
792: try {
793: parameters = new PKIXBuilderParameters(trustStore,
794: certSelector);
795: parameters.setRevocationEnabled(false);
796: builder = CertPathBuilder.getInstance("PKIX");
797: } catch (Exception e) {
798: e.printStackTrace();
799: throw new CertificateValidationCallback.CertificateValidationException(
800: e.getMessage(), e);
801: }
802:
803: try {
804: PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
805: .build(parameters);
806: } catch (Exception e) {
807: e.printStackTrace();
808: return false;
809: }
810: return true;
811: }
812:
813: private boolean isSelfCert(X509Certificate cert)
814: throws CertificateValidationCallback.CertificateValidationException {
815: try {
816: if (keyStore == null)
817: initKeyStore();
818: Enumeration aliases = keyStore.aliases();
819: while (aliases.hasMoreElements()) {
820: String alias = (String) aliases.nextElement();
821: if (keyStore.isKeyEntry(alias)) {
822: X509Certificate x509Cert = (X509Certificate) keyStore
823: .getCertificate(alias);
824: if (x509Cert != null) {
825: if (x509Cert.equals(cert))
826: return true;
827: }
828: }
829: }
830: return false;
831: } catch (Exception e) {
832: e.printStackTrace();
833: throw new CertificateValidationCallback.CertificateValidationException(
834: e.getMessage(), e);
835: }
836: }
837: }
838:
839: private X509Certificate getCertificateFromTrustStoreForThumbprint(
840: byte[] ski) throws IOException {
841:
842: try {
843: Enumeration aliases = trustStore.aliases();
844: while (aliases.hasMoreElements()) {
845: String alias = (String) aliases.nextElement();
846: Certificate cert = trustStore.getCertificate(alias);
847: if (cert == null || !"X.509".equals(cert.getType())) {
848: continue;
849: }
850: X509Certificate x509Cert = (X509Certificate) cert;
851: byte[] keyId = getThumbprintIdentifier(x509Cert);
852: if (keyId == null) {
853: // Cert does not contain a key identifier
854: continue;
855: }
856: //System.out.println("Alias = " + alias + " ti=" + Base64.encode(keyId));
857: if (Arrays.equals(ski, keyId)) {
858: return x509Cert;
859: }
860: }
861: } catch (Exception e) {
862: throw new IOException(e.getMessage());
863: }
864: return null;
865: }
866:
867: public static byte[] getThumbprintIdentifier(X509Certificate cert)
868: throws Exception {
869: byte[] thumbPrintIdentifier = null;
870:
871: try {
872: thumbPrintIdentifier = MessageDigest.getInstance("SHA-1")
873: .digest(cert.getEncoded());
874: } catch (NoSuchAlgorithmException ex) {
875: throw new Exception("Digest algorithm SHA-1 not found");
876: } catch (CertificateEncodingException ex) {
877: throw new Exception(
878: "Error while getting certificate's raw content");
879: }
880: return thumbPrintIdentifier;
881: }
882:
883: public PrivateKey getPrivateKeyForThumbprint(byte[] ski)
884: throws IOException {
885:
886: try {
887: Enumeration aliases = keyStore.aliases();
888: while (aliases.hasMoreElements()) {
889: String alias = (String) aliases.nextElement();
890: if (!keyStore.isKeyEntry(alias))
891: continue;
892: Certificate cert = keyStore.getCertificate(alias);
893: if (cert == null || !"X.509".equals(cert.getType())) {
894: continue;
895: }
896: X509Certificate x509Cert = (X509Certificate) cert;
897: byte[] keyId = getThumbprintIdentifier(x509Cert);
898: if (keyId == null) {
899: // Cert does not contain a key identifier
900: continue;
901: }
902: if (Arrays.equals(ski, keyId)) {
903: // Asuumed key password same as the keystore password
904: return (PrivateKey) keyStore.getKey(alias,
905: keyStorePassword.toCharArray());
906: }
907: }
908: } catch (Exception e) {
909: throw new IOException(e.getMessage());
910: }
911: return null;
912: }
913:
914: }
|