AbstractSessionContext.java revision e247367fbd5d5b0451c3b3e61e6dba37f27d49e1
108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/*
208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * you may not use this file except in compliance with the License.
608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * You may obtain a copy of the License at
708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * See the License for the specific language governing permissions and
1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * limitations under the License.
1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
194a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.io.ByteArrayInputStream;
204a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.io.ByteArrayOutputStream;
214a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.io.DataInputStream;
224a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.io.DataOutputStream;
234a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.io.IOException;
24e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstromimport java.security.cert.Certificate;
25e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstromimport java.security.cert.CertificateEncodingException;
264a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Arrays;
274a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Enumeration;
284a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Iterator;
2961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstromimport java.util.LinkedHashMap;
3061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstromimport java.util.Map;
314a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.NoSuchElementException;
3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.logging.Level;
3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession;
3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSessionContext;
35e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstromimport org.apache.harmony.security.provider.cert.X509CertImpl;
3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/**
3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Supports SSL session caches.
3908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectabstract class AbstractSessionContext implements SSLSessionContext {
4108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    volatile int maximumSize;
4308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    volatile int timeout;
4408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
452785b7f916644f939b599cf6b01a3df6fae1eca5Brian Carlstrom    final int sslCtxNativePointer = NativeCrypto.SSL_CTX_new();
4608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /** Identifies OpenSSL sessions. */
4808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    static final int OPEN_SSL = 1;
4908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    private final Map<ByteArray, SSLSession> sessions
5161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            = new LinkedHashMap<ByteArray, SSLSession>() {
5261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        @Override
5361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        protected boolean removeEldestEntry(
5461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                Map.Entry<ByteArray, SSLSession> eldest) {
5561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return maximumSize > 0 && size() > maximumSize;
5661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
5761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    };
5861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
5908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
6008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Constructs a new session context.
6108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
6208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param maximumSize of cache
6308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param timeout for cache entries
6408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
652785b7f916644f939b599cf6b01a3df6fae1eca5Brian Carlstrom    AbstractSessionContext(int maximumSize, int timeout) {
6608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.maximumSize = maximumSize;
6708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.timeout = timeout;
6808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
6908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
7008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
7161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * Returns the collection of sessions ordered from oldest to newest
7208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
7361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    private Iterator<SSLSession> sessionIterator() {
7461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
7561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            SSLSession[] array = sessions.values().toArray(
7661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    new SSLSession[sessions.size()]);
7761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return Arrays.asList(array).iterator();
7861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
7961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
8008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
8108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final Enumeration getIds() {
824a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom        final Iterator<SSLSession> i = sessionIterator();
8308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return new Enumeration<byte[]>() {
844a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom            private SSLSession next;
8508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            public boolean hasMoreElements() {
864a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                if (next != null) {
874a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    return true;
884a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
894a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                while (i.hasNext()) {
904a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    SSLSession session = i.next();
914a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    if (session.isValid()) {
924a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                        next = session;
934a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                        return true;
944a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    }
954a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
964a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                next = null;
974a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                return false;
9808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
9908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            public byte[] nextElement() {
1004a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                if (hasMoreElements()) {
1014a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    byte[] id = next.getId();
1024a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    next = null;
1034a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    return id;
1044a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
1054a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                throw new NoSuchElementException();
10608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
10708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        };
10808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
10908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final int getSessionCacheSize() {
11108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return maximumSize;
11208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final int getSessionTimeout() {
11508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return timeout;
11608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
11908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Makes sure cache size is < maximumSize.
12008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
12161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    protected void trimToSize() {
12261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
12361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            int size = sessions.size();
12461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            if (size > maximumSize) {
12561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                int removals = size - maximumSize;
12661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                Iterator<SSLSession> i = sessions.values().iterator();
12761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                do {
12861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    SSLSession session = i.next();
12961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    i.remove();
13061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    sessionRemoved(session);
13161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                } while (--removals > 0);
13261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
13361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
13461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
13561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
13661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    public void setSessionTimeout(int seconds)
13761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throws IllegalArgumentException {
13861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (seconds < 0) {
13961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throw new IllegalArgumentException("seconds < 0");
14061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
14161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        timeout = seconds;
14261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
14361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
14461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            Iterator<SSLSession> i = sessions.values().iterator();
14561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            while (i.hasNext()) {
14661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                SSLSession session = i.next();
14761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                // SSLSession's know their context and consult the
14861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                // timeout as part of their validity condition.
14961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                if (!session.isValid()) {
15061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    i.remove();
15161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    sessionRemoved(session);
15261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                }
15361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
15461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
15561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
15661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
1571f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom    /**
15861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * Called when a session is removed. Used by ClientSessionContext
15961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * to update its host-and-port based cache.
16061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     */
16161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    abstract protected void sessionRemoved(SSLSession session);
16208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
16308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final void setSessionCacheSize(int size)
16408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throws IllegalArgumentException {
16508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (size < 0) {
16608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("size < 0");
16708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
16808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
16908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        int oldMaximum = maximumSize;
17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        maximumSize = size;
17108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // Trim cache to size if necessary.
17308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (size < oldMaximum) {
17408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            trimToSize();
17508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
17608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
17908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Converts the given session to bytes.
18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
18108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return session data as bytes or null if the session can't be converted
18208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
18308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    byte[] toBytes(SSLSession session) {
18408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // TODO: Support SSLSessionImpl, too.
18508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!(session instanceof OpenSSLSessionImpl)) {
18608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
18708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        OpenSSLSessionImpl sslSession = (OpenSSLSessionImpl) session;
19008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
19108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            ByteArrayOutputStream baos = new ByteArrayOutputStream();
19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            DataOutputStream daos = new DataOutputStream(baos);
19308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(OPEN_SSL); // session type ID
19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
19608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // Session data.
19708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            byte[] data = sslSession.getEncoded();
19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(data.length);
19908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.write(data);
20008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
20108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // Certificates.
202e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            Certificate[] certs = session.getPeerCertificates();
20308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(certs.length);
20408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
205e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            for (Certificate cert : certs) {
20608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                data = cert.getEncoded();
20708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                daos.writeInt(data.length);
20808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                daos.write(data);
20908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
2102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // TODO: local certificates?
21108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
21208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return baos.toByteArray();
21308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (IOException e) {
21408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
21508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
21608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (CertificateEncodingException e) {
21708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
21808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
21908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
22008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
22108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
22208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
22308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Creates a session from the given bytes.
22408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
22508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return a session or null if the session can't be converted
22608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
22708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    SSLSession toSession(byte[] data, String host, int port) {
22808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        ByteArrayInputStream bais = new ByteArrayInputStream(data);
22908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        DataInputStream dais = new DataInputStream(bais);
23008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
23108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int type = dais.readInt();
23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (type != OPEN_SSL) {
23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                log(new AssertionError("Unexpected type ID: " + type));
23408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return null;
23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
23608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
23708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int length = dais.readInt();
23808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            byte[] sessionData = new byte[length];
23908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            dais.readFully(sessionData);
24008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
24108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int count = dais.readInt();
242e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            X509CertImpl[] certs = new X509CertImpl[count];
24308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            for (int i = 0; i < count; i++) {
24408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                length = dais.readInt();
24508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                byte[] certData = new byte[length];
24608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                dais.readFully(certData);
247e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                certs[i] = new X509CertImpl(certData);
24808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
24908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
2502828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            return new OpenSSLSessionImpl(sessionData, host, port, certs, this);
25108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (IOException e) {
25208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
25308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
25408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
25508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
25608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
25761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    public SSLSession getSession(byte[] sessionId) {
25861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (sessionId == null) {
25961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throw new NullPointerException("sessionId == null");
26061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        ByteArray key = new ByteArray(sessionId);
26261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        SSLSession session;
26361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
26461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            session = sessions.get(key);
26561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (session != null && session.isValid()) {
26761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return session;
26861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        return null;
27061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
27161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
27261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    void putSession(SSLSession session) {
27361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        byte[] id = session.getId();
27461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (id.length == 0) {
27561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return;
27661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
27761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        ByteArray key = new ByteArray(id);
27861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
27961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            sessions.put(key, session);
28061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
28161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
282f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
28308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    static void log(Throwable t) {
28408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        java.util.logging.Logger.global.log(Level.WARNING,
28508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                "Error converting session.", t);
28608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
28708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
288f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    protected void finalize() throws IOException {
289f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        NativeCrypto.SSL_CTX_free(sslCtxNativePointer);
290f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
291f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
29208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
29308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Byte array wrapper. Implements equals() and hashCode().
29408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
29508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    static class ByteArray {
29608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
29708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        private final byte[] bytes;
29808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
29908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        ByteArray(byte[] bytes) {
30008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            this.bytes = bytes;
30108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
30208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
30308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        @Override
30408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int hashCode() {
30508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return Arrays.hashCode(bytes);
30608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
30708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
30808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        @Override
30908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
31008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public boolean equals(Object o) {
31108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            ByteArray other = (ByteArray) o;
31208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return Arrays.equals(bytes, other.bytes);
31308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
31408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
315f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom}
316