001    /*
002     * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java13.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    
032    package org.apache.commons.ssl;
033    
034    import com.sun.net.ssl.KeyManager;
035    import com.sun.net.ssl.KeyManagerFactory;
036    import com.sun.net.ssl.SSLContext;
037    import com.sun.net.ssl.TrustManager;
038    import com.sun.net.ssl.TrustManagerFactory;
039    import com.sun.net.ssl.X509KeyManager;
040    import com.sun.net.ssl.X509TrustManager;
041    
042    import javax.net.SocketFactory;
043    import javax.net.ssl.SSLPeerUnverifiedException;
044    import javax.net.ssl.SSLServerSocket;
045    import javax.net.ssl.SSLServerSocketFactory;
046    import javax.net.ssl.SSLSession;
047    import javax.net.ssl.SSLSocket;
048    import javax.net.ssl.SSLSocketFactory;
049    import java.io.ByteArrayInputStream;
050    import java.io.ByteArrayOutputStream;
051    import java.io.IOException;
052    import java.io.PrintStream;
053    import java.lang.reflect.Method;
054    import java.net.InetAddress;
055    import java.net.Socket;
056    import java.net.URL;
057    import java.security.KeyManagementException;
058    import java.security.KeyStore;
059    import java.security.KeyStoreException;
060    import java.security.NoSuchAlgorithmException;
061    import java.security.Provider;
062    import java.security.Security;
063    import java.security.UnrecoverableKeyException;
064    import java.security.cert.Certificate;
065    import java.security.cert.CertificateException;
066    import 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     */
074    public 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, 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            // overwrite password
154            for (int i = 0; i < password.length; i++) {
155                password[i] = '*';
156            }
157            return kmf;
158        }
159    
160        protected final Object buildTrustManagerFactory(KeyStore ks)
161            throws NoSuchAlgorithmException, KeyStoreException {
162            String alg = TrustManagerFactory.getDefaultAlgorithm();
163            TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
164            tmf.init(ks);
165            return tmf;
166        }
167    
168    
169        protected final Object[] retrieveKeyManagers(Object keyManagerFactory) {
170            KeyManagerFactory kmf = (KeyManagerFactory) keyManagerFactory;
171            return kmf.getKeyManagers();
172        }
173    
174        protected final Object[] retrieveTrustManagers(Object trustManagerFactory) {
175            TrustManagerFactory tmf = (TrustManagerFactory) trustManagerFactory;
176            return tmf.getTrustManagers();
177        }
178    
179        protected final SSLSocketFactory buildSSLSocketFactory(Object ssl) {
180            return ((SSLContext) ssl).getSocketFactory();
181        }
182    
183        protected final SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl) {
184            return ((SSLContext) ssl).getServerSocketFactory();
185        }
186    
187        protected final RuntimeException buildRuntimeException(Exception cause) {
188            ByteArrayOutputStream byteOut = new ByteArrayOutputStream(512);
189            PrintStream ps = new PrintStream(byteOut);
190            ps.println(cause.toString());
191            cause.printStackTrace(ps);
192            ps.flush();
193            String originalCause = byteOut.toString();
194            return new RuntimeException(originalCause);
195        }
196    
197        protected final SSLSocket buildSocket(SSL ssl) {
198            // Not supported in Java 1.3.
199            throw new UnsupportedOperationException();
200        }
201    
202        protected final SSLSocket buildSocket(SSL ssl, String remoteHost,
203                                              int remotePort, InetAddress localHost,
204                                              int localPort, int connectTimeout)
205            throws IOException {
206            // Connect Timeout ignored for Java 1.3
207            SSLSocketFactory sf = ssl.getSSLSocketFactory();
208            SSLSocket s = (SSLSocket) connectSocket(null, sf, remoteHost,
209                remotePort, localHost,
210                localPort, -1);
211            ssl.doPreConnectSocketStuff(s);
212            ssl.doPostConnectSocketStuff(s, remoteHost);
213            return s;
214        }
215    
216        protected final Socket connectSocket(Socket s, SocketFactory sf,
217                                             String remoteHost, int remotePort,
218                                             InetAddress localHost, int localPort,
219                                             int timeout)
220            throws IOException {
221            // Connect Timeout ignored for Java 1.3
222            if (s == null) {
223                if (sf == null) {
224                    s = new Socket(remoteHost, remotePort, localHost, localPort);
225                } else {
226                    s = sf.createSocket(remoteHost, remotePort, localHost, localPort);
227                }
228            }
229            return s;
230        }
231    
232    
233        protected final SSLServerSocket buildServerSocket(SSL ssl) {
234            // Not supported in Java 1.3.
235            throw new UnsupportedOperationException();
236        }
237    
238        protected final void wantClientAuth(Object o, boolean wantClientAuth) {
239            // Not supported in Java 1.3.
240        }
241    
242        protected final void enabledProtocols(Object o, String[] enabledProtocols) {
243            // Not supported in Java 1.3.
244        }
245    
246        protected void checkTrusted(Object trustManager, X509Certificate[] chain,
247                                    String authType)
248            throws CertificateException {
249            X509TrustManager tm = (X509TrustManager) trustManager;
250            boolean result = tm.isServerTrusted(chain);
251            if (!result) {
252                throw new CertificateException("commons-ssl java13 mode: certificate chain not trusted");
253            }
254        }
255    
256    
257        protected final Object initSSL(SSL ssl, TrustChain tc, KeyMaterial k)
258            throws NoSuchAlgorithmException, KeyStoreException,
259            CertificateException, KeyManagementException, IOException {
260            SSLContext context = SSLContext.getInstance(ssl.getDefaultProtocol());
261            TrustManager[] trustManagers = null;
262            KeyManager[] keyManagers = null;
263            if (tc != null) {
264                trustManagers = (TrustManager[]) tc.getTrustManagers();
265            }
266            if (k != null) {
267                keyManagers = (KeyManager[]) k.getKeyManagers();
268            }
269            if (keyManagers != null) {
270                for (int i = 0; i < keyManagers.length; i++) {
271                    if (keyManagers[i] instanceof X509KeyManager) {
272                        X509KeyManager km = (X509KeyManager) keyManagers[i];
273                        keyManagers[i] = new Java13KeyManagerWrapper(km, k, ssl);
274                    }
275                }
276            }
277            if (trustManagers != null) {
278                for (int i = 0; i < trustManagers.length; i++) {
279                    if (trustManagers[i] instanceof X509TrustManager) {
280                        X509TrustManager tm = (X509TrustManager) trustManagers[i];
281                        trustManagers[i] = new Java13TrustManagerWrapper(tm, tc, ssl);
282                    }
283                }
284            }
285            context.init(keyManagers, trustManagers, null);
286            return context;
287        }
288    
289    
290    }