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