001/*
002 * $HeadURL: file:///opt/dev/not-yet-commons-ssl-SVN-repo/tags/commons-ssl-0.3.17/src/java/org/apache/commons/ssl/Java13.java $
003 * $Revision: 155 $
004 * $Date: 2009-09-17 14:00:58 -0700 (Thu, 17 Sep 2009) $
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 com.sun.net.ssl.KeyManager;
035import com.sun.net.ssl.KeyManagerFactory;
036import com.sun.net.ssl.SSLContext;
037import com.sun.net.ssl.TrustManager;
038import com.sun.net.ssl.TrustManagerFactory;
039import com.sun.net.ssl.X509KeyManager;
040import com.sun.net.ssl.X509TrustManager;
041
042import javax.net.SocketFactory;
043import javax.net.ssl.SSLPeerUnverifiedException;
044import javax.net.ssl.SSLServerSocket;
045import javax.net.ssl.SSLServerSocketFactory;
046import javax.net.ssl.SSLSession;
047import javax.net.ssl.SSLSocket;
048import javax.net.ssl.SSLSocketFactory;
049import java.io.ByteArrayInputStream;
050import java.io.ByteArrayOutputStream;
051import java.io.IOException;
052import java.io.PrintStream;
053import java.lang.reflect.Method;
054import java.net.InetAddress;
055import java.net.Socket;
056import java.net.URL;
057import java.security.KeyManagementException;
058import java.security.KeyStore;
059import java.security.KeyStoreException;
060import java.security.NoSuchAlgorithmException;
061import java.security.Provider;
062import java.security.Security;
063import java.security.UnrecoverableKeyException;
064import java.security.cert.Certificate;
065import java.security.cert.CertificateException;
066import java.security.cert.X509Certificate;
067
068/**
069 * @author Credit Union Central of British Columbia
070 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
071 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
072 * @since 30-Jun-2006
073 */
074public final class Java13 extends JavaImpl {
075    private final static Java13 instance = new Java13();
076
077    private Java13() {
078        try {
079            Class c = Class.forName("javax.crypto.Cipher");
080            Class[] sig = {String.class};
081            String[] args = {"DES/CBC/PKCS5Padding"};
082            Method m = c.getMethod("getInstance", sig);
083            m.invoke(null, (Object[]) args);
084        }
085        catch (Exception e) {
086            try {
087                Class c = Class.forName("com.sun.crypto.provider.SunJCE");
088                Security.addProvider((Provider) c.newInstance());
089                // System.out.println( "jce not loaded: " + e + " - loading SunJCE!" );
090                //e.printStackTrace( System.out );
091            }
092            catch (Exception e2) {
093                System.out.println("com.sun.crypto.provider.SunJCE unavailable: " + e2);
094                // e2.printStackTrace( System.out );
095            }
096        }
097        try {
098            URL u = new URL("https://vancity.com/");
099            u.openConnection();
100        }
101        catch (Exception e) {
102            // System.out.println( "java.net.URL support of https not loaded: " + e + " - attempting to load com.sun.net.ssl.internal.ssl.Provider!" );
103            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
104            System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
105        }
106        // System.out.println( "old HANDLER: " + HANDLER );
107    }
108
109    public static Java13 getInstance() {
110        return instance;
111    }
112
113    public final String getVersion() {
114        return "Java13";
115    }
116
117    protected final String retrieveSubjectX500(X509Certificate cert) {
118        return cert.getSubjectDN().toString();
119    }
120
121    protected final String retrieveIssuerX500(X509Certificate cert) {
122        return cert.getIssuerDN().toString();
123    }
124
125    protected final Certificate[] retrievePeerCerts(SSLSession sslSession)
126        throws SSLPeerUnverifiedException {
127        javax.security.cert.X509Certificate[] chain;
128        chain = sslSession.getPeerCertificateChain();
129        X509Certificate[] newChain = new X509Certificate[chain.length];
130        try {
131            for (int i = 0; i < chain.length; i++) {
132                javax.security.cert.X509Certificate javaxCert = chain[i];
133                byte[] encoded = javaxCert.getEncoded();
134                ByteArrayInputStream in = new ByteArrayInputStream(encoded);
135                synchronized (Certificates.CF) {
136                    Certificate c = Certificates.CF.generateCertificate(in);
137                    newChain[i] = (X509Certificate) c;
138                }
139            }
140        }
141        catch (Exception e) {
142            throw buildRuntimeException(e);
143        }
144        return newChain;
145    }
146
147    protected final Object buildKeyManagerFactory(KeyStore ks, char[] password)
148        throws NoSuchAlgorithmException, KeyStoreException,
149        UnrecoverableKeyException {
150        String alg = KeyManagerFactory.getDefaultAlgorithm();
151        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
152        kmf.init(ks, password);
153        return kmf;
154    }
155
156    protected final Object buildTrustManagerFactory(KeyStore ks)
157        throws NoSuchAlgorithmException, KeyStoreException {
158        String alg = TrustManagerFactory.getDefaultAlgorithm();
159        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
160        tmf.init(ks);
161        return tmf;
162    }
163
164
165    protected final Object[] retrieveKeyManagers(Object keyManagerFactory) {
166        KeyManagerFactory kmf = (KeyManagerFactory) keyManagerFactory;
167        return kmf.getKeyManagers();
168    }
169
170    protected final Object[] retrieveTrustManagers(Object trustManagerFactory) {
171        TrustManagerFactory tmf = (TrustManagerFactory) trustManagerFactory;
172        return tmf.getTrustManagers();
173    }
174
175    protected final SSLSocketFactory buildSSLSocketFactory(Object ssl) {
176        return ((SSLContext) ssl).getSocketFactory();
177    }
178
179    protected final SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl) {
180        return ((SSLContext) ssl).getServerSocketFactory();
181    }
182
183    protected final RuntimeException buildRuntimeException(Exception cause) {
184        ByteArrayOutputStream byteOut = new ByteArrayOutputStream(512);
185        PrintStream ps = new PrintStream(byteOut);
186        ps.println(cause.toString());
187        cause.printStackTrace(ps);
188        ps.flush();
189        String originalCause = byteOut.toString();
190        return new RuntimeException(originalCause);
191    }
192
193    protected final SSLSocket buildSocket(SSL ssl) {
194        // Not supported in Java 1.3.
195        throw new UnsupportedOperationException();
196    }
197
198    protected final SSLSocket buildSocket(SSL ssl, String remoteHost,
199                                          int remotePort, InetAddress localHost,
200                                          int localPort, int connectTimeout)
201        throws IOException {
202        // Connect Timeout ignored for Java 1.3
203        SSLSocketFactory sf = ssl.getSSLSocketFactory();
204        SSLSocket s = (SSLSocket) connectSocket(
205                null, sf, remoteHost, remotePort, localHost, localPort, -1, ssl
206        );
207        ssl.doPreConnectSocketStuff(s);
208        ssl.doPostConnectSocketStuff(s, remoteHost);
209        return s;
210    }
211
212    protected final Socket buildPlainSocket(
213            SSL ssl, String remoteHost, int remotePort, InetAddress localHost, int localPort, int connectTimeout
214    )
215        throws IOException {
216        // Connect Timeout ignored for Java 1.3
217        SocketFactory sf = SocketFactory.getDefault();
218        Socket s = connectSocket(
219                null, sf, remoteHost, remotePort, localHost, localPort, -1, ssl
220        );
221        ssl.doPreConnectSocketStuff(s);
222        ssl.doPostConnectSocketStuff(s, remoteHost);
223        return s;
224    }
225    
226    protected final Socket connectSocket(Socket s, SocketFactory sf,
227                                         String remoteHost, int remotePort,
228                                         InetAddress localHost, int localPort,
229                                         int timeout, SSL ssl)
230        throws IOException {
231
232        remoteHost = ssl.dnsOverride(remoteHost);
233
234        // Connect Timeout ignored for Java 1.3
235        if (s == null) {
236            if (sf == null) {
237                s = new Socket(remoteHost, remotePort, localHost, localPort);
238            } else {
239                s = sf.createSocket(remoteHost, remotePort, localHost, localPort);
240            }
241        }
242        return s;
243    }
244
245
246    protected final SSLServerSocket buildServerSocket(SSL ssl) {
247        // Not supported in Java 1.3.
248        throw new UnsupportedOperationException();
249    }
250
251    protected final void wantClientAuth(Object o, boolean wantClientAuth) {
252        // Not supported in Java 1.3.
253    }
254
255    protected final void enabledProtocols(Object o, String[] enabledProtocols) {
256        // Not supported in Java 1.3.
257    }
258
259    protected void checkTrusted(Object trustManager, X509Certificate[] chain,
260                                String authType)
261        throws CertificateException {
262        X509TrustManager tm = (X509TrustManager) trustManager;
263        boolean result = tm.isServerTrusted(chain);
264        if (!result) {
265            throw new CertificateException("commons-ssl java13 mode: certificate chain not trusted");
266        }
267    }
268
269
270    protected final Object initSSL(SSL ssl, TrustChain tc, KeyMaterial k)
271        throws NoSuchAlgorithmException, KeyStoreException,
272        CertificateException, KeyManagementException, IOException {
273        SSLContext context = SSLContext.getInstance(ssl.getDefaultProtocol());
274        TrustManager[] trustManagers = null;
275        KeyManager[] keyManagers = null;
276        if (tc != null) {
277            trustManagers = (TrustManager[]) tc.getTrustManagers();
278        }
279        if (k != null) {
280            keyManagers = (KeyManager[]) k.getKeyManagers();
281        }
282        if (keyManagers != null) {
283            for (int i = 0; i < keyManagers.length; i++) {
284                if (keyManagers[i] instanceof X509KeyManager) {
285                    X509KeyManager km = (X509KeyManager) keyManagers[i];
286                    keyManagers[i] = new Java13KeyManagerWrapper(km, k, ssl);
287                }
288            }
289        }
290        if (trustManagers != null) {
291            for (int i = 0; i < trustManagers.length; i++) {
292                if (trustManagers[i] instanceof X509TrustManager) {
293                    X509TrustManager tm = (X509TrustManager) trustManagers[i];
294                    trustManagers[i] = new Java13TrustManagerWrapper(tm, tc, ssl);
295                }
296            }
297        }
298        context.init(keyManagers, trustManagers, null);
299        return context;
300    }
301
302
303}