1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2009 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 19a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.io.ByteArrayInputStream; 20a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.io.ByteArrayOutputStream; 21a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.io.DataInputStream; 22a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.io.DataOutputStream; 23a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.io.IOException; 24df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstromimport java.security.cert.Certificate; 25df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstromimport java.security.cert.CertificateEncodingException; 26a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.util.Arrays; 27a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.util.Enumeration; 28a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.util.Iterator; 299acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstromimport java.util.LinkedHashMap; 309acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstromimport java.util.Map; 31a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstromimport java.util.NoSuchElementException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSessionContext; 34df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstromimport org.apache.harmony.security.provider.cert.X509CertImpl; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Supports SSL session caches. 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectabstract class AbstractSessionContext implements SSLSessionContext { 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project volatile int maximumSize; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project volatile int timeout; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44f365a1c9cec94071b7a3161d7bdcb3f61d28f912Brian Carlstrom final int sslCtxNativePointer = NativeCrypto.SSL_CTX_new(); 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** Identifies OpenSSL sessions. */ 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static final int OPEN_SSL = 1; 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 499acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom private final Map<ByteArray, SSLSession> sessions 509acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom = new LinkedHashMap<ByteArray, SSLSession>() { 519acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom @Override 529acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protected boolean removeEldestEntry( 539acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom Map.Entry<ByteArray, SSLSession> eldest) { 549acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return maximumSize > 0 && size() > maximumSize; 559acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 569acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom }; 579acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new session context. 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param maximumSize of cache 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param timeout for cache entries 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 64f365a1c9cec94071b7a3161d7bdcb3f61d28f912Brian Carlstrom AbstractSessionContext(int maximumSize, int timeout) { 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.maximumSize = maximumSize; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.timeout = timeout; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 709acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom * Returns the collection of sessions ordered from oldest to newest 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 729acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom private Iterator<SSLSession> sessionIterator() { 739acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom synchronized (sessions) { 749acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom SSLSession[] array = sessions.values().toArray( 759acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom new SSLSession[sessions.size()]); 769acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return Arrays.asList(array).iterator(); 779acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 789acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Enumeration getIds() { 81a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom final Iterator<SSLSession> i = sessionIterator(); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new Enumeration<byte[]>() { 83a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom private SSLSession next; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean hasMoreElements() { 85a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom if (next != null) { 86a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom return true; 87a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom } 88a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom while (i.hasNext()) { 89a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom SSLSession session = i.next(); 90a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom if (session.isValid()) { 91a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom next = session; 92a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom return true; 93a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom } 94a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom } 95a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom next = null; 96a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom return false; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public byte[] nextElement() { 99a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom if (hasMoreElements()) { 100a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom byte[] id = next.getId(); 101a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom next = null; 102a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom return id; 103a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom } 104a7ae90de24809b266bb5efdc9033a3261e31f521Brian Carlstrom throw new NoSuchElementException(); 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }; 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getSessionCacheSize() { 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return maximumSize; 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int getSessionTimeout() { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return timeout; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Makes sure cache size is < maximumSize. 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1209acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protected void trimToSize() { 1219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom synchronized (sessions) { 1229acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom int size = sessions.size(); 1239acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (size > maximumSize) { 1249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom int removals = size - maximumSize; 1259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom Iterator<SSLSession> i = sessions.values().iterator(); 1269acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom do { 1279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom SSLSession session = i.next(); 1289acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom i.remove(); 1299acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom sessionRemoved(session); 1309acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } while (--removals > 0); 1319acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1329acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1339acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1349acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 1359acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom public void setSessionTimeout(int seconds) 1369acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom throws IllegalArgumentException { 1379acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (seconds < 0) { 1389acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom throw new IllegalArgumentException("seconds < 0"); 1399acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1409acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom timeout = seconds; 1419acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 1429acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom synchronized (sessions) { 1439acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom Iterator<SSLSession> i = sessions.values().iterator(); 1449acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom while (i.hasNext()) { 1459acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom SSLSession session = i.next(); 1469acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom // SSLSession's know their context and consult the 1479acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom // timeout as part of their validity condition. 1489acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!session.isValid()) { 1499acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom i.remove(); 1509acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom sessionRemoved(session); 1519acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1529acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1539acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1549acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 1559acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 15612cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom /** 1579acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom * Called when a session is removed. Used by ClientSessionContext 1589acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom * to update its host-and-port based cache. 1599acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom */ 160d29fddcf333997fc2d7429d531e4d934dc705c88Jesse Wilson protected abstract void sessionRemoved(SSLSession session); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final void setSessionCacheSize(int size) 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IllegalArgumentException { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (size < 0) { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("size < 0"); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int oldMaximum = maximumSize; 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project maximumSize = size; 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Trim cache to size if necessary. 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (size < oldMaximum) { 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project trimToSize(); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts the given session to bytes. 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return session data as bytes or null if the session can't be converted 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] toBytes(SSLSession session) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // TODO: Support SSLSessionImpl, too. 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!(session instanceof OpenSSLSessionImpl)) { 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project OpenSSLSessionImpl sslSession = (OpenSSLSessionImpl) session; 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteArrayOutputStream baos = new ByteArrayOutputStream(); 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DataOutputStream daos = new DataOutputStream(baos); 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.writeInt(OPEN_SSL); // session type ID 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Session data. 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] data = sslSession.getEncoded(); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.writeInt(data.length); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.write(data); 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Certificates. 201df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom Certificate[] certs = session.getPeerCertificates(); 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.writeInt(certs.length); 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (Certificate cert : certs) { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project data = cert.getEncoded(); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.writeInt(data.length); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project daos.write(data); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // TODO: local certificates? 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return baos.toByteArray(); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project log(e); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CertificateEncodingException e) { 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project log(e); 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a session from the given bytes. 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a session or null if the session can't be converted 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLSession toSession(byte[] data, String host, int port) { 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteArrayInputStream bais = new ByteArrayInputStream(data); 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project DataInputStream dais = new DataInputStream(bais); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int type = dais.readInt(); 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (type != OPEN_SSL) { 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project log(new AssertionError("Unexpected type ID: " + type)); 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = dais.readInt(); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] sessionData = new byte[length]; 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dais.readFully(sessionData); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = dais.readInt(); 241df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509CertImpl[] certs = new X509CertImpl[count]; 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < count; i++) { 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project length = dais.readInt(); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] certData = new byte[length]; 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dais.readFully(certData); 246df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom certs[i] = new X509CertImpl(certData); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 249bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return new OpenSSLSessionImpl(sessionData, host, port, certs, this); 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project log(e); 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2569acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom public SSLSession getSession(byte[] sessionId) { 2579acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (sessionId == null) { 2589acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom throw new NullPointerException("sessionId == null"); 2599acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2609acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom ByteArray key = new ByteArray(sessionId); 2619acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom SSLSession session; 2629acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom synchronized (sessions) { 2639acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom session = sessions.get(key); 2649acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2659acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session != null && session.isValid()) { 2669acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 2679acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2689acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2699acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2709acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2719acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom void putSession(SSLSession session) { 2729acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom byte[] id = session.getId(); 2739acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (id.length == 0) { 2749acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return; 2759acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2769acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom ByteArray key = new ByteArray(id); 2779acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom synchronized (sessions) { 2789acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom sessions.put(key, session); 2799acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2809acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 281ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static void log(Throwable t) { 2830c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson System.logW("Error converting session.", t); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 286e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 287e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 288e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom NativeCrypto.SSL_CTX_free(sslCtxNativePointer); 289e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 290e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 291e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 292ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 293ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom} 294