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