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