    001/*
    002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.15/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}