1 /*
2  * Copyright (c) 1996, 2019, 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 sun.security.x509.X509CertImpl;
28 
29 import java.io.IOException;
30 import java.lang.reflect.Array;
31 import java.math.BigInteger;
32 import java.net.InetAddress;
33 import java.nio.ByteBuffer;
34 import java.security.Principal;
35 import java.security.PrivateKey;
36 import java.security.cert.CertificateEncodingException;
37 import java.security.cert.X509Certificate;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Queue;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.Enumeration;
44 import java.util.List;
45 import java.util.concurrent.ConcurrentHashMap;
46 import java.util.concurrent.ConcurrentLinkedQueue;
47 import java.util.concurrent.locks.ReentrantLock;
48 import javax.crypto.SecretKey;
49 import javax.crypto.spec.SecretKeySpec;
50 import javax.net.ssl.ExtendedSSLSession;
51 import javax.net.ssl.SNIHostName;
52 import javax.net.ssl.SNIServerName;
53 import javax.net.ssl.SSLException;
54 import javax.net.ssl.SSLPeerUnverifiedException;
55 import javax.net.ssl.SSLPermission;
56 import javax.net.ssl.SSLSessionBindingEvent;
57 import javax.net.ssl.SSLSessionBindingListener;
58 import javax.net.ssl.SSLSessionContext;
59 
60 /**
61  * Implements the SSL session interface, and exposes the session context
62  * which is maintained by SSL servers.
63  *
64  * <P> Servers have the ability to manage the sessions associated with
65  * their authentication context(s).  They can do this by enumerating the
66  * IDs of the sessions which are cached, examining those sessions, and then
67  * perhaps invalidating a given session so that it can't be used again.
68  * If servers do not explicitly manage the cache, sessions will linger
69  * until memory is low enough that the runtime environment purges cache
70  * entries automatically to reclaim space.
71  *
72  * <P><em> The only reason this class is not package-private is that
73  * there's no other public way to get at the server session context which
74  * is associated with any given authentication context. </em>
75  *
76  * @author David Brownell
77  */
78 final class SSLSessionImpl extends ExtendedSSLSession {
79 
80     /*
81      * The state of a single session, as described in section 7.1
82      * of the SSLv3 spec.
83      */
84     private final ProtocolVersion       protocolVersion;
85     private final SessionId             sessionId;
86     private X509Certificate[]   peerCerts;
87     private CipherSuite         cipherSuite;
88     private SecretKey           masterSecret;
89     final boolean               useExtendedMasterSecret;
90 
91     /*
92      * Information not part of the SSLv3 protocol spec, but used
93      * to support session management policies.
94      */
95     private final long          creationTime;
96     private long                lastUsedTime = 0;
97     private final String        host;
98     private final int           port;
99     private SSLSessionContextImpl       context;
100     private boolean             invalidated;
101     private X509Certificate[]   localCerts;
102     private PrivateKey          localPrivateKey;
103     private final Collection<SignatureScheme>     localSupportedSignAlgs;
104     private Collection<SignatureScheme> peerSupportedSignAlgs; //for certificate
105     private boolean             useDefaultPeerSignAlgs = false;
106     private List<byte[]>        statusResponses;
107     private SecretKey           resumptionMasterSecret;
108     private SecretKey           preSharedKey;
109     private byte[]              pskIdentity;
110     private final long          ticketCreationTime = System.currentTimeMillis();
111     private int                 ticketAgeAdd;
112 
113     private int                 negotiatedMaxFragLen = -1;
114     private int                 maximumPacketSize;
115 
116     private final Queue<SSLSessionImpl> childSessions =
117                                         new ConcurrentLinkedQueue<>();
118 
119     /*
120      * Is the session currently re-established with a session-resumption
121      * abbreviated initial handshake?
122      *
123      * Note that currently we only set this variable in client side.
124      */
125     private boolean isSessionResumption = false;
126 
127     /*
128      * Use of session caches is globally enabled/disabled.
129      */
130     private static boolean      defaultRejoinable = true;
131 
132     // server name indication
133     final SNIServerName         serverNameIndication;
134     private final List<SNIServerName>    requestedServerNames;
135 
136     // Counter used to create unique nonces in NewSessionTicket
137     private BigInteger ticketNonceCounter = BigInteger.ONE;
138 
139     // The endpoint identification algorithm used to check certificates
140     // in this session.
141     private final String        identificationProtocol;
142 
143     private final ReentrantLock sessionLock = new ReentrantLock();
144 
145     /*
146      * Create a new non-rejoinable session, using the default (null)
147      * cipher spec.  This constructor returns a session which could
148      * be used either by a client or by a server, as a connection is
149      * first opened and before handshaking begins.
150      */
SSLSessionImpl()151     SSLSessionImpl() {
152         this.protocolVersion = ProtocolVersion.NONE;
153         this.cipherSuite = CipherSuite.C_NULL;
154         this.sessionId = new SessionId(false, null);
155         this.host = null;
156         this.port = -1;
157         this.localSupportedSignAlgs = Collections.emptySet();
158         this.serverNameIndication = null;
159         this.requestedServerNames = Collections.<SNIServerName>emptyList();
160         this.useExtendedMasterSecret = false;
161         this.creationTime = System.currentTimeMillis();
162         this.identificationProtocol = null;
163         this.boundValues = new ConcurrentHashMap<>();
164     }
165 
166     /*
167      * Create a new session, using a given cipher spec.  This will
168      * be rejoinable if session caching is enabled; the constructor
169      * is intended mostly for use by serves.
170      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite)171     SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) {
172         this(hc, cipherSuite,
173             new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom()));
174     }
175 
176     /*
177      * Record a new session, using a given cipher spec and session ID.
178      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id)179     SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) {
180         this(hc, cipherSuite, id, System.currentTimeMillis());
181     }
182 
183     /*
184      * Record a new session, using a given cipher spec, session ID,
185      * and creation time.
186      * Note: For the unmodifiable collections and lists we are creating new
187      * collections as inputs to avoid potential deep nesting of
188      * unmodifiable collections that can cause StackOverflowErrors
189      * (see JDK-6323374).
190      */
SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id, long creationTime)191     SSLSessionImpl(HandshakeContext hc,
192             CipherSuite cipherSuite, SessionId id, long creationTime) {
193         this.protocolVersion = hc.negotiatedProtocol;
194         this.cipherSuite = cipherSuite;
195         this.sessionId = id;
196         this.host = hc.conContext.transport.getPeerHost();
197         this.port = hc.conContext.transport.getPeerPort();
198         this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ?
199                 Collections.emptySet() :
200                 Collections.unmodifiableCollection(
201                         new ArrayList<>(hc.localSupportedSignAlgs));
202         this.serverNameIndication = hc.negotiatedServerName;
203         this.requestedServerNames = Collections.unmodifiableList(
204                 new ArrayList<>(hc.getRequestedServerNames()));
205         if (hc.sslConfig.isClientMode) {
206             this.useExtendedMasterSecret =
207                 (hc.handshakeExtensions.get(
208                         SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
209                 (hc.handshakeExtensions.get(
210                         SSLExtension.SH_EXTENDED_MASTER_SECRET) != null);
211         } else {
212             this.useExtendedMasterSecret =
213                 (hc.handshakeExtensions.get(
214                         SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) &&
215                 (!hc.negotiatedProtocol.useTLS13PlusSpec());
216         }
217         this.creationTime = creationTime;
218         this.identificationProtocol = hc.sslConfig.identificationProtocol;
219         this.boundValues = new ConcurrentHashMap<>();
220 
221         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
222              SSLLogger.finest("Session initialized:  " + this);
223         }
224     }
225 
SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId)226     SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId) {
227         this.protocolVersion = baseSession.getProtocolVersion();
228         this.cipherSuite = baseSession.cipherSuite;
229         this.sessionId = newId;
230         this.host = baseSession.getPeerHost();
231         this.port = baseSession.getPeerPort();
232         this.localSupportedSignAlgs =
233                 baseSession.localSupportedSignAlgs == null ?
234                 Collections.emptySet() : baseSession.localSupportedSignAlgs;
235         this.peerSupportedSignAlgs =
236                 baseSession.peerSupportedSignAlgs == null ?
237                 Collections.emptySet() : baseSession.peerSupportedSignAlgs;
238         this.serverNameIndication = baseSession.serverNameIndication;
239         this.requestedServerNames = baseSession.getRequestedServerNames();
240         this.masterSecret = baseSession.getMasterSecret();
241         this.useExtendedMasterSecret = baseSession.useExtendedMasterSecret;
242         this.creationTime = baseSession.getCreationTime();
243         this.lastUsedTime = System.currentTimeMillis();
244         this.identificationProtocol = baseSession.getIdentificationProtocol();
245         this.localCerts = baseSession.localCerts;
246         this.peerCerts = baseSession.peerCerts;
247         this.statusResponses = baseSession.statusResponses;
248         this.resumptionMasterSecret = baseSession.resumptionMasterSecret;
249         this.context = baseSession.context;
250         this.negotiatedMaxFragLen = baseSession.negotiatedMaxFragLen;
251         this.maximumPacketSize = baseSession.maximumPacketSize;
252         this.boundValues = baseSession.boundValues;
253 
254         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
255              SSLLogger.finest("Session initialized:  " + this);
256         }
257     }
258 
259     /**
260      * < 2 bytes > protocolVersion
261      * < 2 bytes > cipherSuite
262      * < 1 byte > localSupportedSignAlgs entries
263      *   < 2 bytes per entries > localSupportedSignAlgs
264      * < 1 bytes > peerSupportedSignAlgs entries
265      *   < 2 bytes per entries > peerSupportedSignAlgs
266      * < 2 bytes > preSharedKey length
267      * < length in bytes > preSharedKey
268      * < 1 byte > pskIdentity length
269      * < length in bytes > pskIdentity
270      * < 1 byte > masterSecret length
271      *   < 1 byte > masterSecret algorithm length
272      *   < length in bytes > masterSecret algorithm
273      *   < 2 bytes > masterSecretKey length
274      *   < length in bytes> masterSecretKey
275      * < 1 byte > useExtendedMasterSecret
276      * < 1 byte > identificationProtocol length
277      * < length in bytes > identificationProtocol
278      * < 1 byte > serverNameIndication length
279      * < length in bytes > serverNameIndication
280      * < 1 byte > Number of requestedServerNames entries
281      *   < 1 byte > ServerName length
282      *   < length in bytes > ServerName
283      * < 4 bytes > creationTime
284      * < 2 byte > status response length
285      *   < 2 byte > status response entry length
286      *   < length in byte > status response entry
287      * < 1 byte > Length of peer host
288      *   < length in bytes > peer host
289      * < 2 bytes> peer port
290      * < 1 byte > Number of peerCerts entries
291      *   < 4 byte > peerCert length
292      *   < length in bytes > peerCert
293      * < 1 byte > localCerts type (Cert, PSK, Anonymous)
294      *   Certificate
295      *     < 1 byte > Number of Certificate entries
296      *       < 4 byte> Certificate length
297      *       < length in bytes> Certificate
298      *   PSK
299      *     < 1 byte > Number of PSK entries
300      *       < 1 bytes > PSK algorithm length
301      *       < length in bytes > PSK algorithm string
302      *       < 4 bytes > PSK key length
303      *       < length in bytes> PSK key
304      *       < 4 bytes > PSK identity length
305      *       < length in bytes> PSK identity
306      *   Anonymous
307      *     < 1 byte >
308      * < 4 bytes > maximumPacketSize
309      * < 4 bytes > negotiatedMaxFragSize
310     */
311 
SSLSessionImpl(HandshakeContext hc, ByteBuffer buf)312     SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException {
313         int i = 0;
314         byte[] b;
315 
316         boundValues = new ConcurrentHashMap<>();
317         this.protocolVersion =
318                 ProtocolVersion.valueOf(Short.toUnsignedInt(buf.getShort()));
319 
320         if (protocolVersion.useTLS13PlusSpec()) {
321             this.sessionId = new SessionId(false, null);
322         } else {
323             // The CH session id may reset this if it's provided
324             this.sessionId = new SessionId(true,
325                     hc.sslContext.getSecureRandom());
326         }
327 
328         this.cipherSuite =
329                 CipherSuite.valueOf(Short.toUnsignedInt(buf.getShort()));
330 
331         // Local Supported signature algorithms
332         ArrayList<SignatureScheme> list = new ArrayList<>();
333         i = Byte.toUnsignedInt(buf.get());
334         while (i-- > 0) {
335             list.add(SignatureScheme.valueOf(
336                     Short.toUnsignedInt(buf.getShort())));
337         }
338         this.localSupportedSignAlgs = Collections.unmodifiableCollection(list);
339 
340         // Peer Supported signature algorithms
341         i = Byte.toUnsignedInt(buf.get());
342         list.clear();
343         while (i-- > 0) {
344             list.add(SignatureScheme.valueOf(
345                     Short.toUnsignedInt(buf.getShort())));
346         }
347         this.peerSupportedSignAlgs = Collections.unmodifiableCollection(list);
348 
349         // PSK
350         i = Short.toUnsignedInt(buf.getShort());
351         if (i > 0) {
352             b = new byte[i];
353             // Get algorithm string
354             buf.get(b, 0, i);
355             // Encoded length
356             i = Short.toUnsignedInt(buf.getShort());
357             // Encoded SecretKey
358             b = new byte[i];
359             buf.get(b);
360             this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret");
361         } else {
362             this.preSharedKey = null;
363         }
364 
365         // PSK identity
366         i = buf.get();
367         if (i > 0) {
368             b = new byte[i];
369             buf.get(b);
370             this.pskIdentity = b;
371         } else {
372             this.pskIdentity = null;
373         }
374 
375         // Master secret length of secret key algorithm  (one byte)
376         i = buf.get();
377         if (i > 0) {
378             b = new byte[i];
379             // Get algorithm string
380             buf.get(b, 0, i);
381             // Encoded length
382             i = Short.toUnsignedInt(buf.getShort());
383             // Encoded SecretKey
384             b = new byte[i];
385             buf.get(b);
386             this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret");
387         } else {
388             this.masterSecret = null;
389         }
390         // Use extended master secret
391         this.useExtendedMasterSecret = (buf.get() != 0);
392 
393         // Identification Protocol
394         i = buf.get();
395         if (i == 0) {
396             identificationProtocol = null;
397         } else {
398             b = new byte[i];
399             identificationProtocol =
400                     buf.get(b, 0, i).asCharBuffer().toString();
401         }
402 
403         // SNI
404         i = buf.get();  // length
405         if (i == 0) {
406             serverNameIndication = null;
407         } else {
408             b = new byte[i];
409             buf.get(b, 0, b.length);
410             serverNameIndication = new SNIHostName(b);
411         }
412 
413         // List of SNIServerName
414         int len = Short.toUnsignedInt(buf.getShort());
415         if (len == 0) {
416             this.requestedServerNames = Collections.<SNIServerName>emptyList();
417         } else {
418             requestedServerNames = new ArrayList<>();
419             while (len > 0) {
420                 int l = buf.get();
421                 b = new byte[l];
422                 buf.get(b, 0, l);
423                 requestedServerNames.add(new SNIHostName(new String(b)));
424                 len--;
425             }
426         }
427 
428         maximumPacketSize = buf.getInt();
429         negotiatedMaxFragLen = buf.getInt();
430 
431         // Get creation time
432         this.creationTime = buf.getLong();
433 
434         // Get Buffer sizes
435 
436         // Status Response
437         len = Short.toUnsignedInt(buf.getShort());
438         if (len == 0) {
439             statusResponses = Collections.emptyList();
440         } else {
441             statusResponses = new ArrayList<>();
442         }
443         while (len-- > 0) {
444             b = new byte[Short.toUnsignedInt(buf.getShort())];
445             buf.get(b);
446             statusResponses.add(b);
447         }
448 
449         // Get Peer host & port
450         i = Byte.toUnsignedInt(buf.get());
451         if (i == 0) {
452             this.host = new String();
453         } else {
454             b = new byte[i];
455             this.host = buf.get(b).toString();
456         }
457         this.port = Short.toUnsignedInt(buf.getShort());
458 
459         // Peer certs
460         i = buf.get();
461         if (i == 0) {
462             this.peerCerts = null;
463         } else {
464             this.peerCerts = new X509Certificate[i];
465             int j = 0;
466             while (i > j) {
467                 b = new byte[buf.getInt()];
468                 buf.get(b);
469                 try {
470                     this.peerCerts[j] = new X509CertImpl(b);
471                 } catch (Exception e) {
472                     throw new IOException(e);
473                 }
474                 j++;
475             }
476         }
477 
478         // Get local certs of PSK
479         switch (buf.get()) {
480             case 0:
481                 break;
482             case 1:
483                 // number of certs
484                 len = buf.get();
485                 this.localCerts = new X509Certificate[len];
486                 i = 0;
487                 while (len > i) {
488                     b = new byte[buf.getInt()];
489                     buf.get(b);
490                     try {
491                         this.localCerts[i] = new X509CertImpl(b);
492                     } catch (Exception e) {
493                         throw new IOException(e);
494                     }
495                     i++;
496                 }
497                 break;
498             case 2:
499                 // pre-shared key
500                 // Length of pre-shared key algorithm  (one byte)
501                 i = buf.get();
502                 b = new byte[i];
503                 String alg = buf.get(b, 0, i).asCharBuffer().toString();
504                 // Get length of encoding
505                 i = Short.toUnsignedInt(buf.getShort());
506                 // Get encoding
507                 b = new byte[i];
508                 buf.get(b);
509                 this.preSharedKey = new SecretKeySpec(b, alg);
510                 // Get identity len
511                 this.pskIdentity = new byte[buf.get()];
512                 buf.get(pskIdentity);
513                 break;
514             default:
515                 throw new SSLException("Failed local certs of session.");
516         }
517 
518         context = (SSLSessionContextImpl)
519                 hc.sslContext.engineGetServerSessionContext();
520         this.lastUsedTime = System.currentTimeMillis();
521     }
522 
523     // Some situations we cannot provide a stateless ticket, but after it
524     // has been negotiated
isStatelessable(HandshakeContext hc)525     boolean isStatelessable(HandshakeContext hc) {
526         if (!hc.statelessResumption) {
527             return false;
528         }
529 
530         // If there is no getMasterSecret with TLS1.2 or under, do not resume.
531         if (!protocolVersion.useTLS13PlusSpec() &&
532                 getMasterSecret().getEncoded() == null) {
533             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
534                 SSLLogger.finest("No MasterSecret, cannot make stateless" +
535                         " ticket");
536             }
537             return false;
538         }
539         if (boundValues != null && boundValues.size() > 0) {
540             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
541                 SSLLogger.finest("There are boundValues, cannot make" +
542                         " stateless ticket");
543             }
544             return false;
545         }
546         return true;
547     }
548 
549     /**
550      * Write out a SSLSessionImpl in a byte array for a stateless session ticket
551      */
write()552     byte[] write() throws Exception {
553         byte[] b;
554         HandshakeOutStream hos = new HandshakeOutStream(null);
555 
556         hos.putInt16(protocolVersion.id);
557         hos.putInt16(cipherSuite.id);
558 
559         // Local Supported signature algorithms
560         hos.putInt8(localSupportedSignAlgs.size());
561         for (SignatureScheme s : localSupportedSignAlgs) {
562             hos.putInt16(s.id);
563         }
564 
565         // Peer Supported signature algorithms
566         hos.putInt8(peerSupportedSignAlgs.size());
567         for (SignatureScheme s : peerSupportedSignAlgs) {
568             hos.putInt16(s.id);
569         }
570 
571         // PSK
572         if (preSharedKey == null ||
573                 preSharedKey.getAlgorithm() == null) {
574             hos.putInt16(0);
575         } else {
576             hos.putInt16(preSharedKey.getAlgorithm().length());
577             if (preSharedKey.getAlgorithm().length() != 0) {
578                 hos.write(preSharedKey.getAlgorithm().getBytes());
579             }
580             b = preSharedKey.getEncoded();
581             hos.putInt16(b.length);
582             hos.write(b, 0, b.length);
583         }
584 
585         // PSK Identity
586         if (pskIdentity == null) {
587             hos.putInt8(0);
588         } else {
589             hos.putInt8(pskIdentity.length);
590             hos.write(pskIdentity, 0, pskIdentity.length);
591         }
592 
593         // Master Secret
594         if (getMasterSecret() == null ||
595                 getMasterSecret().getAlgorithm() == null) {
596             hos.putInt8(0);
597         } else {
598             hos.putInt8(getMasterSecret().getAlgorithm().length());
599             if (getMasterSecret().getAlgorithm().length() != 0) {
600                 hos.write(getMasterSecret().getAlgorithm().getBytes());
601             }
602             b = getMasterSecret().getEncoded();
603             hos.putInt16(b.length);
604             hos.write(b, 0, b.length);
605         }
606 
607         hos.putInt8(useExtendedMasterSecret ? 1 : 0);
608 
609         // Identification Protocol
610         if (identificationProtocol == null) {
611             hos.putInt8(0);
612         } else {
613             hos.putInt8(identificationProtocol.length());
614             hos.write(identificationProtocol.getBytes(), 0,
615                     identificationProtocol.length());
616         }
617 
618         // SNI
619         if (serverNameIndication == null) {
620             hos.putInt8(0);
621         } else {
622             b = serverNameIndication.getEncoded();
623             hos.putInt8(b.length);
624             hos.write(b, 0, b.length);
625         }
626 
627         // List of SNIServerName
628         hos.putInt16(requestedServerNames.size());
629         if (requestedServerNames.size() > 0) {
630             for (SNIServerName host : requestedServerNames) {
631                 b = host.getEncoded();
632                 hos.putInt8(b.length);
633                 hos.write(b, 0, b.length);
634             }
635         }
636 
637         // Buffer sizes
638         hos.putInt32(maximumPacketSize);
639         hos.putInt32(negotiatedMaxFragLen);
640 
641         // creation time
642         ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
643         hos.writeBytes(buffer.putLong(creationTime).array());
644 
645         // Status Responses
646         List<byte[]> list = getStatusResponses();
647         int l = list.size();
648         hos.putInt16(l);
649         for (byte[] e : list) {
650             hos.putInt16(e.length);
651             hos.write(e);
652         }
653 
654         // peer Host & Port
655         if (host == null || host.length() == 0) {
656             hos.putInt8(0);
657         } else {
658             hos.putInt8(host.length());
659             hos.writeBytes(host.getBytes());
660         }
661         hos.putInt16(port);
662 
663         // Peer cert
664         if (peerCerts == null || peerCerts.length == 0) {
665             hos.putInt8(0);
666         } else {
667             hos.putInt8(peerCerts.length);
668             for (X509Certificate c : peerCerts) {
669                 b = c.getEncoded();
670                 hos.putInt32(b.length);
671                 hos.writeBytes(b);
672             }
673         }
674 
675         // Client identity
676         if (localCerts != null && localCerts.length > 0) {
677             // certificate based
678             hos.putInt8(1);
679             hos.putInt8(localCerts.length);
680             for (X509Certificate c : localCerts) {
681                 b = c.getEncoded();
682                 hos.putInt32(b.length);
683                 hos.writeBytes(b);
684             }
685         } else if (preSharedKey != null) {
686             // pre-shared key
687             hos.putInt8(2);
688             hos.putInt8(preSharedKey.getAlgorithm().length());
689             hos.write(preSharedKey.getAlgorithm().getBytes());
690             b = preSharedKey.getEncoded();
691             hos.putInt32(b.length);
692             hos.writeBytes(b);
693             hos.putInt32(pskIdentity.length);
694             hos.writeBytes(pskIdentity);
695         } else {
696             // anonymous
697             hos.putInt8(0);
698         }
699 
700         return hos.toByteArray();
701     }
702 
setMasterSecret(SecretKey secret)703     void setMasterSecret(SecretKey secret) {
704         masterSecret = secret;
705     }
706 
setResumptionMasterSecret(SecretKey secret)707     void setResumptionMasterSecret(SecretKey secret) {
708         resumptionMasterSecret = secret;
709     }
710 
setPreSharedKey(SecretKey key)711     void setPreSharedKey(SecretKey key) {
712         preSharedKey = key;
713     }
714 
addChild(SSLSessionImpl session)715     void addChild(SSLSessionImpl session) {
716         childSessions.add(session);
717     }
718 
setTicketAgeAdd(int ticketAgeAdd)719     void setTicketAgeAdd(int ticketAgeAdd) {
720         this.ticketAgeAdd = ticketAgeAdd;
721     }
722 
setPskIdentity(byte[] pskIdentity)723     void setPskIdentity(byte[] pskIdentity) {
724         this.pskIdentity = pskIdentity;
725     }
726 
incrTicketNonceCounter()727     BigInteger incrTicketNonceCounter() {
728         BigInteger result = ticketNonceCounter;
729         ticketNonceCounter = ticketNonceCounter.add(BigInteger.ONE);
730         return result;
731     }
732 
isPSKable()733     boolean isPSKable() {
734         return (ticketNonceCounter.compareTo(BigInteger.ZERO) > 0);
735     }
736 
737     /**
738      * Returns the master secret ... treat with extreme caution!
739      */
getMasterSecret()740     SecretKey getMasterSecret() {
741         return masterSecret;
742     }
743 
getResumptionMasterSecret()744     SecretKey getResumptionMasterSecret() {
745         return resumptionMasterSecret;
746     }
747 
getPreSharedKey()748     SecretKey getPreSharedKey() {
749         sessionLock.lock();
750         try {
751             return preSharedKey;
752         } finally {
753             sessionLock.unlock();
754         }
755     }
756 
consumePreSharedKey()757     SecretKey consumePreSharedKey() {
758         sessionLock.lock();
759         try {
760             return preSharedKey;
761         } finally {
762             preSharedKey = null;
763             sessionLock.unlock();
764         }
765     }
766 
getTicketAgeAdd()767     int getTicketAgeAdd() {
768         return ticketAgeAdd;
769     }
770 
getIdentificationProtocol()771     String getIdentificationProtocol() {
772         return this.identificationProtocol;
773     }
774 
775     /* PSK identities created from new_session_ticket messages should only
776      * be used once. This method will return the identity and then clear it
777      * so it cannot be used again.
778      */
consumePskIdentity()779     byte[] consumePskIdentity() {
780         sessionLock.lock();
781         try {
782             return pskIdentity;
783         } finally {
784             pskIdentity = null;
785             sessionLock.unlock();
786         }
787     }
788 
getPskIdentity()789     byte[] getPskIdentity() {
790         return pskIdentity;
791     }
792 
setPeerCertificates(X509Certificate[] peer)793     void setPeerCertificates(X509Certificate[] peer) {
794         if (peerCerts == null) {
795             peerCerts = peer;
796         }
797     }
798 
setLocalCertificates(X509Certificate[] local)799     void setLocalCertificates(X509Certificate[] local) {
800         localCerts = local;
801     }
802 
setLocalPrivateKey(PrivateKey privateKey)803     void setLocalPrivateKey(PrivateKey privateKey) {
804         localPrivateKey = privateKey;
805     }
806 
setPeerSupportedSignatureAlgorithms( Collection<SignatureScheme> signatureSchemes)807     void setPeerSupportedSignatureAlgorithms(
808             Collection<SignatureScheme> signatureSchemes) {
809         peerSupportedSignAlgs = signatureSchemes;
810     }
811 
812     // TLS 1.2 only
813     //
814     // Per RFC 5246, If the client supports only the default hash
815     // and signature algorithms, it MAY omit the
816     // signature_algorithms extension.  If the client does not
817     // support the default algorithms, or supports other hash
818     // and signature algorithms (and it is willing to use them
819     // for verifying messages sent by the server, i.e., server
820     // certificates and server key exchange), it MUST send the
821     // signature_algorithms extension, listing the algorithms it
822     // is willing to accept.
823     private static final ArrayList<SignatureScheme> defaultPeerSupportedSignAlgs =
824             new ArrayList<>(Arrays.asList(SignatureScheme.RSA_PKCS1_SHA1,
825                     SignatureScheme.DSA_SHA1,
826                     SignatureScheme.ECDSA_SHA1));
827 
setUseDefaultPeerSignAlgs()828     void setUseDefaultPeerSignAlgs() {
829         useDefaultPeerSignAlgs = true;
830         peerSupportedSignAlgs = defaultPeerSupportedSignAlgs;
831     }
832 
833     // Returns the connection session.
finish()834     SSLSessionImpl finish() {
835         if (useDefaultPeerSignAlgs) {
836             peerSupportedSignAlgs = Collections.emptySet();
837         }
838 
839         return this;
840     }
841 
842     /**
843      * Provide status response data obtained during the SSL handshake.
844      *
845      * @param responses a {@link List} of responses in binary form.
846      */
setStatusResponses(List<byte[]> responses)847     void setStatusResponses(List<byte[]> responses) {
848         if (responses != null && !responses.isEmpty()) {
849             statusResponses = responses;
850         } else {
851             statusResponses = Collections.emptyList();
852         }
853     }
854 
855     /**
856      * Returns true iff this session may be resumed ... sessions are
857      * usually resumable.  Security policies may suggest otherwise,
858      * for example sessions that haven't been used for a while (say,
859      * a working day) won't be resumable, and sessions might have a
860      * maximum lifetime in any case.
861      */
isRejoinable()862     boolean isRejoinable() {
863         // TLS 1.3 can have no session id
864         if (protocolVersion.useTLS13PlusSpec()) {
865             return (!invalidated && isLocalAuthenticationValid());
866         }
867         return sessionId != null && sessionId.length() != 0 &&
868                 !invalidated && isLocalAuthenticationValid();
869     }
870 
871     @Override
isValid()872     public boolean isValid() {
873         sessionLock.lock();
874         try {
875             return isRejoinable();
876         } finally {
877             sessionLock.unlock();
878         }
879     }
880 
881     /**
882      * Check if the authentication used when establishing this session
883      * is still valid. Returns true if no authentication was used
884      */
isLocalAuthenticationValid()885     private boolean isLocalAuthenticationValid() {
886         if (localPrivateKey != null) {
887             try {
888                 // if the private key is no longer valid, getAlgorithm()
889                 // should throw an exception
890                 // (e.g. Smartcard has been removed from the reader)
891                 localPrivateKey.getAlgorithm();
892             } catch (Exception e) {
893                 invalidate();
894                 return false;
895             }
896         }
897 
898         return true;
899     }
900 
901     /**
902      * Returns the ID for this session.  The ID is fixed for the
903      * duration of the session; neither it, nor its value, changes.
904      */
905     @Override
getId()906     public byte[] getId() {
907         return sessionId.getId();
908     }
909 
910     /**
911      * For server sessions, this returns the set of sessions which
912      * are currently valid in this process.  For client sessions,
913      * this returns null.
914      */
915     @Override
getSessionContext()916     public SSLSessionContext getSessionContext() {
917         /*
918          * An interim security policy until we can do something
919          * more specific in 1.2. Only allow trusted code (code which
920          * can set system properties) to get an
921          * SSLSessionContext. This is to limit the ability of code to
922          * look up specific sessions or enumerate over them. Otherwise,
923          * code can only get session objects from successful SSL
924          * connections which implies that they must have had permission
925          * to make the network connection in the first place.
926          */
927         SecurityManager sm;
928         if ((sm = System.getSecurityManager()) != null) {
929             sm.checkPermission(new SSLPermission("getSSLSessionContext"));
930         }
931 
932         return context;
933     }
934 
935 
getSessionId()936     SessionId getSessionId() {
937         return sessionId;
938     }
939 
940 
941     /**
942      * Returns the cipher spec in use on this session
943      */
getSuite()944     CipherSuite getSuite() {
945         return cipherSuite;
946     }
947 
948     /**
949      * Resets the cipher spec in use on this session
950      */
setSuite(CipherSuite suite)951     void setSuite(CipherSuite suite) {
952        cipherSuite = suite;
953 
954         if (SSLLogger.isOn && SSLLogger.isOn("session")) {
955              SSLLogger.finest("Negotiating session:  " + this);
956        }
957     }
958 
959     /**
960      * Return true if the session is currently re-established with a
961      * session-resumption abbreviated initial handshake.
962      */
isSessionResumption()963     boolean isSessionResumption() {
964         return isSessionResumption;
965     }
966 
967     /**
968      * Resets whether the session is re-established with a session-resumption
969      * abbreviated initial handshake.
970      */
setAsSessionResumption(boolean flag)971     void setAsSessionResumption(boolean flag) {
972         isSessionResumption = flag;
973     }
974 
975     /**
976      * Returns the name of the cipher suite in use on this session
977      */
978     @Override
getCipherSuite()979     public String getCipherSuite() {
980         return getSuite().name;
981     }
982 
getProtocolVersion()983     ProtocolVersion getProtocolVersion() {
984         return protocolVersion;
985     }
986 
987     /**
988      * Returns the standard name of the protocol in use on this session
989      */
990     @Override
getProtocol()991     public String getProtocol() {
992         return getProtocolVersion().name;
993     }
994 
995     /**
996      * Returns the hashcode for this session
997      */
998     @Override
hashCode()999     public int hashCode() {
1000         return sessionId.hashCode();
1001     }
1002 
1003     /**
1004      * Returns true if sessions have same ids, false otherwise.
1005      */
1006     @Override
equals(Object obj)1007     public boolean equals(Object obj) {
1008 
1009         if (obj == this) {
1010             return true;
1011         }
1012 
1013         if (obj instanceof SSLSessionImpl) {
1014             SSLSessionImpl sess = (SSLSessionImpl) obj;
1015             return (sessionId != null) && (sessionId.equals(
1016                         sess.getSessionId()));
1017         }
1018 
1019         return false;
1020     }
1021 
1022 
1023     /**
1024      * Return the cert chain presented by the peer in the
1025      * java.security.cert format.
1026      * Note: This method can be used only when using certificate-based
1027      * cipher suites; using it with non-certificate-based cipher suites
1028      * will throw an SSLPeerUnverifiedException.
1029      *
1030      * @return array of peer X.509 certs, with the peer's own cert
1031      *  first in the chain, and with the "root" CA last.
1032      */
1033     @Override
getPeerCertificates()1034     public java.security.cert.Certificate[] getPeerCertificates()
1035             throws SSLPeerUnverifiedException {
1036         //
1037         // clone to preserve integrity of session ... caller can't
1038         // change record of peer identity even by accident, much
1039         // less do it intentionally.
1040         //
1041         if (peerCerts == null) {
1042             throw new SSLPeerUnverifiedException("peer not authenticated");
1043         }
1044         // Certs are immutable objects, therefore we don't clone them.
1045         // But do need to clone the array, so that nothing is inserted
1046         // into peerCerts.
1047         return (java.security.cert.Certificate[])peerCerts.clone();
1048     }
1049 
1050     /**
1051      * Return the cert chain presented to the peer in the
1052      * java.security.cert format.
1053      * Note: This method is useful only when using certificate-based
1054      * cipher suites.
1055      *
1056      * @return array of peer X.509 certs, with the peer's own cert
1057      *  first in the chain, and with the "root" CA last.
1058      */
1059     @Override
getLocalCertificates()1060     public java.security.cert.Certificate[] getLocalCertificates() {
1061         //
1062         // clone to preserve integrity of session ... caller can't
1063         // change record of peer identity even by accident, much
1064         // less do it intentionally.
1065         return (localCerts == null ? null :
1066             (java.security.cert.Certificate[])localCerts.clone());
1067     }
1068 
1069     /**
1070      * Return the cert chain presented by the peer in the
1071      * javax.security.cert format.
1072      * Note: This method can be used only when using certificate-based
1073      * cipher suites; using it with non-certificate-based cipher suites
1074      * will throw an SSLPeerUnverifiedException.
1075      *
1076      * @return array of peer X.509 certs, with the peer's own cert
1077      *  first in the chain, and with the "root" CA last.
1078      *
1079      * @deprecated This method returns the deprecated
1080      *  {@code javax.security.cert.X509Certificate} type.
1081      *  Use {@code getPeerCertificates()} instead.
1082      */
1083     @Override
1084     @SuppressWarnings("removal")
1085     @Deprecated(since="9", forRemoval=true)
getPeerCertificateChain()1086     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
1087             throws SSLPeerUnverifiedException {
1088         //
1089         // clone to preserve integrity of session ... caller can't
1090         // change record of peer identity even by accident, much
1091         // less do it intentionally.
1092         //
1093         if (peerCerts == null) {
1094             throw new SSLPeerUnverifiedException("peer not authenticated");
1095         }
1096         javax.security.cert.X509Certificate[] certs;
1097         certs = new javax.security.cert.X509Certificate[peerCerts.length];
1098         for (int i = 0; i < peerCerts.length; i++) {
1099             byte[] der = null;
1100             try {
1101                 der = peerCerts[i].getEncoded();
1102                 certs[i] = javax.security.cert.X509Certificate.getInstance(der);
1103             } catch (CertificateEncodingException e) {
1104                 throw new SSLPeerUnverifiedException(e.getMessage());
1105             } catch (javax.security.cert.CertificateException e) {
1106                 throw new SSLPeerUnverifiedException(e.getMessage());
1107             }
1108         }
1109 
1110         return certs;
1111     }
1112 
1113     /**
1114      * Return the cert chain presented by the peer.
1115      * Note: This method can be used only when using certificate-based
1116      * cipher suites; using it with non-certificate-based cipher suites
1117      * will throw an SSLPeerUnverifiedException.
1118      *
1119      * @return array of peer X.509 certs, with the peer's own cert
1120      *  first in the chain, and with the "root" CA last.
1121      */
getCertificateChain()1122     public X509Certificate[] getCertificateChain()
1123             throws SSLPeerUnverifiedException {
1124         /*
1125          * clone to preserve integrity of session ... caller can't
1126          * change record of peer identity even by accident, much
1127          * less do it intentionally.
1128          */
1129         if (peerCerts != null) {
1130             return peerCerts.clone();
1131         } else {
1132             throw new SSLPeerUnverifiedException("peer not authenticated");
1133         }
1134     }
1135 
1136     /**
1137      * Return a List of status responses presented by the peer.
1138      * Note: This method can be used only when using certificate-based
1139      * server authentication; otherwise an empty {@code List} will be returned.
1140      *
1141      * @return an unmodifiable {@code List} of byte arrays, each consisting
1142      * of a DER-encoded OCSP response (see RFC 6960).  If no responses have
1143      * been presented by the server or non-certificate based server
1144      * authentication is used then an empty {@code List} is returned.
1145      */
1146     @Override
getStatusResponses()1147     public List<byte[]> getStatusResponses() {
1148         if (statusResponses == null || statusResponses.isEmpty()) {
1149             return Collections.emptyList();
1150         } else {
1151             // Clone both the list and the contents
1152             List<byte[]> responses = new ArrayList<>(statusResponses.size());
1153             for (byte[] respBytes : statusResponses) {
1154                 responses.add(respBytes.clone());
1155             }
1156             return Collections.unmodifiableList(responses);
1157         }
1158     }
1159 
1160     /**
1161      * Returns the identity of the peer which was established as part of
1162      * defining the session.
1163      *
1164      * @return the peer's principal. Returns an X500Principal of the
1165      * end-entity certificate for X509-based cipher suites.
1166      *
1167      * @throws SSLPeerUnverifiedException if the peer's identity has not
1168      *          been verified
1169      */
1170     @Override
getPeerPrincipal()1171     public Principal getPeerPrincipal()
1172                 throws SSLPeerUnverifiedException
1173     {
1174         if (peerCerts == null) {
1175             throw new SSLPeerUnverifiedException("peer not authenticated");
1176         }
1177         return peerCerts[0].getSubjectX500Principal();
1178     }
1179 
1180     /**
1181      * Returns the principal that was sent to the peer during handshaking.
1182      *
1183      * @return the principal sent to the peer. Returns an X500Principal
1184      * of the end-entity certificate for X509-based cipher suites.
1185      * If no principal was sent, then null is returned.
1186      */
1187     @Override
getLocalPrincipal()1188     public Principal getLocalPrincipal() {
1189         return ((localCerts == null || localCerts.length == 0) ? null :
1190                 localCerts[0].getSubjectX500Principal());
1191     }
1192 
1193     /*
1194      * Return the time the ticket for this session was created.
1195      */
getTicketCreationTime()1196     public long getTicketCreationTime() {
1197         return ticketCreationTime;
1198     }
1199 
1200     /**
1201      * Returns the time this session was created.
1202      */
1203     @Override
getCreationTime()1204     public long getCreationTime() {
1205         return creationTime;
1206     }
1207 
1208     /**
1209      * Returns the last time this session was used to initialize
1210      * a connection.
1211      */
1212     @Override
getLastAccessedTime()1213     public long getLastAccessedTime() {
1214         return (lastUsedTime != 0) ? lastUsedTime : creationTime;
1215     }
1216 
setLastAccessedTime(long time)1217     void setLastAccessedTime(long time) {
1218         lastUsedTime = time;
1219     }
1220 
1221 
1222     /**
1223      * Returns the network address of the session's peer.  This
1224      * implementation does not insist that connections between
1225      * different ports on the same host must necessarily belong
1226      * to different sessions, though that is of course allowed.
1227      */
getPeerAddress()1228     public InetAddress getPeerAddress() {
1229         try {
1230             return InetAddress.getByName(host);
1231         } catch (java.net.UnknownHostException e) {
1232             return null;
1233         }
1234     }
1235 
1236     @Override
getPeerHost()1237     public String getPeerHost() {
1238         return host;
1239     }
1240 
1241     /**
1242      * Need to provide the port info for caching sessions based on
1243      * host and port. Accessed by SSLSessionContextImpl
1244      */
1245     @Override
getPeerPort()1246     public int getPeerPort() {
1247         return port;
1248     }
1249 
setContext(SSLSessionContextImpl ctx)1250     void setContext(SSLSessionContextImpl ctx) {
1251         if (context == null) {
1252             context = ctx;
1253         }
1254     }
1255 
1256     /**
1257      * Invalidate a session.  Active connections may still exist, but
1258      * no connections will be able to rejoin this session.
1259      */
1260     @Override
invalidate()1261     public void invalidate() {
1262         sessionLock.lock();
1263         try {
1264             if (context != null) {
1265                 context.remove(sessionId);
1266                 context = null;
1267             }
1268 
1269             if (invalidated) {
1270                 return;
1271             }
1272             invalidated = true;
1273             if (SSLLogger.isOn && SSLLogger.isOn("session")) {
1274                  SSLLogger.finest("Invalidated session:  " + this);
1275             }
1276             for (SSLSessionImpl child : childSessions) {
1277                 child.invalidate();
1278             }
1279         } finally {
1280             sessionLock.unlock();
1281         }
1282     }
1283 
1284     /*
1285      * Table of application-specific session data indexed by an application
1286      * key and the calling security context. This is important since
1287      * sessions can be shared across different protection domains.
1288      */
1289     private final ConcurrentHashMap<SecureKey, Object> boundValues;
1290     boolean updateNST;
1291 
1292     /**
1293      * Assigns a session value.  Session change events are given if
1294      * appropriate, to any original value as well as the new value.
1295      */
1296     @Override
putValue(String key, Object value)1297     public void putValue(String key, Object value) {
1298         if ((key == null) || (value == null)) {
1299             throw new IllegalArgumentException("arguments can not be null");
1300         }
1301 
1302         SecureKey secureKey = new SecureKey(key);
1303         Object oldValue = boundValues.put(secureKey, value);
1304 
1305         if (oldValue instanceof SSLSessionBindingListener) {
1306             SSLSessionBindingEvent e;
1307 
1308             e = new SSLSessionBindingEvent(this, key);
1309             ((SSLSessionBindingListener)oldValue).valueUnbound(e);
1310         }
1311         if (value instanceof SSLSessionBindingListener) {
1312             SSLSessionBindingEvent e;
1313 
1314             e = new SSLSessionBindingEvent(this, key);
1315             ((SSLSessionBindingListener)value).valueBound(e);
1316         }
1317         if (protocolVersion.useTLS13PlusSpec()) {
1318             updateNST = true;
1319         }
1320     }
1321 
1322     /**
1323      * Returns the specified session value.
1324      */
1325     @Override
getValue(String key)1326     public Object getValue(String key) {
1327         if (key == null) {
1328             throw new IllegalArgumentException("argument can not be null");
1329         }
1330 
1331         SecureKey secureKey = new SecureKey(key);
1332         return boundValues.get(secureKey);
1333     }
1334 
1335 
1336     /**
1337      * Removes the specified session value, delivering a session changed
1338      * event as appropriate.
1339      */
1340     @Override
removeValue(String key)1341     public void removeValue(String key) {
1342         if (key == null) {
1343             throw new IllegalArgumentException("argument can not be null");
1344         }
1345 
1346         SecureKey secureKey = new SecureKey(key);
1347         Object value = boundValues.remove(secureKey);
1348 
1349         if (value instanceof SSLSessionBindingListener) {
1350             SSLSessionBindingEvent e;
1351 
1352             e = new SSLSessionBindingEvent(this, key);
1353             ((SSLSessionBindingListener)value).valueUnbound(e);
1354         }
1355         if (protocolVersion.useTLS13PlusSpec()) {
1356             updateNST = true;
1357         }
1358     }
1359 
1360 
1361     /**
1362      * Lists the names of the session values.
1363      */
1364     @Override
getValueNames()1365     public String[] getValueNames() {
1366         ArrayList<Object> v = new ArrayList<>();
1367         Object securityCtx = SecureKey.getCurrentSecurityContext();
1368         for (Enumeration<SecureKey> e = boundValues.keys();
1369                 e.hasMoreElements(); ) {
1370             SecureKey key = e.nextElement();
1371             if (securityCtx.equals(key.getSecurityContext())) {
1372                 v.add(key.getAppKey());
1373             }
1374         }
1375 
1376         return v.toArray(new String[0]);
1377     }
1378 
1379     /**
1380      * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
1381      * until changed.
1382      *
1383      * In the TLS specification (section 6.2.1, RFC2246), it is not
1384      * recommended that the plaintext has more than 2^14 bytes.
1385      * However, some TLS implementations violate the specification.
1386      * This is a workaround for interoperability with these stacks.
1387      *
1388      * Application could accept large fragments up to 2^15 bytes by
1389      * setting the system property jsse.SSLEngine.acceptLargeFragments
1390      * to "true".
1391      */
1392     private boolean acceptLargeFragments =
1393             Utilities.getBooleanProperty(
1394                     "jsse.SSLEngine.acceptLargeFragments", false);
1395 
1396     /**
1397      * Expand the buffer size of both SSL/TLS network packet and
1398      * application data.
1399      */
expandBufferSizes()1400     protected void expandBufferSizes() {
1401         sessionLock.lock();
1402         try {
1403             acceptLargeFragments = true;
1404         } finally {
1405             sessionLock.unlock();
1406         }
1407     }
1408 
1409     /**
1410      * Gets the current size of the largest SSL/TLS packet that is expected
1411      * when using this session.
1412      */
1413     @Override
getPacketBufferSize()1414     public int getPacketBufferSize() {
1415         sessionLock.lock();
1416         try {
1417             // Use the bigger packet size calculated from maximumPacketSize
1418             // and negotiatedMaxFragLen.
1419             int packetSize = 0;
1420             if (negotiatedMaxFragLen > 0) {
1421                 packetSize = cipherSuite.calculatePacketSize(
1422                         negotiatedMaxFragLen, protocolVersion,
1423                         protocolVersion.isDTLS);
1424             }
1425 
1426             if (maximumPacketSize > 0) {
1427                 return (maximumPacketSize > packetSize) ?
1428                         maximumPacketSize : packetSize;
1429             }
1430 
1431             if (packetSize != 0) {
1432                return packetSize;
1433             }
1434 
1435             if (protocolVersion.isDTLS) {
1436                 return DTLSRecord.maxRecordSize;
1437             } else {
1438                 return acceptLargeFragments ?
1439                         SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
1440             }
1441         } finally {
1442             sessionLock.unlock();
1443         }
1444     }
1445 
1446     /**
1447      * Gets the current size of the largest application data that is
1448      * expected when using this session.
1449      */
1450     @Override
getApplicationBufferSize()1451     public int getApplicationBufferSize() {
1452         sessionLock.lock();
1453         try {
1454             // Use the bigger fragment size calculated from maximumPacketSize
1455             // and negotiatedMaxFragLen.
1456             int fragmentSize = 0;
1457             if (maximumPacketSize > 0) {
1458                 fragmentSize = cipherSuite.calculateFragSize(
1459                         maximumPacketSize, protocolVersion,
1460                         protocolVersion.isDTLS);
1461             }
1462 
1463             if (negotiatedMaxFragLen > 0) {
1464                 return (negotiatedMaxFragLen > fragmentSize) ?
1465                         negotiatedMaxFragLen : fragmentSize;
1466             }
1467 
1468             if (fragmentSize != 0) {
1469                 return fragmentSize;
1470             }
1471 
1472             if (protocolVersion.isDTLS) {
1473                 return Record.maxDataSize;
1474             } else {
1475                 int maxPacketSize = acceptLargeFragments ?
1476                             SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize;
1477                 return (maxPacketSize - SSLRecord.headerSize);
1478             }
1479         } finally {
1480             sessionLock.unlock();
1481         }
1482     }
1483 
1484     /**
1485      * Sets the negotiated maximum fragment length, as specified by the
1486      * max_fragment_length ClientHello extension in RFC 6066.
1487      *
1488      * @param  negotiatedMaxFragLen
1489      *         the negotiated maximum fragment length, or {@code -1} if
1490      *         no such length has been negotiated.
1491      */
setNegotiatedMaxFragSize( int negotiatedMaxFragLen)1492     void setNegotiatedMaxFragSize(
1493             int negotiatedMaxFragLen) {
1494         sessionLock.lock();
1495         try {
1496             this.negotiatedMaxFragLen = negotiatedMaxFragLen;
1497         } finally {
1498             sessionLock.unlock();
1499         }
1500     }
1501 
1502     /**
1503      * Get the negotiated maximum fragment length, as specified by the
1504      * max_fragment_length ClientHello extension in RFC 6066.
1505      *
1506      * @return the negotiated maximum fragment length, or {@code -1} if
1507      *         no such length has been negotiated.
1508      */
getNegotiatedMaxFragSize()1509     int getNegotiatedMaxFragSize() {
1510         sessionLock.lock();
1511         try {
1512             return negotiatedMaxFragLen;
1513         } finally {
1514             sessionLock.unlock();
1515         }
1516     }
1517 
setMaximumPacketSize(int maximumPacketSize)1518     void setMaximumPacketSize(int maximumPacketSize) {
1519         sessionLock.lock();
1520         try {
1521             this.maximumPacketSize = maximumPacketSize;
1522         } finally {
1523             sessionLock.unlock();
1524         }
1525     }
1526 
getMaximumPacketSize()1527     int getMaximumPacketSize() {
1528         sessionLock.lock();
1529         try {
1530             return maximumPacketSize;
1531         } finally {
1532             sessionLock.unlock();
1533         }
1534     }
1535 
1536     /**
1537      * Gets an array of supported signature algorithm names that the local
1538      * side is willing to verify.
1539      */
1540     @Override
getLocalSupportedSignatureAlgorithms()1541     public String[] getLocalSupportedSignatureAlgorithms() {
1542         return SignatureScheme.getAlgorithmNames(localSupportedSignAlgs);
1543     }
1544 
1545     /**
1546      * Gets an array of supported signature schemes that the local side is
1547      * willing to verify.
1548      */
getLocalSupportedSignatureSchemes()1549     public Collection<SignatureScheme> getLocalSupportedSignatureSchemes() {
1550         return localSupportedSignAlgs;
1551     }
1552 
1553     /**
1554      * Gets an array of supported signature algorithms that the peer is
1555      * able to verify.
1556      */
1557     @Override
getPeerSupportedSignatureAlgorithms()1558     public String[] getPeerSupportedSignatureAlgorithms() {
1559         return SignatureScheme.getAlgorithmNames(peerSupportedSignAlgs);
1560     }
1561 
1562     /**
1563      * Obtains a <code>List</code> containing all {@link SNIServerName}s
1564      * of the requested Server Name Indication (SNI) extension.
1565      */
1566     @Override
getRequestedServerNames()1567     public List<SNIServerName> getRequestedServerNames() {
1568         return requestedServerNames;
1569     }
1570 
1571     /** Returns a string representation of this SSL session */
1572     @Override
toString()1573     public String toString() {
1574         return "Session(" + creationTime + "|" + getCipherSuite() + ")";
1575     }
1576 }
1577 
1578 /**
1579  * This "struct" class serves as a Hash Key that combines an
1580  * application-specific key and a security context.
1581  */
1582 class SecureKey {
1583     private static final Object     nullObject = new Object();
1584     private final Object            appKey;
1585     private final Object            securityCtx;
1586 
getCurrentSecurityContext()1587     static Object getCurrentSecurityContext() {
1588         SecurityManager sm = System.getSecurityManager();
1589         Object context = null;
1590 
1591         if (sm != null)
1592             context = sm.getSecurityContext();
1593         if (context == null)
1594             context = nullObject;
1595         return context;
1596     }
1597 
SecureKey(Object key)1598     SecureKey(Object key) {
1599         this.appKey = key;
1600         this.securityCtx = getCurrentSecurityContext();
1601     }
1602 
getAppKey()1603     Object getAppKey() {
1604         return appKey;
1605     }
1606 
getSecurityContext()1607     Object getSecurityContext() {
1608         return securityCtx;
1609     }
1610 
1611     @Override
hashCode()1612     public int hashCode() {
1613         return appKey.hashCode() ^ securityCtx.hashCode();
1614     }
1615 
1616     @Override
equals(Object o)1617     public boolean equals(Object o) {
1618         return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
1619                         && ((SecureKey)o).securityCtx.equals(securityCtx);
1620     }
1621 }
1622