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