OpenSSLSocketImpl.java revision 4ae3fd787741bfe1b808f447dcb0785250024119
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 195900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrickimport dalvik.system.BlockGuard; 20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 21df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstromimport java.io.FileDescriptor; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 286df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey; 296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom; 3012cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 346c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.HashSet; 356c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.Set; 3630da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybobimport java.util.concurrent.atomic.AtomicInteger; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Logger; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException; 41bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 43f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager; 44059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 51ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document. 524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include: 544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul> 554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout 564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>compression methods 574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets 584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication 594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul> 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 61ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl 62ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom extends javax.net.ssl.SSLSocket 636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 64df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom 65ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private int sslNativePointer; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream is; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream os; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Object handshakeLock = new Object(); 69ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object readLock = new Object(); 70ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object writeLock = new Object(); 716812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private SSLParametersImpl sslParameters; 72bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 73bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String[] enabledCompressionMethods; 754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean useSessionTickets; 764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String hostname; 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 78df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final Socket socket; 79df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final FileDescriptor fd; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 8212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 83bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 84bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 85bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 86bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 93a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 94a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom /** 95a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 96a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * write for non-wrapped sockets. Note that 97a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 98a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom */ 100a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int timeoutMilliseconds = 0; 101a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 1029d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // BEGIN android-added 103a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 1049d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // END android-added 105a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 106a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 1 parameter 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sslParameters Parameters for the SSL 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * context 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1156812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(); 117df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 118df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 119ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 123bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl 124bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 125bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param sslParameters Parameters for the SSL 126bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * context 127bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @throws IOException if network fails 128bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 1296812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 130bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1314559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCipherSuites, 1324559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 133bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom super(); 134df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 135df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 1364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods); 137bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 138bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 139bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 3 parameters 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1456812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 146df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 148df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 149df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 150ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 3 parameters: 1st is InetAddress 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1596812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 160df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 162df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 163df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 164ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 5 parameters: 1st is host 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1740c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1750c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1766812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom SSLParametersImpl sslParameters) 177df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 179df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 180df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 181ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Class constructor with 5 parameters: 1st is InetAddress 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws java.net.UnknownHostException host not defined 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1910c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1926812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom SSLParametersImpl sslParameters) 193df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 195df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 196df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 197ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructor with 5 parameters: 1st is socket. Enhances an existing socket 202a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor. 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException if network fails 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 2076812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 210df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.fd = NativeCrypto.getFileDescriptor(socket); 211a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 212a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 214ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 215a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 216a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // this.timeout is not set intentionally. 217a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 218a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // to wrapped socket 219ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 220ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 221ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 222ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 223ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 224ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 2256812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 226bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 227bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.getSupportedProtocols(), 2284559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom NativeCrypto.getDefaultCipherSuites(), 2294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom NativeCrypto.getDefaultCompressionMethods()); 230ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 231ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 232ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 233bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 234bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 235ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 2366812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters, 237bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 2384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCipherSuites, 2394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 240bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 241bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 242bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 2434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.enabledCompressionMethods = enabledCompressionMethods; 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return OpenSSLSessionImpl 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 251bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (super.getInetAddress() == null || 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostAddress() == null || 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostName() == null) { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2579acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession( 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getInetAddress().getHostName(), 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.getPort()); 2609acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2619acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2629acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2639acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2649acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2659acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2669acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2679acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2689acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2699acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2709acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2719acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2729acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2739acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2749acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2759acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2769acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2779acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2789acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2799acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2809acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2819acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2829acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2839acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2849acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2859acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2869acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2876df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2884559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String compressionMethod = session.getCompressionMethod(); 2894559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom boolean compressionMethodFound = false; 2904559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom for (String enabledCompressionMethod : enabledCompressionMethods) { 2914559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom if (compressionMethod.equals(enabledCompressionMethod)) { 2924559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom compressionMethodFound = true; 2934559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom break; 2944559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 2954559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 2964559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom if (!compressionMethodFound) { 2974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return null; 2984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 2994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 3009acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Ensures that logger is lazily loaded. The outer class seems to load 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * before logging is ready. 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static class LoggerHolder { 308ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName()); 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts a TLS/SSL handshake on this connection using some native methods 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from the OpenSSL library. It can negotiate new encryption keys, change 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * cipher suites, or initiate a new session. The certificate chain is 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * verified if the correspondent property in java.Security is set. All 316ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * listeners are notified at the end of the TLS/SSL handshake. 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if network fails 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 321bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void startHandshake() throws IOException { 322bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom startHandshake(true); 323bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 324bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 325bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 3265f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom * Checks whether the socket is closed, and throws an exception. 3275f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom * 3285f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom * @throws SocketException 3295f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom * if the socket is closed. 3305f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom */ 3315f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom private void checkOpen() throws SocketException { 3325f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom if (isClosed()) { 3335f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom throw new SocketException("Socket is closed"); 3345f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 3355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 3365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom 3375f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom /** 338bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Perform the handshake 339bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param full If true, disable handshake cutthrough for a fully synchronous handshake 340bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 341bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public synchronized void startHandshake(boolean full) throws IOException { 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 34312e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3516df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 3526df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 3536df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 3546df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 3556df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 3566df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 3576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 3586df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 3606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 3616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 3626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int sslCtxNativePointer = (client) ? 3636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 3646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 3656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 366f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this.sslNativePointer = 0; 367f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean exception = true; 368f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 369f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 370f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 3716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 372f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup server certificates and private keys. 373f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // clients will receive a call back to request certificates. 374f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!client) { 3756c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 3766c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 3774ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 3786c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom if (keyType != null) { 3796c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom keyTypes.add(keyType); 3806c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3816c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3826c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String keyType : keyTypes) { 383f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 384f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 385f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom null, 386f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this)); 387f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 388f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException(e); 389f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 390ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3916df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3926df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 393f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 394f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 395f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (enabledCompressionMethods.length != 0) { 396f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCompressionMethods(sslNativePointer, 397f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enabledCompressionMethods); 398f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 399f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (useSessionTickets) { 400f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 401f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 402f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (hostname != null) { 403f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 405bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 406f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 407f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 409f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enableSessionCreation); 410bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 411bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 412f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom AbstractSessionContext sessionContext; 413f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom OpenSSLSessionImpl session; 414f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 415f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // look for client session to reuse 416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 417f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = clientSessionContext; 418f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom session = getCachedClientSession(clientSessionContext); 419f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (session != null) { 420f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom session.sslSessionNativePointer); 422f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 423ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 424f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 425f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom session = null; 426ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 427059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 428f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup peer certificate verification 429f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 430f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // TODO support for anonymous cipher would require us to 431f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // conditionally use SSL_VERIFY_NONE 432f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 433f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // needing client auth takes priority... 434f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean certRequested = false; 435f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 436f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 437f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 438f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 439f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 440f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... over just wanting it... 441f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 442f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 443f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 444f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 445f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 446f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 447f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = false; 448f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 449f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 450f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (certRequested) { 451f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 452f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 453f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (issuers != null && issuers.length != 0) { 454f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[][] issuersBytes; 455f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 456f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 457f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 458f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException("Problem encoding principals", e); 459f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 460f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 461ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 462ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 463ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 464ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 465f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client && full) { 466f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 467f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 468f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 469f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 470ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 471f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // BEGIN android-added 472f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Temporarily use a different timeout for the handshake process 473f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int savedTimeoutMilliseconds = getSoTimeout(); 474f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 475f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 476f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 477f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // END android-added 478bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 479f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int sslSessionNativePointer; 480f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 481f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, fd, this, 482f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom getSoTimeout(), client); 483f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateException e) { 484f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new SSLPeerUnverifiedException(e.getMessage()); 485bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 486f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 487f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 488f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslSession != null) { 489f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 490f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom LoggerHolder.logger.fine("Reused cached session for " 491f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom + getInetAddress() + "."); 492f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 493f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 494f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 495f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 496f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 497f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 498f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] localCertificates 499f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 500f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] peerCertificates 501f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 502f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (wrappedHost == null) { 503f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 504f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom localCertificates, peerCertificates, 505f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom super.getInetAddress().getHostName(), 506f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom super.getPort(), sessionContext); 507f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 508f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 509f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom localCertificates, peerCertificates, 510f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom wrappedHost, wrappedPort, 511f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext); 512f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 513f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 514f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 515f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext.putSession(sslSession); 516f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 517f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom LoggerHolder.logger.fine("Created new session for " 518f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom + getInetAddress().getHostName() + "."); 519ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 520f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 521f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // BEGIN android-added 522f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Restore the original timeout now that the handshake is complete 523f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 524f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(savedTimeoutMilliseconds); 5259d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 526f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // END android-added 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 528f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 529f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 530f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom notifyHandshakeCompletedListeners(); 531f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 532ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 533f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom exception = false; 534f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } finally { 5358a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom // on exceptional exit, treat the socket as closed 536f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (exception) { 5378a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom close(); 538f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 540df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 542df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom /** 543df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * Return a possibly null array of X509Certificates given the 544df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * possibly null array of DER encoded bytes. 545df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom */ 546df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 547df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (certificatesBytes == null) { 548df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 549df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 550df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 551df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 552df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 553df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 554df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 555df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 556df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 557df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 558df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return certificates; 559bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 561ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 5626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 5636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 5646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 56712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom byte[] privateKeyBytes = privateKey.getEncoded(); 5686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 5696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 571ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 5726df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 5736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 5756df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 5766df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 5776df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5786df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5796df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom /** 5806df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 5816df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * invoked via JNI from client_cert_cb 5826df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom */ 583059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 584ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 585059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 586059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 587059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 5884ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 589059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 590059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 591059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 592059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 593059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 594059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 595059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 596059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 597059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 598059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 599059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 600059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 6016df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 6026df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6046df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 605bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * invoked via JNI from info_callback 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 607bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 608bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 610bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 611bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 612bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // later read operation. That means we do not need to fixup 613bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 614bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 615bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 616bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 617bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 618bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 620bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 621bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 622bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 623bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 624bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 625bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 626bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 628bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 629bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 630bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 631bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 632bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 633bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 634bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 635bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 636bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 637bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 638bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 639bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 640bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 641bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 642e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 643e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 644e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 645e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 646e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 647e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 648e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 649bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 650bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 651bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6556df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 656ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 657059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom * @param bytes An array of ASN.1 DER encoded certficates 658bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param authMethod auth algorithm name 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 660bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @throws CertificateException if the certificate is untrusted 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @SuppressWarnings("unused") 6636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom public void verifyCertificateChain(byte[][] bytes, String authMethod) 6646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 666e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 667e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 668e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 669bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 670bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 671a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 673bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 674bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 6756df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 6766df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom authMethod); 677bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 6784ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 6796df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 6804ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom authType); 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 682bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 683bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 684bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 685bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 686bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new RuntimeException(e); 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an input stream for this SSL socket using native calls to the 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OpenSSL library. 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return: an input stream for reading bytes from this socket. 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws: <code>IOException</code> if an I/O error occurs when creating 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input stream, the socket is closed, the socket is not 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connected, or the socket input has been shutdown. 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStream getInputStream() throws IOException { 7015f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 702ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns an output stream for this SSL socket using native calls to the 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OpenSSL library. 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an output stream for writing bytes to this socket. 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if an I/O error occurs when creating 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output stream, or no connection to the socket exists. 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public OutputStream getOutputStream() throws IOException { 7215f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 722ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 731bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 732bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * This method is not supported for this SSLSocket implementation 733bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * because reading from an SSLSocket may involve writing to the 734bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * network. 735bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 7364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void shutdownInput() throws IOException { 738bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new UnsupportedOperationException(); 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 741bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 742bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * This method is not supported for this SSLSocket implementation 743bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * because writing to an SSLSocket may involve reading from the 744bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * network. 745bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 7464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void shutdownOutput() throws IOException { 748bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new UnsupportedOperationException(); 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 762bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 7745900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 775ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 77612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 777df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom return NativeCrypto.SSL_read_byte(sslNativePointer, fd, OpenSSLSocketImpl.this, 778df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom getSoTimeout()); 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7864559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read(byte[] b, int off, int len) throws IOException { 7885900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 789ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 79012e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 79112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if (b == null) { 79212e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom throw new NullPointerException("b == null"); 79312e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 79412e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if ((len | off) < 0 || len > b.length - off) { 79512e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom throw new IndexOutOfBoundsException(); 79612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 79712e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if (0 == len) { 79812e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return 0; 79912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 800df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom return NativeCrypto.SSL_read(sslNativePointer, fd, OpenSSLSocketImpl.this, 801df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom b, off, len, getSoTimeout()); 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 815ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 817bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 8244559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(int b) throws IOException { 8265900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 827ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 82812e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 829df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom NativeCrypto.SSL_write_byte(sslNativePointer, fd, OpenSSLSocketImpl.this, b); 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 8374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(byte[] b, int start, int len) throws IOException { 8395900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 840ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 84112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 84212e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if (b == null) { 84312e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom throw new NullPointerException("b == null"); 84412e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 84512e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if ((len | start) < 0 || len > b.length - start) { 84612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom throw new IndexOutOfBoundsException(); 84712e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 84812e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom if (len == 0) { 84912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return; 85012e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 851df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom NativeCrypto.SSL_write(sslNativePointer, fd, OpenSSLSocketImpl.this, b, start, len); 852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The SSL session used by this connection is returned. The SSL session 859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * determines which cipher suite should be used by all connections within 860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * that session and which identities have the session's client and server. 861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method starts the SSL handshake. 862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the SSLSession. 863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if the handshake fails 864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 8654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public SSLSession getSession() { 867df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (sslSession == null) { 868df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 869df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom startHandshake(true); 870df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 871df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // return an invalid session with 872df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 873df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 874df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Registers a listener to be notified that a SSL handshake 881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * was successfully completed on this connection. 882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IllegalArgumentException</code> if listener is null. 883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 8844559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void addHandshakeCompletedListener( 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners = new ArrayList(); 892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The method removes a registered listener. 898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException if listener is null or not registered 899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void removeHandshakeCompletedListener( 902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if new SSL sessions may be established by this socket. 918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the session may be created; false if a session already 920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exists and must be resumed. 921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getEnableSessionCreation() { 924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set a flag for the socket to inhibit or to allow the creation of a new 929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSL sessions. If the flag is set to false, and there are no actual 930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sessions to resume, then there will be no successful handshaking. 931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param flag true if session may be created; false 933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a session already exists and must be resumed. 934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setEnableSessionCreation(boolean flag) { 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the cipher suites which could be used by the SSL connection 942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * are returned. 943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of cipher suite names 944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getSupportedCipherSuites() { 947ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the cipher suites that are in use in the actual the SSL 952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection are returned. 953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of cipher suite names 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getEnabledCipherSuites() { 958bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method enables the cipher suites listed by 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * getSupportedCipherSuites(). 964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param suites names of all the cipher suites to 966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * put on use 967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException when one or more of the 968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ciphers in array suites are not supported, or when the array 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is null. 970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setEnabledCipherSuites(String[] suites) { 973bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 976adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the protocols' versions that may be used on this SSL 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection. 979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of protocols names 980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9814559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getSupportedProtocols() { 983ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 984adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 986adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The names of the protocols' versions that are in use on this SSL 988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * connection. 989ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an array of protocols names 991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String[] getEnabledProtocols() { 994bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method enables the protocols' versions listed by 999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * getSupportedProtocols(). 1000ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 10014559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param protocols The names of all the protocols to allow 1002ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * 1003adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException when one or more of the names in the 1004adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * array are not supported, or when the array is null. 1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 10074559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setEnabledProtocols(String[] protocols) { 1008bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1011adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 10124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * The names of the compression methods that may be used on this SSL 10134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * connection. 10144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return an array of compression methods 10154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public String[] getSupportedCompressionMethods() { 10174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return NativeCrypto.getSupportedCompressionMethods(); 10184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10214559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * The names of the compression methods versions that are in use 10224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * on this SSL connection. 10234559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10244559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return an array of compression methods 10254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10264559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public String[] getEnabledCompressionMethods() { 10274559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return enabledCompressionMethods.clone(); 10284559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10314559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables the compression method listed by 10324559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * getSupportedCompressionMethods(). 10334559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param methods The names of all the compression methods to allow 10354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @throws IllegalArgumentException when one or more of the names in the 10374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * array are not supported, or when the array is null. 10384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setEnabledCompressionMethods (String[] methods) { 10404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 10414559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10444559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables session ticket support. 10454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param useSessionTickets True to enable session tickets 10474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 10494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.useSessionTickets = useSessionTickets; 10504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method gives true back if the SSL socket is set to client mode. 10544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return true if the socket should do the handshaking as client. 10564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public boolean getUseSessionTickets() { 10584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return useSessionTickets; 10594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10614559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10624559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables Server Name Indication 10634559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10644559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 10654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setHostname(String hostname) { 10674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.hostname = hostname; 10684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10704559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 10714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method returns the current SNI hostname 10724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 10734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return a host name if SNI is enabled, or null otherwise 10744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 10754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public String getHostname() { 10764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return hostname; 10774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 10784559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 10794559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method gives true back if the SSL socket is set to client mode. 1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the socket should do the handshaking as client. 1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getUseClientMode() { 1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method set the actual SSL socket to client mode. 1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param mode true if the socket starts in client 1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mode 1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException if mode changes during 1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handshake. 1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 10964559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 10974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseClientMode(boolean mode) { 1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Could not change the mode after the initial handshake has begun."); 1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the SSL socket requests client's authentication. Relevant 1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * only for server sockets! 1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if client authentication is desired, false if not. 1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11114559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getWantClientAuth() { 1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the SSL socket needs client's authentication. Relevant 1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * only for server sockets! 1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if client authentication is desired, false if not. 1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean getNeedClientAuth() { 1124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 1125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * server sockets! 1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param need true if client authentication is 1132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * desired, false if not. 1133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setNeedClientAuth(boolean need) { 1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * server sockets! Notice that in contrast to setNeedClientAuth(..) this 1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method will continue the negotiation if the client decide not to send 1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * authentication credentials. 1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param want true if client authentication is 1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * desired, false if not. 1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setWantClientAuth(boolean want) { 1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method is not supported for SSLSocket implementation. 1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void sendUrgentData(int data) throws IOException { 1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SocketException( 1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Method sendUrgentData() is not supported."); 1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method is not supported for SSLSocket implementation. 1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void setOOBInline(boolean on) throws SocketException { 1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new SocketException( 1168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Methods sendUrgentData, setOOBInline are not supported."); 1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Set the read timeout on this socket. The SO_TIMEOUT option, is specified 1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * in milliseconds. The read operation will block indefinitely for a zero 1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * value. 1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout the read timeout value 1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SocketException if an error occurs setting the option 1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 11794559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1180a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom public void setSoTimeout(int timeoutMilliseconds) throws SocketException { 1181a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom super.setSoTimeout(timeoutMilliseconds); 1182a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom this.timeoutMilliseconds = timeoutMilliseconds; 1183a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom } 1184a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 1185a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom @Override 1186a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom public int getSoTimeout() throws SocketException { 1187a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom return timeoutMilliseconds; 1188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 11909d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // BEGIN android-added 11919d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 11929d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 11939d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 11949d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * 11959d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * @param timeout the handshake timeout value 11969d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 1197a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException { 1198a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom this.handshakeTimeoutMilliseconds = timeoutMilliseconds; 11999d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 12009d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor // END android-added 12019d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 1202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes the SSL socket. Once closed, a socket is not available for further 1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * use anymore under any circumstance. A new socket must be created. 1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> if an I/O error happens during the 1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * socket's closure. 1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 12094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // TODO: Close SSL sockets using a background thread so they close 1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // gracefully. 1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 1216bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // prevent further attemps to start handshake 1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 1218ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 1220ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1222df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1228ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 12333e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (writeLock) { 1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (readLock) { 1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project IOException pendingException = null; 1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 12445900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 1245df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom NativeCrypto.SSL_shutdown(sslNativePointer, fd, this); 1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note the exception at this point, but try to continue 1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to clean the rest of this all up before rethrowing. 1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pendingException = ex; 1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Even if the above call failed, it is still safe to free 1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the native structs, and we need to do so lest we leak 1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * memory. 1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1260ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1262df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) 1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socket.close(); 1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 1266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) 1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.close(); 1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pendingException != null) { 1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw pendingException; 1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1278ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 1279ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 1280ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 1281ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1282ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1283ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 1284f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 1285ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1287e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 1288e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 1289e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom /* 1290e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * Just worry about our own state. Notably we do not try and 1291e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * close anything. The SocketImpl, either our own 1292e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 1293e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 1294e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * if you want to do that, properly close the socket yourself. 1295e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * 1296e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 1297e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 1298e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * finalizer runs first and closes the socket. However, in the 1299e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 1300e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 1301e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * underlying socket BIOs still have the old file descriptor 1302e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * and will write the close notify to some unsuspecting 1303e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * reader. 1304e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom */ 130512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 130612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 130712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 1308e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom free(); 1309e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 1310e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 1311e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 1312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1314