OpenSSLServerSocketImpl.java revision 32c2297a959b72abdb18743f0519e1d8b7c7ea88
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package org.apache.harmony.xnet.provider.jsse; 18 19import java.io.IOException; 20import java.net.InetAddress; 21import java.net.Socket; 22import java.security.PrivateKey; 23import java.security.interfaces.ECPrivateKey; 24import java.security.interfaces.DSAPrivateKey; 25import java.security.interfaces.RSAPrivateKey; 26import javax.net.ssl.SSLException; 27 28/** 29 * OpenSSL-based implementation of server sockets. 30 * 31 * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 32 * later, for example in the package.html or a separate reference document. 33 */ 34public class OpenSSLServerSocketImpl extends javax.net.ssl.SSLServerSocket { 35 private final SSLParametersImpl sslParameters; 36 private String[] enabledProtocols = NativeCrypto.getSupportedProtocols(); 37 private String[] enabledCipherSuites = NativeCrypto.getDefaultCipherSuites(); 38 private String[] enabledCompressionMethods = NativeCrypto.getDefaultCompressionMethods(); 39 40 protected OpenSSLServerSocketImpl(SSLParametersImpl sslParameters) throws IOException { 41 this.sslParameters = sslParameters; 42 } 43 44 protected OpenSSLServerSocketImpl(int port, SSLParametersImpl sslParameters) 45 throws IOException { 46 super(port); 47 this.sslParameters = sslParameters; 48 } 49 50 protected OpenSSLServerSocketImpl(int port, int backlog, SSLParametersImpl sslParameters) 51 throws IOException { 52 super(port, backlog); 53 this.sslParameters = sslParameters; 54 } 55 56 protected OpenSSLServerSocketImpl(int port, 57 int backlog, 58 InetAddress iAddress, 59 SSLParametersImpl sslParameters) 60 throws IOException { 61 super(port, backlog, iAddress); 62 this.sslParameters = sslParameters; 63 } 64 65 @Override 66 public boolean getEnableSessionCreation() { 67 return sslParameters.getEnableSessionCreation(); 68 } 69 70 @Override 71 public void setEnableSessionCreation(boolean flag) { 72 sslParameters.setEnableSessionCreation(flag); 73 } 74 75 /** 76 * The names of the protocols' versions that may be used on this SSL 77 * connection. 78 * @return an array of protocols names 79 */ 80 @Override 81 public String[] getSupportedProtocols() { 82 return NativeCrypto.getSupportedProtocols(); 83 } 84 85 /** 86 * The names of the protocols' versions that in use on this SSL connection. 87 * 88 * @return an array of protocols names 89 */ 90 @Override 91 public String[] getEnabledProtocols() { 92 return enabledProtocols.clone(); 93 } 94 95 /** 96 * This method enables the protocols' versions listed by 97 * getSupportedProtocols(). 98 * 99 * @param protocols names of all the protocols to enable. 100 * 101 * @throws IllegalArgumentException when one or more of the names in the 102 * array are not supported, or when the array is null. 103 */ 104 @Override 105 public void setEnabledProtocols(String[] protocols) { 106 enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 107 } 108 109 @Override 110 public String[] getSupportedCipherSuites() { 111 return NativeCrypto.getSupportedCipherSuites(); 112 } 113 114 @Override 115 public String[] getEnabledCipherSuites() { 116 return enabledCipherSuites.clone(); 117 } 118 119 /** 120 * This method enables the cipher suites listed by 121 * getSupportedCipherSuites(). 122 * 123 * @param suites the names of all the cipher suites to enable 124 * @throws IllegalArgumentException when one or more of the ciphers in array 125 * suites are not supported, or when the array is null. 126 */ 127 @Override 128 public void setEnabledCipherSuites(String[] suites) { 129 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 130 } 131 132 public String[] getSupportedCompressionMethods() { 133 return NativeCrypto.getSupportedCompressionMethods(); 134 } 135 136 public String[] getEnabledCompressionMethods() { 137 return enabledCompressionMethods.clone(); 138 } 139 140 /** 141 * This method enables the compression methods listed by 142 * getSupportedCompressionMethods(). 143 * 144 * @param suites the names of all the compression methods to enable 145 * @throws IllegalArgumentException when one or more of the ciphers in array 146 * suites are not supported, or when the array is null. 147 */ 148 public void setEnabledCompressionMethods(String[] methods) { 149 enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 150 } 151 152 @Override 153 public boolean getWantClientAuth() { 154 return sslParameters.getWantClientAuth(); 155 } 156 157 @Override 158 public void setWantClientAuth(boolean want) { 159 sslParameters.setWantClientAuth(want); 160 } 161 162 @Override 163 public boolean getNeedClientAuth() { 164 return sslParameters.getNeedClientAuth(); 165 } 166 167 @Override 168 public void setNeedClientAuth(boolean need) { 169 sslParameters.setNeedClientAuth(need); 170 } 171 172 @Override 173 public void setUseClientMode(boolean mode) { 174 sslParameters.setUseClientMode(mode); 175 } 176 177 @Override 178 public boolean getUseClientMode() { 179 return sslParameters.getUseClientMode(); 180 } 181 182 @Override 183 public Socket accept() throws IOException { 184 185 if (!sslParameters.getUseClientMode()) { 186 checkEnabledCipherSuites(); 187 } 188 189 OpenSSLSocketImpl socket = new OpenSSLSocketImpl(sslParameters, 190 enabledProtocols.clone(), 191 enabledCipherSuites.clone(), 192 enabledCompressionMethods.clone()); 193 implAccept(socket); 194 return socket; 195 } 196 197 /** 198 * Check if any of the enabled cipher suites has a chance to work. 199 * Not 100% accurate, just a useful diagnostic that the RI does. 200 */ 201 private void checkEnabledCipherSuites() throws SSLException { 202 /* Loop over all enabled cipher suites. If we find a problem, 203 * we just continue to the next one. If we find one that could 204 * work, we return. This basically makes sure the caller has 205 * configured some appropriate certificate/key unless 206 * an anonymous cipher is picked. 207 */ 208 for (String enabledCipherSuite : enabledCipherSuites) { 209 if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 210 continue; 211 } 212 String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 213 if (keyType == null) { 214 // anonymous always work 215 return; 216 } 217 if (keyType.equals(CipherSuite.KEY_TYPE_RSA) 218 || keyType.equals(CipherSuite.KEY_TYPE_DH_RSA)) { 219 if (checkForPrivateKey(keyType, RSAPrivateKey.class)) { 220 return; 221 } 222 continue; 223 } 224 if (keyType.equals(CipherSuite.KEY_TYPE_DSA) 225 || keyType.equals(CipherSuite.KEY_TYPE_DH_DSA)) { 226 if (checkForPrivateKey(keyType, DSAPrivateKey.class)) { 227 return; 228 } 229 continue; 230 } 231 if (keyType.equals(CipherSuite.KEY_TYPE_EC) 232 || keyType.equals(CipherSuite.KEY_TYPE_EC_RSA) 233 || keyType.equals(CipherSuite.KEY_TYPE_EC_EC)) { 234 if (checkForPrivateKey(keyType, ECPrivateKey.class)) { 235 return; 236 } 237 continue; 238 } 239 throw new IllegalStateException("Unknown key type " + keyType); 240 } 241 throw new SSLException("Could not find any key store entries " 242 + "to support the enabled cipher suites."); 243 } 244 245 private boolean checkForPrivateKey(String keyType, Class keyClass) { 246 String alias = sslParameters.getKeyManager().chooseServerAlias(keyType, null, null); 247 if (alias == null) { 248 return false; 249 } 250 PrivateKey key = sslParameters.getKeyManager().getPrivateKey(alias); 251 return (key != null && keyClass.isAssignableFrom(key.getClass())); 252 } 253} 254