Home | History | Annotate | Download | only in conscrypt
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.conscrypt;
     19 
     20 import java.security.Principal;
     21 import java.security.SecureRandom;
     22 import java.security.cert.Certificate;
     23 import java.security.cert.CertificateEncodingException;
     24 import java.security.cert.X509Certificate;
     25 import java.util.HashMap;
     26 import java.util.Map;
     27 import javax.net.ssl.SSLPeerUnverifiedException;
     28 import javax.net.ssl.SSLSession;
     29 import javax.net.ssl.SSLSessionBindingEvent;
     30 import javax.net.ssl.SSLSessionBindingListener;
     31 import javax.net.ssl.SSLSessionContext;
     32 import org.conscrypt.util.EmptyArray;
     33 
     34 public final class SSLSessionImpl implements SSLSession, Cloneable  {
     35 
     36     /*
     37      * Holds default instances so class preloading doesn't create an instance of
     38      * it.
     39      */
     40     private static class DefaultHolder {
     41         public static final SSLSessionImpl NULL_SESSION = new SSLSessionImpl(null);
     42     }
     43 
     44     private long creationTime;
     45     private boolean isValid = true;
     46     private final Map<String, Object> values = new HashMap<String, Object>();
     47 
     48     byte[] id;
     49     long lastAccessedTime;
     50     ProtocolVersion protocol;
     51     CipherSuite cipherSuite;
     52     SSLSessionContext context;
     53     X509Certificate[] localCertificates;
     54     X509Certificate[] peerCertificates;
     55     private String peerHost;
     56     private int peerPort = -1;
     57     byte[] master_secret;
     58     byte[] clientRandom;
     59     byte[] serverRandom;
     60     final boolean isServer;
     61 
     62     public static SSLSessionImpl getNullSession() {
     63         return DefaultHolder.NULL_SESSION;
     64     }
     65 
     66     public SSLSessionImpl(CipherSuite cipher_suite, SecureRandom secureRandom) {
     67         creationTime = System.currentTimeMillis();
     68         lastAccessedTime = creationTime;
     69         if (cipher_suite == null) {
     70             this.cipherSuite = CipherSuite.SSL_NULL_WITH_NULL_NULL;
     71             id = EmptyArray.BYTE;
     72             isServer = false;
     73             isValid = false;
     74         } else {
     75             this.cipherSuite = cipher_suite;
     76             id = new byte[32];
     77             secureRandom.nextBytes(id);
     78             long time = creationTime / 1000;
     79             id[28] = (byte) ((time & 0xFF000000) >>> 24);
     80             id[29] = (byte) ((time & 0x00FF0000) >>> 16);
     81             id[30] = (byte) ((time & 0x0000FF00) >>> 8);
     82             id[31] = (byte) ((time & 0x000000FF));
     83             isServer = true;
     84         }
     85 
     86     }
     87 
     88     public SSLSessionImpl(SecureRandom secureRandom) {
     89         this(null, secureRandom);
     90     }
     91 
     92     public int getApplicationBufferSize() {
     93         return SSLRecordProtocol.MAX_DATA_LENGTH;
     94     }
     95 
     96     public String getCipherSuite() {
     97         return cipherSuite.getName();
     98     }
     99 
    100     public long getCreationTime() {
    101         return creationTime;
    102     }
    103 
    104     public byte[] getId() {
    105         return id;
    106     }
    107 
    108     public long getLastAccessedTime() {
    109         return lastAccessedTime;
    110     }
    111 
    112     public Certificate[] getLocalCertificates() {
    113         return localCertificates;
    114     }
    115 
    116     public Principal getLocalPrincipal() {
    117         if (localCertificates != null && localCertificates.length > 0) {
    118             return localCertificates[0].getSubjectX500Principal();
    119         }
    120         return null;
    121     }
    122 
    123     public int getPacketBufferSize() {
    124         return SSLRecordProtocol.MAX_SSL_PACKET_SIZE;
    125     }
    126 
    127     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
    128             throws SSLPeerUnverifiedException {
    129         if (peerCertificates == null) {
    130             throw new SSLPeerUnverifiedException("No peer certificate");
    131         }
    132         javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[peerCertificates.length];
    133         for (int i = 0; i < certs.length; i++) {
    134             try {
    135                 certs[i] = javax.security.cert.X509Certificate.getInstance(peerCertificates[i]
    136                         .getEncoded());
    137             } catch (javax.security.cert.CertificateException ignored) {
    138             } catch (CertificateEncodingException ignored) {
    139             }
    140         }
    141         return certs;
    142     }
    143 
    144     public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
    145         if (peerCertificates == null) {
    146             throw new SSLPeerUnverifiedException("No peer certificate");
    147         }
    148         return peerCertificates;
    149     }
    150 
    151     public String getPeerHost() {
    152         return peerHost;
    153     }
    154 
    155     public int getPeerPort() {
    156         return peerPort;
    157     }
    158 
    159     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
    160         if (peerCertificates == null) {
    161             throw new SSLPeerUnverifiedException("No peer certificate");
    162         }
    163         return peerCertificates[0].getSubjectX500Principal();
    164     }
    165 
    166     public String getProtocol() {
    167         return (protocol == null) ? "NONE" : protocol.name;
    168     }
    169 
    170     public SSLSessionContext getSessionContext() {
    171         return context;
    172     }
    173 
    174     public Object getValue(String name) {
    175         if (name == null) {
    176             throw new IllegalArgumentException("name == null");
    177         }
    178         return values.get(name);
    179     }
    180 
    181     public String[] getValueNames() {
    182         return values.keySet().toArray(new String[values.size()]);
    183     }
    184 
    185     public void invalidate() {
    186         isValid = false;
    187         context = null;
    188     }
    189 
    190     public boolean isValid() {
    191         if (isValid && context != null && context.getSessionTimeout() != 0
    192                 && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) {
    193             isValid = false;
    194         }
    195         return isValid;
    196     }
    197 
    198     public void putValue(String name, Object value) {
    199         if (name == null || value == null) {
    200             throw new IllegalArgumentException("name == null || value == null");
    201         }
    202         Object old = values.put(name, value);
    203         if (value instanceof SSLSessionBindingListener) {
    204             ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
    205         }
    206         if (old instanceof SSLSessionBindingListener) {
    207             ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
    208         }
    209 
    210     }
    211 
    212     public void removeValue(String name) {
    213         if (name == null) {
    214             throw new IllegalArgumentException("name == null");
    215         }
    216         Object old = values.remove(name);
    217         if (old instanceof SSLSessionBindingListener) {
    218             SSLSessionBindingListener listener = (SSLSessionBindingListener) old;
    219             listener.valueUnbound(new SSLSessionBindingEvent(this, name));
    220         }
    221     }
    222 
    223     @Override
    224     public Object clone() {
    225         try {
    226             return super.clone();
    227         } catch (CloneNotSupportedException e) {
    228             throw new AssertionError(e);
    229         }
    230     }
    231 
    232     void setPeer(String peerHost, int peerPort) {
    233         this.peerHost = peerHost;
    234         this.peerPort = peerPort;
    235     }
    236 }
    237