OpenSSLSocketImpl.java revision f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8a
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;
3430da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybobimport java.util.concurrent.atomic.AtomicInteger;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Logger;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException;
39bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession;
41f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager;
42059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p>
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere
49ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document.
504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p>
514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include:
524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul>
534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout
544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>compression methods
554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets
564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication
574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul>
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
59ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl
60ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        extends javax.net.ssl.SSLSocket
616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        implements NativeCrypto.SSLHandshakeCallbacks {
62df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom
63ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private int sslNativePointer;
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private InputStream is;
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OutputStream os;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Object handshakeLock = new Object();
67ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object readLock = new Object();
68ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object writeLock = new Object();
696812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    private SSLParametersImpl sslParameters;
70bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private String[] enabledProtocols;
71bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private String[] enabledCipherSuites;
724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private String[] enabledCompressionMethods;
734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private boolean useSessionTickets;
744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private String hostname;
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OpenSSLSessionImpl sslSession;
76df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom    private final Socket socket;
77df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom    private final FileDescriptor fd;
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean autoClose;
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean handshakeStarted = false;
80f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    private final CloseGuard guard = CloseGuard.getUnopened();
81bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
82bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
83bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Not set to true until the update from native that tells us the
84bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * full handshake is complete, since SSL_do_handshake can return
85bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * before the handshake is completely done due to
86bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * handshake_cutthrough support.
87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private boolean handshakeCompleted = false;
89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private ArrayList<HandshakeCompletedListener> listeners;
91a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
92a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    /**
93a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom     * Local cache of timeout to avoid getsockopt on every read and
94a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom     * write for non-wrapped sockets. Note that
95a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom     * OpenSSLSocketImplWrapper overrides setSoTimeout and
96a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom     * getSoTimeout to delegate to the wrapped socket.
97a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom     */
98a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    private int timeoutMilliseconds = 0;
99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1009d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
101a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    private int handshakeTimeoutMilliseconds = -1;  // -1 = same as timeout; 0 = infinite
1029d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
103a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom    private String wrappedHost;
104a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom    private int wrappedPort;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10630da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob    private static final AtomicInteger instanceCount = new AtomicInteger(0);
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static int getInstanceCount() {
10930da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        return instanceCount.get();
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static void updateInstanceCount(int amount) {
11330da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        instanceCount.addAndGet(amount);
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 1 parameter
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param sslParameters Parameters for the SSL
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            context
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1236812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException {
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
125df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
126df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
127ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
131bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl
132bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     *
133bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param sslParameters Parameters for the SSL
134bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     *            context
135bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @throws IOException if network fails
136bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
1376812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters,
138bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                String[] enabledProtocols,
1394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                                String[] enabledCipherSuites,
1404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                                String[] enabledCompressionMethods) throws IOException {
141bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        super();
142df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
143df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
1444559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods);
145bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
146bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
147bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1536812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters)
154df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom            throws IOException {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port);
156df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
157df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
158ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters: 1st is InetAddress
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1676812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters)
168df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom            throws IOException {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port);
170df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
171df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
172ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is host
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1820c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    protected OpenSSLSocketImpl(String host, int port,
1830c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                InetAddress clientAddress, int clientPort,
1846812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom                                SSLParametersImpl sslParameters)
185df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom            throws IOException {
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port, clientAddress, clientPort);
187df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
188df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
189ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is InetAddress
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
1990c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                InetAddress clientAddress, int clientPort,
2006812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom                                SSLParametersImpl sslParameters)
201df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom            throws IOException {
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port, clientAddress, clientPort);
203df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.socket = this;
204df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
205ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructor with 5 parameters: 1st is socket. Enhances an existing socket
210a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom     * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor.
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(Socket socket, String host, int port,
2156812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom            boolean autoClose, SSLParametersImpl sslParameters) throws IOException {
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.socket = socket;
218df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom        this.fd = NativeCrypto.getFileDescriptor(socket);
219a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom        this.wrappedHost = host;
220a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom        this.wrappedPort = port;
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.autoClose = autoClose;
222ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
223a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
224a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // this.timeout is not set intentionally.
225a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout
226a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        // to wrapped socket
227ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
228ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
229ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
230ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Initialize the SSL socket and set the certificates for the
231ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * future handshaking.
232ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
2336812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    private void init(SSLParametersImpl sslParameters) throws IOException {
234bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        init(sslParameters,
235bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom             NativeCrypto.getSupportedProtocols(),
2364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom             NativeCrypto.getDefaultCipherSuites(),
2374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom             NativeCrypto.getDefaultCompressionMethods());
238ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
239ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
240ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
241bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Initialize the SSL socket and set the certificates for the
242bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * future handshaking.
243ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
2446812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    private void init(SSLParametersImpl sslParameters,
245bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                      String[] enabledProtocols,
2464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                      String[] enabledCipherSuites,
2474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                      String[] enabledCompressionMethods) throws IOException {
248bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.sslParameters = sslParameters;
249bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.enabledProtocols = enabledProtocols;
250bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.enabledCipherSuites = enabledCipherSuites;
2514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.enabledCompressionMethods = enabledCompressionMethods;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updateInstanceCount(1);
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the suitable session reference from the session cache container.
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return OpenSSLSessionImpl
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
260bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (super.getInetAddress() == null ||
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostAddress() == null ||
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName() == null) {
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
2669acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName(),
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getPort());
2699acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (session == null) {
2709acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2719acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2729acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom
2739acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        String protocol = session.getProtocol();
2749acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        boolean protocolFound = false;
2759acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        for (String enabledProtocol : enabledProtocols) {
2769acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            if (protocol.equals(enabledProtocol)) {
2779acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                protocolFound = true;
2789acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                break;
2799acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            }
2809acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2819acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (!protocolFound) {
2829acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2839acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2849acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom
2859acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        String cipherSuite = session.getCipherSuite();
2869acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        boolean cipherSuiteFound = false;
2879acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        for (String enabledCipherSuite : enabledCipherSuites) {
2889acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            if (cipherSuite.equals(enabledCipherSuite)) {
2899acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                cipherSuiteFound = true;
2909acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                break;
2919acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            }
2929acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2939acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (!cipherSuiteFound) {
2949acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2959acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2966df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
2974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        String compressionMethod = session.getCompressionMethod();
2984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        boolean compressionMethodFound = false;
2994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        for (String enabledCompressionMethod : enabledCompressionMethods) {
3004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            if (compressionMethod.equals(enabledCompressionMethod)) {
3014559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                compressionMethodFound = true;
3024559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                break;
3034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            }
3044559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
3054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        if (!compressionMethodFound) {
3064559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            return null;
3074559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
3084559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
3099acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        return session;
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Ensures that logger is lazily loaded. The outer class seems to load
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * before logging is ready.
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static class LoggerHolder {
317ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName());
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts a TLS/SSL handshake on this connection using some native methods
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * from the OpenSSL library. It can negotiate new encryption keys, change
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * cipher suites, or initiate a new session. The certificate chain is
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * verified if the correspondent property in java.Security is set. All
325ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * listeners are notified at the end of the TLS/SSL handshake.
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if network fails
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
3294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
330bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public void startHandshake() throws IOException {
331bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        startHandshake(true);
332bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
333bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
334bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
3355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     * Checks whether the socket is closed, and throws an exception.
3365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     *
3375f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     * @throws SocketException
3385f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     *             if the socket is closed.
3395f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     */
3405f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    private void checkOpen() throws SocketException {
3415f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        if (isClosed()) {
3425f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            throw new SocketException("Socket is closed");
3435f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
3445f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    }
3455f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
3465f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    /**
347bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Perform the handshake
348bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param full If true, disable handshake cutthrough for a fully synchronous handshake
349bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
350bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public synchronized void startHandshake(boolean full) throws IOException {
3515f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
3606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // note that this modifies the global seed, not something specific to the connection
3616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
3626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
3636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        if (secureRandom == null) {
3646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
3656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        } else {
3666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
3676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        }
3686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final boolean client = sslParameters.getUseClientMode();
3706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final int sslCtxNativePointer = (client) ?
3726df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            sslParameters.getClientSessionContext().sslCtxNativePointer :
3736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            sslParameters.getServerSessionContext().sslCtxNativePointer;
3746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
375f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        this.sslNativePointer = 0;
376f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        boolean exception = true;
377f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        try {
378f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
379f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            guard.open("close");
3806df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
381f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // setup server certificates and private keys.
382f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // clients will receive a call back to request certificates.
383f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (!client) {
384f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                for (String keyType : NativeCrypto.KEY_TYPES) {
385f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    try {
386f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType,
387f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                                                       null,
388f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                                                       this));
389f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    } catch (CertificateEncodingException e) {
390f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        throw new IOException(e);
391f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    }
392ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                }
3936df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            }
3946df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
395f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols);
396f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites);
397f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (enabledCompressionMethods.length != 0) {
398f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.setEnabledCompressionMethods(sslNativePointer,
399f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                          enabledCompressionMethods);
400f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
401f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (useSessionTickets) {
402f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET);
403f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (hostname != null) {
405f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname);
406f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
407bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            boolean enableSessionCreation = sslParameters.getEnableSessionCreation();
409f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (!enableSessionCreation) {
410f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer,
411f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                              enableSessionCreation);
412bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
413bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
414f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            AbstractSessionContext sessionContext;
415f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            OpenSSLSessionImpl session;
416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (client) {
417f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // look for client session to reuse
418f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext();
419f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                sessionContext = clientSessionContext;
420f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                session = getCachedClientSession(clientSessionContext);
421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (session != null) {
422f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    NativeCrypto.SSL_set_session(sslNativePointer,
423f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                 session.sslSessionNativePointer);
424f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                }
425ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            } else {
426f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                sessionContext = sslParameters.getServerSessionContext();
427f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                session = null;
428ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
429059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
430f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // setup peer certificate verification
431f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (client) {
432f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // TODO support for anonymous cipher would require us to
433f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // conditionally use SSL_VERIFY_NONE
434f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            } else {
435f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // needing client auth takes priority...
436f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                boolean certRequested = false;
437f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (sslParameters.getNeedClientAuth()) {
438f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    NativeCrypto.SSL_set_verify(sslNativePointer,
439f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                NativeCrypto.SSL_VERIFY_PEER
440f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
441f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    certRequested = true;
442f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // ... over just wanting it...
443f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                } else if (sslParameters.getWantClientAuth()) {
444f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    NativeCrypto.SSL_set_verify(sslNativePointer,
445f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                NativeCrypto.SSL_VERIFY_PEER);
446f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    certRequested = true;
447f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // ... and it defaults properly so don't call SSL_set_verify in the common case.
448f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                } else {
449f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    certRequested = false;
450f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                }
451f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
452f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (certRequested) {
453f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    X509TrustManager trustManager = sslParameters.getTrustManager();
454f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    X509Certificate[] issuers = trustManager.getAcceptedIssuers();
455f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    if (issuers != null && issuers.length != 0) {
456f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        byte[][] issuersBytes;
457f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        try {
458f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                            issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers);
459f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        } catch (CertificateEncodingException e) {
460f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                            throw new IOException("Problem encoding principals", e);
461f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        }
462f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes);
463ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    }
464ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                }
465ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
466ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
467f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (client && full) {
468f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // we want to do a full synchronous handshake, so turn off cutthrough
469f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.SSL_clear_mode(sslNativePointer,
470f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                            NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH);
471f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
472ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
473f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // BEGIN android-added
474f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // Temporarily use a different timeout for the handshake process
475f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            int savedTimeoutMilliseconds = getSoTimeout();
476f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
477f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                setSoTimeout(handshakeTimeoutMilliseconds);
478f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
479f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // END android-added
480bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
481f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            int sslSessionNativePointer;
482f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            try {
483f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, fd, this,
484f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                                        getSoTimeout(), client);
485f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            } catch (CertificateException e) {
486f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                throw new SSLPeerUnverifiedException(e.getMessage());
487bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
488f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
489f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId);
490f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (sslSession != null) {
491f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                sslSession.lastAccessedTime = System.currentTimeMillis();
492f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                LoggerHolder.logger.fine("Reused cached session for "
493f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                         + getInetAddress() + ".");
494f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
495f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            } else {
496f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (!enableSessionCreation) {
497f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled
498f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    throw new IllegalStateException("SSL Session may not be created");
499f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                }
500f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                X509Certificate[] localCertificates
501f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer));
502f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                X509Certificate[] peerCertificates
503f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                        = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer));
504f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (wrappedHost == null) {
505f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    sslSession = new OpenSSLSessionImpl(sslSessionNativePointer,
506f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        localCertificates, peerCertificates,
507f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        super.getInetAddress().getHostName(),
508f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        super.getPort(), sessionContext);
509f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                } else  {
510f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    sslSession = new OpenSSLSessionImpl(sslSessionNativePointer,
511f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        localCertificates, peerCertificates,
512f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        wrappedHost, wrappedPort,
513f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                                        sessionContext);
514f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                }
515f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                // if not, putSession later in handshakeCompleted() callback
516f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                if (handshakeCompleted) {
517f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                    sessionContext.putSession(sslSession);
518f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                }
519f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                LoggerHolder.logger.fine("Created new session for "
520f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                                         + getInetAddress().getHostName() + ".");
521ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            }
522f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
523f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // BEGIN android-added
524f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // Restore the original timeout now that the handshake is complete
525f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
526f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                setSoTimeout(savedTimeoutMilliseconds);
5279d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor            }
528f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // END android-added
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
530f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
531f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (handshakeCompleted) {
532f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                notifyHandshakeCompletedListeners();
533f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
534ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
535f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            exception = false;
536f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        } finally {
537f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            // on exceptional exit, free the native content immediate to avoid CloseGuard warning
538f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            if (exception) {
539f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                free();
540f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            }
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
542df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom    }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
544df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom    /**
545df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom     * Return a possibly null array of X509Certificates given the
546df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom     * possibly null array of DER encoded bytes.
547df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom     */
548df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom    private static X509Certificate[] createCertChain(byte[][] certificatesBytes) {
549df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        if (certificatesBytes == null) {
550df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            return null;
551df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        }
552df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        X509Certificate[] certificates = new X509Certificate[certificatesBytes.length];
553df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        for (int i = 0; i < certificatesBytes.length; i++) {
554df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            try {
555df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                certificates[i] = new X509CertImpl(certificatesBytes[i]);
556df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            } catch (IOException e) {
557df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                return null;
558df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            }
559df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        }
560df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        return certificates;
561bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
563ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom    private void setCertificate(String alias) throws CertificateEncodingException, SSLException {
5646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        if (alias == null) {
5656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            return;
5666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        }
5676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias);
56912cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom        byte[] privateKeyBytes = privateKey.getEncoded();
5706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
5716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5726df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias);
573ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
5746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
5756df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5766df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // checks the last installed private key and certificate,
5776df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // so need to do this once per loop iteration
5786df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_check_private_key(sslNativePointer);
5796df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    }
5806df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5816df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    /**
5826df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
5836df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * invoked via JNI from client_cert_cb
5846df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     */
585059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
586ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            throws CertificateEncodingException, SSLException {
587059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
588059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        String[] keyTypes = new String[keyTypeBytes.length];
589059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        for (int i = 0; i < keyTypeBytes.length; i++) {
590059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
591059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        }
592059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
593059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        X500Principal[] issuers;
594059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        if (asn1DerEncodedPrincipals == null) {
595059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            issuers = null;
596059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        } else {
597059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            issuers = new X500Principal[asn1DerEncodedPrincipals.length];
598059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) {
599059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]);
600059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            }
601059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        }
602059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this));
6036df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    }
6046df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
6066df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
607bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * invoked via JNI from info_callback
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
609bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public void handshakeCompleted() {
610bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        handshakeCompleted = true;
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
612bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // If sslSession is null, the handshake was completed during
613bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // the call to NativeCrypto.SSL_do_handshake and not during a
614bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // later read operation. That means we do not need to fixup
615bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // the SSLSession and session cache or notify
616bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // HandshakeCompletedListeners, it will be done in
617bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // startHandshake.
618bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (sslSession == null) {
619bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            return;
620bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
622bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // reset session id from the native pointer and update the
623bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // appropriate cache.
624bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        sslSession.resetId();
625bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        AbstractSessionContext sessionContext =
626bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            (sslParameters.getUseClientMode())
627bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            ? sslParameters.getClientSessionContext()
628bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                : sslParameters.getServerSessionContext();
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sessionContext.putSession(sslSession);
630bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
631bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // let listeners know we are finally done
632bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        notifyHandshakeCompletedListeners();
633bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
634bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
635bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
636bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
637bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // notify the listeners
638bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            HandshakeCompletedEvent event =
639bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
640bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
641bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                try {
642bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                    listener.handshakeCompleted(event);
643bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                } catch (RuntimeException e) {
644e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // The RI runs the handlers in a separate thread,
645e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // which we do not. But we try to preserve their
646e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // behavior of logging a problem and not killing
647e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // the handshaking thread just because a listener
648e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // has a problem.
649e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    Thread thread = Thread.currentThread();
650e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
651bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                }
652bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
653bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
6576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
658ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
659059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom     * @param bytes An array of ASN.1 DER encoded certficates
660bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param authMethod auth algorithm name
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
662bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @throws CertificateException if the certificate is untrusted
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unused")
6656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    public void verifyCertificateChain(byte[][] bytes, String authMethod)
6666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            throws CertificateException {
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
668e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            if (bytes == null || bytes.length == 0) {
669e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                throw new SSLException("Peer sent no certificate");
670e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            }
671bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
672bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            for (int i = 0; i < bytes.length; i++) {
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                peerCertificateChain[i] =
6746df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                    new X509CertImpl(
6756df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                        javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
677bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
678bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (client) {
6796df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain,
6806df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                                                                   authMethod);
681bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            } else {
6826df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain,
6836df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                                                                   authMethod);
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
685bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
686bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } catch (CertificateException e) {
687bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            throw e;
688bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } catch (Exception e) {
689bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            throw new RuntimeException(e);
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an input stream for this SSL socket using native calls to the
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return: an input stream for reading bytes from this socket.
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws: <code>IOException</code> if an I/O error occurs when creating
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          the input stream, the socket is closed, the socket is not
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          connected, or the socket input has been shutdown.
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
7024559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InputStream getInputStream() throws IOException {
7045f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
705ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        synchronized (this) {
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (is == null) {
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                is = new SSLInputStream();
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return is;
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an output stream for this SSL socket using native calls to the
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an output stream for writing bytes to this socket.
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error occurs when creating
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             the output stream, or no connection to the socket exists.
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
7224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public OutputStream getOutputStream() throws IOException {
7245f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
725ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        synchronized (this) {
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (os == null) {
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                os = new SSLOutputStream();
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return os;
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
734bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
735bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * This method is not supported for this SSLSocket implementation
736bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * because reading from an SSLSocket may involve writing to the
737bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * network.
738bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
7394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownInput() throws IOException {
741bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        throw new UnsupportedOperationException();
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
744bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
745bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * This method is not supported for this SSLSocket implementation
746bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * because writing to an SSLSocket may involve reading from the
747bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * network.
748bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
7494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownOutput() throws IOException {
751bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        throw new UnsupportedOperationException();
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides input data stream functionality
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read data received via SSL protocol.
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLInputStream extends InputStream {
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLInputStream() throws IOException {
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * SSLInputStream object will be created.
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
765bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this operation can block until the data will be
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * available.
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return read value.
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws <code>IOException</code>
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read() throws IOException {
7775f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
7785900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
779ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (readLock) {
780df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                return NativeCrypto.SSL_read_byte(sslNativePointer, fd, OpenSSLSocketImpl.this,
781df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                                                  getSoTimeout());
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7894559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read(byte[] b, int off, int len) throws IOException {
7915f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
7925900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
793ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (b == null) {
794ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new NullPointerException("b == null");
795ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
796ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if ((len | off) < 0 || len > b.length - off) {
797ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new IndexOutOfBoundsException();
798ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
799ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (0 == len) {
800ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                return 0;
801ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
802ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (readLock) {
803df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                return NativeCrypto.SSL_read(sslNativePointer, fd, OpenSSLSocketImpl.this,
804df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                                             b, off, len, getSoTimeout());
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides output data stream functionality
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * write data according to the encryption parameters given in SSL context.
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLOutputStream extends OutputStream {
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLOutputStream() throws IOException {
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
818ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom             * SSLOutputStream object will be created.
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
820bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(int)
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
8274559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(int b) throws IOException {
8295f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
8305900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
831ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (writeLock) {
832df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                NativeCrypto.SSL_write_byte(sslNativePointer, fd, OpenSSLSocketImpl.this, b);
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
8404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(byte[] b, int start, int len) throws IOException {
8425f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
8435900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
844ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (b == null) {
845ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new NullPointerException("b == null");
846ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
847ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if ((len | start) < 0 || len > b.length - start) {
848ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new IndexOutOfBoundsException();
849ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
850ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (len == 0) {
851ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                return;
852ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
853ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (writeLock) {
854df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                NativeCrypto.SSL_write(sslNativePointer, fd, OpenSSLSocketImpl.this, b, start, len);
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The SSL session used by this connection is returned. The SSL session
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * determines which cipher suite should be used by all connections within
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that session and which identities have the session's client and server.
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method starts the SSL handshake.
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the SSLSession.
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if the handshake fails
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLSession getSession() {
870df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom        if (sslSession == null) {
871df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            try {
872df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                startHandshake(true);
873df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            } catch (IOException e) {
874df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                // return an invalid session with
875df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
876df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom                return SSLSessionImpl.NULL_SESSION;
877df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            }
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslSession;
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Registers a listener to be notified that a SSL handshake
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * was successfully completed on this connection.
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IllegalArgumentException</code> if listener is null.
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8874559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void addHandshakeCompletedListener(
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            listeners = new ArrayList();
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        listeners.add(listener);
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method removes a registered listener.
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if listener is null or not registered
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void removeHandshakeCompletedListener(
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!listeners.remove(listener)) {
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if new SSL sessions may be established by this socket.
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the session may be created; false if a session already
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         exists and must be resumed.
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getEnableSessionCreation() {
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnableSessionCreation();
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set a flag for the socket to inhibit or to allow the creation of a new
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * SSL sessions. If the flag is set to false, and there are no actual
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * sessions to resume, then there will be no successful handshaking.
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param flag true if session may be created; false
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if a session already exists and must be resumed.
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites which could be used by the SSL connection
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * are returned.
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedCipherSuites() {
950ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites that are in use in the actual the SSL
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection are returned.
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledCipherSuites() {
961bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        return enabledCipherSuites.clone();
962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
964adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the cipher suites listed by
966adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedCipherSuites().
967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param suites names of all the cipher suites to
969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            put on use
970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the
971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             ciphers in array suites are not supported, or when the array
972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             is null.
973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
976bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites);
977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that may be used on this SSL
981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9844559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedProtocols() {
986ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that are in use on this SSL
991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
992ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledProtocols() {
997bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        return enabledProtocols.clone();
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the protocols' versions listed by
1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedProtocols().
1003ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
10044559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param protocols The names of all the protocols to allow
1005ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the names in the
1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             array are not supported, or when the array is null.
1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1009adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
10104559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setEnabledProtocols(String[] protocols) {
1011bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols);
1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
10154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * The names of the compression methods that may be used on this SSL
10164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * connection.
10174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return an array of compression methods
10184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String[] getSupportedCompressionMethods() {
10204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return NativeCrypto.getSupportedCompressionMethods();
10214559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10234559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10244559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * The names of the compression methods versions that are in use
10254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * on this SSL connection.
10264559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10274559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return an array of compression methods
10284559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String[] getEnabledCompressionMethods() {
10304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return enabledCompressionMethods.clone();
10314559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10324559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10334559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables the compression method listed by
10354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * getSupportedCompressionMethods().
10364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param methods The names of all the compression methods to allow
10384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @throws IllegalArgumentException when one or more of the names in the
10404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *             array are not supported, or when the array is null.
10414559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setEnabledCompressionMethods (String[] methods) {
10434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods);
10444559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables session ticket support.
10484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param useSessionTickets True to enable session tickets
10504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
10524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.useSessionTickets = useSessionTickets;
10534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method gives true back if the SSL socket is set to client mode.
10574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return true if the socket should do the handshaking as client.
10594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public boolean getUseSessionTickets() {
10614559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return useSessionTickets;
10624559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10634559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10644559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables Server Name Indication
10664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
10684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setHostname(String hostname) {
10704559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.hostname = hostname;
10714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method returns the current SNI hostname
10754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return a host name if SNI is enabled, or null otherwise
10774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10784559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String getHostname() {
10794559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return hostname;
10804559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10814559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10824559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method gives true back if the SSL socket is set to client mode.
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the socket should do the handshaking as client.
1086adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getUseClientMode() {
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getUseClientMode();
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method set the actual SSL socket to client mode.
1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1094adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param mode true if the socket starts in client
1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            mode
1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if mode changes during
1097adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             handshake.
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
11004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setUseClientMode(boolean mode) {
1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshakeStarted) {
1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
1103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setUseClientMode(mode);
1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket requests client's authentication. Relevant
1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getWantClientAuth() {
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getWantClientAuth();
1117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket needs client's authentication. Relevant
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
1124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getNeedClientAuth() {
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getNeedClientAuth();
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
1132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets!
1133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param need true if client authentication is
1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setNeedClientAuth(boolean need) {
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setNeedClientAuth(need);
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets! Notice that in contrast to setNeedClientAuth(..) this
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method will continue the negotiation if the client decide not to send
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * authentication credentials.
1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param want true if client authentication is
1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setWantClientAuth(boolean want) {
1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setWantClientAuth(want);
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void sendUrgentData(int data) throws IOException {
1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Method sendUrgentData() is not supported.");
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOOBInline(boolean on) throws SocketException {
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
1171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Methods sendUrgentData, setOOBInline are not supported.");
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * in milliseconds. The read operation will block indefinitely for a zero
1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * value.
1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timeout the read timeout value
1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException if an error occurs setting the option
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11824559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1183a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    public void setSoTimeout(int timeoutMilliseconds) throws SocketException {
1184a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        super.setSoTimeout(timeoutMilliseconds);
1185a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        this.timeoutMilliseconds = timeoutMilliseconds;
1186a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    }
1187a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom
1188a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    @Override
1189a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    public int getSoTimeout() throws SocketException {
1190a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        return timeoutMilliseconds;
1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11939d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
11949d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    /**
11959d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
11969d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * milliseconds and will be used only during the handshake process.
11979d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     *
11989d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * @param timeout the handshake timeout value
11999d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     */
1200a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom    public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException {
1201a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom        this.handshakeTimeoutMilliseconds = timeoutMilliseconds;
12029d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    }
12039d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
12049d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the SSL socket. Once closed, a socket is not available for further
1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * use anymore under any circumstance. A new socket must be created.
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error happens during the
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket's closure.
1211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
12124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // TODO: Close SSL sockets using a background thread so they close
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // gracefully.
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
1218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
1219bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                // prevent further attemps to start handshake
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
1221ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (this) {
1223ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1225df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                    if (socket != this) {
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed()) socket.close();
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed()) super.close();
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1231ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
1233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
12363e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom        NativeCrypto.SSL_interrupt(sslNativePointer);
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (writeLock) {
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (readLock) {
1241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    IOException pendingException = null;
1243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // Shut down the SSL connection, per se.
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    try {
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (handshakeStarted) {
12475900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick                            BlockGuard.getThreadPolicy().onNetwork();
1248df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                            NativeCrypto.SSL_shutdown(sslNativePointer, fd, this);
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } catch (IOException ex) {
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /*
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * Note the exception at this point, but try to continue
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * to clean the rest of this all up before rethrowing.
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         */
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pendingException = ex;
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Even if the above call failed, it is still safe to free
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * the native structs, and we need to do so lest we leak
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * memory.
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
1263ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1265df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom                    if (socket != this) {
1266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed())
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            socket.close();
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed())
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            super.close();
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (pendingException != null) {
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        throw pendingException;
1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1281ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private void free() {
1282ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (sslNativePointer == 0) {
1283ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return;
1284ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
1285ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1286ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        sslNativePointer = 0;
1287f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        guard.close();
1288ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
1289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1290e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom    @Override protected void finalize() throws Throwable {
1291e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        try {
1292e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            /*
1293e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * Just worry about our own state. Notably we do not try and
1294e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * close anything. The SocketImpl, either our own
1295e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * PlainSocketImpl, or the Socket we are wrapping, will do
1296e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * that. This might mean we do not properly SSL_shutdown, but
1297e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * if you want to do that, properly close the socket yourself.
1298e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             *
1299e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * The reason why we don't try to SSL_shutdown, is that there
1300e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * can be a race between finalizers where the PlainSocketImpl
1301e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * finalizer runs first and closes the socket. However, in the
1302e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * meanwhile, the underlying file descriptor could be reused
1303e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * for another purpose. If we call SSL_shutdown, the
1304e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * underlying socket BIOs still have the old file descriptor
1305e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * and will write the close notify to some unsuspecting
1306e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             * reader.
1307e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom             */
1308f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            guard.warnIfOpen();
1309e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            updateInstanceCount(-1);
1310e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            free();
1311e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        } finally {
1312e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            super.finalize();
1313e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        }
1314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1316