< prev index next >

src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java

Print this page


   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;


< prev index next >