Home | History | Annotate | Download | only in jsse
      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.apache.harmony.xnet.provider.jsse;
     19 
     20 import java.security.AccessControlContext;
     21 import java.security.AccessController;
     22 import java.security.Principal;
     23 import java.security.SecureRandom;
     24 import java.security.cert.Certificate;
     25 import java.security.cert.CertificateEncodingException;
     26 import java.security.cert.X509Certificate;
     27 import java.util.HashMap;
     28 import java.util.Map;
     29 import java.util.Vector;
     30 import javax.net.ssl.SSLPeerUnverifiedException;
     31 import javax.net.ssl.SSLPermission;
     32 import javax.net.ssl.SSLSession;
     33 import javax.net.ssl.SSLSessionBindingEvent;
     34 import javax.net.ssl.SSLSessionBindingListener;
     35 import javax.net.ssl.SSLSessionContext;
     36 import libcore.base.Objects;
     37 
     38 /**
     39  *
     40  * SSLSession implementation
     41  *
     42  * @see javax.net.ssl.SSLSession
     43  */
     44 public class SSLSessionImpl implements SSLSession, Cloneable  {
     45 
     46     /**
     47      * Session object reporting an invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
     48      */
     49     public static final SSLSessionImpl NULL_SESSION = new SSLSessionImpl(null);
     50 
     51     /**
     52      * Container class for the 'value' map's keys.
     53      */
     54     private static final class ValueKey {
     55         final String name;
     56         final AccessControlContext acc;
     57 
     58         ValueKey(String name) {
     59             super();
     60             this.name = name;
     61             this.acc = AccessController.getContext();
     62         }
     63 
     64         @Override
     65         public int hashCode() {
     66             final int prime = 31;
     67             int result = 1;
     68             result = prime * result + ((acc == null) ? 0 : acc.hashCode());
     69             result = prime * result + ((name == null) ? 0 : name.hashCode());
     70             return result;
     71         }
     72 
     73         @Override
     74         public boolean equals(Object obj) {
     75             if (this == obj)
     76                 return true;
     77             if (obj == null)
     78                 return false;
     79             if (!(obj instanceof ValueKey))
     80                 return false;
     81             ValueKey other = (ValueKey) obj;
     82             if (acc == null) {
     83                 if (other.acc != null)
     84                     return false;
     85             } else if (!acc.equals(other.acc))
     86                 return false;
     87             if (name == null) {
     88                 if (other.name != null)
     89                     return false;
     90             } else if (!name.equals(other.name))
     91                 return false;
     92             return true;
     93         }
     94     }
     95 
     96     private long creationTime;
     97     private boolean isValid = true;
     98     private Map<ValueKey, Object> values = new HashMap<ValueKey, Object>();
     99 
    100     /**
    101      * ID of the session
    102      */
    103     byte[] id;
    104 
    105     /**
    106      * Last time the session was accessed
    107      */
    108     long lastAccessedTime;
    109 
    110     /**
    111      * Protocol used in the session
    112      */
    113     ProtocolVersion protocol;
    114 
    115     /**
    116      * CipherSuite used in the session
    117      */
    118     CipherSuite cipherSuite;
    119 
    120     /**
    121      * Context of the session
    122      */
    123 // BEGIN android-changed
    124     SSLSessionContext context;
    125 // END android-changed
    126 
    127     /**
    128      * certificates were sent to the peer
    129      */
    130     X509Certificate[] localCertificates;
    131 
    132     /**
    133      * Peer certificates
    134      */
    135     X509Certificate[] peerCertificates;
    136 
    137     /**
    138      * Peer host name
    139      */
    140     private String peerHost;
    141 
    142     /**
    143      * Peer port number
    144      */
    145     private int peerPort = -1;
    146 
    147     /**
    148      * Master secret
    149      */
    150     byte[] master_secret;
    151 
    152     /**
    153      * clientRandom
    154      */
    155     byte[] clientRandom;
    156 
    157     /**
    158      * serverRandom
    159      */
    160     byte[] serverRandom;
    161 
    162     /**
    163      * True if this entity is considered the server
    164      */
    165     final boolean isServer;
    166 
    167     /**
    168      * Creates SSLSession implementation
    169      *
    170      * @param cipher_suite
    171      * @param sr
    172      */
    173     public SSLSessionImpl(CipherSuite cipher_suite, SecureRandom sr) {
    174         creationTime = System.currentTimeMillis();
    175         lastAccessedTime = creationTime;
    176         if (cipher_suite == null) {
    177             this.cipherSuite = CipherSuite.SSL_NULL_WITH_NULL_NULL;
    178             id = new byte[0];
    179             isServer = false;
    180             isValid = false;
    181         } else {
    182             this.cipherSuite = cipher_suite;
    183             id = new byte[32];
    184             sr.nextBytes(id);
    185             long time = creationTime / 1000;
    186             id[28] = (byte) ((time & 0xFF000000) >>> 24);
    187             id[29] = (byte) ((time & 0x00FF0000) >>> 16);
    188             id[30] = (byte) ((time & 0x0000FF00) >>> 8);
    189             id[31] = (byte) ((time & 0x000000FF));
    190             isServer = true;
    191         }
    192 
    193     }
    194 
    195     /**
    196      * Creates SSLSession implementation
    197      *
    198      * @param sr
    199      */
    200     public SSLSessionImpl(SecureRandom sr) {
    201         this(null, sr);
    202     }
    203 
    204     public int getApplicationBufferSize() {
    205         return SSLRecordProtocol.MAX_DATA_LENGTH;
    206     }
    207 
    208     public String getCipherSuite() {
    209         return cipherSuite.getName();
    210     }
    211 
    212     public long getCreationTime() {
    213         return creationTime;
    214     }
    215 
    216     public byte[] getId() {
    217         return id;
    218     }
    219 
    220     public long getLastAccessedTime() {
    221         return lastAccessedTime;
    222     }
    223 
    224     public Certificate[] getLocalCertificates() {
    225         return localCertificates;
    226     }
    227 
    228     public Principal getLocalPrincipal() {
    229         if (localCertificates != null && localCertificates.length > 0) {
    230             return localCertificates[0].getSubjectX500Principal();
    231         }
    232         return null;
    233     }
    234 
    235     public int getPacketBufferSize() {
    236         return SSLRecordProtocol.MAX_SSL_PACKET_SIZE;
    237     }
    238 
    239     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
    240             throws SSLPeerUnverifiedException {
    241         if (peerCertificates == null) {
    242             throw new SSLPeerUnverifiedException("No peer certificate");
    243         }
    244         javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[peerCertificates.length];
    245         for (int i = 0; i < certs.length; i++) {
    246             try {
    247                 certs[i] = javax.security.cert.X509Certificate.getInstance(peerCertificates[i]
    248                         .getEncoded());
    249             } catch (javax.security.cert.CertificateException e) {
    250             } catch (CertificateEncodingException e) {
    251             }
    252         }
    253         return certs;
    254     }
    255 
    256     public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
    257         if (peerCertificates == null) {
    258             throw new SSLPeerUnverifiedException("No peer certificate");
    259         }
    260         return peerCertificates;
    261     }
    262 
    263     public String getPeerHost() {
    264         return peerHost;
    265     }
    266 
    267     public int getPeerPort() {
    268         return peerPort;
    269     }
    270 
    271     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
    272         if (peerCertificates == null) {
    273             throw new SSLPeerUnverifiedException("No peer certificate");
    274         }
    275         return peerCertificates[0].getSubjectX500Principal();
    276     }
    277 
    278     public String getProtocol() {
    279         return (protocol == null) ? "NONE" : protocol.name;
    280     }
    281 
    282     public SSLSessionContext getSessionContext() {
    283         SecurityManager sm = System.getSecurityManager();
    284         if (sm != null) {
    285             sm.checkPermission(new SSLPermission("getSSLSessionContext"));
    286         }
    287         return context;
    288     }
    289 
    290     public Object getValue(String name) {
    291         if (name == null) {
    292             throw new IllegalArgumentException("Parameter is null");
    293         }
    294         return values.get(new ValueKey(name));
    295     }
    296 
    297     public String[] getValueNames() {
    298         final Vector<String> v = new Vector<String>();
    299         final AccessControlContext currAcc = AccessController.getContext();
    300         for (ValueKey key : values.keySet()) {
    301             if (Objects.equal(currAcc, key.acc)) {
    302                 v.add(key.name);
    303             }
    304         }
    305         return v.toArray(new String[v.size()]);
    306     }
    307 
    308     public void invalidate() {
    309         isValid = false;
    310         context = null;
    311     }
    312 
    313     public boolean isValid() {
    314         if (isValid && context != null && context.getSessionTimeout() != 0
    315                 && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) {
    316             isValid = false;
    317         }
    318         return isValid;
    319     }
    320 
    321     public void putValue(String name, Object value) {
    322         if (name == null || value == null) {
    323             throw new IllegalArgumentException("Parameter is null");
    324         }
    325         Object old = values.put(new ValueKey(name), value);
    326         if (value instanceof SSLSessionBindingListener) {
    327             ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
    328         }
    329         if (old instanceof SSLSessionBindingListener) {
    330             ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
    331         }
    332 
    333     }
    334 
    335     public void removeValue(String name) {
    336         if (name == null) {
    337             throw new IllegalArgumentException("Parameter is null");
    338         }
    339         Object old = values.remove(new ValueKey(name));
    340         if (old instanceof SSLSessionBindingListener) {
    341             SSLSessionBindingListener listener = (SSLSessionBindingListener) old;
    342             listener.valueUnbound(new SSLSessionBindingEvent(this, name));
    343         }
    344     }
    345 
    346     @Override
    347     public Object clone() {
    348         try {
    349             return super.clone();
    350         } catch (CloneNotSupportedException e) {
    351             throw new AssertionError(e);
    352         }
    353     }
    354 
    355     /**
    356      * Sets the address of the peer
    357      *
    358      * @param peerHost
    359      * @param peerPort
    360      */
    361     void setPeer(String peerHost, int peerPort) {
    362         this.peerHost = peerHost;
    363         this.peerPort = peerPort;
    364     }
    365 }
    366