AbstractSessionContext.java revision 860d2707ce126ef8f66e3eac7ceeab6d24218cd8
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
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
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;
26860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.X509Certificate;
274a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Arrays;
284a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Enumeration;
294a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.Iterator;
3061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstromimport java.util.LinkedHashMap;
3161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstromimport java.util.Map;
324a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstromimport java.util.NoSuchElementException;
33860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession;
3508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSessionContext;
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
4538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice    final long 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) {
55a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom            boolean remove = maximumSize > 0 && size() > maximumSize;
56a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom            if (remove) {
57a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom                remove(eldest.getKey());
58a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom                sessionRemoved(eldest.getValue());
59a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom            }
60a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom            return false;
6161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
6261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    };
6361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
6408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
6508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Constructs a new session context.
6608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
6708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param maximumSize of cache
6808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @param timeout for cache entries
6908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
702785b7f916644f939b599cf6b01a3df6fae1eca5Brian Carlstrom    AbstractSessionContext(int maximumSize, int timeout) {
7108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.maximumSize = maximumSize;
7208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.timeout = timeout;
7308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
7408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
7508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
7661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * Returns the collection of sessions ordered from oldest to newest
7708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
7861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    private Iterator<SSLSession> sessionIterator() {
7961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
8061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            SSLSession[] array = sessions.values().toArray(
8161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    new SSLSession[sessions.size()]);
8261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return Arrays.asList(array).iterator();
8361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
8461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
8508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
8608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final Enumeration getIds() {
874a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom        final Iterator<SSLSession> i = sessionIterator();
8808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return new Enumeration<byte[]>() {
894a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom            private SSLSession next;
9008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            public boolean hasMoreElements() {
914a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                if (next != null) {
924a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    return true;
934a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
944a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                while (i.hasNext()) {
954a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    SSLSession session = i.next();
964a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    if (session.isValid()) {
974a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                        next = session;
984a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                        return true;
994a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    }
1004a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
1014a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                next = null;
1024a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                return false;
10308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
10408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            public byte[] nextElement() {
1054a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                if (hasMoreElements()) {
1064a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    byte[] id = next.getId();
1074a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    next = null;
1084a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                    return id;
1094a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                }
1104a91f8a9c955b7cd64fbdf36233295ac3dd515d3Brian Carlstrom                throw new NoSuchElementException();
11108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
11208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        };
11308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final int getSessionCacheSize() {
11608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return maximumSize;
11708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final int getSessionTimeout() {
12008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return timeout;
12108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
12208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
12308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
12408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Makes sure cache size is < maximumSize.
12508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
12661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    protected void trimToSize() {
12761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
12861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            int size = sessions.size();
12961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            if (size > maximumSize) {
13061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                int removals = size - maximumSize;
13161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                Iterator<SSLSession> i = sessions.values().iterator();
13261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                do {
13361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    SSLSession session = i.next();
13461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    i.remove();
13561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    sessionRemoved(session);
13661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                } while (--removals > 0);
13761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
13861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
13961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
14061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
14161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    public void setSessionTimeout(int seconds)
14261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throws IllegalArgumentException {
14361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (seconds < 0) {
14461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throw new IllegalArgumentException("seconds < 0");
14561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
14661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        timeout = seconds;
14761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
14861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
14961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            Iterator<SSLSession> i = sessions.values().iterator();
15061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            while (i.hasNext()) {
15161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                SSLSession session = i.next();
15261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                // SSLSession's know their context and consult the
15361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                // timeout as part of their validity condition.
15461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                if (!session.isValid()) {
15561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    i.remove();
15661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                    sessionRemoved(session);
15761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom                }
15861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            }
15961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
16061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
16161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
1621f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom    /**
16361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * Called when a session is removed. Used by ClientSessionContext
16461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     * to update its host-and-port based cache.
16561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom     */
166ff69e28cd239217f33fe96a9c8e7c40b658c19f9Jesse Wilson    protected abstract void sessionRemoved(SSLSession session);
16708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
16808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    public final void setSessionCacheSize(int size)
16908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throws IllegalArgumentException {
17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (size < 0) {
17108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("size < 0");
17208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
17308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        int oldMaximum = maximumSize;
17508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        maximumSize = size;
17608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // Trim cache to size if necessary.
17808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (size < oldMaximum) {
17908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            trimToSize();
18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
18108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
18208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
18308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
18408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Converts the given session to bytes.
18508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
18608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return session data as bytes or null if the session can't be converted
18708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    byte[] toBytes(SSLSession session) {
18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        // TODO: Support SSLSessionImpl, too.
19008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!(session instanceof OpenSSLSessionImpl)) {
19108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
19308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        OpenSSLSessionImpl sslSession = (OpenSSLSessionImpl) session;
19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
19608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            ByteArrayOutputStream baos = new ByteArrayOutputStream();
19708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            DataOutputStream daos = new DataOutputStream(baos);
19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
19908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(OPEN_SSL); // session type ID
20008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
20108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // Session data.
20208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            byte[] data = sslSession.getEncoded();
20308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(data.length);
20408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.write(data);
20508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
20608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            // Certificates.
207e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            Certificate[] certs = session.getPeerCertificates();
20808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            daos.writeInt(certs.length);
20908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
210e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            for (Certificate cert : certs) {
21108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                data = cert.getEncoded();
21208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                daos.writeInt(data.length);
21308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                daos.write(data);
21408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
2152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // TODO: local certificates?
21608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
21708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return baos.toByteArray();
21808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (IOException e) {
21908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
22008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
22108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (CertificateEncodingException e) {
22208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
22308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
22408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
22508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
22608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
22708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
22808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * Creates a session from the given bytes.
22908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     *
23008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * @return a session or null if the session can't be converted
23108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    SSLSession toSession(byte[] data, String host, int port) {
23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        ByteArrayInputStream bais = new ByteArrayInputStream(data);
23408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        DataInputStream dais = new DataInputStream(bais);
23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
23608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int type = dais.readInt();
23708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (type != OPEN_SSL) {
23808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                log(new AssertionError("Unexpected type ID: " + type));
23908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return null;
24008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
24108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
24208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int length = dais.readInt();
24308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            byte[] sessionData = new byte[length];
24408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            dais.readFully(sessionData);
24508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
24608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            int count = dais.readInt();
247860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            X509Certificate[] certs = new X509Certificate[count];
24808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            for (int i = 0; i < count; i++) {
24908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                length = dais.readInt();
25008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                byte[] certData = new byte[length];
25108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                dais.readFully(certData);
252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                certs[i] = OpenSSLX509Certificate.fromX509Der(certData);
25308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
25408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
2552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            return new OpenSSLSessionImpl(sessionData, host, port, certs, this);
25608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        } catch (IOException e) {
25708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            log(e);
25808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            return null;
25908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
26008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
26108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
26261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    public SSLSession getSession(byte[] sessionId) {
26361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (sessionId == null) {
26461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            throw new NullPointerException("sessionId == null");
26561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
26661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        ByteArray key = new ByteArray(sessionId);
26761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        SSLSession session;
26861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
26961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            session = sessions.get(key);
27061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
27161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (session != null && session.isValid()) {
27261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return session;
27361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
27461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        return null;
27561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
27661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom
27761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    void putSession(SSLSession session) {
27861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        byte[] id = session.getId();
27961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        if (id.length == 0) {
28061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            return;
28161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
28261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        ByteArray key = new ByteArray(id);
28361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        synchronized (sessions) {
28461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom            sessions.put(key, session);
28561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom        }
28661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom    }
287f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
28808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    static void log(Throwable t) {
2895006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        System.logW("Error converting session.", t);
29008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
29108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
2921990574e420184f3ad43400171f624dad44700d8Brian Carlstrom    @Override protected void finalize() throws Throwable {
2931990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        try {
2941990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            NativeCrypto.SSL_CTX_free(sslCtxNativePointer);
2951990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        } finally {
2961990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            super.finalize();
2971990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        }
298f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
299f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom}
300