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