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