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