1 /*
2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package sun.security.ssl;
26 
27 import java.math.BigInteger;
28 import java.net.InetAddress;
29 import java.security.Principal;
30 import java.security.PrivateKey;
31 import java.security.cert.CertificateEncodingException;
32 import java.security.cert.X509Certificate;
33 import java.util.ArrayList;
34 import java.util.Queue;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Enumeration;
38 import java.util.List;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.concurrent.ConcurrentLinkedQueue;
41 import javax.crypto.SecretKey;
42 import javax.net.ssl.ExtendedSSLSession;
43 import javax.net.ssl.SNIServerName;
44 import javax.net.ssl.SSLPeerUnverifiedException;
45 import javax.net.ssl.SSLPermission;
46 import javax.net.ssl.SSLSessionBindingEvent;
47 import javax.net.ssl.SSLSessionBindingListener;
48 import javax.net.ssl.SSLSessionContext;
49 
50 /**
51  * Implements the SSL session interface, and exposes the session context
52  * which is maintained by SSL servers.
53  *
54  * <P> Servers have the ability to manage the sessions associated with
55  * their authentication context(s).  They can do this by enumerating the
56  * IDs of the sessions which are cached, examining those sessions, and then
57  * perhaps invalidating a given session so that it can't be used again.
58  * If servers do not explicitly manage the cache, sessions will linger
59  * until memory is low enough that the runtime environment purges cache
60  * entries automatically to reclaim space.
61  *
62  * <P><em> The only reason this class is not package-private is that
63  * there's no other public way to get at the server session context which
64  * is associated with any given authentication context. </em>
65  *
66  * @author David Brownell
67  */
68 final class SSLSessionImpl extends ExtendedSSLSession {
69 
70     /*
71      * The state of a single session, as described in section 7.1
72      * of the SSLv3 spec.
73      */
74     private final ProtocolVersion       protocolVersion;
75     private final SessionId             sessionId;
76     private X509Certificate[]   peerCerts;
77     private CipherSuite         cipherSuite;
78     private SecretKey           masterSecret;
79     final boolean               useExtendedMasterSecret;
80 
81     /*
82      * Information not part of the SSLv3 protocol spec, but used
83      * to support session management policies.
84      */
85     private final long          creationTime;
86     private long                lastUsedTime = 0;
87     private final String        host;
88     private final int           port;
89     private SSLSessionContextImpl       context;
90     private boolean             invalidated;
91     private X509Certificate[]   localCerts;
92     private PrivateKey          localPrivateKey;
93     private final Collection<SignatureScheme>     localSupportedSignAlgs;
94     private String[]            peerSupportedSignAlgs;      // for certificate
95     private boolean             useDefaultPeerSignAlgs = false;
96     private List<byte[]>        statusResponses;
97     private SecretKey           resumptionMasterSecret;
98     private SecretKey           preSharedKey;
99     private byte[]              pskIdentity;
100     private final long          ticketCreationTime = System.currentTimeMillis();
101     private int                 ticketAgeAdd;
102 
103     private int                 negotiatedMaxFragLen = -1;
104     private int                 maximumPacketSize;
105 
106     private final Queue<SSLSessionImpl> childSessions =
107                                         new ConcurrentLinkedQueue<>();
108 
109     /*
110      * Is the session currently re-established with a session-resumption
111      * abbreviated initial handshake?
112      *
113      * Note that currently we only set this variable in client side.
114      */
115     private boolean isSessionResumption = false;
116 
117     /*
118      * Use of session caches is globally enabled/disabled.
119      */
120     private static boolean      defaultRejoinable = true;
121 
122     // server name indication
123     final SNIServerName         serverNameIndication;
124     private final List<SNIServerName>    requestedServerNames;
125 
126     // Counter used to create unique nonces in NewSessionTicket
127     private BigInteger ticketNonceCounter = BigInteger.ONE;
128 
129     // The endpoint identification algorithm used to check certificates
130     // in this session.
131     private final String              identificationProtocol;
132 
133     /*
134      * Create a new non-rejoinable session, using the default (null)
135      * cipher spec.  This constructor returns a session which could
136      * be used either by a client or by a server, as a connection is
137      * first opened and before handshaking begins.
138      */
SSLSessionImpl()139     SSLSessionImpl() {
140         this.protocolVersion = ProtocolVersion.NONE;
141         this.cipherSuite = CipherSuite.C_NULL;
142         this.sessionId = new SessionId(false, null);
143         this.host = null;
144         this.port = -1;
145         this.localSupportedSignAlgs = Collections.emptySet();
146         this.serverNameIndication = null;
147         this.requestedServerNames = Collections.<SNIServerName>emptyList();
148         this.useExtendedMasterSecret = false;
149         this.creationTime = System.currentTimeMillis();
150         this.identificationProtocol = null;
151         this.boundValues = new ConcurrentHashMap<>();
152     }
153 
154     /*
155      * Create a new session, using a given cipher spec.  This will
156      * be rejoinable if session caching is enabled; the constructor
157      * is intended mostly for use by serves.
158      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite)159     SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) {
160         this(hc, cipherSuite,
161             new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom()));
162     }
163 
164     /*
165      * Record a new session, using a given cipher spec and session ID.
166      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id)167     SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) {
168         this(hc, cipherSuite, id, System.currentTimeMillis());
169     }
170 
171     /*
172      * Record a new session, using a given cipher spec, session ID,
173      * and creation time.
174      * Note: For the unmodifiable collections and lists we are creating new
175      * collections as inputs to avoid potential deep nesting of
176      * unmodifiable collections that can cause StackOverflowErrors
177      * (see JDK-6323374).
178      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id, long creationTime)179     SSLSessionImpl(HandshakeContext hc,
180             CipherSuite cipherSuite, SessionId id, long creationTime) {
181         this.protocolVersion = hc.negotiatedProtocol;
182         this.cipherSuite = cipherSuite;
183         this.sessionId = id;
184         this.host = hc.conContext.transport.getPeerHost();
185         this.port = hc.conContext.transport.getPeerPort();
186         this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ?
187                 Collections.emptySet() :
188                 Collections.unmodifiableCollection(
189                         new ArrayList<>(hc.localSupportedSignAlgs));
190         this.serverNameIndication = hc.negotiatedServerName;
191         this.requestedServerNames = Collections.unmodifiableList(
192                 new ArrayList<>(hc.getRequestedServerNames()));
193         if (hc.sslConfig.isClientMode) {
194             this.useExtendedMasterSecret =
195                 (hc.handshakeExtensions.get(
196                         SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
197                 (hc.handshakeExtensions.get(
198                         SSLExtension.SH_EXTENDED_MASTER_SECRET) != null);
199         } else {
200             this.useExtendedMasterSecret =
201                 (hc.handshakeExtensions.get(
202                         SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
203                 (!hc.negotiatedProtocol.useTLS13PlusSpec());
204         }
205         this.creationTime = creationTime;
206         this.identificationProtocol = hc.sslConfig.identificationProtocol;
207         this.boundValues = new ConcurrentHashMap<>();
208 
209         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
210              SSLLogger.finest("Session initialized:  " + this);
211         }
212     }
213 
SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId)214     SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId) {
215         this.protocolVersion = baseSession.getProtocolVersion();
216         this.cipherSuite = baseSession.cipherSuite;
217         this.sessionId = newId;
218         this.host = baseSession.getPeerHost();
219         this.port = baseSession.getPeerPort();
220         this.localSupportedSignAlgs =
221                 baseSession.localSupportedSignAlgs == null ?
222                 Collections.emptySet() : baseSession.localSupportedSignAlgs;
223         this.peerSupportedSignAlgs =
224                 baseSession.getPeerSupportedSignatureAlgorithms();
225         this.serverNameIndication = baseSession.serverNameIndication;
226         this.requestedServerNames = baseSession.getRequestedServerNames();
227         this.masterSecret = baseSession.getMasterSecret();
228         this.useExtendedMasterSecret = baseSession.useExtendedMasterSecret;
229         this.creationTime = baseSession.getCreationTime();
230         this.lastUsedTime = System.currentTimeMillis();
231         this.identificationProtocol = baseSession.getIdentificationProtocol();
232         this.localCerts = baseSession.localCerts;
233         this.peerCerts = baseSession.peerCerts;
234         this.statusResponses = baseSession.statusResponses;
235         this.resumptionMasterSecret = baseSession.resumptionMasterSecret;
236         this.context = baseSession.context;
237         this.negotiatedMaxFragLen = baseSession.negotiatedMaxFragLen;
238         this.maximumPacketSize = baseSession.maximumPacketSize;
239         this.boundValues = baseSession.boundValues;
240 
241         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
242              SSLLogger.finest("Session initialized:  " + this);
243         }
244     }
245 
setMasterSecret(SecretKey secret)246     void setMasterSecret(SecretKey secret) {
247         masterSecret = secret;
248     }
249 
setResumptionMasterSecret(SecretKey secret)250     void setResumptionMasterSecret(SecretKey secret) {
251         resumptionMasterSecret = secret;
252     }
253 
setPreSharedKey(SecretKey key)254     void setPreSharedKey(SecretKey key) {
255         preSharedKey = key;
256     }
257 
addChild(SSLSessionImpl session)258     void addChild(SSLSessionImpl session) {
259         childSessions.add(session);
260     }
261 
setTicketAgeAdd(int ticketAgeAdd)262     void setTicketAgeAdd(int ticketAgeAdd) {
263         this.ticketAgeAdd = ticketAgeAdd;
264     }
265 
setPskIdentity(byte[] pskIdentity)266     void setPskIdentity(byte[] pskIdentity) {
267         this.pskIdentity = pskIdentity;
268     }
269 
incrTicketNonceCounter()270     BigInteger incrTicketNonceCounter() {
271         BigInteger result = ticketNonceCounter;
272         ticketNonceCounter = ticketNonceCounter.add(BigInteger.valueOf(1));
273         return result;
274     }
275 
276     /**
277      * Returns the master secret ... treat with extreme caution!
278      */
getMasterSecret()279     SecretKey getMasterSecret() {
280         return masterSecret;
281     }
282 
getResumptionMasterSecret()283     SecretKey getResumptionMasterSecret() {
284         return resumptionMasterSecret;
285     }
286 
getPreSharedKey()287     synchronized SecretKey getPreSharedKey() {
288         return preSharedKey;
289     }
290 
consumePreSharedKey()291     synchronized SecretKey consumePreSharedKey() {
292         try {
293             return preSharedKey;
294         } finally {
295             preSharedKey = null;
296         }
297     }
298 
getTicketAgeAdd()299     int getTicketAgeAdd() {
300         return ticketAgeAdd;
301     }
302 
getIdentificationProtocol()303     String getIdentificationProtocol() {
304         return this.identificationProtocol;
305     }
306 
307     /* PSK identities created from new_session_ticket messages should only
308      * be used once. This method will return the identity and then clear it
309      * so it cannot be used again.
310      */
consumePskIdentity()311     synchronized byte[] consumePskIdentity() {
312         try {
313             return pskIdentity;
314         } finally {
315             pskIdentity = null;
316         }
317     }
318 
setPeerCertificates(X509Certificate[] peer)319     void setPeerCertificates(X509Certificate[] peer) {
320         if (peerCerts == null) {
321             peerCerts = peer;
322         }
323     }
324 
setLocalCertificates(X509Certificate[] local)325     void setLocalCertificates(X509Certificate[] local) {
326         localCerts = local;
327     }
328 
setLocalPrivateKey(PrivateKey privateKey)329     void setLocalPrivateKey(PrivateKey privateKey) {
330         localPrivateKey = privateKey;
331     }
332 
setPeerSupportedSignatureAlgorithms( Collection<SignatureScheme> signatureSchemes)333     void setPeerSupportedSignatureAlgorithms(
334             Collection<SignatureScheme> signatureSchemes) {
335         peerSupportedSignAlgs =
336             SignatureScheme.getAlgorithmNames(signatureSchemes);
337     }
338 
339     // TLS 1.2 only
340     //
341     // Per RFC 5246, If the client supports only the default hash
342     // and signature algorithms, it MAY omit the
343     // signature_algorithms extension.  If the client does not
344     // support the default algorithms, or supports other hash
345     // and signature algorithms (and it is willing to use them
346     // for verifying messages sent by the server, i.e., server
347     // certificates and server key exchange), it MUST send the
348     // signature_algorithms extension, listing the algorithms it
349     // is willing to accept.
setUseDefaultPeerSignAlgs()350     void setUseDefaultPeerSignAlgs() {
351         useDefaultPeerSignAlgs = true;
352         peerSupportedSignAlgs = new String[] {
353             "SHA1withRSA", "SHA1withDSA", "SHA1withECDSA"};
354     }
355 
356     // Returns the connection session.
finish()357     SSLSessionImpl finish() {
358         if (useDefaultPeerSignAlgs) {
359             this.peerSupportedSignAlgs = new String[0];
360         }
361 
362         return this;
363     }
364 
365     /**
366      * Provide status response data obtained during the SSL handshake.
367      *
368      * @param responses a {@link List} of responses in binary form.
369      */
setStatusResponses(List<byte[]> responses)370     void setStatusResponses(List<byte[]> responses) {
371         if (responses != null && !responses.isEmpty()) {
372             statusResponses = responses;
373         } else {
374             statusResponses = Collections.emptyList();
375         }
376     }
377 
378     /**
379      * Returns true iff this session may be resumed ... sessions are
380      * usually resumable.  Security policies may suggest otherwise,
381      * for example sessions that haven't been used for a while (say,
382      * a working day) won't be resumable, and sessions might have a
383      * maximum lifetime in any case.
384      */
isRejoinable()385     boolean isRejoinable() {
386         return sessionId != null && sessionId.length() != 0 &&
387             !invalidated && isLocalAuthenticationValid();
388     }
389 
390     @Override
isValid()391     public synchronized boolean isValid() {
392         return isRejoinable();
393     }
394 
395     /**
396      * Check if the authentication used when establishing this session
397      * is still valid. Returns true if no authentication was used
398      */
isLocalAuthenticationValid()399     private boolean isLocalAuthenticationValid() {
400         if (localPrivateKey != null) {
401             try {
402                 // if the private key is no longer valid, getAlgorithm()
403                 // should throw an exception
404                 // (e.g. Smartcard has been removed from the reader)
405                 localPrivateKey.getAlgorithm();
406             } catch (Exception e) {
407                 invalidate();
408                 return false;
409             }
410         }
411 
412         return true;
413     }
414 
415     /**
416      * Returns the ID for this session.  The ID is fixed for the
417      * duration of the session; neither it, nor its value, changes.
418      */
419     @Override
getId()420     public byte[] getId() {
421         return sessionId.getId();
422     }
423 
424     /**
425      * For server sessions, this returns the set of sessions which
426      * are currently valid in this process.  For client sessions,
427      * this returns null.
428      */
429     @Override
getSessionContext()430     public SSLSessionContext getSessionContext() {
431         /*
432          * An interim security policy until we can do something
433          * more specific in 1.2. Only allow trusted code (code which
434          * can set system properties) to get an
435          * SSLSessionContext. This is to limit the ability of code to
436          * look up specific sessions or enumerate over them. Otherwise,
437          * code can only get session objects from successful SSL
438          * connections which implies that they must have had permission
439          * to make the network connection in the first place.
440          */
441         SecurityManager sm;
442         if ((sm = System.getSecurityManager()) != null) {
443             sm.checkPermission(new SSLPermission("getSSLSessionContext"));
444         }
445 
446         return context;
447     }
448 
449 
getSessionId()450     SessionId getSessionId() {
451         return sessionId;
452     }
453 
454 
455     /**
456      * Returns the cipher spec in use on this session
457      */
getSuite()458     CipherSuite getSuite() {
459         return cipherSuite;
460     }
461 
462     /**
463      * Resets the cipher spec in use on this session
464      */
setSuite(CipherSuite suite)465     void setSuite(CipherSuite suite) {
466        cipherSuite = suite;
467 
468         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
469              SSLLogger.finest("Negotiating session:  " + this);
470        }
471     }
472 
473     /**
474      * Return true if the session is currently re-established with a
475      * session-resumption abbreviated initial handshake.
476      */
isSessionResumption()477     boolean isSessionResumption() {
478         return isSessionResumption;
479     }
480 
481     /**
482      * Resets whether the session is re-established with a session-resumption
483      * abbreviated initial handshake.
484      */
setAsSessionResumption(boolean flag)485     void setAsSessionResumption(boolean flag) {
486         isSessionResumption = flag;
487     }
488 
489     /**
490      * Returns the name of the cipher suite in use on this session
491      */
492     @Override
getCipherSuite()493     public String getCipherSuite() {
494         return getSuite().name;
495     }
496 
getProtocolVersion()497     ProtocolVersion getProtocolVersion() {
498         return protocolVersion;
499     }
500 
501     /**
502      * Returns the standard name of the protocol in use on this session
503      */
504     @Override
getProtocol()505     public String getProtocol() {
506         return getProtocolVersion().name;
507     }
508 
509     /**
510      * Returns the hashcode for this session
511      */
512     @Override
hashCode()513     public int hashCode() {
514         return sessionId.hashCode();
515     }
516 
517     /**
518      * Returns true if sessions have same ids, false otherwise.
519      */
520     @Override
equals(Object obj)521     public boolean equals(Object obj) {
522 
523         if (obj == this) {
524             return true;
525         }
526 
527         if (obj instanceof SSLSessionImpl) {
528             SSLSessionImpl sess = (SSLSessionImpl) obj;
529             return (sessionId != null) && (sessionId.equals(
530                         sess.getSessionId()));
531         }
532 
533         return false;
534     }
535 
536 
537     /**
538      * Return the cert chain presented by the peer in the
539      * java.security.cert format.
540      * Note: This method can be used only when using certificate-based
541      * cipher suites; using it with non-certificate-based cipher suites
542      * will throw an SSLPeerUnverifiedException.
543      *
544      * @return array of peer X.509 certs, with the peer's own cert
545      *  first in the chain, and with the "root" CA last.
546      */
547     @Override
getPeerCertificates()548     public java.security.cert.Certificate[] getPeerCertificates()
549             throws SSLPeerUnverifiedException {
550         //
551         // clone to preserve integrity of session ... caller can't
552         // change record of peer identity even by accident, much
553         // less do it intentionally.
554         //
555         if (peerCerts == null) {
556             throw new SSLPeerUnverifiedException("peer not authenticated");
557         }
558         // Certs are immutable objects, therefore we don't clone them.
559         // But do need to clone the array, so that nothing is inserted
560         // into peerCerts.
561         return (java.security.cert.Certificate[])peerCerts.clone();
562     }
563 
564     /**
565      * Return the cert chain presented to the peer in the
566      * java.security.cert format.
567      * Note: This method is useful only when using certificate-based
568      * cipher suites.
569      *
570      * @return array of peer X.509 certs, with the peer's own cert
571      *  first in the chain, and with the "root" CA last.
572      */
573     @Override
getLocalCertificates()574     public java.security.cert.Certificate[] getLocalCertificates() {
575         //
576         // clone to preserve integrity of session ... caller can't
577         // change record of peer identity even by accident, much
578         // less do it intentionally.
579         return (localCerts == null ? null :
580             (java.security.cert.Certificate[])localCerts.clone());
581     }
582 
583     /**
584      * Return the cert chain presented by the peer in the
585      * javax.security.cert format.
586      * Note: This method can be used only when using certificate-based
587      * cipher suites; using it with non-certificate-based cipher suites
588      * will throw an SSLPeerUnverifiedException.
589      *
590      * @return array of peer X.509 certs, with the peer's own cert
591      *  first in the chain, and with the "root" CA last.
592      *
593      * @deprecated This method returns the deprecated
594      *  {@code javax.security.cert.X509Certificate} type.
595      *  Use {@code getPeerCertificates()} instead.
596      */
597     @Override
598     @Deprecated
getPeerCertificateChain()599     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
600             throws SSLPeerUnverifiedException {
601         //
602         // clone to preserve integrity of session ... caller can't
603         // change record of peer identity even by accident, much
604         // less do it intentionally.
605         //
606         if (peerCerts == null) {
607             throw new SSLPeerUnverifiedException("peer not authenticated");
608         }
609         javax.security.cert.X509Certificate[] certs;
610         certs = new javax.security.cert.X509Certificate[peerCerts.length];
611         for (int i = 0; i < peerCerts.length; i++) {
612             byte[] der = null;
613             try {
614                 der = peerCerts[i].getEncoded();
615                 certs[i] = javax.security.cert.X509Certificate.getInstance(der);
616             } catch (CertificateEncodingException e) {
617                 throw new SSLPeerUnverifiedException(e.getMessage());
618             } catch (javax.security.cert.CertificateException e) {
619                 throw new SSLPeerUnverifiedException(e.getMessage());
620             }
621         }
622 
623         return certs;
624     }
625 
626     /**
627      * Return the cert chain presented by the peer.
628      * Note: This method can be used only when using certificate-based
629      * cipher suites; using it with non-certificate-based cipher suites
630      * will throw an SSLPeerUnverifiedException.
631      *
632      * @return array of peer X.509 certs, with the peer's own cert
633      *  first in the chain, and with the "root" CA last.
634      */
getCertificateChain()635     public X509Certificate[] getCertificateChain()
636             throws SSLPeerUnverifiedException {
637         /*
638          * clone to preserve integrity of session ... caller can't
639          * change record of peer identity even by accident, much
640          * less do it intentionally.
641          */
642         if (peerCerts != null) {
643             return peerCerts.clone();
644         } else {
645             throw new SSLPeerUnverifiedException("peer not authenticated");
646         }
647     }
648 
649     /**
650      * Return a List of status responses presented by the peer.
651      * Note: This method can be used only when using certificate-based
652      * server authentication; otherwise an empty {@code List} will be returned.
653      *
654      * @return an unmodifiable {@code List} of byte arrays, each consisting
655      * of a DER-encoded OCSP response (see RFC 6960).  If no responses have
656      * been presented by the server or non-certificate based server
657      * authentication is used then an empty {@code List} is returned.
658      */
659     @Override
getStatusResponses()660     public List<byte[]> getStatusResponses() {
661         if (statusResponses == null || statusResponses.isEmpty()) {
662             return Collections.emptyList();
663         } else {
664             // Clone both the list and the contents
665             List<byte[]> responses = new ArrayList<>(statusResponses.size());
666             for (byte[] respBytes : statusResponses) {
667                 responses.add(respBytes.clone());
668             }
669             return Collections.unmodifiableList(responses);
670         }
671     }
672 
673     /**
674      * Returns the identity of the peer which was established as part of
675      * defining the session.
676      *
677      * @return the peer's principal. Returns an X500Principal of the
678      * end-entity certificate for X509-based cipher suites.
679      *
680      * @throws SSLPeerUnverifiedException if the peer's identity has not
681      *          been verified
682      */
683     @Override
getPeerPrincipal()684     public Principal getPeerPrincipal()
685                 throws SSLPeerUnverifiedException
686     {
687         if (peerCerts == null) {
688             throw new SSLPeerUnverifiedException("peer not authenticated");
689         }
690         return peerCerts[0].getSubjectX500Principal();
691     }
692 
693     /**
694      * Returns the principal that was sent to the peer during handshaking.
695      *
696      * @return the principal sent to the peer. Returns an X500Principal
697      * of the end-entity certificate for X509-based cipher suites.
698      * If no principal was sent, then null is returned.
699      */
700     @Override
getLocalPrincipal()701     public Principal getLocalPrincipal() {
702         return ((localCerts == null || localCerts.length == 0) ? null :
703                 localCerts[0].getSubjectX500Principal());
704     }
705 
706     /*
707      * Return the time the ticket for this session was created.
708      */
getTicketCreationTime()709     public long getTicketCreationTime() {
710         return ticketCreationTime;
711     }
712 
713     /**
714      * Returns the time this session was created.
715      */
716     @Override
getCreationTime()717     public long getCreationTime() {
718         return creationTime;
719     }
720 
721     /**
722      * Returns the last time this session was used to initialize
723      * a connection.
724      */
725     @Override
getLastAccessedTime()726     public long getLastAccessedTime() {
727         return (lastUsedTime != 0) ? lastUsedTime : creationTime;
728     }
729 
setLastAccessedTime(long time)730     void setLastAccessedTime(long time) {
731         lastUsedTime = time;
732     }
733 
734 
735     /**
736      * Returns the network address of the session's peer.  This
737      * implementation does not insist that connections between
738      * different ports on the same host must necessarily belong
739      * to different sessions, though that is of course allowed.
740      */
getPeerAddress()741     public InetAddress getPeerAddress() {
742         try {
743             return InetAddress.getByName(host);
744         } catch (java.net.UnknownHostException e) {
745             return null;
746         }
747     }
748 
749     @Override
getPeerHost()750     public String getPeerHost() {
751         return host;
752     }
753 
754     /**
755      * Need to provide the port info for caching sessions based on
756      * host and port. Accessed by SSLSessionContextImpl
757      */
758     @Override
getPeerPort()759     public int getPeerPort() {
760         return port;
761     }
762 
setContext(SSLSessionContextImpl ctx)763     void setContext(SSLSessionContextImpl ctx) {
764         if (context == null) {
765             context = ctx;
766         }
767     }
768 
769     /**
770      * Invalidate a session.  Active connections may still exist, but
771      * no connections will be able to rejoin this session.
772      */
773     @Override
invalidate()774     public synchronized void invalidate() {
775         if (context != null) {
776             context.remove(sessionId);
777             context = null;
778         }
779         if (invalidated) {
780             return;
781         }
782         invalidated = true;
783         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
784              SSLLogger.finest("Invalidated session:  " + this);
785         }
786         for (SSLSessionImpl child : childSessions) {
787             child.invalidate();
788         }
789     }
790 
791     /*
792      * Table of application-specific session data indexed by an application
793      * key and the calling security context. This is important since
794      * sessions can be shared across different protection domains.
795      */
796     private final ConcurrentHashMap<SecureKey, Object> boundValues;
797 
798     /**
799      * Assigns a session value.  Session change events are given if
800      * appropriate, to any original value as well as the new value.
801      */
802     @Override
putValue(String key, Object value)803     public void putValue(String key, Object value) {
804         if ((key == null) || (value == null)) {
805             throw new IllegalArgumentException("arguments can not be null");
806         }
807 
808         SecureKey secureKey = new SecureKey(key);
809         Object oldValue = boundValues.put(secureKey, value);
810 
811         if (oldValue instanceof SSLSessionBindingListener) {
812             SSLSessionBindingEvent e;
813 
814             e = new SSLSessionBindingEvent(this, key);
815             ((SSLSessionBindingListener)oldValue).valueUnbound(e);
816         }
817         if (value instanceof SSLSessionBindingListener) {
818             SSLSessionBindingEvent e;
819 
820             e = new SSLSessionBindingEvent(this, key);
821             ((SSLSessionBindingListener)value).valueBound(e);
822         }
823     }
824 
825     /**
826      * Returns the specified session value.
827      */
828     @Override
getValue(String key)829     public Object getValue(String key) {
830         if (key == null) {
831             throw new IllegalArgumentException("argument can not be null");
832         }
833 
834         SecureKey secureKey = new SecureKey(key);
835         return boundValues.get(secureKey);
836     }
837 
838 
839     /**
840      * Removes the specified session value, delivering a session changed
841      * event as appropriate.
842      */
843     @Override
removeValue(String key)844     public void removeValue(String key) {
845         if (key == null) {
846             throw new IllegalArgumentException("argument can not be null");
847         }
848 
849         SecureKey secureKey = new SecureKey(key);
850         Object value = boundValues.remove(secureKey);
851 
852         if (value instanceof SSLSessionBindingListener) {
853             SSLSessionBindingEvent e;
854 
855             e = new SSLSessionBindingEvent(this, key);
856             ((SSLSessionBindingListener)value).valueUnbound(e);
857         }
858     }
859 
860 
861     /**
862      * Lists the names of the session values.
863      */
864     @Override
getValueNames()865     public String[] getValueNames() {
866         ArrayList<Object> v = new ArrayList<>();
867         Object securityCtx = SecureKey.getCurrentSecurityContext();
868         for (Enumeration<SecureKey> e = boundValues.keys();
869                 e.hasMoreElements(); ) {
870             SecureKey key = e.nextElement();
871             if (securityCtx.equals(key.getSecurityContext())) {
872                 v.add(key.getAppKey());
873             }
874         }
875 
876         return v.toArray(new String[0]);
877     }
878 
879     /**
880      * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
881      * until changed.
882      *
883      * In the TLS specification (section 6.2.1, RFC2246), it is not
884      * recommended that the plaintext has more than 2^14 bytes.
885      * However, some TLS implementations violate the specification.
886      * This is a workaround for interoperability with these stacks.
887      *
888      * Application could accept large fragments up to 2^15 bytes by
889      * setting the system property jsse.SSLEngine.acceptLargeFragments
890      * to "true".
891      */
892     private boolean acceptLargeFragments =
893             Utilities.getBooleanProperty(
894                     "jsse.SSLEngine.acceptLargeFragments", false);
895 
896     /**
897      * Expand the buffer size of both SSL/TLS network packet and
898      * application data.
899      */
expandBufferSizes()900     protected synchronized void expandBufferSizes() {
901         acceptLargeFragments = true;
902     }
903 
904     /**
905      * Gets the current size of the largest SSL/TLS packet that is expected
906      * when using this session.
907      */
908     @Override
getPacketBufferSize()909     public synchronized int getPacketBufferSize() {
910         // Use the bigger packet size calculated from maximumPacketSize
911         // and negotiatedMaxFragLen.
912         int packetSize = 0;
913         if (negotiatedMaxFragLen > 0) {
914             packetSize = cipherSuite.calculatePacketSize(
915                     negotiatedMaxFragLen, protocolVersion,
916                     protocolVersion.isDTLS);
917         }
918 
919         if (maximumPacketSize > 0) {
920             return (maximumPacketSize > packetSize) ?
921                     maximumPacketSize : packetSize;
922         }
923 
924         if (packetSize != 0) {
925            return packetSize;
926         }
927 
928         if (protocolVersion.isDTLS) {
929             return DTLSRecord.maxRecordSize;
930         } else {
931             return acceptLargeFragments ?
932                     SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
933         }
934     }
935 
936     /**
937      * Gets the current size of the largest application data that is
938      * expected when using this session.
939      */
940     @Override
getApplicationBufferSize()941     public synchronized int getApplicationBufferSize() {
942         // Use the bigger fragment size calculated from maximumPacketSize
943         // and negotiatedMaxFragLen.
944         int fragmentSize = 0;
945         if (maximumPacketSize > 0) {
946             fragmentSize = cipherSuite.calculateFragSize(
947                     maximumPacketSize, protocolVersion,
948                     protocolVersion.isDTLS);
949         }
950 
951         if (negotiatedMaxFragLen > 0) {
952             return (negotiatedMaxFragLen > fragmentSize) ?
953                     negotiatedMaxFragLen : fragmentSize;
954         }
955 
956         if (fragmentSize != 0) {
957             return fragmentSize;
958         }
959 
960         if (protocolVersion.isDTLS) {
961             return Record.maxDataSize;
962         } else {
963             int maxPacketSize = acceptLargeFragments ?
964                         SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
965             return (maxPacketSize - SSLRecord.headerSize);
966         }
967     }
968 
969     /**
970      * Sets the negotiated maximum fragment length, as specified by the
971      * max_fragment_length ClientHello extension in RFC 6066.
972      *
973      * @param  negotiatedMaxFragLen
974      *         the negotiated maximum fragment length, or {@code -1} if
975      *         no such length has been negotiated.
976      */
setNegotiatedMaxFragSize( int negotiatedMaxFragLen)977     synchronized void setNegotiatedMaxFragSize(
978             int negotiatedMaxFragLen) {
979 
980         this.negotiatedMaxFragLen = negotiatedMaxFragLen;
981     }
982 
983     /**
984      * Get the negotiated maximum fragment length, as specified by the
985      * max_fragment_length ClientHello extension in RFC 6066.
986      *
987      * @return the negotiated maximum fragment length, or {@code -1} if
988      *         no such length has been negotiated.
989      */
getNegotiatedMaxFragSize()990     synchronized int getNegotiatedMaxFragSize() {
991         return negotiatedMaxFragLen;
992     }
993 
setMaximumPacketSize(int maximumPacketSize)994     synchronized void setMaximumPacketSize(int maximumPacketSize) {
995         this.maximumPacketSize = maximumPacketSize;
996     }
997 
getMaximumPacketSize()998     synchronized int getMaximumPacketSize() {
999         return maximumPacketSize;
1000     }
1001 
1002     /**
1003      * Gets an array of supported signature algorithm names that the local
1004      * side is willing to verify.
1005      */
1006     @Override
getLocalSupportedSignatureAlgorithms()1007     public String[] getLocalSupportedSignatureAlgorithms() {
1008         return SignatureScheme.getAlgorithmNames(localSupportedSignAlgs);
1009     }
1010 
1011     /**
1012      * Gets an array of supported signature schemes that the local side is
1013      * willing to verify.
1014      */
getLocalSupportedSignatureSchemes()1015     public Collection<SignatureScheme> getLocalSupportedSignatureSchemes() {
1016         return localSupportedSignAlgs;
1017     }
1018 
1019     /**
1020      * Gets an array of supported signature algorithms that the peer is
1021      * able to verify.
1022      */
1023     @Override
getPeerSupportedSignatureAlgorithms()1024     public String[] getPeerSupportedSignatureAlgorithms() {
1025         if (peerSupportedSignAlgs != null) {
1026             return peerSupportedSignAlgs.clone();
1027         }
1028 
1029         return new String[0];
1030     }
1031 
1032     /**
1033      * Obtains a <code>List</code> containing all {@link SNIServerName}s
1034      * of the requested Server Name Indication (SNI) extension.
1035      */
1036     @Override
getRequestedServerNames()1037     public List<SNIServerName> getRequestedServerNames() {
1038         return requestedServerNames;
1039     }
1040 
1041     /** Returns a string representation of this SSL session */
1042     @Override
toString()1043     public String toString() {
1044         return "Session(" + creationTime + "|" + getCipherSuite() + ")";
1045     }
1046 }
1047 
1048 /**
1049  * This "struct" class serves as a Hash Key that combines an
1050  * application-specific key and a security context.
1051  */
1052 class SecureKey {
1053     private static final Object     nullObject = new Object();
1054     private final Object            appKey;
1055     private final Object            securityCtx;
1056 
getCurrentSecurityContext()1057     static Object getCurrentSecurityContext() {
1058         SecurityManager sm = System.getSecurityManager();
1059         Object context = null;
1060 
1061         if (sm != null)
1062             context = sm.getSecurityContext();
1063         if (context == null)
1064             context = nullObject;
1065         return context;
1066     }
1067 
SecureKey(Object key)1068     SecureKey(Object key) {
1069         this.appKey = key;
1070         this.securityCtx = getCurrentSecurityContext();
1071     }
1072 
getAppKey()1073     Object getAppKey() {
1074         return appKey;
1075     }
1076 
getSecurityContext()1077     Object getSecurityContext() {
1078         return securityCtx;
1079     }
1080 
1081     @Override
hashCode()1082     public int hashCode() {
1083         return appKey.hashCode() ^ securityCtx.hashCode();
1084     }
1085 
1086     @Override
equals(Object o)1087     public boolean equals(Object o) {
1088         return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
1089                         && ((SecureKey)o).securityCtx.equals(securityCtx);
1090     }
1091 }
1092