OpenSSLSocketImpl.java revision ecaf759ba374a3e53613c97b47920bf520bb93cf
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.io.OutputStreamWriter;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.interfaces.RSAPublicKey;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
3130da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybobimport java.util.concurrent.atomic.AtomicInteger;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Level;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Logger;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLHandshakeException;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implementation of the class OpenSSLSocketImpl
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * based on OpenSSL. The JNI native interface for some methods
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this this class are defined in the file:
47ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
48ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom *
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere
50ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document.
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
52ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl
53ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        extends javax.net.ssl.SSLSocket
54ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        implements NativeCrypto.CertificateChainVerifier {
55ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private int sslNativePointer;
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private InputStream is;
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OutputStream os;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Object handshakeLock = new Object();
59ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object readLock = new Object();
60ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object writeLock = new Object();
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLParameters sslParameters;
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OpenSSLSessionImpl sslSession;
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Socket socket;
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean autoClose;
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean handshakeStarted = false;
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private ArrayList<HandshakeCompletedListener> listeners;
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int timeout = 0;
689d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
699d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    private int handshakeTimeout = -1;  // -1 = same as timeout; 0 = infinite
709d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private InetSocketAddress address;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7330da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob    private static final AtomicInteger instanceCount = new AtomicInteger(0);
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static int getInstanceCount() {
7630da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        return instanceCount.get();
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static void updateInstanceCount(int amount) {
8030da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        instanceCount.addAndGet(amount);
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 1 parameter
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param sslParameters Parameters for the SSL
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            context
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(SSLParameters sslParameters) throws IOException {
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
92ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(String host, int port,
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SSLParameters sslParameters)
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port);
105ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters: 1st is InetAddress
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SSLParameters sslParameters)
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port);
118ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is host
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(String host, int port, InetAddress clientAddress,
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int clientPort, SSLParameters sslParameters)
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port, clientAddress, clientPort);
132ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is InetAddress
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress clientAddress, int clientPort, SSLParameters sslParameters)
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port, clientAddress, clientPort);
145ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructor with 5 parameters: 1st is socket. Enhances an existing socket
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * with SSL functionality.
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(Socket socket, String host, int port,
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean autoClose, SSLParameters sslParameters) throws IOException {
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.socket = socket;
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.timeout = socket.getSoTimeout();
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.address = new InetSocketAddress(host, port);
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.autoClose = autoClose;
161ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
162ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
163ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
164ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
165ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Initialize the SSL socket and set the certificates for the
166ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * future handshaking.
167ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
168ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private void init(SSLParameters sslParameters) throws IOException {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.sslParameters = sslParameters;
170ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        this.sslNativePointer = NativeCrypto.SSL_new(sslParameters);
171ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        updateInstanceCount(1);
172ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
173ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
174ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
175ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Construct a OpenSSLSocketImpl from an SSLParameters and an
176ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * existing SSL native pointer. Used for transitioning accepting
177ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * the OpenSSLSocketImpl within OpenSSLServerSocketImpl.
178ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
179ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    protected OpenSSLSocketImpl(SSLParameters sslParameters,
180ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                OpenSSLServerSocketImpl dummy) {
181ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        super();
182ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        this.sslParameters = (SSLParameters) sslParameters.clone();
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updateInstanceCount(1);
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Adds OpenSSL functionality to the existing socket and starts the SSL
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * handshaking.
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
190ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native boolean nativeconnect(int sslNativePointer, Socket sock, int timeout, boolean client_mode, int sslSessionNativePointer) throws IOException;
191ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native int nativegetsslsession(int sslNativePointer);
192ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native String nativecipherauthenticationmethod(int sslNativePointer);
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the suitable session reference from the session cache container.
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return OpenSSLSessionImpl
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OpenSSLSessionImpl getCachedClientSession() {
200ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (!sslParameters.getUseClientMode()) {
201ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return null;
202ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (super.getInetAddress() == null ||
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostAddress() == null ||
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName() == null) {
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ClientSessionContext sessionContext
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                = sslParameters.getClientSessionContext();
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (OpenSSLSessionImpl) sessionContext.getSession(
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName(),
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getPort());
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Ensures that logger is lazily loaded. The outer class seems to load
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * before logging is ready.
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static class LoggerHolder {
220ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName());
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts a TLS/SSL handshake on this connection using some native methods
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * from the OpenSSL library. It can negotiate new encryption keys, change
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * cipher suites, or initiate a new session. The certificate chain is
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * verified if the correspondent property in java.Security is set. All
228ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * listeners are notified at the end of the TLS/SSL handshake.
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if network fails
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void startHandshake() throws IOException {
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        OpenSSLSessionImpl session = getCachedClientSession();
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Check if it's allowed to create a new session (default is true)
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session == null && !sslParameters.getEnableSessionCreation()) {
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new SSLHandshakeException("SSL Session may not be created");
246ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
247ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
248ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // BEGIN android-added
249ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // Temporarily use a different timeout for the handshake process
250ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        int savedTimeout = timeout;
251ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (handshakeTimeout >= 0) {
252ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            setSoTimeout(handshakeTimeout);
253ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
254ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // END android-added
255ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
256ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        Socket socket = this.socket != null ? this.socket : this;
257ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        int sslSessionNativePointer = session != null ? session.sslSessionNativePointer : 0;
258ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        boolean reusedSession = nativeconnect(sslNativePointer, socket, timeout,
259ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                              sslParameters.getUseClientMode(), sslSessionNativePointer);
260ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (reusedSession) {
261ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            // nativeconnect shouldn't return true if the session is not
262ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            // done
263ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            session.lastAccessedTime = System.currentTimeMillis();
264ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            sslSession = session;
265ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
266ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            LoggerHolder.logger.fine("Reused cached session for "
267ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                     + getInetAddress().getHostName() + ".");
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
269ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            if (session != null) {
270ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                LoggerHolder.logger.fine("Reuse of cached session for "
271ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                         + getInetAddress().getHostName() + " failed.");
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
273ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                LoggerHolder.logger.fine("Created new session for "
274ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                         + getInetAddress().getHostName() + ".");
275ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            }
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
277ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            AbstractSessionContext sessionContext =
278ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                (sslParameters.getUseClientMode()) ?
279ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sslParameters.getClientSessionContext() :
280ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sslParameters.getServerSessionContext();
281ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            sslSessionNativePointer = nativegetsslsession(sslNativePointer);
282ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            if (address == null) {
283ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, sslParameters,
284ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    super.getInetAddress().getHostName(),
285ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    super.getPort(), sessionContext);
286ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            } else  {
287ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, sslParameters,
288ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    address.getHostName(), address.getPort(),
289ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    sessionContext);
290ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            }
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
292ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            try {
293ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                X509Certificate[] peerCertificates = (X509Certificate[])
294ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    sslSession.getPeerCertificates();
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
296ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                if (peerCertificates == null
297ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    || peerCertificates.length == 0) {
298ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    throw new SSLException("Server sends no certificate");
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
3009d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor
301ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                String authMethod = nativecipherauthenticationmethod(sslNativePointer);
302ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sslParameters.getTrustManager().checkServerTrusted(peerCertificates,
303ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                                   authMethod);
304ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sessionContext.putSession(sslSession);
305ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            } catch (CertificateException e) {
306ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                throw new SSLException("Not trusted server certificate", e);
3079d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor            }
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
310ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // BEGIN android-added
311ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // Restore the original timeout now that the handshake is complete
312ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (handshakeTimeout >= 0) {
313ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            setSoTimeout(savedTimeout);
314ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
315ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // END android-added
316ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners != null) {
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // notify the listeners
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedEvent event =
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                new HandshakeCompletedEvent(this, sslSession);
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int size = listeners.size();
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < size; i++) {
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                listeners.get(i).handshakeCompleted(event);
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // To be synchronized because of the verify_callback
329ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    native synchronized int nativeaccept(int sslNativePointer, Socket socketObject);
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Performs the first part of a SSL/TLS handshaking process with a given
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * 'host' connection and initializes the SSLSession.
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
335ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    protected void accept(int serverSslNativePointer) throws IOException {
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Must be set because no handshaking is necessary
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // in this situation
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        handshakeStarted = true;
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
340ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        sslNativePointer = nativeaccept(serverSslNativePointer, this);
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ServerSessionContext sessionContext
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                = sslParameters.getServerSessionContext();
344ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        sslSession = new OpenSSLSessionImpl(nativegetsslsession(sslNativePointer),
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                sslParameters, super.getInetAddress().getHostName(),
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getPort(), sessionContext);
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslSession.lastAccessedTime = System.currentTimeMillis();
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sessionContext.putSession(sslSession);
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
352ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Implementation of NativeCrypto.CertificateChainVerifier.
353ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
354ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Callback method for the OpenSSL native certificate verification process.
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bytes Byte array containing the cert's
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            information.
358ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * @return false if the certificate verification fails or true if OK
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unused")
361ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    public boolean verifyCertificateChain(byte[][] bytes) {
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            X509Certificate[] peerCertificateChain
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    = new X509Certificate[bytes.length];
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for(int i = 0; i < bytes.length; i++) {
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                peerCertificateChain[i] =
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    new X509CertImpl(javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // TODO "null" String
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, "null");
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (CertificateException e) {
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new AlertException(AlertProtocol.BAD_CERTIFICATE,
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        new SSLException("Not trusted server certificate", e));
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (javax.security.cert.CertificateException e) {
378ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            // TODO throw in all cases for consistency
379ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return false;
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IOException e) {
381ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            // TODO throw in all cases for consistency
382ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return false;
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
384ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return true;
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an input stream for this SSL socket using native calls to the
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return: an input stream for reading bytes from this socket.
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws: <code>IOException</code> if an I/O error occurs when creating
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          the input stream, the socket is closed, the socket is not
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          connected, or the socket input has been shutdown.
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InputStream getInputStream() throws IOException {
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized(this) {
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (is == null) {
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                is = new SSLInputStream();
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return is;
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an output stream for this SSL socket using native calls to the
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an output stream for writing bytes to this socket.
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error occurs when creating
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             the output stream, or no connection to the socket exists.
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public OutputStream getOutputStream() throws IOException {
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized(this) {
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (os == null) {
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                os = new SSLOutputStream();
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return os;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownInput() throws IOException {
425ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (socket == null) {
426ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            super.shutdownInput();
427ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return;
428ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
429ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        socket.shutdownInput();
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownOutput() throws IOException {
433ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (socket == null) {
434ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            super.shutdownOutput();
435ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return;
436ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
437ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        socket.shutdownOutput();
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Reads with the native SSL_read function from the encrypted data stream
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return -1 if error or the end of the stream is reached.
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
444ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native int nativeread(int sslNativePointer, int timeout) throws IOException;
445ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native int nativeread(int sslNativePointer, byte[] b, int off, int len, int timeout) throws IOException;
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides input data stream functionality
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read data received via SSL protocol.
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLInputStream extends InputStream {
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLInputStream() throws IOException {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * SSLInputStream object will be created.
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            OpenSSLSocketImpl.this.startHandshake();
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this operation can block until the data will be
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * available.
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return read value.
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws <code>IOException</code>
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read() throws IOException {
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized(readLock) {
470ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                return OpenSSLSocketImpl.this.nativeread(sslNativePointer, timeout);
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read(byte[] b, int off, int len) throws IOException {
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized(readLock) {
480ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                return OpenSSLSocketImpl.this.nativeread(sslNativePointer, b, off, len, timeout);
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Writes with the native SSL_write function to the encrypted data stream.
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
488ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native void nativewrite(int sslNativePointer, int b) throws IOException;
489ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native void nativewrite(int sslNativePointer, byte[] b, int off, int len) throws IOException;
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides output data stream functionality
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * write data according to the encryption parameters given in SSL context.
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLOutputStream extends OutputStream {
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLOutputStream() throws IOException {
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
500ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom             * SSLOutputStream object will be created.
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            OpenSSLSocketImpl.this.startHandshake();
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(int)
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(int b) throws IOException {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized(writeLock) {
511ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                OpenSSLSocketImpl.this.nativewrite(sslNativePointer, b);
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(byte[] b, int start, int len) throws IOException {
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized(writeLock) {
521ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                OpenSSLSocketImpl.this.nativewrite(sslNativePointer, b, start, len);
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The SSL session used by this connection is returned. The SSL session
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * determines which cipher suite should be used by all connections within
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that session and which identities have the session's client and server.
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method starts the SSL handshake.
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the SSLSession.
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if the handshake fails
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLSession getSession() {
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            startHandshake();
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IOException e) {
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // return an invalid session with
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return SSLSessionImpl.NULL_SESSION;
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslSession;
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Registers a listener to be notified that a SSL handshake
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * was successfully completed on this connection.
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IllegalArgumentException</code> if listener is null.
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void addHandshakeCompletedListener(
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            listeners = new ArrayList();
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        listeners.add(listener);
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method removes a registered listener.
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if listener is null or not registered
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void removeHandshakeCompletedListener(
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!listeners.remove(listener)) {
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if new SSL sessions may be established by this socket.
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the session may be created; false if a session already
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         exists and must be resumed.
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getEnableSessionCreation() {
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnableSessionCreation();
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set a flag for the socket to inhibit or to allow the creation of a new
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * SSL sessions. If the flag is set to false, and there are no actual
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * sessions to resume, then there will be no successful handshaking.
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param flag true if session may be created; false
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if a session already exists and must be resumed.
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites which could be used by the SSL connection
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * are returned.
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedCipherSuites() {
609ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites that are in use in the actual the SSL
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection are returned.
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledCipherSuites() {
619ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.SSL_get_ciphers(sslNativePointer);
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the cipher suites listed by
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedCipherSuites().
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param suites names of all the cipher suites to
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            put on use
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             ciphers in array suites are not supported, or when the array
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             is null.
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
633ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        NativeCrypto.setEnabledCipherSuites(sslNativePointer, suites);
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that may be used on this SSL
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedProtocols() {
642ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that are in use on this SSL
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
648ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledProtocols() {
653ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getEnabledProtocols(sslNativePointer);
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the protocols' versions listed by
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedProtocols().
659ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param protocols The names of all the protocols to put on use
661ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the names in the
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             array are not supported, or when the array is null.
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setEnabledProtocols(String[] protocols) {
667ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        NativeCrypto.setEnabledProtocols(sslNativePointer, protocols);
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method gives true back if the SSL socket is set to client mode.
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the socket should do the handshaking as client.
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getUseClientMode() {
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getUseClientMode();
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method set the actual SSL socket to client mode.
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param mode true if the socket starts in client
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            mode
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if mode changes during
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             handshake.
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setUseClientMode(boolean mode) {
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshakeStarted) {
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setUseClientMode(mode);
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket requests client's authentication. Relevant
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getWantClientAuth() {
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getWantClientAuth();
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket needs client's authentication. Relevant
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getNeedClientAuth() {
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getNeedClientAuth();
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets!
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param need true if client authentication is
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setNeedClientAuth(boolean need) {
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setNeedClientAuth(need);
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets! Notice that in contrast to setNeedClientAuth(..) this
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method will continue the negotiation if the client decide not to send
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * authentication credentials.
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param want true if client authentication is
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setWantClientAuth(boolean want) {
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setWantClientAuth(want);
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void sendUrgentData(int data) throws IOException {
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Method sendUrgentData() is not supported.");
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOOBInline(boolean on) throws SocketException {
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Methods sendUrgentData, setOOBInline are not supported.");
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * in milliseconds. The read operation will block indefinitely for a zero
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * value.
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timeout the read timeout value
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException if an error occurs setting the option
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public synchronized void setSoTimeout(int timeout) throws SocketException {
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setSoTimeout(timeout);
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.timeout = timeout;
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7689d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
7699d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    /**
7709d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
7719d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * milliseconds and will be used only during the handshake process.
7729d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     *
7739d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * @param timeout the handshake timeout value
7749d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     */
7759d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    public synchronized void setHandshakeTimeout(int timeout) throws SocketException {
7769d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor        this.handshakeTimeout = timeout;
7779d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    }
7789d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
7799d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor
780ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native void nativeinterrupt(int sslNativePointer) throws IOException;
781ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private native void nativeclose(int sslNativePointer) throws IOException;
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the SSL socket. Once closed, a socket is not available for further
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * use anymore under any circumstance. A new socket must be created.
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error happens during the
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket's closure.
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // TODO: Close SSL sockets using a background thread so they close
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // gracefully.
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
797ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (this) {
799ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (socket != null) {
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed()) socket.close();
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed()) super.close();
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
807ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
812ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        nativeinterrupt(sslNativePointer);
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (writeLock) {
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (readLock) {
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    IOException pendingException = null;
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // Shut down the SSL connection, per se.
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    try {
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (handshakeStarted) {
823ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                            nativeclose(sslNativePointer);
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } catch (IOException ex) {
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /*
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * Note the exception at this point, but try to continue
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * to clean the rest of this all up before rethrowing.
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         */
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pendingException = ex;
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Even if the above call failed, it is still safe to free
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * the native structs, and we need to do so lest we leak
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * memory.
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
838ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (socket != null) {
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed())
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            socket.close();
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed())
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            super.close();
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (pendingException != null) {
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        throw pendingException;
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
856ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private void free() {
857ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (sslNativePointer == 0) {
858ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return;
859ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
860ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
861ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        sslNativePointer = 0;
862ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void finalize() throws IOException {
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updateInstanceCount(-1);
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
867ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (sslNativePointer == 0) {
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * It's already been closed, so there's no need to do anything
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * more at this point.
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Note the underlying socket up-front, for possible later use.
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Socket underlyingSocket = socket;
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Fire up a thread to (hopefully) do all the real work.
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Finalizer f = new Finalizer();
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        f.setDaemon(true);
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        f.start();
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Give the finalizer thread one second to run. If it fails to
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * terminate in that time, interrupt it (which may help if it
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * is blocked on an interruptible I/O operation), make a note
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * in the log, and go ahead and close the underlying socket if
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * possible.
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            f.join(1000);
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (InterruptedException ex) {
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Reassert interrupted status.
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Thread.currentThread().interrupt();
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (f.isAlive()) {
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            f.interrupt();
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Logger.global.log(Level.SEVERE,
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Slow finalization of SSL socket (" + this + ", for " +
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    underlyingSocket + ")");
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((underlyingSocket != null) && !underlyingSocket.isClosed()) {
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                underlyingSocket.close();
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Helper class for a thread that knows how to call
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link OpenSSLSocketImpl#close} on behalf of instances being finalized,
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * since that call can take arbitrarily long (e.g., due to a slow network),
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and an overly long-running finalizer will cause the process to be
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * totally aborted.
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class Finalizer extends Thread {
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void run() {
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Socket underlyingSocket = socket; // for error reporting
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                close();
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException ex) {
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /*
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 * Clear interrupted status, so that the Logger call
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 * immediately below won't get spuriously interrupted.
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                 */
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Thread.interrupted();
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Logger.global.log(Level.SEVERE,
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        "Trouble finalizing SSL socket (" +
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        OpenSSLSocketImpl.this + ", for " + underlyingSocket +
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ")",
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ex);
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Verifies an RSA signature. Conceptually, this method doesn't really
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * belong here, but due to its native code being closely tied to OpenSSL
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * (just like the rest of this class), we put it here for the time being.
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This also solves potential problems with native library initialization.
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param message The message to verify
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param signature The signature to verify
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param algorithm The hash/sign algorithm to use, i.e. "RSA-SHA1"
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param key The RSA public key to use
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the verification succeeds, false otherwise
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static boolean verifySignature(byte[] message, byte[] signature, String algorithm, RSAPublicKey key) {
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] modulus = key.getModulus().toByteArray();
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] exponent = key.getPublicExponent().toByteArray();
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return nativeverifysignature(message, signature, algorithm, modulus, exponent) == 1;
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static native int nativeverifysignature(byte[] message, byte[] signature,
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String algorithm, byte[] modulus, byte[] exponent);
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
958