001/*
002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java14.java $
003 * $Revision: 121 $
004 * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
005 *
006 * ====================================================================
007 * Licensed to the Apache Software Foundation (ASF) under one
008 * or more contributor license agreements.  See the NOTICE file
009 * distributed with this work for additional information
010 * regarding copyright ownership.  The ASF licenses this file
011 * to you under the Apache License, Version 2.0 (the
012 * "License"); you may not use this file except in compliance
013 * with the License.  You may obtain a copy of the License at
014 *
015 *   http://www.apache.org/licenses/LICENSE-2.0
016 *
017 * Unless required by applicable law or agreed to in writing,
018 * software distributed under the License is distributed on an
019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020 * KIND, either express or implied.  See the License for the
021 * specific language governing permissions and limitations
022 * under the License.
023 * ====================================================================
024 *
025 * This software consists of voluntary contributions made by many
026 * individuals on behalf of the Apache Software Foundation.  For more
027 * information on the Apache Software Foundation, please see
028 * <http://www.apache.org/>.
029 *
030 */
031
032package org.apache.commons.ssl;
033
034import javax.net.SocketFactory;
035import javax.net.ssl.KeyManager;
036import javax.net.ssl.KeyManagerFactory;
037import javax.net.ssl.SSLContext;
038import javax.net.ssl.SSLPeerUnverifiedException;
039import javax.net.ssl.SSLServerSocket;
040import javax.net.ssl.SSLServerSocketFactory;
041import javax.net.ssl.SSLSession;
042import javax.net.ssl.SSLSocket;
043import javax.net.ssl.SSLSocketFactory;
044import javax.net.ssl.TrustManager;
045import javax.net.ssl.TrustManagerFactory;
046import javax.net.ssl.X509KeyManager;
047import javax.net.ssl.X509TrustManager;
048import java.io.IOException;
049import java.net.InetAddress;
050import java.net.InetSocketAddress;
051import java.net.ServerSocket;
052import java.net.Socket;
053import java.security.KeyManagementException;
054import java.security.KeyStore;
055import java.security.KeyStoreException;
056import java.security.NoSuchAlgorithmException;
057import java.security.UnrecoverableKeyException;
058import java.security.cert.Certificate;
059import java.security.cert.CertificateException;
060import java.security.cert.X509Certificate;
061
062
063/**
064 * @author Credit Union Central of British Columbia
065 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
066 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
067 * @since 30-Jun-2006
068 */
069public final class Java14 extends JavaImpl {
070    private static Java14 instance = new Java14();
071
072    private Java14() {
073        try {
074            SSLSocketFactory.getDefault().createSocket();
075        }
076        catch (IOException ioe) {
077            ioe.hashCode();
078        }
079    }
080
081    public static Java14 getInstance() {
082        return instance;
083    }
084
085    public final String getVersion() {
086        return "Java14";
087    }
088
089    protected final String retrieveSubjectX500(X509Certificate cert) {
090        return cert.getSubjectX500Principal().toString();
091    }
092
093    protected final String retrieveIssuerX500(X509Certificate cert) {
094        return cert.getIssuerX500Principal().toString();
095    }
096
097    protected final Certificate[] retrievePeerCerts(SSLSession sslSession)
098        throws SSLPeerUnverifiedException {
099        return sslSession.getPeerCertificates();
100    }
101
102    protected final Object buildKeyManagerFactory(KeyStore ks, char[] password)
103        throws NoSuchAlgorithmException, KeyStoreException,
104        UnrecoverableKeyException {
105        String alg = KeyManagerFactory.getDefaultAlgorithm();
106        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
107        kmf.init(ks, password);
108        // overwrite password
109        for (int i = 0; i < password.length; i++) {
110            password[i] = '*';
111        }
112        return kmf;
113    }
114
115    protected final Object buildTrustManagerFactory(KeyStore ks)
116        throws NoSuchAlgorithmException, KeyStoreException {
117        String alg = TrustManagerFactory.getDefaultAlgorithm();
118        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
119        tmf.init(ks);
120        return tmf;
121    }
122
123    protected final Object[] retrieveKeyManagers(Object keyManagerFactory) {
124        KeyManagerFactory kmf = (KeyManagerFactory) keyManagerFactory;
125        return kmf.getKeyManagers();
126    }
127
128    protected final Object[] retrieveTrustManagers(Object trustManagerFactory) {
129        TrustManagerFactory tmf = (TrustManagerFactory) trustManagerFactory;
130        return tmf.getTrustManagers();
131    }
132
133    protected final SSLSocketFactory buildSSLSocketFactory(Object ssl) {
134        return ((SSLContext) ssl).getSocketFactory();
135    }
136
137    protected final SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl) {
138        return ((SSLContext) ssl).getServerSocketFactory();
139    }
140
141    protected final RuntimeException buildRuntimeException(Exception cause) {
142        return new RuntimeException(cause);
143    }
144
145    protected final SSLSocket buildSocket(SSL ssl) throws IOException {
146        SSLSocketFactory sf = ssl.getSSLSocketFactory();
147        SSLSocket s = (SSLSocket) sf.createSocket();
148        ssl.doPreConnectSocketStuff(s);
149        return s;
150    }
151
152    protected final SSLSocket buildSocket(SSL ssl, String remoteHost,
153                                          int remotePort, InetAddress localHost,
154                                          int localPort, int timeout)
155        throws IOException {
156        SSLSocket s = buildSocket(ssl);
157        s = (SSLSocket) connectSocket(s, null, remoteHost, remotePort,
158            localHost, localPort, timeout);
159        ssl.doPostConnectSocketStuff(s, remoteHost);
160        return s;
161    }
162
163    protected final Socket connectSocket(Socket s, SocketFactory sf,
164                                         String remoteHost, int remotePort,
165                                         InetAddress localHost, int localPort,
166                                         int timeout)
167        throws IOException {
168        if (s == null) {
169            if (sf == null) {
170                s = new Socket();
171            } else {
172                s = sf.createSocket();
173            }
174        }
175        InetSocketAddress dest = new InetSocketAddress(remoteHost, remotePort);
176        InetSocketAddress src = new InetSocketAddress(localHost, localPort);
177        s.bind(src);
178        s.connect(dest, timeout);
179        return s;
180    }
181
182    protected final SSLServerSocket buildServerSocket(SSL ssl)
183        throws IOException {
184        ServerSocket s = ssl.getSSLServerSocketFactory().createServerSocket();
185        SSLServerSocket ss = (SSLServerSocket) s;
186        ssl.doPreConnectServerSocketStuff(ss);
187        return ss;
188    }
189
190    protected final void wantClientAuth(Object o, boolean wantClientAuth) {
191        SSLSocket s;
192        SSLServerSocket ss;
193        if (o instanceof SSLSocket) {
194            s = (SSLSocket) o;
195            s.setWantClientAuth(wantClientAuth);
196        } else if (o instanceof SSLServerSocket) {
197            ss = (SSLServerSocket) o;
198            ss.setWantClientAuth(wantClientAuth);
199        } else {
200            throw new ClassCastException("need SSLSocket or SSLServerSocket");
201        }
202    }
203
204    protected final void enabledProtocols(Object o, String[] enabledProtocols) {
205        SSLSocket s;
206        SSLServerSocket ss;
207        if (o instanceof SSLSocket) {
208            s = (SSLSocket) o;
209            s.setEnabledProtocols(enabledProtocols);
210        } else if (o instanceof SSLServerSocket) {
211            ss = (SSLServerSocket) o;
212            ss.setEnabledProtocols(enabledProtocols);
213        } else {
214            throw new ClassCastException("need SSLSocket or SSLServerSocket");
215        }
216    }
217
218    protected void checkTrusted(Object trustManager, X509Certificate[] chain,
219                                String authType)
220        throws CertificateException {
221        X509TrustManager tm = (X509TrustManager) trustManager;
222        tm.checkServerTrusted(chain, authType);
223    }
224
225    protected final Object initSSL(SSL ssl, TrustChain tc, KeyMaterial k)
226        throws NoSuchAlgorithmException, KeyStoreException,
227        CertificateException, KeyManagementException, IOException {
228        SSLContext context = SSLContext.getInstance(ssl.getDefaultProtocol());
229        TrustManager[] trustManagers = null;
230        KeyManager[] keyManagers = null;
231        if (tc != null) {
232            trustManagers = (TrustManager[]) tc.getTrustManagers();
233        }
234        if (k != null) {
235            keyManagers = (KeyManager[]) k.getKeyManagers();
236        }
237        if (keyManagers != null) {
238            for (int i = 0; i < keyManagers.length; i++) {
239                if (keyManagers[i] instanceof X509KeyManager) {
240                    X509KeyManager km = (X509KeyManager) keyManagers[i];
241                    keyManagers[i] = new Java14KeyManagerWrapper(km, k, ssl);
242                }
243            }
244        }
245        if (trustManagers != null) {
246            for (int i = 0; i < trustManagers.length; i++) {
247                if (trustManagers[i] instanceof X509TrustManager) {
248                    X509TrustManager tm = (X509TrustManager) trustManagers[i];
249                    trustManagers[i] = new Java14TrustManagerWrapper(tm, tc, ssl);
250                }
251            }
252        }
253        context.init(keyManagers, trustManagers, null);
254        return context;
255    }
256
257
258}