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