1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufAllocator;
20 import io.netty.handler.ssl.util.LazyJavaxX509Certificate;
21 import io.netty.handler.ssl.util.LazyX509Certificate;
22 import io.netty.internal.tcnative.AsyncTask;
23 import io.netty.internal.tcnative.Buffer;
24 import io.netty.internal.tcnative.SSL;
25 import io.netty.util.AbstractReferenceCounted;
26 import io.netty.util.CharsetUtil;
27 import io.netty.util.ReferenceCounted;
28 import io.netty.util.ResourceLeakDetector;
29 import io.netty.util.ResourceLeakDetectorFactory;
30 import io.netty.util.ResourceLeakTracker;
31 import io.netty.util.internal.EmptyArrays;
32 import io.netty.util.internal.PlatformDependent;
33 import io.netty.util.internal.StringUtil;
34 import io.netty.util.internal.SuppressJava6Requirement;
35 import io.netty.util.internal.ThrowableUtil;
36 import io.netty.util.internal.UnstableApi;
37 import io.netty.util.internal.logging.InternalLogger;
38 import io.netty.util.internal.logging.InternalLoggerFactory;
39
40 import java.nio.ByteBuffer;
41 import java.nio.ReadOnlyBufferException;
42 import java.security.Principal;
43 import java.security.cert.Certificate;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.LinkedHashSet;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Set;
52 import java.util.concurrent.ConcurrentHashMap;
53 import java.util.concurrent.locks.Lock;
54
55 import javax.crypto.spec.SecretKeySpec;
56 import javax.net.ssl.SSLEngine;
57 import javax.net.ssl.SSLEngineResult;
58 import javax.net.ssl.SSLException;
59 import javax.net.ssl.SSLHandshakeException;
60 import javax.net.ssl.SSLParameters;
61 import javax.net.ssl.SSLPeerUnverifiedException;
62 import javax.net.ssl.SSLSession;
63 import javax.net.ssl.SSLSessionBindingEvent;
64 import javax.net.ssl.SSLSessionBindingListener;
65 import javax.security.cert.X509Certificate;
66
67 import static io.netty.handler.ssl.OpenSsl.memoryAddress;
68 import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
69 import static io.netty.util.internal.EmptyArrays.EMPTY_STRINGS;
70 import static io.netty.util.internal.ObjectUtil.checkNotNull;
71 import static io.netty.util.internal.ObjectUtil.checkNotNullArrayParam;
72 import static io.netty.util.internal.ObjectUtil.checkNotNullWithIAE;
73 import static java.lang.Integer.MAX_VALUE;
74 import static java.lang.Math.min;
75 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
76 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_TASK;
77 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
78 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
79 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
80 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
81 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
82 import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
83 import static javax.net.ssl.SSLEngineResult.Status.OK;
84
85
86
87
88
89
90
91
92
93
94 public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor {
95
96 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class);
97
98 private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
99 ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
100 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0;
101 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1;
102 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
103 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
104 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
105 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3 = 5;
106 private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
107 SSL.SSL_OP_NO_SSLv2,
108 SSL.SSL_OP_NO_SSLv3,
109 SSL.SSL_OP_NO_TLSv1,
110 SSL.SSL_OP_NO_TLSv1_1,
111 SSL.SSL_OP_NO_TLSv1_2,
112 SSL.SSL_OP_NO_TLSv1_3
113 };
114
115
116
117
118 static final int MAX_PLAINTEXT_LENGTH = SSL.SSL_MAX_PLAINTEXT_LENGTH;
119
120
121
122 static final int MAX_RECORD_SIZE = SSL.SSL_MAX_RECORD_LENGTH;
123
124 private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
125 private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
126 private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
127 private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
128 private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
129
130
131 private long ssl;
132 private long networkBIO;
133
134 private enum HandshakeState {
135
136
137
138 NOT_STARTED,
139
140
141
142 STARTED_IMPLICITLY,
143
144
145
146 STARTED_EXPLICITLY,
147
148
149
150 FINISHED
151 }
152
153 private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
154 private boolean receivedShutdown;
155 private volatile boolean destroyed;
156 private volatile String applicationProtocol;
157 private volatile boolean needTask;
158 private boolean hasTLSv13Cipher;
159 private boolean sessionSet;
160
161
162 private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> leak;
163 private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() {
164 @Override
165 public ReferenceCounted touch(Object hint) {
166 if (leak != null) {
167 leak.record(hint);
168 }
169
170 return ReferenceCountedOpenSslEngine.this;
171 }
172
173 @Override
174 protected void deallocate() {
175 shutdown();
176 if (leak != null) {
177 boolean closed = leak.close(ReferenceCountedOpenSslEngine.this);
178 assert closed;
179 }
180 parentContext.release();
181 }
182 };
183
184 private final Set<String> enabledProtocols = new LinkedHashSet<String>();
185
186 private volatile ClientAuth clientAuth = ClientAuth.NONE;
187
188 private String endPointIdentificationAlgorithm;
189
190 private Object algorithmConstraints;
191 private List<String> sniHostNames;
192
193
194
195 private volatile Collection<?> matchers;
196
197
198 private boolean isInboundDone;
199 private boolean outboundClosed;
200
201 final boolean jdkCompatibilityMode;
202 private final boolean clientMode;
203 final ByteBufAllocator alloc;
204 private final OpenSslEngineMap engineMap;
205 private final OpenSslApplicationProtocolNegotiator apn;
206 private final ReferenceCountedOpenSslContext parentContext;
207 private final OpenSslSession session;
208 private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
209 private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
210 private final boolean enableOcsp;
211 private int maxWrapOverhead;
212 private int maxWrapBufferSize;
213 private Throwable pendingException;
214
215
216
217
218
219
220
221
222
223
224
225
226
227 ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, final ByteBufAllocator alloc, String peerHost,
228 int peerPort, boolean jdkCompatibilityMode, boolean leakDetection) {
229 super(peerHost, peerPort);
230 OpenSsl.ensureAvailability();
231 engineMap = context.engineMap;
232 enableOcsp = context.enableOcsp;
233 this.jdkCompatibilityMode = jdkCompatibilityMode;
234 this.alloc = checkNotNull(alloc, "alloc");
235 apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
236 clientMode = context.isClient();
237
238 if (PlatformDependent.javaVersion() >= 7) {
239 session = new ExtendedOpenSslSession(new DefaultOpenSslSession(context.sessionContext())) {
240 private String[] peerSupportedSignatureAlgorithms;
241 private List requestedServerNames;
242
243 @Override
244 public List getRequestedServerNames() {
245 if (clientMode) {
246 return Java8SslUtils.getSniHostNames(sniHostNames);
247 } else {
248 synchronized (ReferenceCountedOpenSslEngine.this) {
249 if (requestedServerNames == null) {
250 if (isDestroyed()) {
251 requestedServerNames = Collections.emptyList();
252 } else {
253 String name = SSL.getSniHostname(ssl);
254 if (name == null) {
255 requestedServerNames = Collections.emptyList();
256 } else {
257
258
259 requestedServerNames =
260 Java8SslUtils.getSniHostName(
261 SSL.getSniHostname(ssl).getBytes(CharsetUtil.UTF_8));
262 }
263 }
264 }
265 return requestedServerNames;
266 }
267 }
268 }
269
270 @Override
271 public String[] getPeerSupportedSignatureAlgorithms() {
272 synchronized (ReferenceCountedOpenSslEngine.this) {
273 if (peerSupportedSignatureAlgorithms == null) {
274 if (isDestroyed()) {
275 peerSupportedSignatureAlgorithms = EMPTY_STRINGS;
276 } else {
277 String[] algs = SSL.getSigAlgs(ssl);
278 if (algs == null) {
279 peerSupportedSignatureAlgorithms = EMPTY_STRINGS;
280 } else {
281 Set<String> algorithmList = new LinkedHashSet<String>(algs.length);
282 for (String alg: algs) {
283 String converted = SignatureAlgorithmConverter.toJavaName(alg);
284
285 if (converted != null) {
286 algorithmList.add(converted);
287 }
288 }
289 peerSupportedSignatureAlgorithms = algorithmList.toArray(EMPTY_STRINGS);
290 }
291 }
292 }
293 return peerSupportedSignatureAlgorithms.clone();
294 }
295 }
296
297 @Override
298 public List<byte[]> getStatusResponses() {
299 byte[] ocspResponse = null;
300 if (enableOcsp && clientMode) {
301 synchronized (ReferenceCountedOpenSslEngine.this) {
302 if (!isDestroyed()) {
303 ocspResponse = SSL.getOcspResponse(ssl);
304 }
305 }
306 }
307 return ocspResponse == null ?
308 Collections.<byte[]>emptyList() : Collections.singletonList(ocspResponse);
309 }
310 };
311 } else {
312 session = new DefaultOpenSslSession(context.sessionContext());
313 }
314
315 if (!context.sessionContext().useKeyManager()) {
316 session.setLocalCertificate(context.keyCertChain);
317 }
318
319 Lock readerLock = context.ctxLock.readLock();
320 readerLock.lock();
321 final long finalSsl;
322 try {
323 finalSsl = SSL.newSSL(context.ctx, !context.isClient());
324 } finally {
325 readerLock.unlock();
326 }
327 synchronized (this) {
328 ssl = finalSsl;
329 try {
330 networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize());
331
332
333
334 setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
335
336 assert context.protocols != null;
337 this.hasTLSv13Cipher = context.hasTLSv13Cipher;
338
339 setEnabledProtocols(context.protocols);
340
341
342
343 if (clientMode && SslUtils.isValidHostNameForSNI(peerHost)) {
344
345
346 if (PlatformDependent.javaVersion() >= 8) {
347 if (Java8SslUtils.isValidHostNameForSNI(peerHost)) {
348 SSL.setTlsExtHostName(ssl, peerHost);
349 sniHostNames = Collections.singletonList(peerHost);
350 }
351 } else {
352 SSL.setTlsExtHostName(ssl, peerHost);
353 sniHostNames = Collections.singletonList(peerHost);
354 }
355 }
356
357 if (enableOcsp) {
358 SSL.enableOcsp(ssl);
359 }
360
361 if (!jdkCompatibilityMode) {
362 SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
363 }
364
365 if (isProtocolEnabled(SSL.getOptions(ssl), SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
366 final boolean enableTickets = clientMode ?
367 ReferenceCountedOpenSslContext.CLIENT_ENABLE_SESSION_TICKET_TLSV13 :
368 ReferenceCountedOpenSslContext.SERVER_ENABLE_SESSION_TICKET_TLSV13;
369 if (enableTickets) {
370
371
372
373
374
375
376
377 SSL.clearOptions(ssl, SSL.SSL_OP_NO_TICKET);
378 }
379 }
380
381 if (OpenSsl.isBoringSSL() && clientMode) {
382
383
384
385
386 SSL.setRenegotiateMode(ssl, SSL.SSL_RENEGOTIATE_ONCE);
387 }
388
389 calculateMaxWrapOverhead();
390 } catch (Throwable cause) {
391
392
393 shutdown();
394
395 PlatformDependent.throwException(cause);
396 }
397 }
398
399
400
401 parentContext = context;
402 parentContext.retain();
403
404
405
406 leak = leakDetection ? leakDetector.track(this) : null;
407 }
408
409 final synchronized String[] authMethods() {
410 if (isDestroyed()) {
411 return EMPTY_STRINGS;
412 }
413 return SSL.authenticationMethods(ssl);
414 }
415
416 final boolean setKeyMaterial(OpenSslKeyMaterial keyMaterial) throws Exception {
417 synchronized (this) {
418 if (isDestroyed()) {
419 return false;
420 }
421 SSL.setKeyMaterial(ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress());
422 }
423 session.setLocalCertificate(keyMaterial.certificateChain());
424 return true;
425 }
426
427 final synchronized SecretKeySpec masterKey() {
428 if (isDestroyed()) {
429 return null;
430 }
431 return new SecretKeySpec(SSL.getMasterKey(ssl), "AES");
432 }
433
434 synchronized boolean isSessionReused() {
435 if (isDestroyed()) {
436 return false;
437 }
438 return SSL.isSessionReused(ssl);
439 }
440
441
442
443
444 @UnstableApi
445 public void setOcspResponse(byte[] response) {
446 if (!enableOcsp) {
447 throw new IllegalStateException("OCSP stapling is not enabled");
448 }
449
450 if (clientMode) {
451 throw new IllegalStateException("Not a server SSLEngine");
452 }
453
454 synchronized (this) {
455 if (!isDestroyed()) {
456 SSL.setOcspResponse(ssl, response);
457 }
458 }
459 }
460
461
462
463
464 @UnstableApi
465 public byte[] getOcspResponse() {
466 if (!enableOcsp) {
467 throw new IllegalStateException("OCSP stapling is not enabled");
468 }
469
470 if (!clientMode) {
471 throw new IllegalStateException("Not a client SSLEngine");
472 }
473
474 synchronized (this) {
475 if (isDestroyed()) {
476 return EmptyArrays.EMPTY_BYTES;
477 }
478 return SSL.getOcspResponse(ssl);
479 }
480 }
481
482 @Override
483 public final int refCnt() {
484 return refCnt.refCnt();
485 }
486
487 @Override
488 public final ReferenceCounted retain() {
489 refCnt.retain();
490 return this;
491 }
492
493 @Override
494 public final ReferenceCounted retain(int increment) {
495 refCnt.retain(increment);
496 return this;
497 }
498
499 @Override
500 public final ReferenceCounted touch() {
501 refCnt.touch();
502 return this;
503 }
504
505 @Override
506 public final ReferenceCounted touch(Object hint) {
507 refCnt.touch(hint);
508 return this;
509 }
510
511 @Override
512 public final boolean release() {
513 return refCnt.release();
514 }
515
516 @Override
517 public final boolean release(int decrement) {
518 return refCnt.release(decrement);
519 }
520
521
522
523 public String getApplicationProtocol() {
524 return applicationProtocol;
525 }
526
527
528
529 public String getHandshakeApplicationProtocol() {
530 return applicationProtocol;
531 }
532
533 @Override
534 public final synchronized SSLSession getHandshakeSession() {
535
536
537
538
539 switch(handshakeState) {
540 case NOT_STARTED:
541 case FINISHED:
542 return null;
543 default:
544 return session;
545 }
546 }
547
548
549
550
551
552
553 public final synchronized long sslPointer() {
554 return ssl;
555 }
556
557
558
559
560 public final synchronized void shutdown() {
561 if (!destroyed) {
562 destroyed = true;
563
564
565
566 if (engineMap != null) {
567 engineMap.remove(ssl);
568 }
569 SSL.freeSSL(ssl);
570 ssl = networkBIO = 0;
571
572 isInboundDone = outboundClosed = true;
573 }
574
575
576 SSL.clearError();
577 }
578
579
580
581
582
583
584 private int writePlaintextData(final ByteBuffer src, int len) {
585 final int pos = src.position();
586 final int limit = src.limit();
587 final int sslWrote;
588
589 if (src.isDirect()) {
590 sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len);
591 if (sslWrote > 0) {
592 src.position(pos + sslWrote);
593 }
594 } else {
595 ByteBuf buf = alloc.directBuffer(len);
596 try {
597 src.limit(pos + len);
598
599 buf.setBytes(0, src);
600 src.limit(limit);
601
602 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
603 if (sslWrote > 0) {
604 src.position(pos + sslWrote);
605 } else {
606 src.position(pos);
607 }
608 } finally {
609 buf.release();
610 }
611 }
612 return sslWrote;
613 }
614
615 synchronized void bioSetFd(int fd) {
616 if (!isDestroyed()) {
617 SSL.bioSetFd(this.ssl, fd);
618 }
619 }
620
621
622
623
624 private ByteBuf writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
625 final int pos = src.position();
626 if (src.isDirect()) {
627 SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false);
628 } else {
629 final ByteBuf buf = alloc.directBuffer(len);
630 try {
631 final int limit = src.limit();
632 src.limit(pos + len);
633 buf.writeBytes(src);
634
635 src.position(pos);
636 src.limit(limit);
637
638 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
639 return buf;
640 } catch (Throwable cause) {
641 buf.release();
642 PlatformDependent.throwException(cause);
643 }
644 }
645 return null;
646 }
647
648
649
650
651 private int readPlaintextData(final ByteBuffer dst) throws SSLException {
652 final int sslRead;
653 final int pos = dst.position();
654 if (dst.isDirect()) {
655 sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos);
656 if (sslRead > 0) {
657 dst.position(pos + sslRead);
658 }
659 } else {
660 final int limit = dst.limit();
661 final int len = min(maxEncryptedPacketLength0(), limit - pos);
662 final ByteBuf buf = alloc.directBuffer(len);
663 try {
664 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
665 if (sslRead > 0) {
666 dst.limit(pos + sslRead);
667 buf.getBytes(buf.readerIndex(), dst);
668 dst.limit(limit);
669 }
670 } finally {
671 buf.release();
672 }
673 }
674
675 return sslRead;
676 }
677
678
679
680
681 final synchronized int maxWrapOverhead() {
682 return maxWrapOverhead;
683 }
684
685
686
687
688 final synchronized int maxEncryptedPacketLength() {
689 return maxEncryptedPacketLength0();
690 }
691
692
693
694
695
696 final int maxEncryptedPacketLength0() {
697 return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
698 }
699
700
701
702
703
704
705
706
707
708 final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
709 return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
710 }
711
712
713
714
715
716
717
718
719 final int calculateOutNetBufSize(int plaintextLength, int numComponents) {
720 return (int) min(MAX_VALUE, plaintextLength + (long) maxWrapOverhead * numComponents);
721 }
722
723 final synchronized int sslPending() {
724 return sslPending0();
725 }
726
727
728
729
730 private void calculateMaxWrapOverhead() {
731 maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
732
733
734
735
736 maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
737 }
738
739 private int sslPending0() {
740
741
742
743
744 return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
745 }
746
747 private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
748 return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
749 }
750
751 @Override
752 public final SSLEngineResult wrap(
753 final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
754
755 checkNotNullWithIAE(srcs, "srcs");
756 checkNotNullWithIAE(dst, "dst");
757
758 if (offset >= srcs.length || offset + length > srcs.length) {
759 throw new IndexOutOfBoundsException(
760 "offset: " + offset + ", length: " + length +
761 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
762 }
763
764 if (dst.isReadOnly()) {
765 throw new ReadOnlyBufferException();
766 }
767
768 synchronized (this) {
769 if (isOutboundDone()) {
770
771 return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
772 }
773
774 int bytesProduced = 0;
775 ByteBuf bioReadCopyBuf = null;
776 try {
777
778 if (dst.isDirect()) {
779 SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(),
780 true);
781 } else {
782 bioReadCopyBuf = alloc.directBuffer(dst.remaining());
783 SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
784 true);
785 }
786
787 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
788
789
790 if (outboundClosed) {
791
792
793
794
795
796 if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) {
797 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
798 }
799
800
801
802 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
803 if (bytesProduced <= 0) {
804 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
805 }
806
807
808
809 if (!doSSLShutdown()) {
810 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
811 }
812 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
813 return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
814 }
815
816
817 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
818 HandshakeState oldHandshakeState = handshakeState;
819
820
821 if (handshakeState != HandshakeState.FINISHED) {
822 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
823
824 handshakeState = HandshakeState.STARTED_IMPLICITLY;
825 }
826
827
828 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
829
830 if (pendingException != null) {
831
832
833
834
835
836
837
838
839
840
841
842 if (bytesProduced > 0) {
843 return newResult(NEED_WRAP, 0, bytesProduced);
844 }
845
846
847
848 return newResult(handshakeException(), 0, 0);
849 }
850
851 status = handshake();
852
853
854
855 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
856
857 if (status == NEED_TASK) {
858 return newResult(status, 0, bytesProduced);
859 }
860
861 if (bytesProduced > 0) {
862
863
864
865 return newResult(mayFinishHandshake(status != FINISHED ?
866 bytesProduced == bioLengthBefore ? NEED_WRAP :
867 getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
868 0, bytesProduced);
869 }
870
871 if (status == NEED_UNWRAP) {
872
873 return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
874 }
875
876
877
878 if (outboundClosed) {
879 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
880 return newResultMayFinishHandshake(status, 0, bytesProduced);
881 }
882 }
883
884 final int endOffset = offset + length;
885 if (jdkCompatibilityMode ||
886
887
888
889 oldHandshakeState != HandshakeState.FINISHED) {
890 int srcsLen = 0;
891 for (int i = offset; i < endOffset; ++i) {
892 final ByteBuffer src = srcs[i];
893 if (src == null) {
894 throw new IllegalArgumentException("srcs[" + i + "] is null");
895 }
896 if (srcsLen == MAX_PLAINTEXT_LENGTH) {
897 continue;
898 }
899
900 srcsLen += src.remaining();
901 if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
902
903
904
905 srcsLen = MAX_PLAINTEXT_LENGTH;
906 }
907 }
908
909
910
911 if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
912 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
913 }
914 }
915
916
917 int bytesConsumed = 0;
918 assert bytesProduced == 0;
919
920
921 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
922
923 if (bytesProduced > 0) {
924 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
925 }
926
927
928 if (pendingException != null) {
929 Throwable error = pendingException;
930 pendingException = null;
931 shutdown();
932
933
934 throw new SSLException(error);
935 }
936
937 for (; offset < endOffset; ++offset) {
938 final ByteBuffer src = srcs[offset];
939 final int remaining = src.remaining();
940 if (remaining == 0) {
941 continue;
942 }
943
944 final int bytesWritten;
945 if (jdkCompatibilityMode) {
946
947
948
949 bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
950 } else {
951
952
953
954 final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
955 if (availableCapacityForWrap <= 0) {
956 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
957 bytesProduced);
958 }
959 bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
960 }
961
962
963
964
965
966
967 final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
968 bytesProduced += bioLengthBefore - pendingNow;
969 bioLengthBefore = pendingNow;
970
971 if (bytesWritten > 0) {
972 bytesConsumed += bytesWritten;
973
974 if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
975 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
976 }
977 } else {
978 int sslError = SSL.getError(ssl, bytesWritten);
979 if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
980
981 if (!receivedShutdown) {
982 closeAll();
983
984 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
985
986
987
988
989 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
990 status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
991 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
992 : FINISHED);
993 return newResult(hs, bytesConsumed, bytesProduced);
994 }
995
996 return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
997 } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
998
999
1000
1001 return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
1002 } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 if (bytesProduced > 0) {
1016
1017
1018 return newResult(NEED_WRAP, bytesConsumed, bytesProduced);
1019 }
1020 return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
1021 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1022 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1023 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1024
1025 return newResult(NEED_TASK, bytesConsumed, bytesProduced);
1026 } else {
1027
1028 throw shutdownWithError("SSL_write", sslError);
1029 }
1030 }
1031 }
1032 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1033 } finally {
1034 SSL.bioClearByteBuffer(networkBIO);
1035 if (bioReadCopyBuf == null) {
1036 dst.position(dst.position() + bytesProduced);
1037 } else {
1038 assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
1039 " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
1040 dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
1041 bioReadCopyBuf.release();
1042 }
1043 }
1044 }
1045 }
1046
1047 private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
1048 return newResult(OK, hs, bytesConsumed, bytesProduced);
1049 }
1050
1051 private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
1052 int bytesConsumed, int bytesProduced) {
1053
1054
1055
1056 if (isOutboundDone()) {
1057 if (isInboundDone()) {
1058
1059 hs = NOT_HANDSHAKING;
1060
1061
1062 shutdown();
1063 }
1064 return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
1065 }
1066 if (hs == NEED_TASK) {
1067
1068 needTask = true;
1069 }
1070 return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
1071 }
1072
1073 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
1074 int bytesConsumed, int bytesProduced) throws SSLException {
1075 return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1076 }
1077
1078 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
1079 SSLEngineResult.HandshakeStatus hs,
1080 int bytesConsumed, int bytesProduced) throws SSLException {
1081 return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1082 }
1083
1084
1085
1086
1087 private SSLException shutdownWithError(String operations, int sslError) {
1088 return shutdownWithError(operations, sslError, SSL.getLastErrorNumber());
1089 }
1090
1091 private SSLException shutdownWithError(String operation, int sslError, int error) {
1092 if (logger.isDebugEnabled()) {
1093 String errorString = SSL.getErrorString(error);
1094 logger.debug("{} failed with {}: OpenSSL error: {} {}",
1095 operation, sslError, error, errorString);
1096 }
1097
1098
1099 shutdown();
1100
1101 SSLException exception = newSSLExceptionForError(error);
1102
1103 if (pendingException != null) {
1104 exception.initCause(pendingException);
1105 pendingException = null;
1106 }
1107 return exception;
1108 }
1109
1110 private SSLEngineResult handleUnwrapException(int bytesConsumed, int bytesProduced, SSLException e)
1111 throws SSLException {
1112 int lastError = SSL.getLastErrorNumber();
1113 if (lastError != 0) {
1114 return sslReadErrorResult(SSL.SSL_ERROR_SSL, lastError, bytesConsumed,
1115 bytesProduced);
1116 }
1117 throw e;
1118 }
1119
1120 public final SSLEngineResult unwrap(
1121 final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
1122 final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
1123
1124
1125 checkNotNullWithIAE(srcs, "srcs");
1126 if (srcsOffset >= srcs.length
1127 || srcsOffset + srcsLength > srcs.length) {
1128 throw new IndexOutOfBoundsException(
1129 "offset: " + srcsOffset + ", length: " + srcsLength +
1130 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
1131 }
1132 checkNotNullWithIAE(dsts, "dsts");
1133 if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
1134 throw new IndexOutOfBoundsException(
1135 "offset: " + dstsOffset + ", length: " + dstsLength +
1136 " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
1137 }
1138 long capacity = 0;
1139 final int dstsEndOffset = dstsOffset + dstsLength;
1140 for (int i = dstsOffset; i < dstsEndOffset; i ++) {
1141 ByteBuffer dst = checkNotNullArrayParam(dsts[i], i, "dsts");
1142 if (dst.isReadOnly()) {
1143 throw new ReadOnlyBufferException();
1144 }
1145 capacity += dst.remaining();
1146 }
1147
1148 final int srcsEndOffset = srcsOffset + srcsLength;
1149 long len = 0;
1150 for (int i = srcsOffset; i < srcsEndOffset; i++) {
1151 ByteBuffer src = checkNotNullArrayParam(srcs[i], i, "srcs");
1152 len += src.remaining();
1153 }
1154
1155 synchronized (this) {
1156 if (isInboundDone()) {
1157 return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
1158 }
1159
1160 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
1161 HandshakeState oldHandshakeState = handshakeState;
1162
1163 if (handshakeState != HandshakeState.FINISHED) {
1164 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
1165
1166 handshakeState = HandshakeState.STARTED_IMPLICITLY;
1167 }
1168
1169 status = handshake();
1170
1171 if (status == NEED_TASK) {
1172 return newResult(status, 0, 0);
1173 }
1174
1175 if (status == NEED_WRAP) {
1176 return NEED_WRAP_OK;
1177 }
1178
1179 if (isInboundDone) {
1180 return NEED_WRAP_CLOSED;
1181 }
1182 }
1183
1184 int sslPending = sslPending0();
1185 int packetLength;
1186
1187
1188
1189
1190 if (jdkCompatibilityMode ||
1191
1192
1193
1194 oldHandshakeState != HandshakeState.FINISHED) {
1195 if (len < SSL_RECORD_HEADER_LENGTH) {
1196 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1197 }
1198
1199 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
1200 if (packetLength == SslUtils.NOT_ENCRYPTED) {
1201 throw new NotSslRecordException("not an SSL/TLS record");
1202 }
1203
1204 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
1205 if (packetLengthDataOnly > capacity) {
1206
1207
1208 if (packetLengthDataOnly > MAX_RECORD_SIZE) {
1209
1210
1211
1212
1213
1214 throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
1215 session.getApplicationBufferSize());
1216 } else {
1217 session.tryExpandApplicationBufferSize(packetLengthDataOnly);
1218 }
1219 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1220 }
1221
1222 if (len < packetLength) {
1223
1224
1225 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1226 }
1227 } else if (len == 0 && sslPending <= 0) {
1228 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1229 } else if (capacity == 0) {
1230 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1231 } else {
1232 packetLength = (int) min(MAX_VALUE, len);
1233 }
1234
1235
1236 assert srcsOffset < srcsEndOffset;
1237
1238
1239 assert capacity > 0;
1240
1241
1242 int bytesProduced = 0;
1243 int bytesConsumed = 0;
1244 try {
1245 srcLoop:
1246 for (;;) {
1247 ByteBuffer src = srcs[srcsOffset];
1248 int remaining = src.remaining();
1249 final ByteBuf bioWriteCopyBuf;
1250 int pendingEncryptedBytes;
1251 if (remaining == 0) {
1252 if (sslPending <= 0) {
1253
1254
1255 if (++srcsOffset >= srcsEndOffset) {
1256 break;
1257 }
1258 continue;
1259 } else {
1260 bioWriteCopyBuf = null;
1261 pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
1262 }
1263 } else {
1264
1265
1266 pendingEncryptedBytes = min(packetLength, remaining);
1267 try {
1268 bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
1269 } catch (SSLException e) {
1270
1271 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1272 }
1273 }
1274 try {
1275 for (;;) {
1276 ByteBuffer dst = dsts[dstsOffset];
1277 if (!dst.hasRemaining()) {
1278
1279 if (++dstsOffset >= dstsEndOffset) {
1280 break srcLoop;
1281 }
1282 continue;
1283 }
1284
1285 int bytesRead;
1286 try {
1287 bytesRead = readPlaintextData(dst);
1288 } catch (SSLException e) {
1289
1290 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1291 }
1292
1293
1294
1295 int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1296 bytesConsumed += localBytesConsumed;
1297 packetLength -= localBytesConsumed;
1298 pendingEncryptedBytes -= localBytesConsumed;
1299 src.position(src.position() + localBytesConsumed);
1300
1301 if (bytesRead > 0) {
1302 bytesProduced += bytesRead;
1303
1304 if (!dst.hasRemaining()) {
1305 sslPending = sslPending0();
1306
1307 if (++dstsOffset >= dstsEndOffset) {
1308 return sslPending > 0 ?
1309 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1310 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1311 bytesConsumed, bytesProduced);
1312 }
1313 } else if (packetLength == 0 || jdkCompatibilityMode) {
1314
1315
1316 break srcLoop;
1317 }
1318 } else {
1319 int sslError = SSL.getError(ssl, bytesRead);
1320 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1321
1322
1323 break;
1324 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1325
1326 if (!receivedShutdown) {
1327 closeAll();
1328 }
1329 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1330 bytesConsumed, bytesProduced);
1331 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1332 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1333 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1334 return newResult(isInboundDone() ? CLOSED : OK,
1335 NEED_TASK, bytesConsumed, bytesProduced);
1336 } else {
1337 return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed,
1338 bytesProduced);
1339 }
1340 }
1341 }
1342
1343 if (++srcsOffset >= srcsEndOffset) {
1344 break;
1345 }
1346 } finally {
1347 if (bioWriteCopyBuf != null) {
1348 bioWriteCopyBuf.release();
1349 }
1350 }
1351 }
1352 } finally {
1353 SSL.bioClearByteBuffer(networkBIO);
1354 rejectRemoteInitiatedRenegotiation();
1355 }
1356
1357
1358 if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1359 closeAll();
1360 }
1361
1362 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1363 }
1364 }
1365
1366 private boolean needWrapAgain(int stackError) {
1367
1368
1369
1370
1371 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1372
1373
1374 if (pendingException == null) {
1375 pendingException = newSSLExceptionForError(stackError);
1376 } else if (shouldAddSuppressed(pendingException, stackError)) {
1377 ThrowableUtil.addSuppressed(pendingException, newSSLExceptionForError(stackError));
1378 }
1379
1380
1381 SSL.clearError();
1382 return true;
1383 }
1384 return false;
1385 }
1386
1387 private SSLException newSSLExceptionForError(int stackError) {
1388 String message = SSL.getErrorString(stackError);
1389 return handshakeState == HandshakeState.FINISHED ?
1390 new OpenSslException(message, stackError) : new OpenSslHandshakeException(message, stackError);
1391 }
1392
1393 private static boolean shouldAddSuppressed(Throwable target, int errorCode) {
1394 for (Throwable suppressed: ThrowableUtil.getSuppressed(target)) {
1395 if (suppressed instanceof NativeSslException &&
1396 ((NativeSslException) suppressed).errorCode() == errorCode) {
1397
1398 return false;
1399 }
1400 }
1401 return true;
1402 }
1403
1404 private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced)
1405 throws SSLException {
1406 if (needWrapAgain(stackError)) {
1407
1408
1409 return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1410 }
1411 throw shutdownWithError("SSL_read", error, stackError);
1412 }
1413
1414 private void closeAll() throws SSLException {
1415 receivedShutdown = true;
1416 closeOutbound();
1417 closeInbound();
1418 }
1419
1420 private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1421
1422
1423
1424 if (!isDestroyed() && (!clientMode && SSL.getHandshakeCount(ssl) > 1 ||
1425
1426 clientMode && SSL.getHandshakeCount(ssl) > 2) &&
1427
1428
1429 !SslProtocols.TLS_v1_3.equals(session.getProtocol()) && handshakeState == HandshakeState.FINISHED) {
1430
1431
1432 shutdown();
1433 throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1434 }
1435 }
1436
1437 public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1438 return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1439 }
1440
1441 private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1442 singleSrcBuffer[0] = src;
1443 return singleSrcBuffer;
1444 }
1445
1446 private void resetSingleSrcBuffer() {
1447 singleSrcBuffer[0] = null;
1448 }
1449
1450 private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1451 singleDstBuffer[0] = src;
1452 return singleDstBuffer;
1453 }
1454
1455 private void resetSingleDstBuffer() {
1456 singleDstBuffer[0] = null;
1457 }
1458
1459 @Override
1460 public final synchronized SSLEngineResult unwrap(
1461 final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1462 try {
1463 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1464 } finally {
1465 resetSingleSrcBuffer();
1466 }
1467 }
1468
1469 @Override
1470 public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1471 try {
1472 return wrap(singleSrcBuffer(src), dst);
1473 } finally {
1474 resetSingleSrcBuffer();
1475 }
1476 }
1477
1478 @Override
1479 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1480 try {
1481 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1482 } finally {
1483 resetSingleSrcBuffer();
1484 resetSingleDstBuffer();
1485 }
1486 }
1487
1488 @Override
1489 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1490 try {
1491 return unwrap(singleSrcBuffer(src), dsts);
1492 } finally {
1493 resetSingleSrcBuffer();
1494 }
1495 }
1496
1497 private class TaskDecorator<R extends Runnable> implements Runnable {
1498 protected final R task;
1499 TaskDecorator(R task) {
1500 this.task = task;
1501 }
1502
1503 @Override
1504 public void run() {
1505 runAndResetNeedTask(task);
1506 }
1507 }
1508
1509 private final class AsyncTaskDecorator extends TaskDecorator<AsyncTask> implements AsyncRunnable {
1510 AsyncTaskDecorator(AsyncTask task) {
1511 super(task);
1512 }
1513
1514 @Override
1515 public void run(final Runnable runnable) {
1516 if (isDestroyed()) {
1517
1518 return;
1519 }
1520 task.runAsync(new TaskDecorator<Runnable>(runnable));
1521 }
1522 }
1523
1524 private void runAndResetNeedTask(Runnable task) {
1525
1526
1527 synchronized (ReferenceCountedOpenSslEngine.this) {
1528 try {
1529 if (isDestroyed()) {
1530
1531 return;
1532 }
1533 task.run();
1534 if (handshakeState != HandshakeState.FINISHED && !isDestroyed()) {
1535
1536
1537
1538 if (SSL.doHandshake(ssl) <= 0) {
1539 SSL.clearError();
1540 }
1541 }
1542 } finally {
1543
1544 needTask = false;
1545 }
1546 }
1547 }
1548
1549 @Override
1550 public final synchronized Runnable getDelegatedTask() {
1551 if (isDestroyed()) {
1552 return null;
1553 }
1554 final Runnable task = SSL.getTask(ssl);
1555 if (task == null) {
1556 return null;
1557 }
1558 if (task instanceof AsyncTask) {
1559 return new AsyncTaskDecorator((AsyncTask) task);
1560 }
1561 return new TaskDecorator<Runnable>(task);
1562 }
1563
1564 @Override
1565 public final synchronized void closeInbound() throws SSLException {
1566 if (isInboundDone) {
1567 return;
1568 }
1569
1570 isInboundDone = true;
1571
1572 if (isOutboundDone()) {
1573
1574
1575 shutdown();
1576 }
1577
1578 if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1579 throw new SSLException(
1580 "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1581 }
1582 }
1583
1584 @Override
1585 public final synchronized boolean isInboundDone() {
1586 return isInboundDone;
1587 }
1588
1589 @Override
1590 public final synchronized void closeOutbound() {
1591 if (outboundClosed) {
1592 return;
1593 }
1594
1595 outboundClosed = true;
1596
1597 if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) {
1598 int mode = SSL.getShutdown(ssl);
1599 if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1600 doSSLShutdown();
1601 }
1602 } else {
1603
1604 shutdown();
1605 }
1606 }
1607
1608
1609
1610
1611
1612 private boolean doSSLShutdown() {
1613 if (SSL.isInInit(ssl) != 0) {
1614
1615
1616
1617
1618 return false;
1619 }
1620 int err = SSL.shutdownSSL(ssl);
1621 if (err < 0) {
1622 int sslErr = SSL.getError(ssl, err);
1623 if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1624 if (logger.isDebugEnabled()) {
1625 int error = SSL.getLastErrorNumber();
1626 logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error));
1627 }
1628
1629 shutdown();
1630 return false;
1631 }
1632 SSL.clearError();
1633 }
1634 return true;
1635 }
1636
1637 @Override
1638 public final synchronized boolean isOutboundDone() {
1639
1640
1641 return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1642 }
1643
1644 @Override
1645 public final String[] getSupportedCipherSuites() {
1646 return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(EMPTY_STRINGS);
1647 }
1648
1649 @Override
1650 public final String[] getEnabledCipherSuites() {
1651 final String[] extraCiphers;
1652 final String[] enabled;
1653 final boolean tls13Enabled;
1654 synchronized (this) {
1655 if (!isDestroyed()) {
1656 enabled = SSL.getCiphers(ssl);
1657 int opts = SSL.getOptions(ssl);
1658 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
1659 extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
1660 tls13Enabled = true;
1661 } else {
1662 extraCiphers = EMPTY_STRINGS;
1663 tls13Enabled = false;
1664 }
1665 } else {
1666 return EMPTY_STRINGS;
1667 }
1668 }
1669 if (enabled == null) {
1670 return EMPTY_STRINGS;
1671 } else {
1672 Set<String> enabledSet = new LinkedHashSet<String>(enabled.length + extraCiphers.length);
1673 synchronized (this) {
1674 for (int i = 0; i < enabled.length; i++) {
1675 String mapped = toJavaCipherSuite(enabled[i]);
1676 final String cipher = mapped == null ? enabled[i] : mapped;
1677 if ((!tls13Enabled || !OpenSsl.isTlsv13Supported()) && SslUtils.isTLSv13Cipher(cipher)) {
1678 continue;
1679 }
1680 enabledSet.add(cipher);
1681 }
1682 Collections.addAll(enabledSet, extraCiphers);
1683 }
1684 return enabledSet.toArray(EMPTY_STRINGS);
1685 }
1686 }
1687
1688 @Override
1689 public final void setEnabledCipherSuites(String[] cipherSuites) {
1690 checkNotNull(cipherSuites, "cipherSuites");
1691
1692 final StringBuilder buf = new StringBuilder();
1693 final StringBuilder bufTLSv13 = new StringBuilder();
1694
1695 CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13, OpenSsl.isBoringSSL());
1696 final String cipherSuiteSpec = buf.toString();
1697 final String cipherSuiteSpecTLSv13 = bufTLSv13.toString();
1698
1699 if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) {
1700 throw new IllegalArgumentException("TLSv1.3 is not supported by this java version.");
1701 }
1702 synchronized (this) {
1703 hasTLSv13Cipher = !cipherSuiteSpecTLSv13.isEmpty();
1704 if (!isDestroyed()) {
1705 try {
1706
1707 SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
1708 if (OpenSsl.isTlsv13Supported()) {
1709
1710 SSL.setCipherSuites(ssl, OpenSsl.checkTls13Ciphers(logger, cipherSuiteSpecTLSv13), true);
1711 }
1712
1713
1714
1715 Set<String> protocols = new HashSet<String>(enabledProtocols);
1716
1717
1718
1719 if (cipherSuiteSpec.isEmpty()) {
1720 protocols.remove(SslProtocols.TLS_v1);
1721 protocols.remove(SslProtocols.TLS_v1_1);
1722 protocols.remove(SslProtocols.TLS_v1_2);
1723 protocols.remove(SslProtocols.SSL_v3);
1724 protocols.remove(SslProtocols.SSL_v2);
1725 protocols.remove(SslProtocols.SSL_v2_HELLO);
1726 }
1727
1728 if (cipherSuiteSpecTLSv13.isEmpty()) {
1729 protocols.remove(SslProtocols.TLS_v1_3);
1730 }
1731
1732
1733 setEnabledProtocols0(protocols.toArray(EMPTY_STRINGS), !hasTLSv13Cipher);
1734 } catch (Exception e) {
1735 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1736 }
1737 } else {
1738 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1739 }
1740 }
1741 }
1742
1743 @Override
1744 public final String[] getSupportedProtocols() {
1745 return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(EMPTY_STRINGS);
1746 }
1747
1748 @Override
1749 public final String[] getEnabledProtocols() {
1750 return enabledProtocols.toArray(EMPTY_STRINGS);
1751 }
1752
1753 private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1754
1755
1756 return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString);
1757 }
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768 @Override
1769 public final void setEnabledProtocols(String[] protocols) {
1770 checkNotNullWithIAE(protocols, "protocols");
1771 synchronized (this) {
1772 enabledProtocols.clear();
1773
1774 enabledProtocols.add(SslProtocols.SSL_v2_HELLO);
1775
1776 Collections.addAll(enabledProtocols, protocols);
1777
1778 setEnabledProtocols0(protocols, !hasTLSv13Cipher);
1779 }
1780 }
1781
1782 private void setEnabledProtocols0(String[] protocols, boolean explicitDisableTLSv13) {
1783 assert Thread.holdsLock(this);
1784
1785 int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1786 int maxProtocolIndex = 0;
1787 for (String p: protocols) {
1788 if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
1789 throw new IllegalArgumentException("Protocol " + p + " is not supported.");
1790 }
1791 if (p.equals(SslProtocols.SSL_v2)) {
1792 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1793 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1794 }
1795 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1796 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1797 }
1798 } else if (p.equals(SslProtocols.SSL_v3)) {
1799 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1800 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1801 }
1802 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1803 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1804 }
1805 } else if (p.equals(SslProtocols.TLS_v1)) {
1806 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1807 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1808 }
1809 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1810 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1811 }
1812 } else if (p.equals(SslProtocols.TLS_v1_1)) {
1813 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1814 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1815 }
1816 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1817 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1818 }
1819 } else if (p.equals(SslProtocols.TLS_v1_2)) {
1820 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1821 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1822 }
1823 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1824 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1825 }
1826 } else if (!explicitDisableTLSv13 && p.equals(SslProtocols.TLS_v1_3)) {
1827 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
1828 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1829 }
1830 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
1831 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1832 }
1833 }
1834 }
1835 if (!isDestroyed()) {
1836
1837 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
1838 SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3);
1839
1840 int opts = 0;
1841 for (int i = 0; i < minProtocolIndex; ++i) {
1842 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1843 }
1844 assert maxProtocolIndex != MAX_VALUE;
1845 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1846 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1847 }
1848
1849
1850 SSL.setOptions(ssl, opts);
1851 } else {
1852 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1853 }
1854 }
1855
1856 @Override
1857 public final SSLSession getSession() {
1858 return session;
1859 }
1860
1861 @Override
1862 public final synchronized void beginHandshake() throws SSLException {
1863 switch (handshakeState) {
1864 case STARTED_IMPLICITLY:
1865 checkEngineClosed();
1866
1867
1868
1869
1870
1871
1872
1873 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1874 calculateMaxWrapOverhead();
1875
1876 break;
1877 case STARTED_EXPLICITLY:
1878
1879 break;
1880 case FINISHED:
1881 throw new SSLException("renegotiation unsupported");
1882 case NOT_STARTED:
1883 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1884 if (handshake() == NEED_TASK) {
1885
1886 needTask = true;
1887 }
1888 calculateMaxWrapOverhead();
1889 break;
1890 default:
1891 throw new Error();
1892 }
1893 }
1894
1895 private void checkEngineClosed() throws SSLException {
1896 if (isDestroyed()) {
1897 throw new SSLException("engine closed");
1898 }
1899 }
1900
1901 private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1902
1903 return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1904 }
1905
1906 private static boolean isEmpty(Object[] arr) {
1907 return arr == null || arr.length == 0;
1908 }
1909
1910 private static boolean isEmpty(byte[] cert) {
1911 return cert == null || cert.length == 0;
1912 }
1913
1914 private SSLEngineResult.HandshakeStatus handshakeException() throws SSLException {
1915 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1916
1917 return NEED_WRAP;
1918 }
1919
1920 Throwable exception = pendingException;
1921 assert exception != null;
1922 pendingException = null;
1923 shutdown();
1924 if (exception instanceof SSLHandshakeException) {
1925 throw (SSLHandshakeException) exception;
1926 }
1927 SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem");
1928 e.initCause(exception);
1929 throw e;
1930 }
1931
1932
1933
1934
1935
1936 final void initHandshakeException(Throwable cause) {
1937 if (pendingException == null) {
1938 pendingException = cause;
1939 } else {
1940 ThrowableUtil.addSuppressed(pendingException, cause);
1941 }
1942 }
1943
1944 private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1945 if (needTask) {
1946 return NEED_TASK;
1947 }
1948 if (handshakeState == HandshakeState.FINISHED) {
1949 return FINISHED;
1950 }
1951
1952 checkEngineClosed();
1953
1954 if (pendingException != null) {
1955
1956
1957 if (SSL.doHandshake(ssl) <= 0) {
1958
1959 SSL.clearError();
1960 }
1961 return handshakeException();
1962 }
1963
1964
1965 engineMap.add(this);
1966
1967 if (!sessionSet) {
1968 if (!parentContext.sessionContext().setSessionFromCache(ssl, session, getPeerHost(), getPeerPort())) {
1969
1970
1971 session.prepareHandshake();
1972 }
1973 sessionSet = true;
1974 }
1975
1976 int code = SSL.doHandshake(ssl);
1977 if (code <= 0) {
1978 int sslError = SSL.getError(ssl, code);
1979 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1980 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
1981 }
1982
1983 if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1984 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1985 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1986 return NEED_TASK;
1987 }
1988
1989 if (needWrapAgain(SSL.getLastErrorNumber())) {
1990
1991
1992 return NEED_WRAP;
1993 }
1994
1995
1996 if (pendingException != null) {
1997 return handshakeException();
1998 }
1999
2000
2001 throw shutdownWithError("SSL_do_handshake", sslError);
2002 }
2003
2004 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
2005 return NEED_WRAP;
2006 }
2007
2008 session.handshakeFinished(SSL.getSessionId(ssl), SSL.getCipherForSSL(ssl), SSL.getVersion(ssl),
2009 SSL.getPeerCertificate(ssl), SSL.getPeerCertChain(ssl),
2010 SSL.getTime(ssl) * 1000L, parentContext.sessionTimeout() * 1000L);
2011 selectApplicationProtocol();
2012 return FINISHED;
2013 }
2014
2015 private SSLEngineResult.HandshakeStatus mayFinishHandshake(
2016 SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) throws SSLException {
2017 return hs == NEED_UNWRAP && bytesProduced > 0 || hs == NEED_WRAP && bytesConsumed > 0 ?
2018 handshake() : mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED);
2019 }
2020
2021 private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
2022 throws SSLException {
2023 if (status == NOT_HANDSHAKING) {
2024 if (handshakeState != HandshakeState.FINISHED) {
2025
2026
2027 return handshake();
2028 }
2029 if (!isDestroyed() && SSL.bioLengthNonApplication(networkBIO) > 0) {
2030
2031 return NEED_WRAP;
2032 }
2033 }
2034 return status;
2035 }
2036
2037 @Override
2038 public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
2039
2040 if (needPendingStatus()) {
2041 if (needTask) {
2042
2043 return NEED_TASK;
2044 }
2045 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
2046 }
2047 return NOT_HANDSHAKING;
2048 }
2049
2050 private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
2051
2052 if (needPendingStatus()) {
2053 if (needTask) {
2054
2055 return NEED_TASK;
2056 }
2057 return pendingStatus(pending);
2058 }
2059 return NOT_HANDSHAKING;
2060 }
2061
2062 private boolean needPendingStatus() {
2063 return handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()
2064 && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone());
2065 }
2066
2067
2068
2069
2070 private String toJavaCipherSuite(String openSslCipherSuite) {
2071 if (openSslCipherSuite == null) {
2072 return null;
2073 }
2074
2075 String version = SSL.getVersion(ssl);
2076 String prefix = toJavaCipherSuitePrefix(version);
2077 return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
2078 }
2079
2080
2081
2082
2083 private static String toJavaCipherSuitePrefix(String protocolVersion) {
2084 final char c;
2085 if (protocolVersion == null || protocolVersion.isEmpty()) {
2086 c = 0;
2087 } else {
2088 c = protocolVersion.charAt(0);
2089 }
2090
2091 switch (c) {
2092 case 'T':
2093 return "TLS";
2094 case 'S':
2095 return "SSL";
2096 default:
2097 return "UNKNOWN";
2098 }
2099 }
2100
2101 @Override
2102 public final void setUseClientMode(boolean clientMode) {
2103 if (clientMode != this.clientMode) {
2104 throw new UnsupportedOperationException();
2105 }
2106 }
2107
2108 @Override
2109 public final boolean getUseClientMode() {
2110 return clientMode;
2111 }
2112
2113 @Override
2114 public final void setNeedClientAuth(boolean b) {
2115 setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
2116 }
2117
2118 @Override
2119 public final boolean getNeedClientAuth() {
2120 return clientAuth == ClientAuth.REQUIRE;
2121 }
2122
2123 @Override
2124 public final void setWantClientAuth(boolean b) {
2125 setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
2126 }
2127
2128 @Override
2129 public final boolean getWantClientAuth() {
2130 return clientAuth == ClientAuth.OPTIONAL;
2131 }
2132
2133
2134
2135
2136
2137 @UnstableApi
2138 public final synchronized void setVerify(int verifyMode, int depth) {
2139 if (!isDestroyed()) {
2140 SSL.setVerify(ssl, verifyMode, depth);
2141 }
2142 }
2143
2144 private void setClientAuth(ClientAuth mode) {
2145 if (clientMode) {
2146 return;
2147 }
2148 synchronized (this) {
2149 if (clientAuth == mode) {
2150
2151 return;
2152 }
2153 if (!isDestroyed()) {
2154 switch (mode) {
2155 case NONE:
2156 SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2157 break;
2158 case REQUIRE:
2159 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2160 break;
2161 case OPTIONAL:
2162 SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
2163 break;
2164 default:
2165 throw new Error(mode.toString());
2166 }
2167 }
2168 clientAuth = mode;
2169 }
2170 }
2171
2172 @Override
2173 public final void setEnableSessionCreation(boolean b) {
2174 if (b) {
2175 throw new UnsupportedOperationException();
2176 }
2177 }
2178
2179 @Override
2180 public final boolean getEnableSessionCreation() {
2181 return false;
2182 }
2183
2184 @SuppressJava6Requirement(reason = "Usage guarded by java version check")
2185 @Override
2186 public final synchronized SSLParameters getSSLParameters() {
2187 SSLParameters sslParameters = super.getSSLParameters();
2188
2189 int version = PlatformDependent.javaVersion();
2190 if (version >= 7) {
2191 sslParameters.setEndpointIdentificationAlgorithm(endPointIdentificationAlgorithm);
2192 Java7SslParametersUtils.setAlgorithmConstraints(sslParameters, algorithmConstraints);
2193 if (version >= 8) {
2194 if (sniHostNames != null) {
2195 Java8SslUtils.setSniHostNames(sslParameters, sniHostNames);
2196 }
2197 if (!isDestroyed()) {
2198 Java8SslUtils.setUseCipherSuitesOrder(
2199 sslParameters, (SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
2200 }
2201
2202 Java8SslUtils.setSNIMatchers(sslParameters, matchers);
2203 }
2204 }
2205 return sslParameters;
2206 }
2207
2208 @SuppressJava6Requirement(reason = "Usage guarded by java version check")
2209 @Override
2210 public final synchronized void setSSLParameters(SSLParameters sslParameters) {
2211 int version = PlatformDependent.javaVersion();
2212 if (version >= 7) {
2213 if (sslParameters.getAlgorithmConstraints() != null) {
2214 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
2215 }
2216
2217 boolean isDestroyed = isDestroyed();
2218 if (version >= 8) {
2219 if (!isDestroyed) {
2220 if (clientMode) {
2221 final List<String> sniHostNames = Java8SslUtils.getSniHostNames(sslParameters);
2222 for (String name: sniHostNames) {
2223 SSL.setTlsExtHostName(ssl, name);
2224 }
2225 this.sniHostNames = sniHostNames;
2226 }
2227 if (Java8SslUtils.getUseCipherSuitesOrder(sslParameters)) {
2228 SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2229 } else {
2230 SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
2231 }
2232 }
2233 matchers = sslParameters.getSNIMatchers();
2234 }
2235
2236 final String endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
2237 if (!isDestroyed) {
2238
2239
2240 if (clientMode && isEndPointVerificationEnabled(endPointIdentificationAlgorithm)) {
2241 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
2242 }
2243 }
2244 this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
2245 algorithmConstraints = sslParameters.getAlgorithmConstraints();
2246 }
2247 super.setSSLParameters(sslParameters);
2248 }
2249
2250 private static boolean isEndPointVerificationEnabled(String endPointIdentificationAlgorithm) {
2251 return endPointIdentificationAlgorithm != null && !endPointIdentificationAlgorithm.isEmpty();
2252 }
2253
2254 private boolean isDestroyed() {
2255 return destroyed;
2256 }
2257
2258 final boolean checkSniHostnameMatch(byte[] hostname) {
2259 return Java8SslUtils.checkSniHostnameMatch(matchers, hostname);
2260 }
2261
2262 @Override
2263 public String getNegotiatedApplicationProtocol() {
2264 return applicationProtocol;
2265 }
2266
2267 private static long bufferAddress(ByteBuffer b) {
2268 assert b.isDirect();
2269 if (PlatformDependent.hasUnsafe()) {
2270 return PlatformDependent.directBufferAddress(b);
2271 }
2272 return Buffer.address(b);
2273 }
2274
2275
2276
2277
2278 private void selectApplicationProtocol() throws SSLException {
2279 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
2280 List<String> protocols = apn.protocols();
2281 String applicationProtocol;
2282 switch (apn.protocol()) {
2283 case NONE:
2284 break;
2285
2286
2287 case ALPN:
2288 applicationProtocol = SSL.getAlpnSelected(ssl);
2289 if (applicationProtocol != null) {
2290 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2291 protocols, behavior, applicationProtocol);
2292 }
2293 break;
2294 case NPN:
2295 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2296 if (applicationProtocol != null) {
2297 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2298 protocols, behavior, applicationProtocol);
2299 }
2300 break;
2301 case NPN_AND_ALPN:
2302 applicationProtocol = SSL.getAlpnSelected(ssl);
2303 if (applicationProtocol == null) {
2304 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2305 }
2306 if (applicationProtocol != null) {
2307 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2308 protocols, behavior, applicationProtocol);
2309 }
2310 break;
2311 default:
2312 throw new Error();
2313 }
2314 }
2315
2316 private String selectApplicationProtocol(List<String> protocols,
2317 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2318 String applicationProtocol) throws SSLException {
2319 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2320 return applicationProtocol;
2321 } else {
2322 int size = protocols.size();
2323 assert size > 0;
2324 if (protocols.contains(applicationProtocol)) {
2325 return applicationProtocol;
2326 } else {
2327 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2328 return protocols.get(size - 1);
2329 } else {
2330 throw new SSLException("unknown protocol " + applicationProtocol);
2331 }
2332 }
2333 }
2334 }
2335
2336 private static final X509Certificate[] JAVAX_CERTS_NOT_SUPPORTED = new X509Certificate[0];
2337
2338 private final class DefaultOpenSslSession implements OpenSslSession {
2339 private final OpenSslSessionContext sessionContext;
2340
2341
2342
2343 private X509Certificate[] x509PeerCerts;
2344 private Certificate[] peerCerts;
2345
2346 private boolean valid = true;
2347 private String protocol;
2348 private String cipher;
2349 private OpenSslSessionId id = OpenSslSessionId.NULL_ID;
2350 private long creationTime;
2351
2352
2353 private long lastAccessed = -1;
2354
2355 private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
2356 private volatile Certificate[] localCertificateChain;
2357 private volatile Map<String, Object> keyValueStorage = new ConcurrentHashMap<String, Object>();
2358
2359 DefaultOpenSslSession(OpenSslSessionContext sessionContext) {
2360 this.sessionContext = sessionContext;
2361 }
2362
2363 private SSLSessionBindingEvent newSSLSessionBindingEvent(String name) {
2364 return new SSLSessionBindingEvent(session, name);
2365 }
2366
2367 @Override
2368 public void prepareHandshake() {
2369 keyValueStorage.clear();
2370 }
2371
2372 @Override
2373 public void setSessionDetails(
2374 long creationTime, long lastAccessedTime, OpenSslSessionId sessionId,
2375 Map<String, Object> keyValueStorage) {
2376 synchronized (ReferenceCountedOpenSslEngine.this) {
2377 if (this.id == OpenSslSessionId.NULL_ID) {
2378 this.id = sessionId;
2379 this.creationTime = creationTime;
2380 this.lastAccessed = lastAccessedTime;
2381
2382
2383
2384
2385 this.keyValueStorage = keyValueStorage;
2386 }
2387 }
2388 }
2389
2390 @Override
2391 public Map<String, Object> keyValueStorage() {
2392 return keyValueStorage;
2393 }
2394
2395 @Override
2396 public OpenSslSessionId sessionId() {
2397 synchronized (ReferenceCountedOpenSslEngine.this) {
2398 if (this.id == OpenSslSessionId.NULL_ID && !isDestroyed()) {
2399 byte[] sessionId = SSL.getSessionId(ssl);
2400 if (sessionId != null) {
2401 id = new OpenSslSessionId(sessionId);
2402 }
2403 }
2404
2405 return id;
2406 }
2407 }
2408
2409 @Override
2410 public void setLocalCertificate(Certificate[] localCertificate) {
2411 this.localCertificateChain = localCertificate;
2412 }
2413
2414 @Override
2415 public byte[] getId() {
2416 return sessionId().cloneBytes();
2417 }
2418
2419 @Override
2420 public OpenSslSessionContext getSessionContext() {
2421 return sessionContext;
2422 }
2423
2424 @Override
2425 public long getCreationTime() {
2426 synchronized (ReferenceCountedOpenSslEngine.this) {
2427 return creationTime;
2428 }
2429 }
2430
2431 @Override
2432 public void setLastAccessedTime(long time) {
2433 synchronized (ReferenceCountedOpenSslEngine.this) {
2434 this.lastAccessed = time;
2435 }
2436 }
2437
2438 @Override
2439 public long getLastAccessedTime() {
2440
2441 synchronized (ReferenceCountedOpenSslEngine.this) {
2442 return lastAccessed == -1 ? creationTime : lastAccessed;
2443 }
2444 }
2445
2446 @Override
2447 public void invalidate() {
2448 synchronized (ReferenceCountedOpenSslEngine.this) {
2449 valid = false;
2450 sessionContext.removeFromCache(id);
2451 }
2452 }
2453
2454 @Override
2455 public boolean isValid() {
2456 synchronized (ReferenceCountedOpenSslEngine.this) {
2457 return valid || sessionContext.isInCache(id);
2458 }
2459 }
2460
2461 @Override
2462 public void putValue(String name, Object value) {
2463 checkNotNull(name, "name");
2464 checkNotNull(value, "value");
2465
2466 final Object old = keyValueStorage.put(name, value);
2467 if (value instanceof SSLSessionBindingListener) {
2468
2469 ((SSLSessionBindingListener) value).valueBound(newSSLSessionBindingEvent(name));
2470 }
2471 notifyUnbound(old, name);
2472 }
2473
2474 @Override
2475 public Object getValue(String name) {
2476 checkNotNull(name, "name");
2477 return keyValueStorage.get(name);
2478 }
2479
2480 @Override
2481 public void removeValue(String name) {
2482 checkNotNull(name, "name");
2483 final Object old = keyValueStorage.remove(name);
2484 notifyUnbound(old, name);
2485 }
2486
2487 @Override
2488 public String[] getValueNames() {
2489 return keyValueStorage.keySet().toArray(EMPTY_STRINGS);
2490 }
2491
2492 private void notifyUnbound(Object value, String name) {
2493 if (value instanceof SSLSessionBindingListener) {
2494
2495 ((SSLSessionBindingListener) value).valueUnbound(newSSLSessionBindingEvent(name));
2496 }
2497 }
2498
2499
2500
2501
2502
2503 @Override
2504 public void handshakeFinished(byte[] id, String cipher, String protocol, byte[] peerCertificate,
2505 byte[][] peerCertificateChain, long creationTime, long timeout)
2506 throws SSLException {
2507 synchronized (ReferenceCountedOpenSslEngine.this) {
2508 if (!isDestroyed()) {
2509 if (this.id == OpenSslSessionId.NULL_ID) {
2510
2511
2512 this.id = id == null ? OpenSslSessionId.NULL_ID : new OpenSslSessionId(id);
2513
2514
2515 this.creationTime = lastAccessed = creationTime;
2516 }
2517 this.cipher = toJavaCipherSuite(cipher);
2518 this.protocol = protocol;
2519
2520 if (clientMode) {
2521 if (isEmpty(peerCertificateChain)) {
2522 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2523 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2524 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2525 } else {
2526 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2527 }
2528 } else {
2529 peerCerts = new Certificate[peerCertificateChain.length];
2530 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2531 x509PeerCerts = new X509Certificate[peerCertificateChain.length];
2532 } else {
2533 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2534 }
2535 initCerts(peerCertificateChain, 0);
2536 }
2537 } else {
2538
2539
2540
2541
2542
2543 if (isEmpty(peerCertificate)) {
2544 peerCerts = EmptyArrays.EMPTY_CERTIFICATES;
2545 x509PeerCerts = EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
2546 } else {
2547 if (isEmpty(peerCertificateChain)) {
2548 peerCerts = new Certificate[] {new LazyX509Certificate(peerCertificate)};
2549 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2550 x509PeerCerts = new X509Certificate[] {
2551 new LazyJavaxX509Certificate(peerCertificate)
2552 };
2553 } else {
2554 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2555 }
2556 } else {
2557 peerCerts = new Certificate[peerCertificateChain.length + 1];
2558 peerCerts[0] = new LazyX509Certificate(peerCertificate);
2559
2560 if (OpenSsl.JAVAX_CERTIFICATE_CREATION_SUPPORTED) {
2561 x509PeerCerts = new X509Certificate[peerCertificateChain.length + 1];
2562 x509PeerCerts[0] = new LazyJavaxX509Certificate(peerCertificate);
2563 } else {
2564 x509PeerCerts = JAVAX_CERTS_NOT_SUPPORTED;
2565 }
2566
2567 initCerts(peerCertificateChain, 1);
2568 }
2569 }
2570 }
2571
2572 calculateMaxWrapOverhead();
2573
2574 handshakeState = HandshakeState.FINISHED;
2575 } else {
2576 throw new SSLException("Already closed");
2577 }
2578 }
2579 }
2580
2581 private void initCerts(byte[][] chain, int startPos) {
2582 for (int i = 0; i < chain.length; i++) {
2583 int certPos = startPos + i;
2584 peerCerts[certPos] = new LazyX509Certificate(chain[i]);
2585 if (x509PeerCerts != JAVAX_CERTS_NOT_SUPPORTED) {
2586 x509PeerCerts[certPos] = new LazyJavaxX509Certificate(chain[i]);
2587 }
2588 }
2589 }
2590
2591 @Override
2592 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2593 synchronized (ReferenceCountedOpenSslEngine.this) {
2594 if (isEmpty(peerCerts)) {
2595 throw new SSLPeerUnverifiedException("peer not verified");
2596 }
2597 return peerCerts.clone();
2598 }
2599 }
2600
2601 @Override
2602 public Certificate[] getLocalCertificates() {
2603 Certificate[] localCerts = this.localCertificateChain;
2604 if (localCerts == null) {
2605 return null;
2606 }
2607 return localCerts.clone();
2608 }
2609
2610 @Override
2611 public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2612 synchronized (ReferenceCountedOpenSslEngine.this) {
2613 if (x509PeerCerts == JAVAX_CERTS_NOT_SUPPORTED) {
2614
2615
2616 throw new UnsupportedOperationException();
2617 }
2618 if (isEmpty(x509PeerCerts)) {
2619 throw new SSLPeerUnverifiedException("peer not verified");
2620 }
2621 return x509PeerCerts.clone();
2622 }
2623 }
2624
2625 @Override
2626 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2627 Certificate[] peer = getPeerCertificates();
2628
2629
2630 return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2631 }
2632
2633 @Override
2634 public Principal getLocalPrincipal() {
2635 Certificate[] local = this.localCertificateChain;
2636 if (local == null || local.length == 0) {
2637 return null;
2638 }
2639 return ((java.security.cert.X509Certificate) local[0]).getSubjectX500Principal();
2640 }
2641
2642 @Override
2643 public String getCipherSuite() {
2644 synchronized (ReferenceCountedOpenSslEngine.this) {
2645 if (cipher == null) {
2646 return SslUtils.INVALID_CIPHER;
2647 }
2648 return cipher;
2649 }
2650 }
2651
2652 @Override
2653 public String getProtocol() {
2654 String protocol = this.protocol;
2655 if (protocol == null) {
2656 synchronized (ReferenceCountedOpenSslEngine.this) {
2657 if (!isDestroyed()) {
2658 protocol = SSL.getVersion(ssl);
2659 } else {
2660 protocol = StringUtil.EMPTY_STRING;
2661 }
2662 }
2663 }
2664 return protocol;
2665 }
2666
2667 @Override
2668 public String getPeerHost() {
2669 return ReferenceCountedOpenSslEngine.this.getPeerHost();
2670 }
2671
2672 @Override
2673 public int getPeerPort() {
2674 return ReferenceCountedOpenSslEngine.this.getPeerPort();
2675 }
2676
2677 @Override
2678 public int getPacketBufferSize() {
2679 return SSL.SSL_MAX_ENCRYPTED_LENGTH;
2680 }
2681
2682 @Override
2683 public int getApplicationBufferSize() {
2684 return applicationBufferSize;
2685 }
2686
2687 @Override
2688 public void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2689 if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2690 applicationBufferSize = MAX_RECORD_SIZE;
2691 }
2692 }
2693
2694 @Override
2695 public String toString() {
2696 return "DefaultOpenSslSession{" +
2697 "sessionContext=" + sessionContext +
2698 ", id=" + id +
2699 '}';
2700 }
2701
2702 @Override
2703 public int hashCode() {
2704 return sessionId().hashCode();
2705 }
2706
2707 @Override
2708 public boolean equals(Object o) {
2709 if (o == this) {
2710 return true;
2711 }
2712
2713 if (!(o instanceof OpenSslSession)) {
2714 return false;
2715 }
2716 return sessionId().equals(((OpenSslSession) o).sessionId());
2717 }
2718 }
2719
2720 private interface NativeSslException {
2721 int errorCode();
2722 }
2723
2724 private static final class OpenSslException extends SSLException implements NativeSslException {
2725 private final int errorCode;
2726
2727 OpenSslException(String reason, int errorCode) {
2728 super(reason);
2729 this.errorCode = errorCode;
2730 }
2731
2732 @Override
2733 public int errorCode() {
2734 return errorCode;
2735 }
2736 }
2737
2738 private static final class OpenSslHandshakeException extends SSLHandshakeException implements NativeSslException {
2739 private final int errorCode;
2740
2741 OpenSslHandshakeException(String reason, int errorCode) {
2742 super(reason);
2743 this.errorCode = errorCode;
2744 }
2745
2746 @Override
2747 public int errorCode() {
2748 return errorCode;
2749 }
2750 }
2751 }