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