OpenSSLSocketImpl.java revision ef628d1464e57552403ad43366e153c1ef50b926
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 256df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey; 266df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom; 2712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 3130da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybobimport java.util.concurrent.atomic.AtomicInteger; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Logger; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException; 36bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 38059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implementation of the class OpenSSLSocketImpl 433e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom * based on OpenSSL. 44ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 46ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document. 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 48ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl 49ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom extends javax.net.ssl.SSLSocket 506df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 51ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private int sslNativePointer; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream is; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream os; 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Object handshakeLock = new Object(); 55ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object readLock = new Object(); 56ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object writeLock = new Object(); 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private SSLParameters sslParameters; 58bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 59bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Socket socket; 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 64bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 65bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 66bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 67bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 68bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 69bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 70bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 71bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 72bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int timeout = 0; 759d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // BEGIN android-added 769d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor private int handshakeTimeout = -1; // -1 = same as timeout; 0 = infinite 779d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // END android-added 78a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 79a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8130da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob private static final AtomicInteger instanceCount = new AtomicInteger(0); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static int getInstanceCount() { 8430da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob return instanceCount.get(); 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static void updateInstanceCount(int amount) { 8830da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob instanceCount.addAndGet(amount); 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 1 parameter 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sslParameters Parameters for the SSL 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * context 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(SSLParameters sslParameters) throws IOException { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(); 100ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 104bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl 105bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 106bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param sslParameters Parameters for the SSL 107bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * context 108bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @throws IOException if network fails 109bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 110bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom protected OpenSSLSocketImpl(SSLParameters sslParameters, 111bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 112bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledCipherSuites) throws IOException { 113bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom super(); 114bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites); 115bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 116bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 3 parameters 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1230c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParameters sslParameters) 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 126ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 3 parameters: 1st is InetAddress 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParameters sslParameters) 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 138ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 5 parameters: 1st is host 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1480c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1490c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1500c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom SSLParameters sslParameters) 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 153ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 5 parameters: 1st is InetAddress 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1630c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1640c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom SSLParameters sslParameters) 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 167ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructor with 5 parameters: 1st is socket. Enhances an existing socket 172a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor. 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean autoClose, SSLParameters sslParameters) throws IOException { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.timeout = socket.getSoTimeout(); 181a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 182a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 184ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 185ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 186ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 187ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 188ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 189ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 190ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 191ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void init(SSLParameters sslParameters) throws IOException { 192bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 193bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.getSupportedProtocols(), 194bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.getDefaultCipherSuites()); 195ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 196ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 197ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 198bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 199bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 200ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 201bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void init(SSLParameters sslParameters, 202bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 203bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledCipherSuites) throws IOException { 204bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 205bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 206bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project updateInstanceCount(1); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return OpenSSLSessionImpl 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 215bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (super.getInetAddress() == null || 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostAddress() == null || 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostName() == null) { 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession( 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostName(), 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getPort()); 2249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2269acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2289acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2299acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2309acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2319acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2329acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2339acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2349acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2359acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2369acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2379acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2389acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2399acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2409acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2419acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2429acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2439acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2449acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2459acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2469acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2479acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2489acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2499acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2509acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2516df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2529acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Ensures that logger is lazily loaded. The outer class seems to load 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * before logging is ready. 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static class LoggerHolder { 260ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName()); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts a TLS/SSL handshake on this connection using some native methods 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from the OpenSSL library. It can negotiate new encryption keys, change 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * cipher suites, or initiate a new session. The certificate chain is 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * verified if the correspondent property in java.Security is set. All 268ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * listeners are notified at the end of the TLS/SSL handshake. 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if network fails 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 272bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void startHandshake() throws IOException { 273bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom startHandshake(true); 274bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 275bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 276bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 277bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Perform the handshake 278bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param full If true, disable handshake cutthrough for a fully synchronous handshake 279bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 280bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public synchronized void startHandshake(boolean full) throws IOException { 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2896df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 2906df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 2916df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 2926df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 2936df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 2946df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 2956df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 2966df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 2976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 2996df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 3006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int sslCtxNativePointer = (client) ? 3016df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 3026df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 3036df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 3046df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom this.sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 3056df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 3066df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // setup server certificates and private keys. 3076df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // clients will receive a call back to request certificates. 3086df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (!client) { 3096df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom for (String keyType : NativeCrypto.KEY_TYPES) { 310ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom try { 311ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 312ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom null, 313ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom this)); 314ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } catch (CertificateEncodingException e) { 315ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new IOException(e); 316ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3176df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3186df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3196df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 320bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 321bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 322bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 323bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 324bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (!enableSessionCreation) { 325bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 326bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enableSessionCreation); 327bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 328bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 329bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext; 330bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSessionImpl session; 331bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 332bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // look for client session to reuse 333bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 334bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sessionContext = clientSessionContext; 335bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom session = getCachedClientSession(clientSessionContext); 336bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (session != null) { 337bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, session.sslSessionNativePointer); 338bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 339bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 340bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 341bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom session = null; 342bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 343bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 344bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // setup peer certificate verification 345bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 3466df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // TODO support for anonymous cipher would require us to 3476df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // conditionally use SSL_VERIFY_NONE 348bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 349bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // needing client auth takes priority... 350ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom boolean certRequested = false; 351bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslParameters.getNeedClientAuth()) { 352bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 353ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom NativeCrypto.SSL_VERIFY_PEER 354ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 355ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom certRequested = true; 356bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // ... over just wanting it... 357bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else if (sslParameters.getWantClientAuth()) { 358bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 359e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 360ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom certRequested = true; 361bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // ... and it defaults properly so we don't need call SSL_set_verify in the common case. 362ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 363ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom certRequested = false; 364ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 365059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 366ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (certRequested) { 367ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom X509Certificate[] issuers = sslParameters.getTrustManager().getAcceptedIssuers(); 368ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (issuers != null) { 369ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] issuersBytes; 370ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom try { 371ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 372ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } catch (CertificateEncodingException e) { 373ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new IOException("Problem encoding principals", e); 374ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 375ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 376ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 377ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 378bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 379bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 380bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client && full) { 381bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 3826df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 3836df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 384ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 385ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 386ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // BEGIN android-added 387ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // Temporarily use a different timeout for the handshake process 388ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom int savedTimeout = timeout; 389ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (handshakeTimeout >= 0) { 390ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom setSoTimeout(handshakeTimeout); 391ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 392ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // END android-added 393ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 394bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 395ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom Socket socket = this.socket != null ? this.socket : this; 396bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom int sslSessionNativePointer; 397bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 3986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslSessionNativePointer 3996df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom = NativeCrypto.SSL_do_handshake(sslNativePointer, socket, this, timeout, client); 400bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 401bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new SSLPeerUnverifiedException(e.getMessage()); 402bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 403f002bdddce924e2145a4a2b60592b7a40f4112f6Brian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 404bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 405bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession != null) { 4069acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 407ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom LoggerHolder.logger.fine("Reused cached session for " 408bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom + getInetAddress() + "."); 409f002bdddce924e2145a4a2b60592b7a40f4112f6Brian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 411bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (!enableSessionCreation) { 412bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 413bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 414bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 415bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom byte[][] localCertificatesBytes = NativeCrypto.SSL_get_certificate(sslNativePointer); 416bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] localCertificates; 417bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (localCertificatesBytes == null) { 418bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom localCertificates = null; 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 420bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom localCertificates = new X509Certificate[localCertificatesBytes.length]; 421bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < localCertificatesBytes.length; i++) { 422059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom localCertificates[i] = new X509CertImpl(localCertificatesBytes[i]); 423bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 424ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 426a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom if (wrappedHost == null) { 427bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 428ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom super.getInetAddress().getHostName(), 429ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom super.getPort(), sessionContext); 430ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } else { 431bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 432a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom wrappedHost, wrappedPort, 433ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sessionContext); 434ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 4350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 436bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (handshakeCompleted) { 437ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sessionContext.putSession(sslSession); 4389d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 439bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom LoggerHolder.logger.fine("Created new session for " 440bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom + getInetAddress().getHostName() + "."); 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 443ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // BEGIN android-added 444ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // Restore the original timeout now that the handshake is complete 445ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (handshakeTimeout >= 0) { 446ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom setSoTimeout(savedTimeout); 447ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 448ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom // END android-added 449ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 4500c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 451bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (handshakeCompleted) { 452bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 455bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 457ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 4586df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 4596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 4606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 46312cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom byte[] privateKeyBytes = privateKey.getEncoded(); 4646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 4656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 467ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 4686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 4696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 4716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 4726df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 4736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4756df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom /** 4766df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 4776df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * invoked via JNI from client_cert_cb 4786df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom */ 479059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 480ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 481059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 482059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 483059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 484059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]); 485059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 486059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 487059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 488059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 489059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 490059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 491059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 492059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 493059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 494059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 495059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 496059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 4976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 501bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * invoked via JNI from info_callback 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 503bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 504bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 506bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 507bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 508bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // later read operation. That means we do not need to fixup 509bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 510bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 511bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 512bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 513bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 514bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 516bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 517bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 518bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 519bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 520bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 521bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 522bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 524bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 525bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 526bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 527bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 528bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 529bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 530bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 531bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 532bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 533bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 534bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 535bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 536bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 537bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 538e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 539e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 540e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 541e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 542e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 543e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 544e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 545bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 546bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 547bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5516df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 552ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 553059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom * @param bytes An array of ASN.1 DER encoded certficates 554bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param authMethod auth algorithm name 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 556bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @throws CertificateException if the certificate is untrusted 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @SuppressWarnings("unused") 5596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom public void verifyCertificateChain(byte[][] bytes, String authMethod) 5606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 562e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 563e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 564e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 566bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project peerCertificateChain[i] = 5686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom new X509CertImpl( 5696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded()); 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 571bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 572bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 5736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 5746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom authMethod); 575bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 5766df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 5776df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom authMethod); 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 579bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 580bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 581bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 582bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 583bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new RuntimeException(e); 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an input stream for this SSL socket using native calls to the 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OpenSSL library. 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return: an input stream for reading bytes from this socket. 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws: <code>IOException</code> if an I/O error occurs when creating 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input stream, the socket is closed, the socket is not 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connected, or the socket input has been shutdown. 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStream getInputStream() throws IOException { 597ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an output stream for this SSL socket using native calls to the 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OpenSSL library. 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an output stream for writing bytes to this socket. 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if an I/O error occurs when creating 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output stream, or no connection to the socket exists. 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public OutputStream getOutputStream() throws IOException { 615ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 624bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 625bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * This method is not supported for this SSLSocket implementation 626bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * because reading from an SSLSocket may involve writing to the 627bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * network. 628bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void shutdownInput() throws IOException { 630bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new UnsupportedOperationException(); 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 633bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 634bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * This method is not supported for this SSLSocket implementation 635bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * because writing to an SSLSocket may involve reading from the 636bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * network. 637bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void shutdownOutput() throws IOException { 639bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new UnsupportedOperationException(); 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 653bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 664ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 6653e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom return NativeCrypto.SSL_read_byte(sslNativePointer, timeout); 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read(byte[] b, int off, int len) throws IOException { 674ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (b == null) { 675ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new NullPointerException("b == null"); 676ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 677ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if ((len | off) < 0 || len > b.length - off) { 678ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new IndexOutOfBoundsException(); 679ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 680ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (0 == len) { 681ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom return 0; 682ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 683ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 6843e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom return NativeCrypto.SSL_read(sslNativePointer, b, off, len, timeout); 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 698ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 700bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(int b) throws IOException { 708ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 7093e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_write_byte(sslNativePointer, b); 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(byte[] b, int start, int len) throws IOException { 718ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (b == null) { 719ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new NullPointerException("b == null"); 720ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 721ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if ((len | start) < 0 || len > b.length - start) { 722ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throw new IndexOutOfBoundsException(); 723ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 724ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom if (len == 0) { 725ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom return; 726ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 727ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 7283e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_write(sslNativePointer, b, start, len); 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The SSL session used by this connection is returned. The SSL session 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * determines which cipher suite should be used by all connections within 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * that session and which identities have the session's client and server. 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method starts the SSL handshake. 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the SSLSession. 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if the handshake fails 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SSLSession getSession() { 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 744bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom startHandshake(true); 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // return an invalid session with 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return SSLSessionImpl.NULL_SESSION; 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Registers a listener to be notified that a SSL handshake 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * was successfully completed on this connection. 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IllegalArgumentException</code> if listener is null. 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void addHandshakeCompletedListener( 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners = new ArrayList(); 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The method removes a registered listener. 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException if listener is null or not registered 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void removeHandshakeCompletedListener( 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if new SSL sessions may be established by this socket. 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the session may be created; false if a session already 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exists and must be resumed. 793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getEnableSessionCreation() { 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set a flag for the socket to inhibit or to allow the creation of a new 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSL sessions. If the flag is set to false, and there are no actual 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sessions to resume, then there will be no successful handshaking. 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param flag true if session may be created; false 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a session already exists and must be resumed. 805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setEnableSessionCreation(boolean flag) { 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the cipher suites which could be used by the SSL connection 812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * are returned. 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of cipher suite names 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getSupportedCipherSuites() { 816ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the cipher suites that are in use in the actual the SSL 821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection are returned. 822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of cipher suite names 824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getEnabledCipherSuites() { 826bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method enables the cipher suites listed by 831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * getSupportedCipherSuites(). 832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param suites names of all the cipher suites to 834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * put on use 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException when one or more of the 836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ciphers in array suites are not supported, or when the array 837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is null. 838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setEnabledCipherSuites(String[] suites) { 840bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the protocols' versions that may be used on this SSL 845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection. 846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of protocols names 847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getSupportedProtocols() { 849ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the protocols' versions that are in use on this SSL 854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection. 855ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of protocols names 857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getEnabledProtocols() { 860bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method enables the protocols' versions listed by 865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * getSupportedProtocols(). 866ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param protocols The names of all the protocols to put on use 868ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException when one or more of the names in the 870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * array are not supported, or when the array is null. 871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void setEnabledProtocols(String[] protocols) { 874bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method gives true back if the SSL socket is set to client mode. 879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the socket should do the handshaking as client. 881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getUseClientMode() { 883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method set the actual SSL socket to client mode. 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param mode true if the socket starts in client 890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mode 891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException if mode changes during 892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handshake. 893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void setUseClientMode(boolean mode) { 895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Could not change the mode after the initial handshake has begun."); 898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the SSL socket requests client's authentication. Relevant 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * only for server sockets! 905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if client authentication is desired, false if not. 907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getWantClientAuth() { 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the SSL socket needs client's authentication. Relevant 914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * only for server sockets! 915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if client authentication is desired, false if not. 917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getNeedClientAuth() { 919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * server sockets! 925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param need true if client authentication is 927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * desired, false if not. 928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setNeedClientAuth(boolean need) { 930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * server sockets! Notice that in contrast to setNeedClientAuth(..) this 936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method will continue the negotiation if the client decide not to send 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * authentication credentials. 938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param want true if client authentication is 940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * desired, false if not. 941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setWantClientAuth(boolean want) { 943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method is not supported for SSLSocket implementation. 948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void sendUrgentData(int data) throws IOException { 950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SocketException( 951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Method sendUrgentData() is not supported."); 952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method is not supported for SSLSocket implementation. 956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setOOBInline(boolean on) throws SocketException { 958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SocketException( 959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Methods sendUrgentData, setOOBInline are not supported."); 960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the read timeout on this socket. The SO_TIMEOUT option, is specified 964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in milliseconds. The read operation will block indefinitely for a zero 965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * value. 966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout the read timeout value 968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SocketException if an error occurs setting the option 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void setSoTimeout(int timeout) throws SocketException { 971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.setSoTimeout(timeout); 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.timeout = timeout; 973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9759d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // BEGIN android-added 9769d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 9779d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 9789d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 9799d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * 9809d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * @param timeout the handshake timeout value 9819d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 9829d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor public synchronized void setHandshakeTimeout(int timeout) throws SocketException { 9839d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor this.handshakeTimeout = timeout; 9849d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 9859d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // END android-added 9869d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes the SSL socket. Once closed, a socket is not available for further 989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * use anymore under any circumstance. A new socket must be created. 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if an I/O error happens during the 992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * socket's closure. 993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // TODO: Close SSL sockets using a background thread so they close 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // gracefully. 997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 1000bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // prevent further attemps to start handshake 1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 1002ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 1004ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (socket != null) { 1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1012ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1015adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1016adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10173e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (writeLock) { 1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (readLock) { 1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project IOException pendingException = null; 1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 10283e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_shutdown(sslNativePointer); 1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note the exception at this point, but try to continue 1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to clean the rest of this all up before rethrowing. 1034adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1035adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pendingException = ex; 1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Even if the above call failed, it is still safe to free 1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the native structs, and we need to do so lest we leak 1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * memory. 1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1043ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (socket != null) { 1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) 1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socket.close(); 1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) 1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.close(); 1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pendingException != null) { 1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw pendingException; 1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1061ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 1062ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 1063ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 1064ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1065ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1066ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 1067ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void finalize() throws IOException { 1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 1071bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Just worry about our own state. Notably we do not try and 1072bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * close anything. The SocketImpl, either our own 1073bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 1074bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 1075bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * if you want to do that, properly close the socket yourself. 1076bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 1077bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 1078bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 1079bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * finalizer runs first and closes the socket. However, in the 1080bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 1081bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 1082bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * underlying socket BIOs still have the old file descriptor 1083bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * and will write the close notify to some unsuspecting 1084bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * reader. 1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1086bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom updateInstanceCount(-1); 1087bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom free(); 1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1090