001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)PrivateKeyCallbackHandler.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: /**
030: * PrivateKeyCallbackHandler.java
031: *
032: * SUN PROPRIETARY/CONFIDENTIAL.
033: * This software is the proprietary information of Sun Microsystems, Inc.
034: * Use is subject to license terms.
035: *
036: * Created on February 23, 2005, 11:31 AM
037: */package com.sun.jbi.internal.security.callback;
038:
039: import com.sun.enterprise.security.jauth.callback.PrivateKeyCallback;
040: import com.sun.jbi.internal.security.KeyStoreManager;
041:
042: import java.io.IOException;
043: import java.security.cert.Certificate;
044: import java.security.cert.X509Certificate;
045: import java.security.Key;
046: import java.security.KeyStore;
047: import java.security.PrivateKey;
048:
049: import javax.security.auth.callback.Callback;
050: import javax.security.auth.callback.CallbackHandler;
051: import javax.security.auth.callback.UnsupportedCallbackException;
052:
053: /**
054: *
055: * @author Sun Microsystems, Inc.
056: */
057: public class PrivateKeyCallbackHandler implements CallbackHandler {
058: /** The reference to the KeyStoreManager. */
059: private KeyStoreManager mKeyMgr;
060:
061: /** The X509 Certificate Type. */
062: private static final String X509 = "X.509";
063:
064: /**
065: * Creates a new instance of PrivateKeyCallbackHandler.
066: *
067: * @param mgr - KeyStoreManager instance which provides the handle
068: * to the KeyStores.
069: */
070: public PrivateKeyCallbackHandler(KeyStoreManager mgr) {
071: mKeyMgr = mgr;
072: }
073:
074: /**
075: * The implementation on the CallbackInterface. This method only handles
076: * PrivateKeyCallback.
077: *
078: * @param callbacks - array of Callbacks to be handled.
079: * @throws IOException - if an input or output error occurs.
080: * @throws UnsupportedCallbackException - if the implementation of this method
081: * does not support one or more of the Callbacks specified in the callbacks
082: * parameter.
083: */
084: public void handle(Callback[] callbacks) throws IOException,
085: UnsupportedCallbackException {
086: for (int i = 0; i < callbacks.length; i++) {
087: CallbackHandler handler = null;
088:
089: if (callbacks[i] instanceof PrivateKeyCallback) {
090: PrivateKeyCallback cb = (PrivateKeyCallback) callbacks[i];
091: cb.setKey(null, null);
092: Object req = cb.getRequest();
093:
094: if (req == null) {
095: setAnyKey(cb);
096: }
097: if (req instanceof PrivateKeyCallback.AliasRequest) {
098: handleAliasRequest(
099: (PrivateKeyCallback.AliasRequest) req, cb);
100: } else if (req instanceof PrivateKeyCallback.IssuerSerialNumRequest) {
101: handleIssuerSerialNumRequest(
102: (PrivateKeyCallback.IssuerSerialNumRequest) req,
103: cb);
104: } else if (req instanceof PrivateKeyCallback.SubjectKeyIDRequest) {
105: handleSubjectKeyIdRequest(
106: (PrivateKeyCallback.SubjectKeyIDRequest) req,
107: cb);
108: }
109: } else {
110: throw new UnsupportedCallbackException(callbacks[i]);
111: }
112: }
113: }
114:
115: /**
116: * Handle a request for a Private Key based on alias. Go through the KeyStore and
117: * get the PrivateKey for the alias. If there is no key entry for the alias then
118: * the key and cert chain in the Callback is null.
119: *
120: * @param req is the alias request from the PrivateKeyCallback
121: * @param cb is the PrivateKeyCallback
122: * @throws IOException - if an input or output error occurs. This would indicate
123: * that the Key / Cert Chain could not be retrieved from the store.
124: */
125: private void handleAliasRequest(
126: PrivateKeyCallback.AliasRequest req, PrivateKeyCallback cb)
127: throws IOException {
128: KeyStore ks = mKeyMgr.getKeyStore();
129:
130: if (req.getAlias() == null) {
131: setAnyKey(cb);
132: }
133:
134: try {
135: if (ks.containsAlias(req.getAlias())) {
136: Key key = ks.getKey(req.getAlias(), mKeyMgr
137: .getKeyStorePassword().toCharArray());
138: if (key instanceof PrivateKey) {
139: cb.setKey((PrivateKey) key, ks
140: .getCertificateChain(req.getAlias()));
141: }
142: }
143: } catch (Exception ex) {
144: throw new IOException(ex.getMessage());
145: }
146: }
147:
148: /**
149: * Handle a request for a Private Key based on the Issuer Name and Serial Number
150: * for the corresponding Public Key. Basically get the Key Entry for the alias,
151: * then check if the Public Key Certificate's Issuer Name and Serial Number match
152: * those in the IssuerSerialNumRequest .
153: *
154: * @param req is the IssuerSerialNumRequest from the PrivateKeyCallback
155: * @param cb is the PrivateKeyCallback
156: * @throws IOException - if an input or output error occurs. This would indicate
157: * that the Key / Cert Chain could not be retrieved from the store.
158: */
159: private void handleIssuerSerialNumRequest(
160: PrivateKeyCallback.IssuerSerialNumRequest req,
161: PrivateKeyCallback cb) throws IOException {
162: KeyStore ks = mKeyMgr.getKeyStore();
163:
164: try {
165: java.util.Enumeration aliases = ks.aliases();
166: while (aliases.hasMoreElements()) {
167: String alias = (String) aliases.nextElement();
168: if (ks.isKeyEntry(alias)) {
169: Key key = ks.getKey(alias, mKeyMgr
170: .getKeyStorePassword().toCharArray());
171:
172: if (key instanceof PrivateKey) {
173: // -- Check if the Public Key Certificate matches request.
174: Certificate cert = ks.getCertificate(alias);
175: if (cert == null
176: || !X509.equals(cert.getType())) {
177: continue;
178: } else {
179: X509Certificate pkCert = (X509Certificate) cert;
180: if (req.getIssuer().equals(
181: pkCert.getIssuerX500Principal())
182: && req.getSerialNum().equals(
183: pkCert.getSerialNumber())) {
184: // -- Match found
185: cb.setKey((PrivateKey) key, ks
186: .getCertificateChain(alias));
187: }
188: }
189: }
190: }
191: }
192: } catch (Exception ex) {
193: throw new IOException(ex.getMessage());
194: }
195:
196: }
197:
198: /**
199: * Handle a request for a Private Key based on alias.
200: *
201: * @param req is the SubjectKeyIdRequest from the PrivateKeyCallback
202: * @param cb is the PrivateKeyCallback
203: * @throws IOException - if an input or output error occurs. This would indicate
204: * that the Key / Cert Chain could not be retrieved from the store.
205: */
206: private void handleSubjectKeyIdRequest(
207: PrivateKeyCallback.SubjectKeyIDRequest req,
208: PrivateKeyCallback cb) throws IOException {
209: KeyStore ks = mKeyMgr.getKeyStore();
210:
211: try {
212: java.util.Enumeration aliases = ks.aliases();
213: while (aliases.hasMoreElements()) {
214: String alias = (String) aliases.nextElement();
215: if (ks.isKeyEntry(alias)) {
216: Certificate cert = ks.getCertificate(alias);
217: if (cert == null || !X509.equals(cert.getType())) {
218: continue;
219: }
220: X509Certificate x509Cert = (X509Certificate) cert;
221: byte[] keyId = CertificateHelper
222: .getSubjectKeyIdentifier(x509Cert);
223: if (keyId == null) {
224: // -- Cert does not contain a key identifier
225: continue;
226: }
227: if (java.util.Arrays.equals(req.getSubjectKeyID(),
228: keyId)) {
229: // Asuumed key password same as the keystore password
230: cb.setKey((PrivateKey) ks.getKey(alias, mKeyMgr
231: .getKeyStorePassword().toCharArray()),
232: ks.getCertificateChain(alias));
233: }
234: }
235: }
236: } catch (Exception ex) {
237: throw new IOException(ex.getMessage());
238: }
239: }
240:
241: /**
242: * If the request in the PrivateKeyCallback is null or the alias in the Alias request
243: * is null, then we go through the KeyStore and return the entry for the first alias
244: * with a private key entry.
245: *
246: * @param cb is the PrivateKeyCallback.
247: * @throws java.io.IOException if an error occurs in retrieveing the Key.
248: */
249: private void setAnyKey(PrivateKeyCallback cb)
250: throws java.io.IOException {
251: KeyStore ks = mKeyMgr.getKeyStore();
252:
253: try {
254: java.util.Enumeration aliases = ks.aliases();
255: while (aliases.hasMoreElements()) {
256: String alias = (String) aliases.nextElement();
257: if (ks.isKeyEntry(alias)) {
258: Key key = ks.getKey(alias, mKeyMgr
259: .getKeyStorePassword().toCharArray());
260:
261: if (key instanceof PrivateKey) {
262: cb.setKey((PrivateKey) key, ks
263: .getCertificateChain(alias));
264: }
265: }
266: }
267: } catch (Exception ex) {
268: throw new java.io.IOException(ex.toString());
269: }
270: }
271:
272: }
|