1 /* 2 * Copyright (c) 1996, 2019, 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 sun.security.x509.X509CertImpl; 28 29 import java.io.IOException; 30 import java.lang.reflect.Array; 31 import java.math.BigInteger; 32 import java.net.InetAddress; 33 import java.nio.ByteBuffer; 34 import java.security.Principal; 35 import java.security.PrivateKey; 36 import java.security.cert.CertificateEncodingException; 37 import java.security.cert.X509Certificate; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.Queue; 41 import java.util.Collection; 42 import java.util.Collections; 43 import java.util.Enumeration; 44 import java.util.List; 45 import java.util.concurrent.ConcurrentHashMap; 46 import java.util.concurrent.ConcurrentLinkedQueue; 47 import java.util.concurrent.locks.ReentrantLock; 48 import javax.crypto.SecretKey; 49 import javax.crypto.spec.SecretKeySpec; 50 import javax.net.ssl.ExtendedSSLSession; 51 import javax.net.ssl.SNIHostName; 52 import javax.net.ssl.SNIServerName; 53 import javax.net.ssl.SSLException; 54 import javax.net.ssl.SSLPeerUnverifiedException; 55 import javax.net.ssl.SSLPermission; 56 import javax.net.ssl.SSLSessionBindingEvent; 57 import javax.net.ssl.SSLSessionBindingListener; 58 import javax.net.ssl.SSLSessionContext; 59 60 /** 61 * Implements the SSL session interface, and exposes the session context 62 * which is maintained by SSL servers. 63 * 64 * <P> Servers have the ability to manage the sessions associated with 65 * their authentication context(s). They can do this by enumerating the 66 * IDs of the sessions which are cached, examining those sessions, and then 67 * perhaps invalidating a given session so that it can't be used again. 68 * If servers do not explicitly manage the cache, sessions will linger 69 * until memory is low enough that the runtime environment purges cache 70 * entries automatically to reclaim space. 71 * 72 * <P><em> The only reason this class is not package-private is that 73 * there's no other public way to get at the server session context which 74 * is associated with any given authentication context. </em> 75 * 76 * @author David Brownell 77 */ 78 final class SSLSessionImpl extends ExtendedSSLSession { 79 80 /* 81 * The state of a single session, as described in section 7.1 82 * of the SSLv3 spec. 83 */ 84 private final ProtocolVersion protocolVersion; 85 private final SessionId sessionId; 86 private X509Certificate[] peerCerts; 87 private CipherSuite cipherSuite; 88 private SecretKey masterSecret; 89 final boolean useExtendedMasterSecret; 90 91 /* 92 * Information not part of the SSLv3 protocol spec, but used 93 * to support session management policies. 94 */ 95 private final long creationTime; 96 private long lastUsedTime = 0; 97 private final String host; 98 private final int port; 99 private SSLSessionContextImpl context; 100 private boolean invalidated; 101 private X509Certificate[] localCerts; 102 private PrivateKey localPrivateKey; 103 private final Collection<SignatureScheme> localSupportedSignAlgs; 104 private Collection<SignatureScheme> peerSupportedSignAlgs; //for certificate 105 private boolean useDefaultPeerSignAlgs = false; 106 private List<byte[]> statusResponses; 107 private SecretKey resumptionMasterSecret; 108 private SecretKey preSharedKey; 109 private byte[] pskIdentity; 110 private final long ticketCreationTime = System.currentTimeMillis(); 111 private int ticketAgeAdd; 112 113 private int negotiatedMaxFragLen = -1; 114 private int maximumPacketSize; 115 116 private final Queue<SSLSessionImpl> childSessions = 117 new ConcurrentLinkedQueue<>(); 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 * Use of session caches is globally enabled/disabled. 129 */ 130 private static boolean defaultRejoinable = true; 131 132 // server name indication 133 final SNIServerName serverNameIndication; 134 private final List<SNIServerName> requestedServerNames; 135 136 // Counter used to create unique nonces in NewSessionTicket 137 private BigInteger ticketNonceCounter = BigInteger.ONE; 138 139 // The endpoint identification algorithm used to check certificates 140 // in this session. 141 private final String identificationProtocol; 142 143 private final ReentrantLock sessionLock = new ReentrantLock(); 144 145 /* 146 * Create a new non-rejoinable session, using the default (null) 147 * cipher spec. This constructor returns a session which could 148 * be used either by a client or by a server, as a connection is 149 * first opened and before handshaking begins. 150 */ SSLSessionImpl()151 SSLSessionImpl() { 152 this.protocolVersion = ProtocolVersion.NONE; 153 this.cipherSuite = CipherSuite.C_NULL; 154 this.sessionId = new SessionId(false, null); 155 this.host = null; 156 this.port = -1; 157 this.localSupportedSignAlgs = Collections.emptySet(); 158 this.serverNameIndication = null; 159 this.requestedServerNames = Collections.<SNIServerName>emptyList(); 160 this.useExtendedMasterSecret = false; 161 this.creationTime = System.currentTimeMillis(); 162 this.identificationProtocol = null; 163 this.boundValues = new ConcurrentHashMap<>(); 164 } 165 166 /* 167 * Create a new session, using a given cipher spec. This will 168 * be rejoinable if session caching is enabled; the constructor 169 * is intended mostly for use by serves. 170 */ SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite)171 SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) { 172 this(hc, cipherSuite, 173 new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom())); 174 } 175 176 /* 177 * Record a new session, using a given cipher spec and session ID. 178 */ SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id)179 SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) { 180 this(hc, cipherSuite, id, System.currentTimeMillis()); 181 } 182 183 /* 184 * Record a new session, using a given cipher spec, session ID, 185 * and creation time. 186 * Note: For the unmodifiable collections and lists we are creating new 187 * collections as inputs to avoid potential deep nesting of 188 * unmodifiable collections that can cause StackOverflowErrors 189 * (see JDK-6323374). 190 */ SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id, long creationTime)191 SSLSessionImpl(HandshakeContext hc, 192 CipherSuite cipherSuite, SessionId id, long creationTime) { 193 this.protocolVersion = hc.negotiatedProtocol; 194 this.cipherSuite = cipherSuite; 195 this.sessionId = id; 196 this.host = hc.conContext.transport.getPeerHost(); 197 this.port = hc.conContext.transport.getPeerPort(); 198 this.localSupportedSignAlgs = hc.localSupportedSignAlgs == null ? 199 Collections.emptySet() : 200 Collections.unmodifiableCollection( 201 new ArrayList<>(hc.localSupportedSignAlgs)); 202 this.serverNameIndication = hc.negotiatedServerName; 203 this.requestedServerNames = Collections.unmodifiableList( 204 new ArrayList<>(hc.getRequestedServerNames())); 205 if (hc.sslConfig.isClientMode) { 206 this.useExtendedMasterSecret = 207 (hc.handshakeExtensions.get( 208 SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) && 209 (hc.handshakeExtensions.get( 210 SSLExtension.SH_EXTENDED_MASTER_SECRET) != null); 211 } else { 212 this.useExtendedMasterSecret = 213 (hc.handshakeExtensions.get( 214 SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) && 215 (!hc.negotiatedProtocol.useTLS13PlusSpec()); 216 } 217 this.creationTime = creationTime; 218 this.identificationProtocol = hc.sslConfig.identificationProtocol; 219 this.boundValues = new ConcurrentHashMap<>(); 220 221 if (SSLLogger.isOn && SSLLogger.isOn("session")) { 222 SSLLogger.finest("Session initialized: " + this); 223 } 224 } 225 SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId)226 SSLSessionImpl(SSLSessionImpl baseSession, SessionId newId) { 227 this.protocolVersion = baseSession.getProtocolVersion(); 228 this.cipherSuite = baseSession.cipherSuite; 229 this.sessionId = newId; 230 this.host = baseSession.getPeerHost(); 231 this.port = baseSession.getPeerPort(); 232 this.localSupportedSignAlgs = 233 baseSession.localSupportedSignAlgs == null ? 234 Collections.emptySet() : baseSession.localSupportedSignAlgs; 235 this.peerSupportedSignAlgs = 236 baseSession.peerSupportedSignAlgs == null ? 237 Collections.emptySet() : baseSession.peerSupportedSignAlgs; 238 this.serverNameIndication = baseSession.serverNameIndication; 239 this.requestedServerNames = baseSession.getRequestedServerNames(); 240 this.masterSecret = baseSession.getMasterSecret(); 241 this.useExtendedMasterSecret = baseSession.useExtendedMasterSecret; 242 this.creationTime = baseSession.getCreationTime(); 243 this.lastUsedTime = System.currentTimeMillis(); 244 this.identificationProtocol = baseSession.getIdentificationProtocol(); 245 this.localCerts = baseSession.localCerts; 246 this.peerCerts = baseSession.peerCerts; 247 this.statusResponses = baseSession.statusResponses; 248 this.resumptionMasterSecret = baseSession.resumptionMasterSecret; 249 this.context = baseSession.context; 250 this.negotiatedMaxFragLen = baseSession.negotiatedMaxFragLen; 251 this.maximumPacketSize = baseSession.maximumPacketSize; 252 this.boundValues = baseSession.boundValues; 253 254 if (SSLLogger.isOn && SSLLogger.isOn("session")) { 255 SSLLogger.finest("Session initialized: " + this); 256 } 257 } 258 259 /** 260 * < 2 bytes > protocolVersion 261 * < 2 bytes > cipherSuite 262 * < 1 byte > localSupportedSignAlgs entries 263 * < 2 bytes per entries > localSupportedSignAlgs 264 * < 1 bytes > peerSupportedSignAlgs entries 265 * < 2 bytes per entries > peerSupportedSignAlgs 266 * < 2 bytes > preSharedKey length 267 * < length in bytes > preSharedKey 268 * < 1 byte > pskIdentity length 269 * < length in bytes > pskIdentity 270 * < 1 byte > masterSecret length 271 * < 1 byte > masterSecret algorithm length 272 * < length in bytes > masterSecret algorithm 273 * < 2 bytes > masterSecretKey length 274 * < length in bytes> masterSecretKey 275 * < 1 byte > useExtendedMasterSecret 276 * < 1 byte > identificationProtocol length 277 * < length in bytes > identificationProtocol 278 * < 1 byte > serverNameIndication length 279 * < length in bytes > serverNameIndication 280 * < 1 byte > Number of requestedServerNames entries 281 * < 1 byte > ServerName length 282 * < length in bytes > ServerName 283 * < 4 bytes > creationTime 284 * < 2 byte > status response length 285 * < 2 byte > status response entry length 286 * < length in byte > status response entry 287 * < 1 byte > Length of peer host 288 * < length in bytes > peer host 289 * < 2 bytes> peer port 290 * < 1 byte > Number of peerCerts entries 291 * < 4 byte > peerCert length 292 * < length in bytes > peerCert 293 * < 1 byte > localCerts type (Cert, PSK, Anonymous) 294 * Certificate 295 * < 1 byte > Number of Certificate entries 296 * < 4 byte> Certificate length 297 * < length in bytes> Certificate 298 * PSK 299 * < 1 byte > Number of PSK entries 300 * < 1 bytes > PSK algorithm length 301 * < length in bytes > PSK algorithm string 302 * < 4 bytes > PSK key length 303 * < length in bytes> PSK key 304 * < 4 bytes > PSK identity length 305 * < length in bytes> PSK identity 306 * Anonymous 307 * < 1 byte > 308 * < 4 bytes > maximumPacketSize 309 * < 4 bytes > negotiatedMaxFragSize 310 */ 311 SSLSessionImpl(HandshakeContext hc, ByteBuffer buf)312 SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException { 313 int i = 0; 314 byte[] b; 315 316 boundValues = new ConcurrentHashMap<>(); 317 this.protocolVersion = 318 ProtocolVersion.valueOf(Short.toUnsignedInt(buf.getShort())); 319 320 if (protocolVersion.useTLS13PlusSpec()) { 321 this.sessionId = new SessionId(false, null); 322 } else { 323 // The CH session id may reset this if it's provided 324 this.sessionId = new SessionId(true, 325 hc.sslContext.getSecureRandom()); 326 } 327 328 this.cipherSuite = 329 CipherSuite.valueOf(Short.toUnsignedInt(buf.getShort())); 330 331 // Local Supported signature algorithms 332 ArrayList<SignatureScheme> list = new ArrayList<>(); 333 i = Byte.toUnsignedInt(buf.get()); 334 while (i-- > 0) { 335 list.add(SignatureScheme.valueOf( 336 Short.toUnsignedInt(buf.getShort()))); 337 } 338 this.localSupportedSignAlgs = Collections.unmodifiableCollection(list); 339 340 // Peer Supported signature algorithms 341 i = Byte.toUnsignedInt(buf.get()); 342 list.clear(); 343 while (i-- > 0) { 344 list.add(SignatureScheme.valueOf( 345 Short.toUnsignedInt(buf.getShort()))); 346 } 347 this.peerSupportedSignAlgs = Collections.unmodifiableCollection(list); 348 349 // PSK 350 i = Short.toUnsignedInt(buf.getShort()); 351 if (i > 0) { 352 b = new byte[i]; 353 // Get algorithm string 354 buf.get(b, 0, i); 355 // Encoded length 356 i = Short.toUnsignedInt(buf.getShort()); 357 // Encoded SecretKey 358 b = new byte[i]; 359 buf.get(b); 360 this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret"); 361 } else { 362 this.preSharedKey = null; 363 } 364 365 // PSK identity 366 i = buf.get(); 367 if (i > 0) { 368 b = new byte[i]; 369 buf.get(b); 370 this.pskIdentity = b; 371 } else { 372 this.pskIdentity = null; 373 } 374 375 // Master secret length of secret key algorithm (one byte) 376 i = buf.get(); 377 if (i > 0) { 378 b = new byte[i]; 379 // Get algorithm string 380 buf.get(b, 0, i); 381 // Encoded length 382 i = Short.toUnsignedInt(buf.getShort()); 383 // Encoded SecretKey 384 b = new byte[i]; 385 buf.get(b); 386 this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret"); 387 } else { 388 this.masterSecret = null; 389 } 390 // Use extended master secret 391 this.useExtendedMasterSecret = (buf.get() != 0); 392 393 // Identification Protocol 394 i = buf.get(); 395 if (i == 0) { 396 identificationProtocol = null; 397 } else { 398 b = new byte[i]; 399 identificationProtocol = 400 buf.get(b, 0, i).asCharBuffer().toString(); 401 } 402 403 // SNI 404 i = buf.get(); // length 405 if (i == 0) { 406 serverNameIndication = null; 407 } else { 408 b = new byte[i]; 409 buf.get(b, 0, b.length); 410 serverNameIndication = new SNIHostName(b); 411 } 412 413 // List of SNIServerName 414 int len = Short.toUnsignedInt(buf.getShort()); 415 if (len == 0) { 416 this.requestedServerNames = Collections.<SNIServerName>emptyList(); 417 } else { 418 requestedServerNames = new ArrayList<>(); 419 while (len > 0) { 420 int l = buf.get(); 421 b = new byte[l]; 422 buf.get(b, 0, l); 423 requestedServerNames.add(new SNIHostName(new String(b))); 424 len--; 425 } 426 } 427 428 maximumPacketSize = buf.getInt(); 429 negotiatedMaxFragLen = buf.getInt(); 430 431 // Get creation time 432 this.creationTime = buf.getLong(); 433 434 // Get Buffer sizes 435 436 // Status Response 437 len = Short.toUnsignedInt(buf.getShort()); 438 if (len == 0) { 439 statusResponses = Collections.emptyList(); 440 } else { 441 statusResponses = new ArrayList<>(); 442 } 443 while (len-- > 0) { 444 b = new byte[Short.toUnsignedInt(buf.getShort())]; 445 buf.get(b); 446 statusResponses.add(b); 447 } 448 449 // Get Peer host & port 450 i = Byte.toUnsignedInt(buf.get()); 451 if (i == 0) { 452 this.host = new String(); 453 } else { 454 b = new byte[i]; 455 this.host = buf.get(b).toString(); 456 } 457 this.port = Short.toUnsignedInt(buf.getShort()); 458 459 // Peer certs 460 i = buf.get(); 461 if (i == 0) { 462 this.peerCerts = null; 463 } else { 464 this.peerCerts = new X509Certificate[i]; 465 int j = 0; 466 while (i > j) { 467 b = new byte[buf.getInt()]; 468 buf.get(b); 469 try { 470 this.peerCerts[j] = new X509CertImpl(b); 471 } catch (Exception e) { 472 throw new IOException(e); 473 } 474 j++; 475 } 476 } 477 478 // Get local certs of PSK 479 switch (buf.get()) { 480 case 0: 481 break; 482 case 1: 483 // number of certs 484 len = buf.get(); 485 this.localCerts = new X509Certificate[len]; 486 i = 0; 487 while (len > i) { 488 b = new byte[buf.getInt()]; 489 buf.get(b); 490 try { 491 this.localCerts[i] = new X509CertImpl(b); 492 } catch (Exception e) { 493 throw new IOException(e); 494 } 495 i++; 496 } 497 break; 498 case 2: 499 // pre-shared key 500 // Length of pre-shared key algorithm (one byte) 501 i = buf.get(); 502 b = new byte[i]; 503 String alg = buf.get(b, 0, i).asCharBuffer().toString(); 504 // Get length of encoding 505 i = Short.toUnsignedInt(buf.getShort()); 506 // Get encoding 507 b = new byte[i]; 508 buf.get(b); 509 this.preSharedKey = new SecretKeySpec(b, alg); 510 // Get identity len 511 this.pskIdentity = new byte[buf.get()]; 512 buf.get(pskIdentity); 513 break; 514 default: 515 throw new SSLException("Failed local certs of session."); 516 } 517 518 context = (SSLSessionContextImpl) 519 hc.sslContext.engineGetServerSessionContext(); 520 this.lastUsedTime = System.currentTimeMillis(); 521 } 522 523 // Some situations we cannot provide a stateless ticket, but after it 524 // has been negotiated isStatelessable(HandshakeContext hc)525 boolean isStatelessable(HandshakeContext hc) { 526 if (!hc.statelessResumption) { 527 return false; 528 } 529 530 // If there is no getMasterSecret with TLS1.2 or under, do not resume. 531 if (!protocolVersion.useTLS13PlusSpec() && 532 getMasterSecret().getEncoded() == null) { 533 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 534 SSLLogger.finest("No MasterSecret, cannot make stateless" + 535 " ticket"); 536 } 537 return false; 538 } 539 if (boundValues != null && boundValues.size() > 0) { 540 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 541 SSLLogger.finest("There are boundValues, cannot make" + 542 " stateless ticket"); 543 } 544 return false; 545 } 546 return true; 547 } 548 549 /** 550 * Write out a SSLSessionImpl in a byte array for a stateless session ticket 551 */ write()552 byte[] write() throws Exception { 553 byte[] b; 554 HandshakeOutStream hos = new HandshakeOutStream(null); 555 556 hos.putInt16(protocolVersion.id); 557 hos.putInt16(cipherSuite.id); 558 559 // Local Supported signature algorithms 560 hos.putInt8(localSupportedSignAlgs.size()); 561 for (SignatureScheme s : localSupportedSignAlgs) { 562 hos.putInt16(s.id); 563 } 564 565 // Peer Supported signature algorithms 566 hos.putInt8(peerSupportedSignAlgs.size()); 567 for (SignatureScheme s : peerSupportedSignAlgs) { 568 hos.putInt16(s.id); 569 } 570 571 // PSK 572 if (preSharedKey == null || 573 preSharedKey.getAlgorithm() == null) { 574 hos.putInt16(0); 575 } else { 576 hos.putInt16(preSharedKey.getAlgorithm().length()); 577 if (preSharedKey.getAlgorithm().length() != 0) { 578 hos.write(preSharedKey.getAlgorithm().getBytes()); 579 } 580 b = preSharedKey.getEncoded(); 581 hos.putInt16(b.length); 582 hos.write(b, 0, b.length); 583 } 584 585 // PSK Identity 586 if (pskIdentity == null) { 587 hos.putInt8(0); 588 } else { 589 hos.putInt8(pskIdentity.length); 590 hos.write(pskIdentity, 0, pskIdentity.length); 591 } 592 593 // Master Secret 594 if (getMasterSecret() == null || 595 getMasterSecret().getAlgorithm() == null) { 596 hos.putInt8(0); 597 } else { 598 hos.putInt8(getMasterSecret().getAlgorithm().length()); 599 if (getMasterSecret().getAlgorithm().length() != 0) { 600 hos.write(getMasterSecret().getAlgorithm().getBytes()); 601 } 602 b = getMasterSecret().getEncoded(); 603 hos.putInt16(b.length); 604 hos.write(b, 0, b.length); 605 } 606 607 hos.putInt8(useExtendedMasterSecret ? 1 : 0); 608 609 // Identification Protocol 610 if (identificationProtocol == null) { 611 hos.putInt8(0); 612 } else { 613 hos.putInt8(identificationProtocol.length()); 614 hos.write(identificationProtocol.getBytes(), 0, 615 identificationProtocol.length()); 616 } 617 618 // SNI 619 if (serverNameIndication == null) { 620 hos.putInt8(0); 621 } else { 622 b = serverNameIndication.getEncoded(); 623 hos.putInt8(b.length); 624 hos.write(b, 0, b.length); 625 } 626 627 // List of SNIServerName 628 hos.putInt16(requestedServerNames.size()); 629 if (requestedServerNames.size() > 0) { 630 for (SNIServerName host : requestedServerNames) { 631 b = host.getEncoded(); 632 hos.putInt8(b.length); 633 hos.write(b, 0, b.length); 634 } 635 } 636 637 // Buffer sizes 638 hos.putInt32(maximumPacketSize); 639 hos.putInt32(negotiatedMaxFragLen); 640 641 // creation time 642 ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); 643 hos.writeBytes(buffer.putLong(creationTime).array()); 644 645 // Status Responses 646 List<byte[]> list = getStatusResponses(); 647 int l = list.size(); 648 hos.putInt16(l); 649 for (byte[] e : list) { 650 hos.putInt16(e.length); 651 hos.write(e); 652 } 653 654 // peer Host & Port 655 if (host == null || host.length() == 0) { 656 hos.putInt8(0); 657 } else { 658 hos.putInt8(host.length()); 659 hos.writeBytes(host.getBytes()); 660 } 661 hos.putInt16(port); 662 663 // Peer cert 664 if (peerCerts == null || peerCerts.length == 0) { 665 hos.putInt8(0); 666 } else { 667 hos.putInt8(peerCerts.length); 668 for (X509Certificate c : peerCerts) { 669 b = c.getEncoded(); 670 hos.putInt32(b.length); 671 hos.writeBytes(b); 672 } 673 } 674 675 // Client identity 676 if (localCerts != null && localCerts.length > 0) { 677 // certificate based 678 hos.putInt8(1); 679 hos.putInt8(localCerts.length); 680 for (X509Certificate c : localCerts) { 681 b = c.getEncoded(); 682 hos.putInt32(b.length); 683 hos.writeBytes(b); 684 } 685 } else if (preSharedKey != null) { 686 // pre-shared key 687 hos.putInt8(2); 688 hos.putInt8(preSharedKey.getAlgorithm().length()); 689 hos.write(preSharedKey.getAlgorithm().getBytes()); 690 b = preSharedKey.getEncoded(); 691 hos.putInt32(b.length); 692 hos.writeBytes(b); 693 hos.putInt32(pskIdentity.length); 694 hos.writeBytes(pskIdentity); 695 } else { 696 // anonymous 697 hos.putInt8(0); 698 } 699 700 return hos.toByteArray(); 701 } 702 setMasterSecret(SecretKey secret)703 void setMasterSecret(SecretKey secret) { 704 masterSecret = secret; 705 } 706 setResumptionMasterSecret(SecretKey secret)707 void setResumptionMasterSecret(SecretKey secret) { 708 resumptionMasterSecret = secret; 709 } 710 setPreSharedKey(SecretKey key)711 void setPreSharedKey(SecretKey key) { 712 preSharedKey = key; 713 } 714 addChild(SSLSessionImpl session)715 void addChild(SSLSessionImpl session) { 716 childSessions.add(session); 717 } 718 setTicketAgeAdd(int ticketAgeAdd)719 void setTicketAgeAdd(int ticketAgeAdd) { 720 this.ticketAgeAdd = ticketAgeAdd; 721 } 722 setPskIdentity(byte[] pskIdentity)723 void setPskIdentity(byte[] pskIdentity) { 724 this.pskIdentity = pskIdentity; 725 } 726 incrTicketNonceCounter()727 BigInteger incrTicketNonceCounter() { 728 BigInteger result = ticketNonceCounter; 729 ticketNonceCounter = ticketNonceCounter.add(BigInteger.ONE); 730 return result; 731 } 732 isPSKable()733 boolean isPSKable() { 734 return (ticketNonceCounter.compareTo(BigInteger.ZERO) > 0); 735 } 736 737 /** 738 * Returns the master secret ... treat with extreme caution! 739 */ getMasterSecret()740 SecretKey getMasterSecret() { 741 return masterSecret; 742 } 743 getResumptionMasterSecret()744 SecretKey getResumptionMasterSecret() { 745 return resumptionMasterSecret; 746 } 747 getPreSharedKey()748 SecretKey getPreSharedKey() { 749 sessionLock.lock(); 750 try { 751 return preSharedKey; 752 } finally { 753 sessionLock.unlock(); 754 } 755 } 756 consumePreSharedKey()757 SecretKey consumePreSharedKey() { 758 sessionLock.lock(); 759 try { 760 return preSharedKey; 761 } finally { 762 preSharedKey = null; 763 sessionLock.unlock(); 764 } 765 } 766 getTicketAgeAdd()767 int getTicketAgeAdd() { 768 return ticketAgeAdd; 769 } 770 getIdentificationProtocol()771 String getIdentificationProtocol() { 772 return this.identificationProtocol; 773 } 774 775 /* PSK identities created from new_session_ticket messages should only 776 * be used once. This method will return the identity and then clear it 777 * so it cannot be used again. 778 */ consumePskIdentity()779 byte[] consumePskIdentity() { 780 sessionLock.lock(); 781 try { 782 return pskIdentity; 783 } finally { 784 pskIdentity = null; 785 sessionLock.unlock(); 786 } 787 } 788 getPskIdentity()789 byte[] getPskIdentity() { 790 return pskIdentity; 791 } 792 setPeerCertificates(X509Certificate[] peer)793 void setPeerCertificates(X509Certificate[] peer) { 794 if (peerCerts == null) { 795 peerCerts = peer; 796 } 797 } 798 setLocalCertificates(X509Certificate[] local)799 void setLocalCertificates(X509Certificate[] local) { 800 localCerts = local; 801 } 802 setLocalPrivateKey(PrivateKey privateKey)803 void setLocalPrivateKey(PrivateKey privateKey) { 804 localPrivateKey = privateKey; 805 } 806 setPeerSupportedSignatureAlgorithms( Collection<SignatureScheme> signatureSchemes)807 void setPeerSupportedSignatureAlgorithms( 808 Collection<SignatureScheme> signatureSchemes) { 809 peerSupportedSignAlgs = signatureSchemes; 810 } 811 812 // TLS 1.2 only 813 // 814 // Per RFC 5246, If the client supports only the default hash 815 // and signature algorithms, it MAY omit the 816 // signature_algorithms extension. If the client does not 817 // support the default algorithms, or supports other hash 818 // and signature algorithms (and it is willing to use them 819 // for verifying messages sent by the server, i.e., server 820 // certificates and server key exchange), it MUST send the 821 // signature_algorithms extension, listing the algorithms it 822 // is willing to accept. 823 private static final ArrayList<SignatureScheme> defaultPeerSupportedSignAlgs = 824 new ArrayList<>(Arrays.asList(SignatureScheme.RSA_PKCS1_SHA1, 825 SignatureScheme.DSA_SHA1, 826 SignatureScheme.ECDSA_SHA1)); 827 setUseDefaultPeerSignAlgs()828 void setUseDefaultPeerSignAlgs() { 829 useDefaultPeerSignAlgs = true; 830 peerSupportedSignAlgs = defaultPeerSupportedSignAlgs; 831 } 832 833 // Returns the connection session. finish()834 SSLSessionImpl finish() { 835 if (useDefaultPeerSignAlgs) { 836 peerSupportedSignAlgs = Collections.emptySet(); 837 } 838 839 return this; 840 } 841 842 /** 843 * Provide status response data obtained during the SSL handshake. 844 * 845 * @param responses a {@link List} of responses in binary form. 846 */ setStatusResponses(List<byte[]> responses)847 void setStatusResponses(List<byte[]> responses) { 848 if (responses != null && !responses.isEmpty()) { 849 statusResponses = responses; 850 } else { 851 statusResponses = Collections.emptyList(); 852 } 853 } 854 855 /** 856 * Returns true iff this session may be resumed ... sessions are 857 * usually resumable. Security policies may suggest otherwise, 858 * for example sessions that haven't been used for a while (say, 859 * a working day) won't be resumable, and sessions might have a 860 * maximum lifetime in any case. 861 */ isRejoinable()862 boolean isRejoinable() { 863 // TLS 1.3 can have no session id 864 if (protocolVersion.useTLS13PlusSpec()) { 865 return (!invalidated && isLocalAuthenticationValid()); 866 } 867 return sessionId != null && sessionId.length() != 0 && 868 !invalidated && isLocalAuthenticationValid(); 869 } 870 871 @Override isValid()872 public boolean isValid() { 873 sessionLock.lock(); 874 try { 875 return isRejoinable(); 876 } finally { 877 sessionLock.unlock(); 878 } 879 } 880 881 /** 882 * Check if the authentication used when establishing this session 883 * is still valid. Returns true if no authentication was used 884 */ isLocalAuthenticationValid()885 private boolean isLocalAuthenticationValid() { 886 if (localPrivateKey != null) { 887 try { 888 // if the private key is no longer valid, getAlgorithm() 889 // should throw an exception 890 // (e.g. Smartcard has been removed from the reader) 891 localPrivateKey.getAlgorithm(); 892 } catch (Exception e) { 893 invalidate(); 894 return false; 895 } 896 } 897 898 return true; 899 } 900 901 /** 902 * Returns the ID for this session. The ID is fixed for the 903 * duration of the session; neither it, nor its value, changes. 904 */ 905 @Override getId()906 public byte[] getId() { 907 return sessionId.getId(); 908 } 909 910 /** 911 * For server sessions, this returns the set of sessions which 912 * are currently valid in this process. For client sessions, 913 * this returns null. 914 */ 915 @Override getSessionContext()916 public SSLSessionContext getSessionContext() { 917 /* 918 * An interim security policy until we can do something 919 * more specific in 1.2. Only allow trusted code (code which 920 * can set system properties) to get an 921 * SSLSessionContext. This is to limit the ability of code to 922 * look up specific sessions or enumerate over them. Otherwise, 923 * code can only get session objects from successful SSL 924 * connections which implies that they must have had permission 925 * to make the network connection in the first place. 926 */ 927 SecurityManager sm; 928 if ((sm = System.getSecurityManager()) != null) { 929 sm.checkPermission(new SSLPermission("getSSLSessionContext")); 930 } 931 932 return context; 933 } 934 935 getSessionId()936 SessionId getSessionId() { 937 return sessionId; 938 } 939 940 941 /** 942 * Returns the cipher spec in use on this session 943 */ getSuite()944 CipherSuite getSuite() { 945 return cipherSuite; 946 } 947 948 /** 949 * Resets the cipher spec in use on this session 950 */ setSuite(CipherSuite suite)951 void setSuite(CipherSuite suite) { 952 cipherSuite = suite; 953 954 if (SSLLogger.isOn && SSLLogger.isOn("session")) { 955 SSLLogger.finest("Negotiating session: " + this); 956 } 957 } 958 959 /** 960 * Return true if the session is currently re-established with a 961 * session-resumption abbreviated initial handshake. 962 */ isSessionResumption()963 boolean isSessionResumption() { 964 return isSessionResumption; 965 } 966 967 /** 968 * Resets whether the session is re-established with a session-resumption 969 * abbreviated initial handshake. 970 */ setAsSessionResumption(boolean flag)971 void setAsSessionResumption(boolean flag) { 972 isSessionResumption = flag; 973 } 974 975 /** 976 * Returns the name of the cipher suite in use on this session 977 */ 978 @Override getCipherSuite()979 public String getCipherSuite() { 980 return getSuite().name; 981 } 982 getProtocolVersion()983 ProtocolVersion getProtocolVersion() { 984 return protocolVersion; 985 } 986 987 /** 988 * Returns the standard name of the protocol in use on this session 989 */ 990 @Override getProtocol()991 public String getProtocol() { 992 return getProtocolVersion().name; 993 } 994 995 /** 996 * Returns the hashcode for this session 997 */ 998 @Override hashCode()999 public int hashCode() { 1000 return sessionId.hashCode(); 1001 } 1002 1003 /** 1004 * Returns true if sessions have same ids, false otherwise. 1005 */ 1006 @Override equals(Object obj)1007 public boolean equals(Object obj) { 1008 1009 if (obj == this) { 1010 return true; 1011 } 1012 1013 if (obj instanceof SSLSessionImpl) { 1014 SSLSessionImpl sess = (SSLSessionImpl) obj; 1015 return (sessionId != null) && (sessionId.equals( 1016 sess.getSessionId())); 1017 } 1018 1019 return false; 1020 } 1021 1022 1023 /** 1024 * Return the cert chain presented by the peer in the 1025 * java.security.cert format. 1026 * Note: This method can be used only when using certificate-based 1027 * cipher suites; using it with non-certificate-based cipher suites 1028 * will throw an SSLPeerUnverifiedException. 1029 * 1030 * @return array of peer X.509 certs, with the peer's own cert 1031 * first in the chain, and with the "root" CA last. 1032 */ 1033 @Override getPeerCertificates()1034 public java.security.cert.Certificate[] getPeerCertificates() 1035 throws SSLPeerUnverifiedException { 1036 // 1037 // clone to preserve integrity of session ... caller can't 1038 // change record of peer identity even by accident, much 1039 // less do it intentionally. 1040 // 1041 if (peerCerts == null) { 1042 throw new SSLPeerUnverifiedException("peer not authenticated"); 1043 } 1044 // Certs are immutable objects, therefore we don't clone them. 1045 // But do need to clone the array, so that nothing is inserted 1046 // into peerCerts. 1047 return (java.security.cert.Certificate[])peerCerts.clone(); 1048 } 1049 1050 /** 1051 * Return the cert chain presented to the peer in the 1052 * java.security.cert format. 1053 * Note: This method is useful only when using certificate-based 1054 * cipher suites. 1055 * 1056 * @return array of peer X.509 certs, with the peer's own cert 1057 * first in the chain, and with the "root" CA last. 1058 */ 1059 @Override getLocalCertificates()1060 public java.security.cert.Certificate[] getLocalCertificates() { 1061 // 1062 // clone to preserve integrity of session ... caller can't 1063 // change record of peer identity even by accident, much 1064 // less do it intentionally. 1065 return (localCerts == null ? null : 1066 (java.security.cert.Certificate[])localCerts.clone()); 1067 } 1068 1069 /** 1070 * Return the cert chain presented by the peer in the 1071 * javax.security.cert format. 1072 * Note: This method can be used only when using certificate-based 1073 * cipher suites; using it with non-certificate-based cipher suites 1074 * will throw an SSLPeerUnverifiedException. 1075 * 1076 * @return array of peer X.509 certs, with the peer's own cert 1077 * first in the chain, and with the "root" CA last. 1078 * 1079 * @deprecated This method returns the deprecated 1080 * {@code javax.security.cert.X509Certificate} type. 1081 * Use {@code getPeerCertificates()} instead. 1082 */ 1083 @Override 1084 @SuppressWarnings("removal") 1085 @Deprecated(since="9", forRemoval=true) getPeerCertificateChain()1086 public javax.security.cert.X509Certificate[] getPeerCertificateChain() 1087 throws SSLPeerUnverifiedException { 1088 // 1089 // clone to preserve integrity of session ... caller can't 1090 // change record of peer identity even by accident, much 1091 // less do it intentionally. 1092 // 1093 if (peerCerts == null) { 1094 throw new SSLPeerUnverifiedException("peer not authenticated"); 1095 } 1096 javax.security.cert.X509Certificate[] certs; 1097 certs = new javax.security.cert.X509Certificate[peerCerts.length]; 1098 for (int i = 0; i < peerCerts.length; i++) { 1099 byte[] der = null; 1100 try { 1101 der = peerCerts[i].getEncoded(); 1102 certs[i] = javax.security.cert.X509Certificate.getInstance(der); 1103 } catch (CertificateEncodingException e) { 1104 throw new SSLPeerUnverifiedException(e.getMessage()); 1105 } catch (javax.security.cert.CertificateException e) { 1106 throw new SSLPeerUnverifiedException(e.getMessage()); 1107 } 1108 } 1109 1110 return certs; 1111 } 1112 1113 /** 1114 * Return the cert chain presented by the peer. 1115 * Note: This method can be used only when using certificate-based 1116 * cipher suites; using it with non-certificate-based cipher suites 1117 * will throw an SSLPeerUnverifiedException. 1118 * 1119 * @return array of peer X.509 certs, with the peer's own cert 1120 * first in the chain, and with the "root" CA last. 1121 */ getCertificateChain()1122 public X509Certificate[] getCertificateChain() 1123 throws SSLPeerUnverifiedException { 1124 /* 1125 * clone to preserve integrity of session ... caller can't 1126 * change record of peer identity even by accident, much 1127 * less do it intentionally. 1128 */ 1129 if (peerCerts != null) { 1130 return peerCerts.clone(); 1131 } else { 1132 throw new SSLPeerUnverifiedException("peer not authenticated"); 1133 } 1134 } 1135 1136 /** 1137 * Return a List of status responses presented by the peer. 1138 * Note: This method can be used only when using certificate-based 1139 * server authentication; otherwise an empty {@code List} will be returned. 1140 * 1141 * @return an unmodifiable {@code List} of byte arrays, each consisting 1142 * of a DER-encoded OCSP response (see RFC 6960). If no responses have 1143 * been presented by the server or non-certificate based server 1144 * authentication is used then an empty {@code List} is returned. 1145 */ 1146 @Override getStatusResponses()1147 public List<byte[]> getStatusResponses() { 1148 if (statusResponses == null || statusResponses.isEmpty()) { 1149 return Collections.emptyList(); 1150 } else { 1151 // Clone both the list and the contents 1152 List<byte[]> responses = new ArrayList<>(statusResponses.size()); 1153 for (byte[] respBytes : statusResponses) { 1154 responses.add(respBytes.clone()); 1155 } 1156 return Collections.unmodifiableList(responses); 1157 } 1158 } 1159 1160 /** 1161 * Returns the identity of the peer which was established as part of 1162 * defining the session. 1163 * 1164 * @return the peer's principal. Returns an X500Principal of the 1165 * end-entity certificate for X509-based cipher suites. 1166 * 1167 * @throws SSLPeerUnverifiedException if the peer's identity has not 1168 * been verified 1169 */ 1170 @Override getPeerPrincipal()1171 public Principal getPeerPrincipal() 1172 throws SSLPeerUnverifiedException 1173 { 1174 if (peerCerts == null) { 1175 throw new SSLPeerUnverifiedException("peer not authenticated"); 1176 } 1177 return peerCerts[0].getSubjectX500Principal(); 1178 } 1179 1180 /** 1181 * Returns the principal that was sent to the peer during handshaking. 1182 * 1183 * @return the principal sent to the peer. Returns an X500Principal 1184 * of the end-entity certificate for X509-based cipher suites. 1185 * If no principal was sent, then null is returned. 1186 */ 1187 @Override getLocalPrincipal()1188 public Principal getLocalPrincipal() { 1189 return ((localCerts == null || localCerts.length == 0) ? null : 1190 localCerts[0].getSubjectX500Principal()); 1191 } 1192 1193 /* 1194 * Return the time the ticket for this session was created. 1195 */ getTicketCreationTime()1196 public long getTicketCreationTime() { 1197 return ticketCreationTime; 1198 } 1199 1200 /** 1201 * Returns the time this session was created. 1202 */ 1203 @Override getCreationTime()1204 public long getCreationTime() { 1205 return creationTime; 1206 } 1207 1208 /** 1209 * Returns the last time this session was used to initialize 1210 * a connection. 1211 */ 1212 @Override getLastAccessedTime()1213 public long getLastAccessedTime() { 1214 return (lastUsedTime != 0) ? lastUsedTime : creationTime; 1215 } 1216 setLastAccessedTime(long time)1217 void setLastAccessedTime(long time) { 1218 lastUsedTime = time; 1219 } 1220 1221 1222 /** 1223 * Returns the network address of the session's peer. This 1224 * implementation does not insist that connections between 1225 * different ports on the same host must necessarily belong 1226 * to different sessions, though that is of course allowed. 1227 */ getPeerAddress()1228 public InetAddress getPeerAddress() { 1229 try { 1230 return InetAddress.getByName(host); 1231 } catch (java.net.UnknownHostException e) { 1232 return null; 1233 } 1234 } 1235 1236 @Override getPeerHost()1237 public String getPeerHost() { 1238 return host; 1239 } 1240 1241 /** 1242 * Need to provide the port info for caching sessions based on 1243 * host and port. Accessed by SSLSessionContextImpl 1244 */ 1245 @Override getPeerPort()1246 public int getPeerPort() { 1247 return port; 1248 } 1249 setContext(SSLSessionContextImpl ctx)1250 void setContext(SSLSessionContextImpl ctx) { 1251 if (context == null) { 1252 context = ctx; 1253 } 1254 } 1255 1256 /** 1257 * Invalidate a session. Active connections may still exist, but 1258 * no connections will be able to rejoin this session. 1259 */ 1260 @Override invalidate()1261 public void invalidate() { 1262 sessionLock.lock(); 1263 try { 1264 if (context != null) { 1265 context.remove(sessionId); 1266 context = null; 1267 } 1268 1269 if (invalidated) { 1270 return; 1271 } 1272 invalidated = true; 1273 if (SSLLogger.isOn && SSLLogger.isOn("session")) { 1274 SSLLogger.finest("Invalidated session: " + this); 1275 } 1276 for (SSLSessionImpl child : childSessions) { 1277 child.invalidate(); 1278 } 1279 } finally { 1280 sessionLock.unlock(); 1281 } 1282 } 1283 1284 /* 1285 * Table of application-specific session data indexed by an application 1286 * key and the calling security context. This is important since 1287 * sessions can be shared across different protection domains. 1288 */ 1289 private final ConcurrentHashMap<SecureKey, Object> boundValues; 1290 boolean updateNST; 1291 1292 /** 1293 * Assigns a session value. Session change events are given if 1294 * appropriate, to any original value as well as the new value. 1295 */ 1296 @Override putValue(String key, Object value)1297 public void putValue(String key, Object value) { 1298 if ((key == null) || (value == null)) { 1299 throw new IllegalArgumentException("arguments can not be null"); 1300 } 1301 1302 SecureKey secureKey = new SecureKey(key); 1303 Object oldValue = boundValues.put(secureKey, value); 1304 1305 if (oldValue instanceof SSLSessionBindingListener) { 1306 SSLSessionBindingEvent e; 1307 1308 e = new SSLSessionBindingEvent(this, key); 1309 ((SSLSessionBindingListener)oldValue).valueUnbound(e); 1310 } 1311 if (value instanceof SSLSessionBindingListener) { 1312 SSLSessionBindingEvent e; 1313 1314 e = new SSLSessionBindingEvent(this, key); 1315 ((SSLSessionBindingListener)value).valueBound(e); 1316 } 1317 if (protocolVersion.useTLS13PlusSpec()) { 1318 updateNST = true; 1319 } 1320 } 1321 1322 /** 1323 * Returns the specified session value. 1324 */ 1325 @Override getValue(String key)1326 public Object getValue(String key) { 1327 if (key == null) { 1328 throw new IllegalArgumentException("argument can not be null"); 1329 } 1330 1331 SecureKey secureKey = new SecureKey(key); 1332 return boundValues.get(secureKey); 1333 } 1334 1335 1336 /** 1337 * Removes the specified session value, delivering a session changed 1338 * event as appropriate. 1339 */ 1340 @Override removeValue(String key)1341 public void removeValue(String key) { 1342 if (key == null) { 1343 throw new IllegalArgumentException("argument can not be null"); 1344 } 1345 1346 SecureKey secureKey = new SecureKey(key); 1347 Object value = boundValues.remove(secureKey); 1348 1349 if (value instanceof SSLSessionBindingListener) { 1350 SSLSessionBindingEvent e; 1351 1352 e = new SSLSessionBindingEvent(this, key); 1353 ((SSLSessionBindingListener)value).valueUnbound(e); 1354 } 1355 if (protocolVersion.useTLS13PlusSpec()) { 1356 updateNST = true; 1357 } 1358 } 1359 1360 1361 /** 1362 * Lists the names of the session values. 1363 */ 1364 @Override getValueNames()1365 public String[] getValueNames() { 1366 ArrayList<Object> v = new ArrayList<>(); 1367 Object securityCtx = SecureKey.getCurrentSecurityContext(); 1368 for (Enumeration<SecureKey> e = boundValues.keys(); 1369 e.hasMoreElements(); ) { 1370 SecureKey key = e.nextElement(); 1371 if (securityCtx.equals(key.getSecurityContext())) { 1372 v.add(key.getAppKey()); 1373 } 1374 } 1375 1376 return v.toArray(new String[0]); 1377 } 1378 1379 /** 1380 * Use large packet sizes now or follow RFC 2246 packet sizes (2^14) 1381 * until changed. 1382 * 1383 * In the TLS specification (section 6.2.1, RFC2246), it is not 1384 * recommended that the plaintext has more than 2^14 bytes. 1385 * However, some TLS implementations violate the specification. 1386 * This is a workaround for interoperability with these stacks. 1387 * 1388 * Application could accept large fragments up to 2^15 bytes by 1389 * setting the system property jsse.SSLEngine.acceptLargeFragments 1390 * to "true". 1391 */ 1392 private boolean acceptLargeFragments = 1393 Utilities.getBooleanProperty( 1394 "jsse.SSLEngine.acceptLargeFragments", false); 1395 1396 /** 1397 * Expand the buffer size of both SSL/TLS network packet and 1398 * application data. 1399 */ expandBufferSizes()1400 protected void expandBufferSizes() { 1401 sessionLock.lock(); 1402 try { 1403 acceptLargeFragments = true; 1404 } finally { 1405 sessionLock.unlock(); 1406 } 1407 } 1408 1409 /** 1410 * Gets the current size of the largest SSL/TLS packet that is expected 1411 * when using this session. 1412 */ 1413 @Override getPacketBufferSize()1414 public int getPacketBufferSize() { 1415 sessionLock.lock(); 1416 try { 1417 // Use the bigger packet size calculated from maximumPacketSize 1418 // and negotiatedMaxFragLen. 1419 int packetSize = 0; 1420 if (negotiatedMaxFragLen > 0) { 1421 packetSize = cipherSuite.calculatePacketSize( 1422 negotiatedMaxFragLen, protocolVersion, 1423 protocolVersion.isDTLS); 1424 } 1425 1426 if (maximumPacketSize > 0) { 1427 return (maximumPacketSize > packetSize) ? 1428 maximumPacketSize : packetSize; 1429 } 1430 1431 if (packetSize != 0) { 1432 return packetSize; 1433 } 1434 1435 if (protocolVersion.isDTLS) { 1436 return DTLSRecord.maxRecordSize; 1437 } else { 1438 return acceptLargeFragments ? 1439 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; 1440 } 1441 } finally { 1442 sessionLock.unlock(); 1443 } 1444 } 1445 1446 /** 1447 * Gets the current size of the largest application data that is 1448 * expected when using this session. 1449 */ 1450 @Override getApplicationBufferSize()1451 public int getApplicationBufferSize() { 1452 sessionLock.lock(); 1453 try { 1454 // Use the bigger fragment size calculated from maximumPacketSize 1455 // and negotiatedMaxFragLen. 1456 int fragmentSize = 0; 1457 if (maximumPacketSize > 0) { 1458 fragmentSize = cipherSuite.calculateFragSize( 1459 maximumPacketSize, protocolVersion, 1460 protocolVersion.isDTLS); 1461 } 1462 1463 if (negotiatedMaxFragLen > 0) { 1464 return (negotiatedMaxFragLen > fragmentSize) ? 1465 negotiatedMaxFragLen : fragmentSize; 1466 } 1467 1468 if (fragmentSize != 0) { 1469 return fragmentSize; 1470 } 1471 1472 if (protocolVersion.isDTLS) { 1473 return Record.maxDataSize; 1474 } else { 1475 int maxPacketSize = acceptLargeFragments ? 1476 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; 1477 return (maxPacketSize - SSLRecord.headerSize); 1478 } 1479 } finally { 1480 sessionLock.unlock(); 1481 } 1482 } 1483 1484 /** 1485 * Sets the negotiated maximum fragment length, as specified by the 1486 * max_fragment_length ClientHello extension in RFC 6066. 1487 * 1488 * @param negotiatedMaxFragLen 1489 * the negotiated maximum fragment length, or {@code -1} if 1490 * no such length has been negotiated. 1491 */ setNegotiatedMaxFragSize( int negotiatedMaxFragLen)1492 void setNegotiatedMaxFragSize( 1493 int negotiatedMaxFragLen) { 1494 sessionLock.lock(); 1495 try { 1496 this.negotiatedMaxFragLen = negotiatedMaxFragLen; 1497 } finally { 1498 sessionLock.unlock(); 1499 } 1500 } 1501 1502 /** 1503 * Get the negotiated maximum fragment length, as specified by the 1504 * max_fragment_length ClientHello extension in RFC 6066. 1505 * 1506 * @return the negotiated maximum fragment length, or {@code -1} if 1507 * no such length has been negotiated. 1508 */ getNegotiatedMaxFragSize()1509 int getNegotiatedMaxFragSize() { 1510 sessionLock.lock(); 1511 try { 1512 return negotiatedMaxFragLen; 1513 } finally { 1514 sessionLock.unlock(); 1515 } 1516 } 1517 setMaximumPacketSize(int maximumPacketSize)1518 void setMaximumPacketSize(int maximumPacketSize) { 1519 sessionLock.lock(); 1520 try { 1521 this.maximumPacketSize = maximumPacketSize; 1522 } finally { 1523 sessionLock.unlock(); 1524 } 1525 } 1526 getMaximumPacketSize()1527 int getMaximumPacketSize() { 1528 sessionLock.lock(); 1529 try { 1530 return maximumPacketSize; 1531 } finally { 1532 sessionLock.unlock(); 1533 } 1534 } 1535 1536 /** 1537 * Gets an array of supported signature algorithm names that the local 1538 * side is willing to verify. 1539 */ 1540 @Override getLocalSupportedSignatureAlgorithms()1541 public String[] getLocalSupportedSignatureAlgorithms() { 1542 return SignatureScheme.getAlgorithmNames(localSupportedSignAlgs); 1543 } 1544 1545 /** 1546 * Gets an array of supported signature schemes that the local side is 1547 * willing to verify. 1548 */ getLocalSupportedSignatureSchemes()1549 public Collection<SignatureScheme> getLocalSupportedSignatureSchemes() { 1550 return localSupportedSignAlgs; 1551 } 1552 1553 /** 1554 * Gets an array of supported signature algorithms that the peer is 1555 * able to verify. 1556 */ 1557 @Override getPeerSupportedSignatureAlgorithms()1558 public String[] getPeerSupportedSignatureAlgorithms() { 1559 return SignatureScheme.getAlgorithmNames(peerSupportedSignAlgs); 1560 } 1561 1562 /** 1563 * Obtains a <code>List</code> containing all {@link SNIServerName}s 1564 * of the requested Server Name Indication (SNI) extension. 1565 */ 1566 @Override getRequestedServerNames()1567 public List<SNIServerName> getRequestedServerNames() { 1568 return requestedServerNames; 1569 } 1570 1571 /** Returns a string representation of this SSL session */ 1572 @Override toString()1573 public String toString() { 1574 return "Session(" + creationTime + "|" + getCipherSuite() + ")"; 1575 } 1576 } 1577 1578 /** 1579 * This "struct" class serves as a Hash Key that combines an 1580 * application-specific key and a security context. 1581 */ 1582 class SecureKey { 1583 private static final Object nullObject = new Object(); 1584 private final Object appKey; 1585 private final Object securityCtx; 1586 getCurrentSecurityContext()1587 static Object getCurrentSecurityContext() { 1588 SecurityManager sm = System.getSecurityManager(); 1589 Object context = null; 1590 1591 if (sm != null) 1592 context = sm.getSecurityContext(); 1593 if (context == null) 1594 context = nullObject; 1595 return context; 1596 } 1597 SecureKey(Object key)1598 SecureKey(Object key) { 1599 this.appKey = key; 1600 this.securityCtx = getCurrentSecurityContext(); 1601 } 1602 getAppKey()1603 Object getAppKey() { 1604 return appKey; 1605 } 1606 getSecurityContext()1607 Object getSecurityContext() { 1608 return securityCtx; 1609 } 1610 1611 @Override hashCode()1612 public int hashCode() { 1613 return appKey.hashCode() ^ securityCtx.hashCode(); 1614 } 1615 1616 @Override equals(Object o)1617 public boolean equals(Object o) { 1618 return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey) 1619 && ((SecureKey)o).securityCtx.equals(securityCtx); 1620 } 1621 } 1622