History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/SSLSessionImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/SSLSessionImpl.java+832−0
@@ -0,0 +1,832 @@
1+/*
2+ * Copyright (c) 1996, 2011, 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.io.*;
30+import java.net.*;
31+import java.util.Enumeration;
32+import java.util.Hashtable;
33+import java.util.Vector;
34+import java.util.Arrays;
35+import java.util.Collection;
36+
37+import java.security.Principal;
38+import java.security.PrivateKey;
39+import java.security.SecureRandom;
40+import java.security.cert.X509Certificate;
41+import java.security.cert.CertificateEncodingException;
42+
43+import javax.crypto.SecretKey;
44+
45+import javax.net.ssl.SSLSession;
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.SSLSession;
51+import javax.net.ssl.SSLPermission;
52+import javax.net.ssl.SSLException;
53+import javax.net.ssl.ExtendedSSLSession;
54+
55+import javax.security.auth.x500.X500Principal;
56+
57+import static sun.security.ssl.CipherSuite.*;
58+import static sun.security.ssl.CipherSuite.KeyExchange.*;
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+ * we only really need a single null session
82+ */
83+ static final SSLSessionImpl nullSession = new SSLSessionImpl();
84+
85+ // compression methods
86+ private static final byte compression_null = 0;
87+
88+ /*
89+ * The state of a single session, as described in section 7.1
90+ * of the SSLv3 spec.
91+ */
92+ private final ProtocolVersion protocolVersion;
93+ private final SessionId sessionId;
94+ private X509Certificate[] peerCerts;
95+ private byte compressionMethod;
96+ private CipherSuite cipherSuite;
97+ private SecretKey masterSecret;
98+
99+ /*
100+ * Information not part of the SSLv3 protocol spec, but used
101+ * to support session management policies.
102+ */
103+ private final long creationTime = System.currentTimeMillis();
104+ private long lastUsedTime = 0;
105+ private final String host;
106+ private final int port;
107+ private SSLSessionContextImpl context;
108+ private int sessionCount;
109+ private boolean invalidated;
110+ private X509Certificate[] localCerts;
111+ private PrivateKey localPrivateKey;
112+ private String[] localSupportedSignAlgs;
113+ private String[] peerSupportedSignAlgs;
114+
115+ // Principals for non-certificate based cipher suites
116+ private Principal peerPrincipal;
117+ private Principal localPrincipal;
118+
119+ /*
120+ * We count session creations, eventually for statistical data but
121+ * also since counters make shorter debugging IDs than the big ones
122+ * we use in the protocol for uniqueness-over-time.
123+ */
124+ private static volatile int counter = 0;
125+
126+ /*
127+ * Use of session caches is globally enabled/disabled.
128+ */
129+ private static boolean defaultRejoinable = true;
130+
131+ /* Class and subclass dynamic debugging support */
132+ private static final Debug debug = Debug.getInstance("ssl");
133+
134+ /*
135+ * Create a new non-rejoinable session, using the default (null)
136+ * cipher spec. This constructor returns a session which could
137+ * be used either by a client or by a server, as a connection is
138+ * first opened and before handshaking begins.
139+ */
140+ private SSLSessionImpl() {
141+ this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
142+ new SessionId(false, null), null, -1);
143+ }
144+
145+ /*
146+ * Create a new session, using a given cipher spec. This will
147+ * be rejoinable if session caching is enabled; the constructor
148+ * is intended mostly for use by serves.
149+ */
150+ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
151+ Collection<SignatureAndHashAlgorithm> algorithms,
152+ SecureRandom generator, String host, int port) {
153+ this(protocolVersion, cipherSuite, algorithms,
154+ new SessionId(defaultRejoinable, generator), host, port);
155+ }
156+
157+ /*
158+ * Record a new session, using a given cipher spec and session ID.
159+ */
160+ SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
161+ Collection<SignatureAndHashAlgorithm> algorithms,
162+ SessionId id, String host, int port) {
163+ this.protocolVersion = protocolVersion;
164+ sessionId = id;
165+ peerCerts = null;
166+ compressionMethod = compression_null;
167+ this.cipherSuite = cipherSuite;
168+ masterSecret = null;
169+ this.host = host;
170+ this.port = port;
171+ sessionCount = ++counter;
172+ localSupportedSignAlgs =
173+ SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
174+
175+ if (debug != null && Debug.isOn("session")) {
176+ System.out.println("%% Initialized: " + this);
177+ }
178+ }
179+
180+ void setMasterSecret(SecretKey secret) {
181+ if (masterSecret == null) {
182+ masterSecret = secret;
183+ } else {
184+ throw new RuntimeException("setMasterSecret() error");
185+ }
186+ }
187+
188+ /**
189+ * Returns the master secret ... treat with extreme caution!
190+ */
191+ SecretKey getMasterSecret() {
192+ return masterSecret;
193+ }
194+
195+ void setPeerCertificates(X509Certificate[] peer) {
196+ if (peerCerts == null) {
197+ peerCerts = peer;
198+ }
199+ }
200+
201+ void setLocalCertificates(X509Certificate[] local) {
202+ localCerts = local;
203+ }
204+
205+ void setLocalPrivateKey(PrivateKey privateKey) {
206+ localPrivateKey = privateKey;
207+ }
208+
209+ void setPeerSupportedSignatureAlgorithms(
210+ Collection<SignatureAndHashAlgorithm> algorithms) {
211+ peerSupportedSignAlgs =
212+ SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
213+ }
214+
215+ /**
216+ * Set the peer principal.
217+ */
218+ void setPeerPrincipal(Principal principal) {
219+ if (peerPrincipal == null) {
220+ peerPrincipal = principal;
221+ }
222+ }
223+
224+ /**
225+ * Set the local principal.
226+ */
227+ void setLocalPrincipal(Principal principal) {
228+ localPrincipal = principal;
229+ }
230+
231+ /**
232+ * Returns true iff this session may be resumed ... sessions are
233+ * usually resumable. Security policies may suggest otherwise,
234+ * for example sessions that haven't been used for a while (say,
235+ * a working day) won't be resumable, and sessions might have a
236+ * maximum lifetime in any case.
237+ */
238+ boolean isRejoinable() {
239+ return sessionId != null && sessionId.length() != 0 &&
240+ !invalidated && isLocalAuthenticationValid();
241+ }
242+
243+ public synchronized boolean isValid() {
244+ return isRejoinable();
245+ }
246+
247+ /**
248+ * Check if the authentication used when establishing this session
249+ * is still valid. Returns true if no authentication was used
250+ */
251+ boolean isLocalAuthenticationValid() {
252+ if (localPrivateKey != null) {
253+ try {
254+ // if the private key is no longer valid, getAlgorithm()
255+ // should throw an exception
256+ // (e.g. Smartcard has been removed from the reader)
257+ localPrivateKey.getAlgorithm();
258+ } catch (Exception e) {
259+ invalidate();
260+ return false;
261+ }
262+ }
263+ return true;
264+ }
265+
266+ /**
267+ * Returns the ID for this session. The ID is fixed for the
268+ * duration of the session; neither it, nor its value, changes.
269+ */
270+ public byte[] getId() {
271+ return sessionId.getId();
272+ }
273+
274+ /**
275+ * For server sessions, this returns the set of sessions which
276+ * are currently valid in this process. For client sessions,
277+ * this returns null.
278+ */
279+ public SSLSessionContext getSessionContext() {
280+ /*
281+ * An interim security policy until we can do something
282+ * more specific in 1.2. Only allow trusted code (code which
283+ * can set system properties) to get an
284+ * SSLSessionContext. This is to limit the ability of code to
285+ * look up specific sessions or enumerate over them. Otherwise,
286+ * code can only get session objects from successful SSL
287+ * connections which implies that they must have had permission
288+ * to make the network connection in the first place.
289+ */
290+ SecurityManager sm;
291+ if ((sm = System.getSecurityManager()) != null) {
292+ sm.checkPermission(new SSLPermission("getSSLSessionContext"));
293+ }
294+
295+ return context;
296+ }
297+
298+
299+ SessionId getSessionId() {
300+ return sessionId;
301+ }
302+
303+
304+ /**
305+ * Returns the cipher spec in use on this session
306+ */
307+ CipherSuite getSuite() {
308+ return cipherSuite;
309+ }
310+
311+ /**
312+ * Resets the cipher spec in use on this session
313+ */
314+ void setSuite(CipherSuite suite) {
315+ cipherSuite = suite;
316+
317+ if (debug != null && Debug.isOn("session")) {
318+ System.out.println("%% Negotiating: " + this);
319+ }
320+ }
321+
322+ /**
323+ * Returns the name of the cipher suite in use on this session
324+ */
325+ public String getCipherSuite() {
326+ return getSuite().name;
327+ }
328+
329+ ProtocolVersion getProtocolVersion() {
330+ return protocolVersion;
331+ }
332+
333+ /**
334+ * Returns the standard name of the protocol in use on this session
335+ */
336+ public String getProtocol() {
337+ return getProtocolVersion().name;
338+ }
339+
340+ /**
341+ * Returns the compression technique used in this session
342+ */
343+ byte getCompression() {
344+ return compressionMethod;
345+ }
346+
347+ /**
348+ * Returns the hashcode for this session
349+ */
350+ public int hashCode() {
351+ return sessionId.hashCode();
352+ }
353+
354+
355+ /**
356+ * Returns true if sessions have same ids, false otherwise.
357+ */
358+ public boolean equals(Object obj) {
359+
360+ if (obj == this) {
361+ return true;
362+ }
363+
364+ if (obj instanceof SSLSessionImpl) {
365+ SSLSessionImpl sess = (SSLSessionImpl) obj;
366+ return (sessionId != null) && (sessionId.equals(
367+ sess.getSessionId()));
368+ }
369+
370+ return false;
371+ }
372+
373+
374+ /**
375+ * Return the cert chain presented by the peer in the
376+ * java.security.cert format.
377+ * Note: This method can be used only when using certificate-based
378+ * cipher suites; using it with non-certificate-based cipher suites,
379+ * such as Kerberos, will throw an SSLPeerUnverifiedException.
380+ *
381+ * @return array of peer X.509 certs, with the peer's own cert
382+ * first in the chain, and with the "root" CA last.
383+ */
384+ public java.security.cert.Certificate[] getPeerCertificates()
385+ throws SSLPeerUnverifiedException {
386+ //
387+ // clone to preserve integrity of session ... caller can't
388+ // change record of peer identity even by accident, much
389+ // less do it intentionally.
390+ //
391+ if ((cipherSuite.keyExchange == K_KRB5) ||
392+ (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
393+ throw new SSLPeerUnverifiedException("no certificates expected"
394+ + " for Kerberos cipher suites");
395+ }
396+ if (peerCerts == null) {
397+ throw new SSLPeerUnverifiedException("peer not authenticated");
398+ }
399+ // Certs are immutable objects, therefore we don't clone them.
400+ // But do need to clone the array, so that nothing is inserted
401+ // into peerCerts.
402+ return (java.security.cert.Certificate[])peerCerts.clone();
403+ }
404+
405+ /**
406+ * Return the cert chain presented to the peer in the
407+ * java.security.cert format.
408+ * Note: This method is useful only when using certificate-based
409+ * cipher suites.
410+ *
411+ * @return array of peer X.509 certs, with the peer's own cert
412+ * first in the chain, and with the "root" CA last.
413+ */
414+ public java.security.cert.Certificate[] getLocalCertificates() {
415+ //
416+ // clone to preserve integrity of session ... caller can't
417+ // change record of peer identity even by accident, much
418+ // less do it intentionally.
419+ return (localCerts == null ? null :
420+ (java.security.cert.Certificate[])localCerts.clone());
421+ }
422+
423+ /**
424+ * Return the cert chain presented by the peer in the
425+ * javax.security.cert format.
426+ * Note: This method can be used only when using certificate-based
427+ * cipher suites; using it with non-certificate-based cipher suites,
428+ * such as Kerberos, will throw an SSLPeerUnverifiedException.
429+ *
430+ * @return array of peer X.509 certs, with the peer's own cert
431+ * first in the chain, and with the "root" CA last.
432+ */
433+ public javax.security.cert.X509Certificate[] getPeerCertificateChain()
434+ throws SSLPeerUnverifiedException {
435+ //
436+ // clone to preserve integrity of session ... caller can't
437+ // change record of peer identity even by accident, much
438+ // less do it intentionally.
439+ //
440+ if ((cipherSuite.keyExchange == K_KRB5) ||
441+ (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
442+ throw new SSLPeerUnverifiedException("no certificates expected"
443+ + " for Kerberos cipher suites");
444+ }
445+ if (peerCerts == null) {
446+ throw new SSLPeerUnverifiedException("peer not authenticated");
447+ }
448+ javax.security.cert.X509Certificate[] certs;
449+ certs = new javax.security.cert.X509Certificate[peerCerts.length];
450+ for (int i = 0; i < peerCerts.length; i++) {
451+ byte[] der = null;
452+ try {
453+ der = peerCerts[i].getEncoded();
454+ certs[i] = javax.security.cert.X509Certificate.getInstance(der);
455+ } catch (CertificateEncodingException e) {
456+ throw new SSLPeerUnverifiedException(e.getMessage());
457+ } catch (javax.security.cert.CertificateException e) {
458+ throw new SSLPeerUnverifiedException(e.getMessage());
459+ }
460+ }
461+
462+ return certs;
463+ }
464+
465+ /**
466+ * Return the cert chain presented by the peer.
467+ * Note: This method can be used only when using certificate-based
468+ * cipher suites; using it with non-certificate-based cipher suites,
469+ * such as Kerberos, will throw an SSLPeerUnverifiedException.
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+ public X509Certificate[] getCertificateChain()
475+ throws SSLPeerUnverifiedException {
476+ /*
477+ * clone to preserve integrity of session ... caller can't
478+ * change record of peer identity even by accident, much
479+ * less do it intentionally.
480+ */
481+ if ((cipherSuite.keyExchange == K_KRB5) ||
482+ (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
483+ throw new SSLPeerUnverifiedException("no certificates expected"
484+ + " for Kerberos cipher suites");
485+ }
486+ if (peerCerts != null) {
487+ return peerCerts.clone();
488+ } else {
489+ throw new SSLPeerUnverifiedException("peer not authenticated");
490+ }
491+ }
492+
493+ /**
494+ * Returns the identity of the peer which was established as part of
495+ * defining the session.
496+ *
497+ * @return the peer's principal. Returns an X500Principal of the
498+ * end-entity certificate for X509-based cipher suites, and
499+ * Principal for Kerberos cipher suites.
500+ *
501+ * @throws SSLPeerUnverifiedException if the peer's identity has not
502+ * been verified
503+ */
504+ public Principal getPeerPrincipal()
505+ throws SSLPeerUnverifiedException
506+ {
507+ if ((cipherSuite.keyExchange == K_KRB5) ||
508+ (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
509+ if (peerPrincipal == null) {
510+ throw new SSLPeerUnverifiedException("peer not authenticated");
511+ } else {
512+ // Eliminate dependency on KerberosPrincipal
513+ return peerPrincipal;
514+ }
515+ }
516+ if (peerCerts == null) {
517+ throw new SSLPeerUnverifiedException("peer not authenticated");
518+ }
519+ return peerCerts[0].getSubjectX500Principal();
520+ }
521+
522+ /**
523+ * Returns the principal that was sent to the peer during handshaking.
524+ *
525+ * @return the principal sent to the peer. Returns an X500Principal
526+ * of the end-entity certificate for X509-based cipher suites, and
527+ * Principal for Kerberos cipher suites. If no principal was
528+ * sent, then null is returned.
529+ */
530+ public Principal getLocalPrincipal() {
531+
532+ if ((cipherSuite.keyExchange == K_KRB5) ||
533+ (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
534+ // Eliminate dependency on KerberosPrincipal
535+ return (localPrincipal == null ? null : localPrincipal);
536+ }
537+ return (localCerts == null ? null :
538+ localCerts[0].getSubjectX500Principal());
539+ }
540+
541+ /**
542+ * Returns the time this session was created.
543+ */
544+ public long getCreationTime() {
545+ return creationTime;
546+ }
547+
548+ /**
549+ * Returns the last time this session was used to initialize
550+ * a connection.
551+ */
552+ public long getLastAccessedTime() {
553+ return (lastUsedTime != 0) ? lastUsedTime : creationTime;
554+ }
555+
556+ void setLastAccessedTime(long time) {
557+ lastUsedTime = time;
558+ }
559+
560+
561+ /**
562+ * Returns the network address of the session's peer. This
563+ * implementation does not insist that connections between
564+ * different ports on the same host must necessarily belong
565+ * to different sessions, though that is of course allowed.
566+ */
567+ public InetAddress getPeerAddress() {
568+ try {
569+ return InetAddress.getByName(host);
570+ } catch (java.net.UnknownHostException e) {
571+ return null;
572+ }
573+ }
574+
575+ public String getPeerHost() {
576+ return host;
577+ }
578+
579+ /**
580+ * Need to provide the port info for caching sessions based on
581+ * host and port. Accessed by SSLSessionContextImpl
582+ */
583+ public int getPeerPort() {
584+ return port;
585+ }
586+
587+ void setContext(SSLSessionContextImpl ctx) {
588+ if (context == null) {
589+ context = ctx;
590+ }
591+ }
592+
593+ /**
594+ * Invalidate a session. Active connections may still exist, but
595+ * no connections will be able to rejoin this session.
596+ */
597+ synchronized public void invalidate() {
598+ //
599+ // Can't invalidate the NULL session -- this would be
600+ // attempted when we get a handshaking error on a brand
601+ // new connection, with no "real" session yet.
602+ //
603+ if (this == nullSession) {
604+ return;
605+ }
606+ invalidated = true;
607+ if (debug != null && Debug.isOn("session")) {
608+ System.out.println("%% Invalidated: " + this);
609+ }
610+ if (context != null) {
611+ context.remove(sessionId);
612+ context = null;
613+ }
614+ }
615+
616+ /*
617+ * Table of application-specific session data indexed by an application
618+ * key and the calling security context. This is important since
619+ * sessions can be shared across different protection domains.
620+ */
621+ private Hashtable<SecureKey, Object> table = new Hashtable<>();
622+
623+ /**
624+ * Assigns a session value. Session change events are given if
625+ * appropriate, to any original value as well as the new value.
626+ */
627+ public void putValue(String key, Object value) {
628+ if ((key == null) || (value == null)) {
629+ throw new IllegalArgumentException("arguments can not be null");
630+ }
631+
632+ SecureKey secureKey = new SecureKey(key);
633+ Object oldValue = table.put(secureKey, value);
634+
635+ if (oldValue instanceof SSLSessionBindingListener) {
636+ SSLSessionBindingEvent e;
637+
638+ e = new SSLSessionBindingEvent(this, key);
639+ ((SSLSessionBindingListener)oldValue).valueUnbound(e);
640+ }
641+ if (value instanceof SSLSessionBindingListener) {
642+ SSLSessionBindingEvent e;
643+
644+ e = new SSLSessionBindingEvent(this, key);
645+ ((SSLSessionBindingListener)value).valueBound(e);
646+ }
647+ }
648+
649+
650+ /**
651+ * Returns the specified session value.
652+ */
653+ public Object getValue(String key) {
654+ if (key == null) {
655+ throw new IllegalArgumentException("argument can not be null");
656+ }
657+
658+ SecureKey secureKey = new SecureKey(key);
659+ return table.get(secureKey);
660+ }
661+
662+
663+ /**
664+ * Removes the specified session value, delivering a session changed
665+ * event as appropriate.
666+ */
667+ public void removeValue(String key) {
668+ if (key == null) {
669+ throw new IllegalArgumentException("argument can not be null");
670+ }
671+
672+ SecureKey secureKey = new SecureKey(key);
673+ Object value = table.remove(secureKey);
674+
675+ if (value instanceof SSLSessionBindingListener) {
676+ SSLSessionBindingEvent e;
677+
678+ e = new SSLSessionBindingEvent(this, key);
679+ ((SSLSessionBindingListener)value).valueUnbound(e);
680+ }
681+ }
682+
683+
684+ /**
685+ * Lists the names of the session values.
686+ */
687+ public String[] getValueNames() {
688+ Enumeration<SecureKey> e;
689+ Vector<Object> v = new Vector<>();
690+ SecureKey key;
691+ Object securityCtx = SecureKey.getCurrentSecurityContext();
692+
693+ for (e = table.keys(); e.hasMoreElements(); ) {
694+ key = e.nextElement();
695+
696+ if (securityCtx.equals(key.getSecurityContext())) {
697+ v.addElement(key.getAppKey());
698+ }
699+ }
700+ String[] names = new String[v.size()];
701+ v.copyInto(names);
702+
703+ return names;
704+ }
705+
706+ /**
707+ * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
708+ * until changed.
709+ *
710+ * In the TLS specification (section 6.2.1, RFC2246), it is not
711+ * recommended that the plaintext has more than 2^14 bytes.
712+ * However, some TLS implementations violate the specification.
713+ * This is a workaround for interoperability with these stacks.
714+ *
715+ * Application could accept large fragments up to 2^15 bytes by
716+ * setting the system property jsse.SSLEngine.acceptLargeFragments
717+ * to "true".
718+ */
719+ private boolean acceptLargeFragments =
720+ Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false);
721+
722+ /**
723+ * Expand the buffer size of both SSL/TLS network packet and
724+ * application data.
725+ */
726+ protected synchronized void expandBufferSizes() {
727+ acceptLargeFragments = true;
728+ }
729+
730+ /**
731+ * Gets the current size of the largest SSL/TLS packet that is expected
732+ * when using this session.
733+ */
734+ public synchronized int getPacketBufferSize() {
735+ return acceptLargeFragments ?
736+ Record.maxLargeRecordSize : Record.maxRecordSize;
737+ }
738+
739+ /**
740+ * Gets the current size of the largest application data that is
741+ * expected when using this session.
742+ */
743+ public synchronized int getApplicationBufferSize() {
744+ return getPacketBufferSize() - Record.headerSize;
745+ }
746+
747+ /**
748+ * Gets an array of supported signature algorithms that the local side is
749+ * willing to verify.
750+ */
751+ public String[] getLocalSupportedSignatureAlgorithms() {
752+ if (localSupportedSignAlgs != null) {
753+ return localSupportedSignAlgs.clone();
754+ }
755+
756+ return new String[0];
757+ }
758+
759+ /**
760+ * Gets an array of supported signature algorithms that the peer is
761+ * able to verify.
762+ */
763+ public String[] getPeerSupportedSignatureAlgorithms() {
764+ if (peerSupportedSignAlgs != null) {
765+ return peerSupportedSignAlgs.clone();
766+ }
767+
768+ return new String[0];
769+ }
770+
771+ /** Returns a string representation of this SSL session */
772+ public String toString() {
773+ return "[Session-" + sessionCount
774+ + ", " + getCipherSuite()
775+ + "]";
776+ }
777+
778+ /**
779+ * When SSL sessions are finalized, all values bound to
780+ * them are removed.
781+ */
782+ public void finalize() {
783+ String[] names = getValueNames();
784+ for (int i = 0; i < names.length; i++) {
785+ removeValue(names[i]);
786+ }
787+ }
788+}
789+
790+
791+/**
792+ * This "struct" class serves as a Hash Key that combines an
793+ * application-specific key and a security context.
794+ */
795+class SecureKey {
796+ private static Object nullObject = new Object();
797+ private Object appKey;
798+ private Object securityCtx;
799+
800+ static Object getCurrentSecurityContext() {
801+ SecurityManager sm = System.getSecurityManager();
802+ Object context = null;
803+
804+ if (sm != null)
805+ context = sm.getSecurityContext();
806+ if (context == null)
807+ context = nullObject;
808+ return context;
809+ }
810+
811+ SecureKey(Object key) {
812+ this.appKey = key;
813+ this.securityCtx = getCurrentSecurityContext();
814+ }
815+
816+ Object getAppKey() {
817+ return appKey;
818+ }
819+
820+ Object getSecurityContext() {
821+ return securityCtx;
822+ }
823+
824+ public int hashCode() {
825+ return appKey.hashCode() ^ securityCtx.hashCode();
826+ }
827+
828+ public boolean equals(Object o) {
829+ return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
830+ && ((SecureKey)o).securityCtx.equals(securityCtx);
831+ }
832+}