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