001/*
002 * $HeadURL: file:///opt/dev/not-yet-commons-ssl-SVN-repo/tags/commons-ssl-0.3.17/src/java/org/apache/commons/ssl/SSLServer.java $
003 * $Revision: 180 $
004 * $Date: 2014-09-23 11:33:47 -0700 (Tue, 23 Sep 2014) $
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.ssl.SSLContext;
035import javax.net.ssl.SSLServerSocketFactory;
036import java.io.File;
037import java.io.IOException;
038import java.net.InetAddress;
039import java.net.ServerSocket;
040import java.security.GeneralSecurityException;
041import java.security.KeyManagementException;
042import java.security.KeyStoreException;
043import java.security.NoSuchAlgorithmException;
044import java.security.cert.CertificateException;
045import java.security.cert.X509Certificate;
046import java.util.Map;
047import java.util.Properties;
048
049/**
050 * @author Credit Union Central of British Columbia
051 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
052 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a>
053 * @since May 1, 2006
054 */
055public class SSLServer extends SSLServerSocketFactory {
056    protected final SSL ssl;
057
058    public SSLServer()
059        throws GeneralSecurityException, IOException {
060        this.ssl = new SSL();
061        // client certs aren't usually tied down to a single host (and who knows
062        // if the DNS reverse-lookup will work!).
063        setCheckHostname(false);
064
065        // If "javax.net.ssl.keyStore" is set, then we won't bother with this
066        // silly SSLServer default behaviour.
067        if (!ssl.usingSystemProperties) {
068            // commons-ssl default KeyMaterial will be
069            //  ~/.keystore with a password of "changeit".
070            useDefaultKeyMaterial();
071        }
072    }
073
074    /**
075     * Tries to extract the TrustMaterial and KeyMaterial being used by a Tomcat
076     * SSL server (usually on 8443) by analyzing Tomcat's "server.xml" file.  If
077     * the extraction is successful, the TrustMaterial and KeyMaterial are
078     * applied to this SSLServer.
079     *
080     * @return true if the operation was successful.
081     * @throws GeneralSecurityException setKeyMaterial() failed
082     * @throws IOException              setKeyMaterial() failed
083     */
084    public boolean useTomcatSSLMaterial()
085        throws GeneralSecurityException, IOException {
086        // If running inside Tomcat, let's try to re-use Tomcat's SSL
087        // certificate for our own stuff (e.g. RMI-SSL).
088        Integer p8443 = Integer.valueOf(8443);
089        KeyMaterial km;
090        TrustMaterial tm;
091        km = (KeyMaterial) TomcatServerXML.KEY_MATERIAL_BY_PORT.get(p8443);
092        tm = (TrustMaterial) TomcatServerXML.TRUST_MATERIAL_BY_PORT.get(p8443);
093
094        // If 8443 isn't set, let's take lowest secure port.
095        km = km == null ? TomcatServerXML.KEY_MATERIAL : km;
096        tm = tm == null ? TomcatServerXML.TRUST_MATERIAL : tm;
097        boolean success = false;
098        if (km != null) {
099            setKeyMaterial(km);
100            success = true;
101            if (tm != null && !TrustMaterial.DEFAULT.equals(tm)) {
102                setTrustMaterial(tm);
103            }
104        }
105        return success;
106    }
107
108    private boolean useDefaultKeyMaterial()
109        throws GeneralSecurityException, IOException {
110        // If we're not able to re-use Tomcat's SSLServerSocket configuration,
111        // commons-ssl default KeyMaterial will be  ~/.keystore with a password
112        // of "changeit".
113        Properties props = System.getProperties();
114        boolean pwdSet = props.containsKey("javax.net.ssl.keyStorePassword");
115        String pwd = props.getProperty("javax.net.ssl.keyStorePassword");
116        pwd = pwdSet ? pwd : "changeit";
117
118        String userHome = System.getProperty("user.home");
119        String path = userHome + "/.keystore";
120        File f = new File(path);
121        boolean success = false;
122        if (f.exists()) {
123            KeyMaterial km = null;
124            try {
125                km = new KeyMaterial(path, pwd.toCharArray());
126            }
127            catch (Exception e) {
128                // Don't want to blowup just because this silly default
129                // behaviour didn't work out.
130                if (pwdSet) {
131                    // Buf if the user has specified a non-standard password for
132                    // "javax.net.ssl.keyStorePassword", then we will warn them
133                    // that things didn't work out.
134                    System.err.println("commons-ssl automatic loading of [" + path + "] failed. ");
135                    System.err.println(e);
136                }
137            }
138            if (km != null) {
139                setKeyMaterial(km);
140                success = true;
141            }
142        }
143        return success;
144    }
145
146    public void setDnsOverride(Map m) { ssl.setDnsOverride(m); }
147
148    public void addTrustMaterial(TrustChain trustChain)
149        throws NoSuchAlgorithmException, KeyStoreException,
150        KeyManagementException, IOException, CertificateException {
151        ssl.addTrustMaterial(trustChain);
152    }
153
154    public void setTrustMaterial(TrustChain trustChain)
155        throws NoSuchAlgorithmException, KeyStoreException,
156        KeyManagementException, IOException, CertificateException {
157        ssl.setTrustMaterial(trustChain);
158    }
159
160    public void setKeyMaterial(KeyMaterial keyMaterial)
161        throws NoSuchAlgorithmException, KeyStoreException,
162        KeyManagementException, IOException, CertificateException {
163        ssl.setKeyMaterial(keyMaterial);
164    }
165
166    public void setCheckCRL(boolean b) { ssl.setCheckCRL(b); }
167
168    public void setCheckExpiry(boolean b) { ssl.setCheckExpiry(b); }
169
170    public void setCheckHostname(boolean b) { ssl.setCheckHostname(b); }
171
172    public void setConnectTimeout(int i) { ssl.setConnectTimeout(i); }
173
174    public void setDefaultProtocol(String s) { ssl.setDefaultProtocol(s); }
175
176    public void setEnabledCiphers(String[] ciphers) {
177        ssl.setEnabledCiphers(ciphers);
178    }
179
180    public void setEnabledProtocols(String[] protocols) {
181        ssl.setEnabledProtocols(protocols);
182    }
183
184    public void setHostnameVerifier(HostnameVerifier verifier) {
185        ssl.setHostnameVerifier(verifier);
186    }
187
188    public void setSoTimeout(int soTimeout) { ssl.setSoTimeout(soTimeout); }
189
190    public void setSSLWrapperFactory(SSLWrapperFactory wf) {
191        ssl.setSSLWrapperFactory(wf);
192    }
193
194    public void setNeedClientAuth(boolean b) { ssl.setNeedClientAuth(b); }
195
196    public void setWantClientAuth(boolean b) { ssl.setWantClientAuth(b); }
197
198    public void setUseClientMode(boolean b) { ssl.setUseClientMode(b); }
199
200    public X509Certificate[] getAssociatedCertificateChain() {
201        return ssl.getAssociatedCertificateChain();
202    }
203
204    public boolean getCheckCRL() { return ssl.getCheckCRL(); }
205
206    public boolean getCheckExpiry() { return ssl.getCheckExpiry(); }
207
208    public boolean getCheckHostname() { return ssl.getCheckHostname(); }
209
210    public int getConnectTimeout() { return ssl.getConnectTimeout(); }
211
212    public String getDefaultProtocol() { return ssl.getDefaultProtocol(); }
213
214    public String[] getEnabledCiphers() { return ssl.getEnabledCiphers(); }
215
216    public String[] getEnabledProtocols() { return ssl.getEnabledProtocols(); }
217
218    public HostnameVerifier getHostnameVerifier() {
219        return ssl.getHostnameVerifier();
220    }
221
222    public int getSoTimeout() { return ssl.getSoTimeout(); }
223
224    public SSLWrapperFactory getSSLWrapperFactory() {
225        return ssl.getSSLWrapperFactory();
226    }
227
228    public boolean getNeedClientAuth() { return ssl.getNeedClientAuth(); }
229
230    public boolean getWantClientAuth() { return ssl.getWantClientAuth(); }
231
232    public boolean getUseClientMode() { /* SSLServer's default is false. */
233        return !ssl.getUseClientModeDefault() && ssl.getUseClientMode();
234    }
235
236    public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
237        return ssl.getSSLContext();
238    }
239
240    public TrustChain getTrustChain() { return ssl.getTrustChain(); }
241
242    public X509Certificate[] getCurrentClientChain() {
243        return ssl.getCurrentClientChain();
244    }
245
246    public String[] getDefaultCipherSuites() {
247        return ssl.getDefaultCipherSuites();
248    }
249
250    public String[] getSupportedCipherSuites() {
251        return ssl.getSupportedCipherSuites();
252    }
253
254    public ServerSocket createServerSocket() throws IOException {
255        return ssl.createServerSocket();
256    }
257
258    public ServerSocket createServerSocket(int port)
259        throws IOException {
260        return createServerSocket(port, 50);
261    }
262
263    public ServerSocket createServerSocket(int port, int backlog)
264        throws IOException {
265        return createServerSocket(port, backlog, null);
266    }
267
268    /**
269     * Attempts to get a new socket connection to the given host within the
270     * given time limit.
271     *
272     * @param localHost the local host name/IP to bind against (null == ANY)
273     * @param port      the port to listen on
274     * @param backlog   number of connections allowed to queue up for accept().
275     * @return SSLServerSocket a new server socket
276     * @throws IOException if an I/O error occurs while creating thesocket
277     */
278    public ServerSocket createServerSocket(int port, int backlog,
279                                           InetAddress localHost)
280        throws IOException {
281        return ssl.createServerSocket(port, backlog, localHost);
282    }
283
284}