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