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