OpenSSLServerSocketImpl.java revision 6c78b7b94c232063ec559436b48b33751373ecf1
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) 41 throws IOException { 42 super(); 43 this.sslParameters = sslParameters; 44 } 45 46 protected OpenSSLServerSocketImpl(int port, SSLParametersImpl sslParameters) 47 throws IOException { 48 super(port); 49 this.sslParameters = sslParameters; 50 } 51 52 protected OpenSSLServerSocketImpl(int port, int backlog, SSLParametersImpl sslParameters) 53 throws IOException { 54 super(port, backlog); 55 this.sslParameters = sslParameters; 56 } 57 58 protected OpenSSLServerSocketImpl(int port, 59 int backlog, 60 InetAddress iAddress, 61 SSLParametersImpl sslParameters) 62 throws IOException { 63 super(port, backlog, iAddress); 64 this.sslParameters = sslParameters; 65 } 66 67 @Override 68 public boolean getEnableSessionCreation() { 69 return sslParameters.getEnableSessionCreation(); 70 } 71 72 @Override 73 public void setEnableSessionCreation(boolean flag) { 74 sslParameters.setEnableSessionCreation(flag); 75 } 76 77 /** 78 * The names of the protocols' versions that may be used on this SSL 79 * connection. 80 * @return an array of protocols names 81 */ 82 @Override 83 public String[] getSupportedProtocols() { 84 return NativeCrypto.getSupportedProtocols(); 85 } 86 87 /** 88 * The names of the protocols' versions that in use on this SSL connection. 89 * 90 * @return an array of protocols names 91 */ 92 @Override 93 public String[] getEnabledProtocols() { 94 return enabledProtocols.clone(); 95 } 96 97 /** 98 * This method enables the protocols' versions listed by 99 * getSupportedProtocols(). 100 * 101 * @param protocols names of all the protocols to enable. 102 * 103 * @throws IllegalArgumentException when one or more of the names in the 104 * array are not supported, or when the array is null. 105 */ 106 @Override 107 public void setEnabledProtocols(String[] protocols) { 108 enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 109 } 110 111 @Override 112 public String[] getSupportedCipherSuites() { 113 return NativeCrypto.getSupportedCipherSuites(); 114 } 115 116 @Override 117 public String[] getEnabledCipherSuites() { 118 return enabledCipherSuites.clone(); 119 } 120 121 /** 122 * This method enables the cipher suites listed by 123 * getSupportedCipherSuites(). 124 * 125 * @param suites the names of all the cipher suites to enable 126 * @throws IllegalArgumentException when one or more of the ciphers in array 127 * suites are not supported, or when the array is null. 128 */ 129 @Override 130 public void setEnabledCipherSuites(String[] suites) { 131 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 132 } 133 134 public String[] getSupportedCompressionMethods() { 135 return NativeCrypto.getSupportedCompressionMethods(); 136 } 137 138 public String[] getEnabledCompressionMethods() { 139 return enabledCompressionMethods.clone(); 140 } 141 142 /** 143 * This method enables the compression methods listed by 144 * getSupportedCompressionMethods(). 145 * 146 * @param suites the names of all the compression methods to enable 147 * @throws IllegalArgumentException when one or more of the ciphers in array 148 * suites are not supported, or when the array is null. 149 */ 150 public void setEnabledCompressionMethods(String[] methods) { 151 enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 152 } 153 154 @Override 155 public boolean getWantClientAuth() { 156 return sslParameters.getWantClientAuth(); 157 } 158 159 @Override 160 public void setWantClientAuth(boolean want) { 161 sslParameters.setWantClientAuth(want); 162 } 163 164 @Override 165 public boolean getNeedClientAuth() { 166 return sslParameters.getNeedClientAuth(); 167 } 168 169 @Override 170 public void setNeedClientAuth(boolean need) { 171 sslParameters.setNeedClientAuth(need); 172 } 173 174 @Override 175 public void setUseClientMode(boolean mode) { 176 sslParameters.setUseClientMode(mode); 177 } 178 179 @Override 180 public boolean getUseClientMode() { 181 return sslParameters.getUseClientMode(); 182 } 183 184 @Override 185 public Socket accept() throws IOException { 186 187 if (!sslParameters.getUseClientMode()) { 188 checkEnabledCipherSuites(); 189 } 190 191 OpenSSLSocketImpl socket = new OpenSSLSocketImpl(sslParameters, 192 enabledProtocols.clone(), 193 enabledCipherSuites.clone(), 194 enabledCompressionMethods.clone()); 195 implAccept(socket); 196 return socket; 197 } 198 199 /** 200 * Check if any of the enabled cipher suites has a chance to work. 201 * Not 100% accurate, just a useful diagnostic that the RI does. 202 */ 203 private void checkEnabledCipherSuites() throws SSLException { 204 /* Loop over all enabled cipher suites. If we find a problem, 205 * we just continue to the next one. If we find one that could 206 * work, we return. This basically makes sure the caller has 207 * configured some appropriate certificate/key unless 208 * an anonymous cipher is picked. 209 */ 210 for (String enabledCipherSuite : enabledCipherSuites) { 211 String keyType = CipherSuite.getByName(enabledCipherSuite).getKeyType(); 212 if (keyType == null) { 213 // anonymous always work 214 return; 215 } 216 if (keyType.equals(NativeCrypto.KEY_TYPE_RSA) 217 || keyType.equals(NativeCrypto.KEY_TYPE_DH_RSA)) { 218 if (checkForPrivateKey(keyType, RSAPrivateKey.class)) { 219 return; 220 } 221 continue; 222 } 223 if (keyType.equals(NativeCrypto.KEY_TYPE_DSA) 224 || keyType.equals(NativeCrypto.KEY_TYPE_DH_DSA)) { 225 if (checkForPrivateKey(keyType, DSAPrivateKey.class)) { 226 return; 227 } 228 continue; 229 } 230 if (keyType.equals(NativeCrypto.KEY_TYPE_EC) 231 || keyType.equals(NativeCrypto.KEY_TYPE_EC_RSA) 232 || keyType.equals(NativeCrypto.KEY_TYPE_EC_EC)) { 233 if (checkForPrivateKey(keyType, ECPrivateKey.class)) { 234 return; 235 } 236 continue; 237 } 238 throw new IllegalStateException("Unknown key type " + keyType); 239 } 240 throw new SSLException("Could not find any key store entries " 241 + "to support the enabled cipher suites."); 242 } 243 244 private boolean checkForPrivateKey(String keyType, Class keyClass) { 245 String alias = sslParameters.getKeyManager().chooseServerAlias(keyType, null, null); 246 if (alias == null) { 247 return false; 248 } 249 PrivateKey key = sslParameters.getKeyManager().getPrivateKey(alias); 250 return (key != null && keyClass.isAssignableFrom(key.getClass())); 251 } 252} 253