The attached 5-pack is stage one of a three-step process working toward a fix for TC4 Bug #1400: proper handling of a keystore with multiple entries. This round is simply a cleanup of the exception handling/logging. The initial implementation had notes about "FIXME", so I did :-) These may look a tad involved, mostly because the security classes like to throw tons of exceptions, which I then have to propagate back up through call stack to get properly logged. There is a fair amount of code here, but all I'm doing is simply handing off exceptions. The second patch(es) will fill out the Javadoc comments and resolve some minor symantical things that the classic compiler allows, but Jikes doesn't like. The final set will be the actual fix for correctly handling multiple keystore entries. - Christopher P.S. I did the happy "clean-then-build" hoo-ha, so it compiles cleanly against the full source.
--- catalina/src/share/org/apache/catalina/connector/http10/HttpConnector.java Sun Jul 22 15:36:10 2001 +++ catalina/src/share/org/apache/catalina/connector/http10/HttpConnector-new.java + Mon Aug 13 01:37:38 2001 @@ -88,6 +88,11 @@ import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.StringManager; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.UnrecoverableKeyException; +import java.security.KeyManagementException; /** * Simple implementation of an HTTP/1.0 Connector, for testing and debugging @@ -822,36 +827,39 @@ * Open and return the server socket for this Connector. If an IP * address has been specified, the socket will be opened only on that * address; otherwise it will be opened on all addresses. - * - * @exception IOException if an input/output error occurs */ - private ServerSocket open() throws IOException { + private ServerSocket open() + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { // Acquire the server socket factory for this Connector ServerSocketFactory factory = getFactory(); - // If no address is specified, open a connection on all addresses if (address == null) { + // If no address is specified, open a connection on all addresses log(sm.getString("httpConnector.allAddresses")); return (factory.createSocket(port, acceptCount)); - } - - // Open a server socket on the specified address - InetAddress[] addresses = - InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()); - int i; - for (i = 0; i < addresses.length; i++) { - if (addresses[i].getHostAddress().equals(address)) - break; - } - if (i < addresses.length) { - log(sm.getString("httpConnector.anAddress", address)); - return (factory.createSocket(port, acceptCount, addresses[i])); } else { - log(sm.getString("httpConnector.noAddress", address)); - return (factory.createSocket(port, acceptCount)); - } + // Open a server socket on the specified address + InetAddress[] addresses = + InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()); + int i; + for (i = 0; i < addresses.length; i++) { + if (addresses[i].getHostAddress().equals(address)) + break; + } + if (i < addresses.length) { + log(sm.getString("httpConnector.anAddress", address)); + return (factory.createSocket(port, acceptCount, addresses[i])); + } else { + // Address error - try socket without specific binding + log(sm.getString("httpConnector.noAddress", address)); + return (factory.createSocket(port, acceptCount)); + } + } } @@ -973,17 +981,40 @@ */ public void initialize() throws LifecycleException { + if (initialized) throw new LifecycleException ( sm.getString("httpConnector.alreadyInitialized")); - this.initialized=true; + + this.initialized = true; + + Exception e = null; // Establish a server socket on the specified port try { serverSocket = open(); - } catch (IOException e) { - throw new LifecycleException(threadName + ".open", e); + } catch (KeyStoreException kse) { + log(sm.getString("httpConnector Keystore Problem", kse)); + e = kse; + } catch (IOException ioe) { + log(sm.getString("httpConnector IO Problem", ioe)); + e = ioe; + } catch (NoSuchAlgorithmException nsae) { + log(sm.getString("httpConnector Keystore Algorithm Problem", nsae)); + e = nsae; + } catch (CertificateException ce) { + log(sm.getString("httpConnector Certificate Problem", ce)); + e = ce; + } catch (UnrecoverableKeyException uke) { + log(sm.getString("httpConnector Key Problem", uke)); + e = uke; + } catch (KeyManagementException kme) { + log(sm.getString("httpConnector Key Management Problem", kme)); + e = kme; } + + if ( e != null ) + throw new LifecycleException(threadName + ".open", e); }
--- catalina/src/share/org/apache/catalina/connector/http/HttpConnector.java Sun Jul 22 15:36:10 2001 +++ catalina/src/share/org/apache/catalina/connector/http/HttpConnector-new.java + Mon Aug 13 01:37:12 2001 @@ -69,6 +69,7 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.net.UnknownHostException; import java.security.AccessControlException; import java.util.Stack; import java.util.Vector; @@ -89,6 +90,11 @@ import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.StringManager; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.UnrecoverableKeyException; +import java.security.KeyManagementException; /** * Implementation of an HTTP/1.1 connector. @@ -897,28 +903,31 @@ * Open and return the server socket for this Connector. If an IP * address has been specified, the socket will be opened only on that * address; otherwise it will be opened on all addresses. - * - * @exception IOException if an input/output error occurs */ - private ServerSocket open() throws IOException { + private ServerSocket open() + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { // Acquire the server socket factory for this Connector ServerSocketFactory factory = getFactory(); - // If no address is specified, open a connection on all addresses if (address == null) { + // If no address is specified, open a connection on all addresses log(sm.getString("httpConnector.allAddresses")); return (factory.createSocket(port, acceptCount)); - } - - // Open a server socket on the specified address - try { - InetAddress is = InetAddress.getByName(address); - log(sm.getString("httpConnector.anAddress", address)); - return (factory.createSocket(port, acceptCount, is)); - } catch (Exception e) { - log(sm.getString("httpConnector.noAddress", address)); - return (factory.createSocket(port, acceptCount)); + } else { + // Open a server socket on the specified address + try { + InetAddress is = InetAddress.getByName(address); + log(sm.getString("httpConnector.anAddress", address)); + return (factory.createSocket(port, acceptCount, is)); + } catch ( Exception e ) { + // Address error - try socket without specific binding + log(sm.getString("httpConnector.noAddress", address)); + return (factory.createSocket(port, acceptCount)); + } } } @@ -955,6 +964,8 @@ // log("run: Accept returned IOException", e); if (started && !stopped) log("accept: ", e); + + // If reopening fails, exit try { // if (debug >= 3) // log("run: Closing server socket"); @@ -966,11 +977,26 @@ } // if (debug >= 3) // log("run: IOException processing completed"); - } catch (IOException ex) { - // If reopening fails, exit - log("socket reopen: ", ex); + } catch (KeyStoreException kse) { + log("socket reopen, keystore problem: ", kse); + break; + } catch (IOException ioe) { + log("socket reopen, io problem: ", ioe); + break; + } catch (NoSuchAlgorithmException nsae) { + log("socket reopen, keystore algorithm problem: ", nsae); + break; + } catch (CertificateException ce) { + log("socket reopen, certificate problem: ", ce); + break; + } catch (UnrecoverableKeyException uke) { + log("socket reopen, key problem: ", uke); + break; + } catch (KeyManagementException kme) { + log("socket reopen, key management problem: ", kme); break; } + continue; } @@ -1069,17 +1095,40 @@ */ public void initialize() throws LifecycleException { + if (initialized) throw new LifecycleException ( sm.getString("httpConnector.alreadyInitialized")); - this.initialized=true; + + this.initialized = true; + + Exception e = null; // Establish a server socket on the specified port try { serverSocket = open(); - } catch (IOException e) { - throw new LifecycleException(threadName + ".open", e); + } catch (KeyStoreException kse) { + log(sm.getString("httpConnector.KeystoreProblem", kse)); + e = kse; + } catch (IOException ioe) { + log(sm.getString("httpConnector.IOProblem", ioe)); + e = ioe; + } catch (NoSuchAlgorithmException nsae) { + log(sm.getString("httpConnector.KeystoreAlgorithmProblem", nsae)); + e = nsae; + } catch (CertificateException ce) { + log(sm.getString("httpConnector.CertificateProblem", ce)); + e = ce; + } catch (UnrecoverableKeyException uke) { + log(sm.getString("httpConnector Key Problem", uke)); + e = uke; + } catch (KeyManagementException kme) { + log(sm.getString("httpConnector Key Management Problem", kme)); + e = kme; } + + if ( e != null ) + throw new LifecycleException(threadName + ".open", e); }
--- catalina/src/share/org/apache/catalina/net/ServerSocketFactory.java Sun Jul 22 13:25:12 2001 +++ catalina/src/share/org/apache/catalina/net/ServerSocketFactory-new.java Mon +Aug 13 01:35:46 2001 @@ -64,6 +64,11 @@ import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.UnrecoverableKeyException; +import java.security.KeyManagementException; /** @@ -90,9 +95,22 @@ * * @param port the port to listen to * - * @exception IOException for networking errors + * @exception KeyStoreException an error instantiating the + * KeyStore from file (SSL only) + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * (SSL only) + * @exception CertificateException an error in the certificate + * (SSL only) + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer */ - public ServerSocket createSocket (int port) throws IOException; + public ServerSocket createSocket (int port) + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException; /** @@ -104,10 +122,22 @@ * @param port the port to listen to * @param backlog how many connections are queued * - * @exception IOException for networking errors + * @exception KeyStoreException an error instantiating the + * KeyStore from file (SSL only) + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * (SSL only) + * @exception CertificateException an error in the certificate + * (SSL only) + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer */ public ServerSocket createSocket (int port, int backlog) - throws IOException; + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException; /** @@ -120,11 +150,22 @@ * @param backlog how many connections are queued * @param ifAddress the network interface address to use * - * @exception IOException for networking errors + * @exception KeyStoreException an error instantiating the + * KeyStore from file (SSL only) + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * (SSL only) + * @exception CertificateException an error in the certificate + * (SSL only) + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer */ public ServerSocket createSocket (int port, int backlog, InetAddress ifAddress) - throws IOException; - + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException; }
--- catalina/src/share/org/apache/catalina/net/SSLServerSocketFactory.java Sun Jul 22 13:25:12 2001 +++ catalina/src/share/org/apache/catalina/net/SSLServerSocketFactory-new.java Mon +Aug 13 01:38:08 2001 @@ -66,6 +66,8 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.KeyManagementException; import java.security.Security; import java.security.cert.CertificateException; import javax.net.ServerSocketFactory; @@ -175,10 +177,16 @@ */ private KeyStore keyStore = null; - public KeyStore getKeyStore() throws IOException { + public KeyStore getKeyStore() + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException,UnrecoverableKeyException, + KeyManagementException + { + if (sslProxy == null) initialize(); return (this.keyStore); + } @@ -249,14 +257,28 @@ * * @param port Port to listen to * - * @exception IOException if an input/output or network error occurs - */ - public ServerSocket createSocket(int port) throws IOException { + * @exception KeyStoreException an error instantiating the + * KeyStore from file + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception CertificateException an error in the certificate + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer + */ + public ServerSocket createSocket(int port) + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { if (sslProxy == null) initialize(); + ServerSocket socket = sslProxy.createServerSocket(port); + initServerSocket(socket); return (socket); @@ -272,15 +294,28 @@ * @param port Port to listen to * @param backlog Maximum number of connections to be queued * - * @exception IOException if an input/output or network error occurs + * @exception KeyStoreException an error instantiating the + * KeyStore from file + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception CertificateException an error in the certificate + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer */ public ServerSocket createSocket(int port, int backlog) - throws IOException { + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { if (sslProxy == null) initialize(); + ServerSocket socket = sslProxy.createServerSocket(port, backlog); + initServerSocket(socket); return (socket); @@ -297,16 +332,29 @@ * @param backlog Maximum number of connections to be queued * @param ifAddress Address of the interface to be used * - * @exception IOException if an input/output or network error occurs + * @exception KeyStoreException an error instantiating the + * KeyStore from file + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception CertificateException an error in the certificate + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer */ public ServerSocket createSocket(int port, int backlog, InetAddress ifAddress) - throws IOException { + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { if (sslProxy == null) initialize(); + ServerSocket socket = sslProxy.createServerSocket(port, backlog, ifAddress); + initServerSocket(socket); return (socket); @@ -319,9 +367,21 @@ /** * Initialize objects that will be required to create sockets. * - * @exception IOException if an input/output error occurs - */ - private synchronized void initialize() throws IOException { + * @exception KeyStoreException an error instantiating the + * KeyStore from file + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception CertificateException an error in the certificate + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer + */ + private synchronized void initialize() + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException, + KeyManagementException + { initHandler(); initKeyStore(); @@ -348,20 +408,35 @@ /** * Initialize the internal representation of the key store file. * - * @exception IOException if an input/output exception occurs - */ - private void initKeyStore() throws IOException { + * @exception KeyStoreException an error instantiating the + * KeyStore from file + * @exception IOException an input/output or network error + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception CertificateException an error in the certificate + */ + private void initKeyStore() + throws KeyStoreException, IOException, NoSuchAlgorithmException, + CertificateException + { + + FileInputStream istream = null; try { keyStore = KeyStore.getInstance(keystoreType); - FileInputStream istream = new FileInputStream(keystoreFile); + istream = new FileInputStream(keystoreFile); keyStore.load(istream, keystorePass.toCharArray()); - istream.close(); - } catch (Exception e) { - // FIXME - send to an appropriate log file? - System.out.println("initKeyStore: " + e); - e.printStackTrace(System.out); - throw new IOException(e.toString()); + } catch (KeyStoreException kse) { + throw kse; + } catch (IOException ioe) { + throw ioe; + } catch (NoSuchAlgorithmException nsae) { + throw nsae; + } catch (CertificateException ce) { + throw ce; + } finally { + if ( istream != null ) + istream.close(); } } @@ -370,44 +445,43 @@ /** * Initialize the SSL socket factory. * - * @exception IOException if an input/output error occurs - */ - private void initProxy() throws IOException { + * @exception NoSuchAlgorithmException unsupported algorithm, for the + * current provider, in the keystore + * @exception UnrecoverableKeyException a problem with the internal keys + * @exception KeyManagementException a problem in the key management + * layer + * @exception KeyStoreException an error with the KeyStore + */ + private void initProxy() + throws NoSuchAlgorithmException, UnrecoverableKeyException, + KeyManagementException, KeyStoreException + { + + /* + Security.addProvider(new sun.security.provider.Sun()); + Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); + */ + + // Create an SSL context used to create an SSL socket factory + SSLContext context = SSLContext.getInstance(protocol); + + // Create the key manager factory used to extract the server key + KeyManagerFactory keyManagerFactory = + KeyManagerFactory.getInstance(algorithm); + keyManagerFactory.init(keyStore, keystorePass.toCharArray()); + + // Create the trust manager factory used for checking certificates + /* + trustManagerFactory = TrustManagerFactory.getInstance(algorithm); + trustManagerFactory.init(keyStore); + */ + + // Initialize the context with the key managers + context.init(keyManagerFactory.getKeyManagers(), null, + new java.security.SecureRandom()); - try { - - /* - Security.addProvider(new sun.security.provider.Sun()); - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - */ - - // Create an SSL context used to create an SSL socket factory - SSLContext context = SSLContext.getInstance(protocol); - - // Create the key manager factory used to extract the server key - KeyManagerFactory keyManagerFactory = - KeyManagerFactory.getInstance(algorithm); - keyManagerFactory.init(keyStore, keystorePass.toCharArray()); - - // Create the trust manager factory used for checking certificates - /* - trustManagerFactory = TrustManagerFactory.getInstance(algorithm); - trustManagerFactory.init(keyStore); - */ - - // Initialize the context with the key managers - context.init(keyManagerFactory.getKeyManagers(), null, - new java.security.SecureRandom()); - - // Create the proxy and return - sslProxy = context.getServerSocketFactory(); - - } catch (Exception e) { - // FIXME - send to an appropriate log file? - System.out.println("initProxy: " + e); - e.printStackTrace(System.out); - throw new IOException(e.toString()); - } + // Create the proxy and return + sslProxy = context.getServerSocketFactory(); } @@ -429,6 +503,5 @@ socket.setNeedClientAuth(clientAuth); } - }
--- catalina/src/share/org/apache/catalina/connector/warp/WarpConnector.java Thu Aug 9 13:08:58 2001 +++ catalina/src/share/org/apache/catalina/connector/warp/WarpConnector-new.java + Mon Aug 13 01:36:26 2001 @@ -77,6 +77,13 @@ import org.apache.catalina.net.ServerSocketFactory; import org.apache.catalina.util.LifecycleSupport; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.UnrecoverableKeyException; +import java.security.KeyManagementException; + + public class WarpConnector implements Connector, Lifecycle, Runnable { /* ==================================================================== */ @@ -453,8 +460,18 @@ InetAddress addr=InetAddress.getByName(this.getAddress()); this.server=fact.createSocket(port,accc,addr); } - } catch (IOException e) { - throw new LifecycleException("Error creating server socket",e); + } catch (KeyStoreException kse) { + throw new LifecycleException("Error creating server socket",kse); + } catch (IOException ioe) { + throw new LifecycleException("Error creating server socket",ioe); + } catch (NoSuchAlgorithmException nsae) { + throw new LifecycleException("Error creating server socket",nsae); + } catch (CertificateException ce) { + throw new LifecycleException("Error creating server socket",ce); + } catch (UnrecoverableKeyException uke) { + throw new LifecycleException("Error creating server socket",uke); + } catch (KeyManagementException kme) { + throw new LifecycleException("Error creating server socket",kme); } }