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