1 /* 2 * Copyright (c) 2003, 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 26 package sun.security.ssl; 27 28 import java.io.IOException; 29 import java.nio.ByteBuffer; 30 import java.nio.ReadOnlyBufferException; 31 import java.security.AccessController; 32 import java.security.PrivilegedActionException; 33 import java.security.PrivilegedExceptionAction; 34 import java.util.List; 35 import java.util.Map; 36 import java.util.function.BiFunction; 37 import javax.net.ssl.SSLEngine; 38 import javax.net.ssl.SSLEngineResult; 39 import javax.net.ssl.SSLEngineResult.HandshakeStatus; 40 import javax.net.ssl.SSLEngineResult.Status; 41 import javax.net.ssl.SSLException; 42 import javax.net.ssl.SSLHandshakeException; 43 import javax.net.ssl.SSLKeyException; 44 import javax.net.ssl.SSLParameters; 45 import javax.net.ssl.SSLPeerUnverifiedException; 46 import javax.net.ssl.SSLProtocolException; 47 import javax.net.ssl.SSLSession; 48 49 /** 50 * Implementation of an non-blocking SSLEngine. 51 * 52 * @author Brad Wetmore 53 */ 54 final class SSLEngineImpl extends SSLEngine implements SSLTransport { 55 private final SSLContextImpl sslContext; 56 final TransportContext conContext; 57 58 /** 59 * Constructor for an SSLEngine from SSLContext, without 60 * host/port hints. 61 * 62 * This Engine will not be able to cache sessions, but must renegotiate 63 * everything by hand. 64 */ 65 SSLEngineImpl(SSLContextImpl sslContext) { 66 this(sslContext, null, -1); 67 } 68 69 /** 70 * Constructor for an SSLEngine from SSLContext. 71 */ 72 SSLEngineImpl(SSLContextImpl sslContext, 73 String host, int port) { 74 super(host, port); 75 this.sslContext = sslContext; 76 HandshakeHash handshakeHash = new HandshakeHash(); 77 if (sslContext.isDTLS()) { 78 this.conContext = new TransportContext(sslContext, this, 79 new DTLSInputRecord(handshakeHash), 80 new DTLSOutputRecord(handshakeHash)); 81 } else { 82 this.conContext = new TransportContext(sslContext, this, 83 new SSLEngineInputRecord(handshakeHash), 84 new SSLEngineOutputRecord(handshakeHash)); 85 } 86 87 // Server name indication is a connection scope extension. 88 if (host != null) { 89 this.conContext.sslConfig.serverNames = 90 Utilities.addToSNIServerNameList( 91 conContext.sslConfig.serverNames, host); 92 } 93 } 94 95 @Override 96 public synchronized void beginHandshake() throws SSLException { 97 if (conContext.isUnsureMode) { 98 throw new IllegalStateException( 99 "Client/Server mode has not yet been set."); 100 } 101 102 try { 103 conContext.kickstart(); 104 } catch (IOException ioe) { 105 conContext.fatal(Alert.HANDSHAKE_FAILURE, 106 "Couldn't kickstart handshaking", ioe); 107 } catch (Exception ex) { // including RuntimeException 108 conContext.fatal(Alert.INTERNAL_ERROR, 109 "Fail to begin handshake", ex); 110 } 111 } 112 113 @Override 114 public synchronized SSLEngineResult wrap(ByteBuffer[] appData, 115 int offset, int length, ByteBuffer netData) throws SSLException { 116 return wrap( 117 appData, offset, length, new ByteBuffer[]{ netData }, 0, 1); 118 } 119 120 // @Override 121 public synchronized SSLEngineResult wrap( 122 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 123 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException { 124 125 if (conContext.isUnsureMode) { 126 throw new IllegalStateException( 127 "Client/Server mode has not yet been set."); 128 } 129 130 // See if the handshaker needs to report back some SSLException. 131 if (conContext.outputRecord.isEmpty()) { 132 checkTaskThrown(); 133 } // Otherwise, deliver cached records before throwing task exception. 134 135 // check parameters 136 checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 137 138 try { 139 return writeRecord( 140 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 141 } catch (SSLProtocolException spe) { 142 // may be an unexpected handshake message 143 conContext.fatal(Alert.UNEXPECTED_MESSAGE, spe); 144 } catch (IOException ioe) { 145 conContext.fatal(Alert.INTERNAL_ERROR, 146 "problem wrapping app data", ioe); 147 } catch (Exception ex) { // including RuntimeException 148 conContext.fatal(Alert.INTERNAL_ERROR, 149 "Fail to wrap application data", ex); 150 } 151 152 return null; // make compiler happy 153 } 154 155 private SSLEngineResult writeRecord( 156 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 157 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 158 159 if (isOutboundDone()) { 160 return new SSLEngineResult( 161 Status.CLOSED, getHandshakeStatus(), 0, 0); 162 } 163 164 HandshakeContext hc = conContext.handshakeContext; 165 HandshakeStatus hsStatus = null; 166 if (!conContext.isNegotiated) { 167 conContext.kickstart(); 168 169 hsStatus = getHandshakeStatus(); 170 if (hsStatus == HandshakeStatus.NEED_UNWRAP) { 171 /* 172 * For DTLS, if the handshake state is 173 * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap() 174 * means that the previous handshake packets (if delivered) 175 * get lost, and need retransmit the handshake messages. 176 */ 177 if (!sslContext.isDTLS() || hc == null || 178 !hc.sslConfig.enableRetransmissions || 179 conContext.outputRecord.firstMessage) { 180 181 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); 182 } // otherwise, need retransmission 183 } 184 } 185 186 if (hsStatus == null) { 187 hsStatus = getHandshakeStatus(); 188 } 189 190 /* 191 * If we have a task outstanding, this *MUST* be done before 192 * doing any more wrapping, because we could be in the middle 193 * of receiving a handshake message, for example, a finished 194 * message which would change the ciphers. 195 */ 196 if (hsStatus == HandshakeStatus.NEED_TASK) { 197 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); 198 } 199 200 int dstsRemains = 0; 201 for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) { 202 dstsRemains += dsts[i].remaining(); 203 } 204 205 // Check destination buffer size. 206 // 207 // We can be smarter about using smaller buffer sizes later. For 208 // now, force it to be large enough to handle any valid record. 209 if (dstsRemains < conContext.conSession.getPacketBufferSize()) { 210 return new SSLEngineResult( 211 Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0); 212 } 213 214 int srcsRemains = 0; 215 for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) { 216 srcsRemains += srcs[i].remaining(); 217 } 218 219 Ciphertext ciphertext = null; 220 try { 221 // Acquire the buffered to-be-delivered records or retransmissions. 222 // 223 // May have buffered records, or need retransmission if handshaking. 224 if (!conContext.outputRecord.isEmpty() || (hc != null && 225 hc.sslConfig.enableRetransmissions && 226 hc.sslContext.isDTLS() && 227 hsStatus == HandshakeStatus.NEED_UNWRAP)) { 228 ciphertext = encode(null, 0, 0, 229 dsts, dstsOffset, dstsLength); 230 } 231 232 if (ciphertext == null && srcsRemains != 0) { 233 ciphertext = encode(srcs, srcsOffset, srcsLength, 234 dsts, dstsOffset, dstsLength); 235 } 236 } catch (IOException ioe) { 237 if (ioe instanceof SSLException) { 238 throw ioe; 239 } else { 240 throw new SSLException("Write problems", ioe); 241 } 242 } 243 244 /* 245 * Check for status. 246 */ 247 Status status = (isOutboundDone() ? Status.CLOSED : Status.OK); 248 if (ciphertext != null && ciphertext.handshakeStatus != null) { 249 hsStatus = ciphertext.handshakeStatus; 250 } else { 251 hsStatus = getHandshakeStatus(); 252 } 253 254 int deltaSrcs = srcsRemains; 255 for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) { 256 deltaSrcs -= srcs[i].remaining(); 257 } 258 259 int deltaDsts = dstsRemains; 260 for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) { 261 deltaDsts -= dsts[i].remaining(); 262 } 263 264 return new SSLEngineResult(status, hsStatus, deltaSrcs, deltaDsts, 265 ciphertext != null ? ciphertext.recordSN : -1L); 266 } 267 268 private Ciphertext encode( 269 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 270 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 271 272 Ciphertext ciphertext = null; 273 try { 274 ciphertext = conContext.outputRecord.encode( 275 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 276 } catch (SSLHandshakeException she) { 277 // may be record sequence number overflow 278 conContext.fatal(Alert.HANDSHAKE_FAILURE, she); 279 } catch (IOException e) { 280 conContext.fatal(Alert.UNEXPECTED_MESSAGE, e); 281 } 282 283 if (ciphertext == null) { 284 return Ciphertext.CIPHERTEXT_NULL; 285 } 286 287 // Is the handshake completed? 288 boolean needRetransmission = 289 conContext.sslContext.isDTLS() && 290 conContext.handshakeContext != null && 291 conContext.handshakeContext.sslConfig.enableRetransmissions; 292 HandshakeStatus hsStatus = 293 tryToFinishHandshake(ciphertext.contentType); 294 if (needRetransmission && 295 hsStatus == HandshakeStatus.FINISHED && 296 conContext.sslContext.isDTLS() && 297 ciphertext.handshakeType == SSLHandshake.FINISHED.id) { 298 // Retransmit the last flight for DTLS. 299 // 300 // The application data transactions may begin immediately 301 // after the last flight. If the last flight get lost, the 302 // application data may be discarded accordingly. As could 303 // be an issue for some applications. This impact can be 304 // mitigated by sending the last fligth twice. 305 if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) { 306 SSLLogger.finest("retransmit the last flight messages"); 307 } 308 309 conContext.outputRecord.launchRetransmission(); 310 hsStatus = HandshakeStatus.NEED_WRAP; 311 } 312 313 if (hsStatus == null) { 314 hsStatus = conContext.getHandshakeStatus(); 315 } 316 317 // Is the sequence number is nearly overflow? 318 if (conContext.outputRecord.seqNumIsHuge()) { 319 hsStatus = tryKeyUpdate(hsStatus); 320 } 321 322 // update context status 323 ciphertext.handshakeStatus = hsStatus; 324 325 return ciphertext; 326 } 327 328 private HandshakeStatus tryToFinishHandshake(byte contentType) { 329 HandshakeStatus hsStatus = null; 330 if ((contentType == ContentType.HANDSHAKE.id) && 331 conContext.outputRecord.isEmpty()) { 332 if (conContext.handshakeContext == null) { 333 hsStatus = HandshakeStatus.FINISHED; 334 } else if (conContext.handshakeContext.handshakeFinished) { 335 hsStatus = conContext.finishHandshake(); 336 } 337 } // Otherwise, the followed call to getHSStatus() will help. 338 339 return hsStatus; 340 } 341 342 /** 343 * Try renegotiation or key update for sequence number wrap. 344 * 345 * Note that in order to maintain the handshake status properly, we check 346 * the sequence number after the last record reading/writing process. As 347 * we request renegotiation or close the connection for wrapped sequence 348 * number when there is enough sequence number space left to handle a few 349 * more records, so the sequence number of the last record cannot be 350 * wrapped. 351 */ 352 private HandshakeStatus tryKeyUpdate( 353 HandshakeStatus currentHandshakeStatus) throws IOException { 354 // Don't bother to kickstart the renegotiation or key update when the 355 // local is asking for it. 356 if ((conContext.handshakeContext == null) && 357 !conContext.isClosed() && !conContext.isBroken) { 358 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 359 SSLLogger.finest("key update to wrap sequence number"); 360 } 361 conContext.keyUpdate(); 362 return conContext.getHandshakeStatus(); 363 } 364 365 return currentHandshakeStatus; 366 } 367 368 private static void checkParams( 369 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 370 ByteBuffer[] dsts, int dstsOffset, int dstsLength) { 371 372 if ((srcs == null) || (dsts == null)) { 373 throw new IllegalArgumentException( 374 "source or destination buffer is null"); 375 } 376 377 if ((srcsOffset < 0) || (srcsLength < 0) || 378 (srcsOffset > srcs.length - srcsLength)) { 379 throw new IndexOutOfBoundsException( 380 "index out of bound of the source buffers"); 381 } 382 383 if ((dstsOffset < 0) || (dstsLength < 0) || 384 (dstsOffset > dsts.length - dstsLength)) { 385 throw new IndexOutOfBoundsException( 386 "index out of bound of the destination buffers"); 387 } 388 389 for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) { 390 if (srcs[i] == null) { 391 throw new IllegalArgumentException( 392 "source buffer[" + i + "] == null"); 393 } 394 } 395 396 for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) { 397 if (dsts[i] == null) { 398 throw new IllegalArgumentException( 399 "destination buffer[" + i + "] == null"); 400 } 401 402 /* 403 * Make sure the destination bufffers are writable. 404 */ 405 if (dsts[i].isReadOnly()) { 406 throw new ReadOnlyBufferException(); 407 } 408 } 409 } 410 411 @Override 412 public synchronized SSLEngineResult unwrap(ByteBuffer src, 413 ByteBuffer[] dsts, int offset, int length) throws SSLException { 414 return unwrap( 415 new ByteBuffer[]{src}, 0, 1, dsts, offset, length); 416 } 417 418 // @Override 419 public synchronized SSLEngineResult unwrap( 420 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 421 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException { 422 423 if (conContext.isUnsureMode) { 424 throw new IllegalStateException( 425 "Client/Server mode has not yet been set."); 426 } 427 428 // See if the handshaker needs to report back some SSLException. 429 checkTaskThrown(); 430 431 // check parameters 432 checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 433 434 try { 435 return readRecord( 436 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength); 437 } catch (SSLProtocolException spe) { 438 // may be an unexpected handshake message 439 conContext.fatal(Alert.UNEXPECTED_MESSAGE, 440 spe.getMessage(), spe); 441 } catch (IOException ioe) { 442 /* 443 * Don't reset position so it looks like we didn't 444 * consume anything. We did consume something, and it 445 * got us into this situation, so report that much back. 446 * Our days of consuming are now over anyway. 447 */ 448 conContext.fatal(Alert.INTERNAL_ERROR, 449 "problem unwrapping net record", ioe); 450 } catch (Exception ex) { // including RuntimeException 451 conContext.fatal(Alert.INTERNAL_ERROR, 452 "Fail to unwrap network record", ex); 453 } 454 455 return null; // make compiler happy 456 } 457 458 private SSLEngineResult readRecord( 459 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 460 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 461 462 /* 463 * Check if we are closing/closed. 464 */ 465 if (isInboundDone()) { 466 return new SSLEngineResult( 467 Status.CLOSED, getHandshakeStatus(), 0, 0); 468 } 469 470 HandshakeStatus hsStatus = null; 471 if (!conContext.isNegotiated) { 472 conContext.kickstart(); 473 474 /* 475 * If there's still outbound data to flush, we 476 * can return without trying to unwrap anything. 477 */ 478 hsStatus = getHandshakeStatus(); 479 if (hsStatus == HandshakeStatus.NEED_WRAP) { 480 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); 481 } 482 } 483 484 if (hsStatus == null) { 485 hsStatus = getHandshakeStatus(); 486 } 487 488 /* 489 * If we have a task outstanding, this *MUST* be done before 490 * doing any more unwrapping, because we could be in the middle 491 * of receiving a handshake message, for example, a finished 492 * message which would change the ciphers. 493 */ 494 if (hsStatus == HandshakeStatus.NEED_TASK) { 495 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); 496 } 497 498 if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) { 499 Plaintext plainText = null; 500 try { 501 plainText = decode(null, 0, 0, 502 dsts, dstsOffset, dstsLength); 503 } catch (IOException ioe) { 504 if (ioe instanceof SSLException) { 505 throw ioe; 506 } else { 507 throw new SSLException("readRecord", ioe); 508 } 509 } 510 511 Status status = (isInboundDone() ? Status.CLOSED : Status.OK); 512 if (plainText.handshakeStatus != null) { 513 hsStatus = plainText.handshakeStatus; 514 } else { 515 hsStatus = getHandshakeStatus(); 516 } 517 518 return new SSLEngineResult( 519 status, hsStatus, 0, 0, plainText.recordSN); 520 } 521 522 int srcsRemains = 0; 523 for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) { 524 srcsRemains += srcs[i].remaining(); 525 } 526 527 if (srcsRemains == 0) { 528 return new SSLEngineResult(Status.OK, getHandshakeStatus(), 0, 0); 529 } 530 531 /* 532 * Check the packet to make sure enough is here. 533 * This will also indirectly check for 0 len packets. 534 */ 535 int packetLen = 0; 536 try { 537 packetLen = conContext.inputRecord.bytesInCompletePacket( 538 srcs, srcsOffset, srcsLength); 539 } catch (SSLException ssle) { 540 // Need to discard invalid records for DTLS protocols. 541 if (sslContext.isDTLS()) { 542 if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) { 543 SSLLogger.finest("Discard invalid DTLS records", ssle); 544 } 545 546 // invalid, discard the entire data [section 4.1.2.7, RFC 6347] 547 // TODO 548 int deltaNet = 0; 549 // int deltaNet = netData.remaining(); 550 // netData.position(netData.limit()); 551 552 Status status = (isInboundDone() ? Status.CLOSED : Status.OK); 553 if (hsStatus == null) { 554 hsStatus = getHandshakeStatus(); 555 } 556 557 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L); 558 } else { 559 throw ssle; 560 } 561 } 562 563 // Is this packet bigger than SSL/TLS normally allows? 564 if (packetLen > conContext.conSession.getPacketBufferSize()) { 565 int largestRecordSize = sslContext.isDTLS() ? 566 DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize; 567 if ((packetLen <= largestRecordSize) && !sslContext.isDTLS()) { 568 // Expand the expected maximum packet/application buffer 569 // sizes. 570 // 571 // Only apply to SSL/TLS protocols. 572 573 // Old behavior: shall we honor the System Property 574 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"? 575 conContext.conSession.expandBufferSizes(); 576 } 577 578 // check the packet again 579 largestRecordSize = conContext.conSession.getPacketBufferSize(); 580 if (packetLen > largestRecordSize) { 581 throw new SSLProtocolException( 582 "Input record too big: max = " + 583 largestRecordSize + " len = " + packetLen); 584 } 585 } 586 587 /* 588 * Check for OVERFLOW. 589 * 590 * Delay enforcing the application buffer free space requirement 591 * until after the initial handshaking. 592 */ 593 int dstsRemains = 0; 594 for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) { 595 dstsRemains += dsts[i].remaining(); 596 } 597 598 if (conContext.isNegotiated) { 599 int FragLen = 600 conContext.inputRecord.estimateFragmentSize(packetLen); 601 if (FragLen > dstsRemains) { 602 return new SSLEngineResult( 603 Status.BUFFER_OVERFLOW, hsStatus, 0, 0); 604 } 605 } 606 607 // check for UNDERFLOW. 608 if ((packetLen == -1) || (srcsRemains < packetLen)) { 609 return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0); 610 } 611 612 /* 613 * We're now ready to actually do the read. 614 */ 615 Plaintext plainText = null; 616 try { 617 plainText = decode(srcs, srcsOffset, srcsLength, 618 dsts, dstsOffset, dstsLength); 619 } catch (IOException ioe) { 620 if (ioe instanceof SSLException) { 621 throw ioe; 622 } else { 623 throw new SSLException("readRecord", ioe); 624 } 625 } 626 627 /* 628 * Check the various condition that we could be reporting. 629 * 630 * It's *possible* something might have happened between the 631 * above and now, but it was better to minimally lock "this" 632 * during the read process. We'll return the current 633 * status, which is more representative of the current state. 634 * 635 * status above should cover: FINISHED, NEED_TASK 636 */ 637 Status status = (isInboundDone() ? Status.CLOSED : Status.OK); 638 if (plainText.handshakeStatus != null) { 639 hsStatus = plainText.handshakeStatus; 640 } else { 641 hsStatus = getHandshakeStatus(); 642 } 643 644 int deltaNet = srcsRemains; 645 for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) { 646 deltaNet -= srcs[i].remaining(); 647 } 648 649 int deltaApp = dstsRemains; 650 for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) { 651 deltaApp -= dsts[i].remaining(); 652 } 653 654 return new SSLEngineResult( 655 status, hsStatus, deltaNet, deltaApp, plainText.recordSN); 656 } 657 658 private Plaintext decode( 659 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 660 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 661 662 Plaintext pt = SSLTransport.decode(conContext, 663 srcs, srcsOffset, srcsLength, 664 dsts, dstsOffset, dstsLength); 665 666 // Is the handshake completed? 667 if (pt != Plaintext.PLAINTEXT_NULL) { 668 HandshakeStatus hsStatus = tryToFinishHandshake(pt.contentType); 669 if (hsStatus == null) { 670 pt.handshakeStatus = conContext.getHandshakeStatus(); 671 } else { 672 pt.handshakeStatus = hsStatus; 673 } 674 675 // Is the sequence number is nearly overflow? 676 if (conContext.inputRecord.seqNumIsHuge()) { 677 pt.handshakeStatus = 678 tryKeyUpdate(pt.handshakeStatus); 679 } 680 } 681 682 return pt; 683 } 684 685 @Override 686 public synchronized Runnable getDelegatedTask() { 687 if (conContext.handshakeContext != null && 688 !conContext.handshakeContext.taskDelegated && 689 !conContext.handshakeContext.delegatedActions.isEmpty()) { 690 conContext.handshakeContext.taskDelegated = true; 691 return new DelegatedTask(this); 692 } 693 694 return null; 695 } 696 697 @Override 698 public synchronized void closeInbound() throws SSLException { 699 conContext.closeInbound(); 700 } 701 702 @Override 703 public synchronized boolean isInboundDone() { 704 return conContext.isInboundDone(); 705 } 706 707 @Override 708 public synchronized void closeOutbound() { 709 conContext.closeOutbound(); 710 } 711 712 @Override 713 public synchronized boolean isOutboundDone() { 714 return conContext.isOutboundDone(); 715 } 716 717 @Override 718 public String[] getSupportedCipherSuites() { 719 return CipherSuite.namesOf(sslContext.getSupportedCipherSuites()); 720 } 721 722 @Override 723 public synchronized String[] getEnabledCipherSuites() { 724 return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites); 725 } 726 727 @Override 728 public synchronized void setEnabledCipherSuites(String[] suites) { 729 if (suites == null) { 730 throw new IllegalArgumentException("CipherSuites cannot be null"); 731 } 732 733 conContext.sslConfig.enabledCipherSuites = 734 CipherSuite.validValuesOf(suites); 735 } 736 737 @Override 738 public String[] getSupportedProtocols() { 739 return ProtocolVersion.toStringArray( 740 sslContext.getSuportedProtocolVersions()); 741 } 742 743 @Override 744 public synchronized String[] getEnabledProtocols() { 745 return ProtocolVersion.toStringArray( 746 conContext.sslConfig.enabledProtocols); 747 } 748 749 @Override 750 public synchronized void setEnabledProtocols(String[] protocols) { 751 if (protocols == null) { 752 throw new IllegalArgumentException("Protocols cannot be null"); 753 } 754 755 conContext.sslConfig.enabledProtocols = 756 ProtocolVersion.namesOf(protocols); 757 } 758 759 @Override 760 public synchronized SSLSession getSession() { 761 return conContext.conSession; 762 } 763 764 @Override 765 public synchronized SSLSession getHandshakeSession() { 766 return conContext.handshakeContext == null ? 767 null : conContext.handshakeContext.handshakeSession; 768 } 769 770 @Override 771 public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() { 772 return conContext.getHandshakeStatus(); 773 } 774 775 @Override 776 public synchronized void setUseClientMode(boolean mode) { 777 conContext.setUseClientMode(mode); 778 } 779 780 @Override 781 public synchronized boolean getUseClientMode() { 782 return conContext.sslConfig.isClientMode; 783 } 784 785 @Override 786 public synchronized void setNeedClientAuth(boolean need) { 787 conContext.sslConfig.clientAuthType = 788 (need ? ClientAuthType.CLIENT_AUTH_REQUIRED : 789 ClientAuthType.CLIENT_AUTH_NONE); 790 } 791 792 @Override 793 public synchronized boolean getNeedClientAuth() { 794 return (conContext.sslConfig.clientAuthType == 795 ClientAuthType.CLIENT_AUTH_REQUIRED); 796 } 797 798 @Override 799 public synchronized void setWantClientAuth(boolean want) { 800 conContext.sslConfig.clientAuthType = 801 (want ? ClientAuthType.CLIENT_AUTH_REQUESTED : 802 ClientAuthType.CLIENT_AUTH_NONE); 803 } 804 805 @Override 806 public synchronized boolean getWantClientAuth() { 807 return (conContext.sslConfig.clientAuthType == 808 ClientAuthType.CLIENT_AUTH_REQUESTED); 809 } 810 811 @Override 812 public synchronized void setEnableSessionCreation(boolean flag) { 813 conContext.sslConfig.enableSessionCreation = flag; 814 } 815 816 @Override 817 public synchronized boolean getEnableSessionCreation() { 818 return conContext.sslConfig.enableSessionCreation; 819 } 820 821 @Override 822 public synchronized SSLParameters getSSLParameters() { 823 return conContext.sslConfig.getSSLParameters(); 824 } 825 826 @Override 827 public synchronized void setSSLParameters(SSLParameters params) { 828 conContext.sslConfig.setSSLParameters(params); 829 830 if (conContext.sslConfig.maximumPacketSize != 0) { 831 conContext.outputRecord.changePacketSize( 832 conContext.sslConfig.maximumPacketSize); 833 } 834 } 835 836 @Override 837 public synchronized String getApplicationProtocol() { 838 return conContext.applicationProtocol; 839 } 840 841 @Override 842 public synchronized String getHandshakeApplicationProtocol() { 843 return conContext.handshakeContext == null ? 844 null : conContext.handshakeContext.applicationProtocol; 845 } 846 847 @Override 848 public synchronized void setHandshakeApplicationProtocolSelector( 849 BiFunction<SSLEngine, List<String>, String> selector) { 850 conContext.sslConfig.engineAPSelector = selector; 851 } 852 853 @Override 854 public synchronized BiFunction<SSLEngine, List<String>, String> 855 getHandshakeApplicationProtocolSelector() { 856 return conContext.sslConfig.engineAPSelector; 857 } 858 859 @Override 860 public boolean useDelegatedTask() { 861 return true; 862 } 863 864 private synchronized void checkTaskThrown() throws SSLException { 865 HandshakeContext hc = conContext.handshakeContext; 866 if (hc != null && hc.delegatedThrown != null) { 867 try { 868 throw getTaskThrown(hc.delegatedThrown); 869 } finally { 870 hc.delegatedThrown = null; 871 } 872 } 873 874 if (conContext.isBroken && conContext.closeReason != null) { 875 throw getTaskThrown(conContext.closeReason); 876 } 877 } 878 879 private static SSLException getTaskThrown(Exception taskThrown) { 880 String msg = taskThrown.getMessage(); 881 882 if (msg == null) { 883 msg = "Delegated task threw Exception or Error"; 884 } 885 886 if (taskThrown instanceof RuntimeException) { 887 throw new RuntimeException(msg, taskThrown); 888 } else if (taskThrown instanceof SSLHandshakeException) { 889 return (SSLHandshakeException) 890 new SSLHandshakeException(msg).initCause(taskThrown); 891 } else if (taskThrown instanceof SSLKeyException) { 892 return (SSLKeyException) 893 new SSLKeyException(msg).initCause(taskThrown); 894 } else if (taskThrown instanceof SSLPeerUnverifiedException) { 895 return (SSLPeerUnverifiedException) 896 new SSLPeerUnverifiedException(msg).initCause(taskThrown); 897 } else if (taskThrown instanceof SSLProtocolException) { 898 return (SSLProtocolException) 899 new SSLProtocolException(msg).initCause(taskThrown); 900 } else if (taskThrown instanceof SSLException) { 901 return (SSLException)taskThrown; 902 } else { 903 return new SSLException(msg, taskThrown); 904 } 905 } 906 907 /** 908 * Implement a simple task delegator. 909 */ 910 private static class DelegatedTask implements Runnable { 911 private final SSLEngineImpl engine; 912 913 DelegatedTask(SSLEngineImpl engineInstance) { 914 this.engine = engineInstance; 915 } 916 917 @Override 918 public void run() { 919 synchronized (engine) { 920 HandshakeContext hc = engine.conContext.handshakeContext; 921 if (hc == null || hc.delegatedActions.isEmpty()) { 922 return; 923 } 924 925 try { 926 AccessController.doPrivileged( 927 new DelegatedAction(hc), engine.conContext.acc); 928 } catch (PrivilegedActionException pae) { 929 // Get the handshake context again in case the 930 // handshaking has completed. 931 hc = engine.conContext.handshakeContext; 932 if (hc != null) { 933 hc.delegatedThrown = pae.getException(); 934 } else if (engine.conContext.closeReason != null) { 935 engine.conContext.closeReason = 936 getTaskThrown(pae.getException()); 937 } 938 } catch (RuntimeException rte) { 939 // Get the handshake context again in case the 940 // handshaking has completed. 941 hc = engine.conContext.handshakeContext; 942 if (hc != null) { 943 hc.delegatedThrown = rte; 944 } else if (engine.conContext.closeReason != null) { 945 engine.conContext.closeReason = rte; 946 } 947 } 948 949 // Get the handshake context again in case the 950 // handshaking has completed. 951 hc = engine.conContext.handshakeContext; 952 if (hc != null) { 953 hc.taskDelegated = false; 954 } 955 } 956 } 957 958 private static class DelegatedAction 959 implements PrivilegedExceptionAction<Void> { 960 final HandshakeContext context; 961 DelegatedAction(HandshakeContext context) { 962 this.context = context; 963 } 964 965 @Override 966 public Void run() throws Exception { 967 while (!context.delegatedActions.isEmpty()) { 968 // Report back the task SSLException 969 if (context.delegatedThrown != null) { 970 Exception delegatedThrown = context.delegatedThrown; 971 context.delegatedThrown = null; 972 throw getTaskThrown(delegatedThrown); 973 } 974 975 Map.Entry<Byte, ByteBuffer> me = 976 context.delegatedActions.poll(); 977 if (me != null) { 978 context.dispatch(me.getKey(), me.getValue()); 979 } 980 } 981 return null; 982 } 983 } 984 } 985 }