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.internal.tcnative.Buffer;
21 import io.netty.internal.tcnative.SSL;
22 import io.netty.util.AbstractReferenceCounted;
23 import io.netty.util.ReferenceCounted;
24 import io.netty.util.ResourceLeakDetector;
25 import io.netty.util.ResourceLeakDetectorFactory;
26 import io.netty.util.ResourceLeakTracker;
27 import io.netty.util.internal.EmptyArrays;
28 import io.netty.util.internal.PlatformDependent;
29 import io.netty.util.internal.StringUtil;
30 import io.netty.util.internal.ThrowableUtil;
31 import io.netty.util.internal.UnstableApi;
32 import io.netty.util.internal.logging.InternalLogger;
33 import io.netty.util.internal.logging.InternalLoggerFactory;
34
35 import java.nio.ByteBuffer;
36 import java.nio.ReadOnlyBufferException;
37 import java.security.Principal;
38 import java.security.cert.Certificate;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
46 import java.util.concurrent.locks.Lock;
47
48 import javax.net.ssl.SSLEngine;
49 import javax.net.ssl.SSLEngineResult;
50 import javax.net.ssl.SSLException;
51 import javax.net.ssl.SSLHandshakeException;
52 import javax.net.ssl.SSLParameters;
53 import javax.net.ssl.SSLPeerUnverifiedException;
54 import javax.net.ssl.SSLSession;
55 import javax.net.ssl.SSLSessionBindingEvent;
56 import javax.net.ssl.SSLSessionBindingListener;
57 import javax.net.ssl.SSLSessionContext;
58 import javax.security.cert.X509Certificate;
59
60 import static io.netty.handler.ssl.OpenSsl.memoryAddress;
61 import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2;
62 import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2_HELLO;
63 import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
64 import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
65 import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
66 import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
67 import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
68 import static io.netty.internal.tcnative.SSL.SSL_MAX_PLAINTEXT_LENGTH;
69 import static io.netty.internal.tcnative.SSL.SSL_MAX_RECORD_LENGTH;
70 import static io.netty.util.internal.EmptyArrays.EMPTY_CERTIFICATES;
71 import static io.netty.util.internal.EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
72 import static io.netty.util.internal.ObjectUtil.checkNotNull;
73 import static java.lang.Integer.MAX_VALUE;
74 import static java.lang.Math.min;
75 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
76 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
77 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
78 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
79 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
80 import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
81 import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
82 import static javax.net.ssl.SSLEngineResult.Status.OK;
83
84
85
86
87
88
89
90
91
92
93 public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor {
94
95 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class);
96
97 private static final SSLException BEGIN_HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
98 new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
99 private static final SSLException HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
100 new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "handshake()");
101 private static final SSLException RENEGOTIATION_UNSUPPORTED = ThrowableUtil.unknownStackTrace(
102 new SSLException("renegotiation unsupported"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
103 private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
104 ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
105 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0;
106 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1;
107 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
108 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
109 private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
110 private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
111 SSL.SSL_OP_NO_SSLv2,
112 SSL.SSL_OP_NO_SSLv3,
113 SSL.SSL_OP_NO_TLSv1,
114 SSL.SSL_OP_NO_TLSv1_1,
115 SSL.SSL_OP_NO_TLSv1_2
116 };
117
118
119
120 private static final int DEFAULT_HOSTNAME_VALIDATION_FLAGS = 0;
121
122
123
124
125 static final int MAX_PLAINTEXT_LENGTH = SSL_MAX_PLAINTEXT_LENGTH;
126
127
128
129 private static final int MAX_RECORD_SIZE = SSL_MAX_RECORD_LENGTH;
130
131 private static final AtomicIntegerFieldUpdater<ReferenceCountedOpenSslEngine> DESTROYED_UPDATER =
132 AtomicIntegerFieldUpdater.newUpdater(ReferenceCountedOpenSslEngine.class, "destroyed");
133
134 private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";
135 private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
136 private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
137 private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
138 private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
139 private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
140
141
142 private long ssl;
143 private long networkBIO;
144 private boolean certificateSet;
145
146 private enum HandshakeState {
147
148
149
150 NOT_STARTED,
151
152
153
154 STARTED_IMPLICITLY,
155
156
157
158 STARTED_EXPLICITLY,
159
160
161
162 FINISHED
163 }
164
165 private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
166 private boolean receivedShutdown;
167 private volatile int destroyed;
168 private volatile String applicationProtocol;
169
170
171 private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> leak;
172 private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() {
173 @Override
174 protected void deallocate() {
175 shutdown();
176 if (leak != null) {
177 boolean closed = leak.close(ReferenceCountedOpenSslEngine.this);
178 assert closed;
179 }
180 }
181 };
182
183 private volatile ClientAuth clientAuth = ClientAuth.NONE;
184
185
186 private volatile long lastAccessed = -1;
187
188 private String endPointIdentificationAlgorithm;
189
190 private Object algorithmConstraints;
191 private List<String> sniHostNames;
192
193
194
195 private volatile Collection<?> matchers;
196
197
198 private boolean isInboundDone;
199 private boolean outboundClosed;
200
201 final boolean jdkCompatibilityMode;
202 private final boolean clientMode;
203 private final ByteBufAllocator alloc;
204 private final OpenSslEngineMap engineMap;
205 private final OpenSslApplicationProtocolNegotiator apn;
206 private final OpenSslSession session;
207 private final Certificate[] localCerts;
208 private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
209 private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
210 private final OpenSslKeyMaterialManager keyMaterialManager;
211 private final boolean enableOcsp;
212 private int maxWrapOverhead;
213 private int maxWrapBufferSize;
214
215
216
217 SSLHandshakeException handshakeException;
218
219
220
221
222
223
224
225
226
227
228
229
230
231 ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, ByteBufAllocator alloc, String peerHost,
232 int peerPort, boolean jdkCompatibilityMode, boolean leakDetection) {
233 super(peerHost, peerPort);
234 OpenSsl.ensureAvailability();
235 this.alloc = checkNotNull(alloc, "alloc");
236 apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
237 session = new OpenSslSession(context.sessionContext());
238 clientMode = context.isClient();
239 engineMap = context.engineMap;
240 localCerts = context.keyCertChain;
241 keyMaterialManager = context.keyMaterialManager();
242 enableOcsp = context.enableOcsp;
243 this.jdkCompatibilityMode = jdkCompatibilityMode;
244 Lock readerLock = context.ctxLock.readLock();
245 readerLock.lock();
246 final long finalSsl;
247 try {
248 finalSsl = SSL.newSSL(context.ctx, !context.isClient());
249 } finally {
250 readerLock.unlock();
251 }
252 synchronized (this) {
253 ssl = finalSsl;
254 try {
255 networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize());
256
257
258
259 setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
260
261 if (context.protocols != null) {
262 setEnabledProtocols(context.protocols);
263 }
264
265
266
267 if (clientMode && peerHost != null) {
268 SSL.setTlsExtHostName(ssl, peerHost);
269 }
270
271 if (enableOcsp) {
272 SSL.enableOcsp(ssl);
273 }
274
275 if (!jdkCompatibilityMode) {
276 SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
277 }
278
279
280 calculateMaxWrapOverhead();
281 } catch (Throwable cause) {
282 SSL.freeSSL(ssl);
283 PlatformDependent.throwException(cause);
284 }
285 }
286
287
288
289 leak = leakDetection ? leakDetector.track(this) : null;
290 }
291
292
293
294
295 @UnstableApi
296 public void setOcspResponse(byte[] response) {
297 if (!enableOcsp) {
298 throw new IllegalStateException("OCSP stapling is not enabled");
299 }
300
301 if (clientMode) {
302 throw new IllegalStateException("Not a server SSLEngine");
303 }
304
305 synchronized (this) {
306 SSL.setOcspResponse(ssl, response);
307 }
308 }
309
310
311
312
313 @UnstableApi
314 public byte[] getOcspResponse() {
315 if (!enableOcsp) {
316 throw new IllegalStateException("OCSP stapling is not enabled");
317 }
318
319 if (!clientMode) {
320 throw new IllegalStateException("Not a client SSLEngine");
321 }
322
323 synchronized (this) {
324 return SSL.getOcspResponse(ssl);
325 }
326 }
327
328 @Override
329 public final int refCnt() {
330 return refCnt.refCnt();
331 }
332
333 @Override
334 public final ReferenceCounted retain() {
335 refCnt.retain();
336 return this;
337 }
338
339 @Override
340 public final ReferenceCounted retain(int increment) {
341 refCnt.retain(increment);
342 return this;
343 }
344
345 @Override
346 public final boolean release() {
347 return refCnt.release();
348 }
349
350 @Override
351 public final boolean release(int decrement) {
352 return refCnt.release(decrement);
353 }
354
355 @Override
356 public final synchronized SSLSession getHandshakeSession() {
357
358
359
360
361 switch(handshakeState) {
362 case NOT_STARTED:
363 case FINISHED:
364 return null;
365 default:
366 return session;
367 }
368 }
369
370
371
372
373
374
375 public final synchronized long sslPointer() {
376 return ssl;
377 }
378
379
380
381
382 public final synchronized void shutdown() {
383 if (DESTROYED_UPDATER.compareAndSet(this, 0, 1)) {
384 engineMap.remove(ssl);
385 SSL.freeSSL(ssl);
386 ssl = networkBIO = 0;
387
388 isInboundDone = outboundClosed = true;
389 }
390
391
392 SSL.clearError();
393 }
394
395
396
397
398
399
400 private int writePlaintextData(final ByteBuffer src, int len) {
401 final int pos = src.position();
402 final int limit = src.limit();
403 final int sslWrote;
404
405 if (src.isDirect()) {
406 sslWrote = SSL.writeToSSL(ssl, Buffer.address(src) + pos, len);
407 if (sslWrote > 0) {
408 src.position(pos + sslWrote);
409 }
410 } else {
411 ByteBuf buf = alloc.directBuffer(len);
412 try {
413 src.limit(pos + len);
414
415 buf.setBytes(0, src);
416 src.limit(limit);
417
418 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
419 if (sslWrote > 0) {
420 src.position(pos + sslWrote);
421 } else {
422 src.position(pos);
423 }
424 } finally {
425 buf.release();
426 }
427 }
428 return sslWrote;
429 }
430
431
432
433
434 private ByteBuf writeEncryptedData(final ByteBuffer src, int len) {
435 final int pos = src.position();
436 if (src.isDirect()) {
437 SSL.bioSetByteBuffer(networkBIO, Buffer.address(src) + pos, len, false);
438 } else {
439 final ByteBuf buf = alloc.directBuffer(len);
440 try {
441 final int limit = src.limit();
442 src.limit(pos + len);
443 buf.writeBytes(src);
444
445 src.position(pos);
446 src.limit(limit);
447
448 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
449 return buf;
450 } catch (Throwable cause) {
451 buf.release();
452 PlatformDependent.throwException(cause);
453 }
454 }
455 return null;
456 }
457
458
459
460
461 private int readPlaintextData(final ByteBuffer dst) {
462 final int sslRead;
463 final int pos = dst.position();
464 if (dst.isDirect()) {
465 sslRead = SSL.readFromSSL(ssl, Buffer.address(dst) + pos, dst.limit() - pos);
466 if (sslRead > 0) {
467 dst.position(pos + sslRead);
468 }
469 } else {
470 final int limit = dst.limit();
471 final int len = min(maxEncryptedPacketLength0(), limit - pos);
472 final ByteBuf buf = alloc.directBuffer(len);
473 try {
474 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
475 if (sslRead > 0) {
476 dst.limit(pos + sslRead);
477 buf.getBytes(buf.readerIndex(), dst);
478 dst.limit(limit);
479 }
480 } finally {
481 buf.release();
482 }
483 }
484
485 return sslRead;
486 }
487
488
489
490
491 final synchronized int maxWrapOverhead() {
492 return maxWrapOverhead;
493 }
494
495
496
497
498 final synchronized int maxEncryptedPacketLength() {
499 return maxEncryptedPacketLength0();
500 }
501
502
503
504
505
506 final int maxEncryptedPacketLength0() {
507 return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
508 }
509
510
511
512
513
514
515 final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
516 return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
517 }
518
519 final synchronized int sslPending() {
520 return sslPending0();
521 }
522
523
524
525
526 private void calculateMaxWrapOverhead() {
527 maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
528
529
530
531
532 maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
533 }
534
535 private int sslPending0() {
536
537
538
539
540 return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
541 }
542
543 private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
544 return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
545 }
546
547 @Override
548 public final SSLEngineResult wrap(
549 final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
550
551 if (srcs == null) {
552 throw new IllegalArgumentException("srcs is null");
553 }
554 if (dst == null) {
555 throw new IllegalArgumentException("dst is null");
556 }
557
558 if (offset >= srcs.length || offset + length > srcs.length) {
559 throw new IndexOutOfBoundsException(
560 "offset: " + offset + ", length: " + length +
561 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
562 }
563
564 if (dst.isReadOnly()) {
565 throw new ReadOnlyBufferException();
566 }
567
568 synchronized (this) {
569 if (isOutboundDone()) {
570
571 return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
572 }
573
574 int bytesProduced = 0;
575 ByteBuf bioReadCopyBuf = null;
576 try {
577
578 if (dst.isDirect()) {
579 SSL.bioSetByteBuffer(networkBIO, Buffer.address(dst) + dst.position(), dst.remaining(),
580 true);
581 } else {
582 bioReadCopyBuf = alloc.directBuffer(dst.remaining());
583 SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
584 true);
585 }
586
587 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
588
589
590 if (outboundClosed) {
591
592
593 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
594 if (bytesProduced <= 0) {
595 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
596 }
597
598
599
600 if (!doSSLShutdown()) {
601 return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
602 }
603 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
604 return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
605 }
606
607
608 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
609
610 if (handshakeState != HandshakeState.FINISHED) {
611 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
612
613 handshakeState = HandshakeState.STARTED_IMPLICITLY;
614 }
615
616
617 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
618
619 if (bytesProduced > 0 && handshakeException != null) {
620
621
622
623
624
625
626
627
628 return newResult(NEED_WRAP, 0, bytesProduced);
629 }
630
631 status = handshake();
632
633
634
635 bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
636
637 if (bytesProduced > 0) {
638
639
640
641 return newResult(mayFinishHandshake(status != FINISHED ?
642 bytesProduced == bioLengthBefore ? NEED_WRAP :
643 getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
644 0, bytesProduced);
645 }
646
647 if (status == NEED_UNWRAP) {
648
649 return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
650 }
651
652
653
654 if (outboundClosed) {
655 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
656 return newResultMayFinishHandshake(status, 0, bytesProduced);
657 }
658 }
659
660 final int endOffset = offset + length;
661 if (jdkCompatibilityMode) {
662 int srcsLen = 0;
663 for (int i = offset; i < endOffset; ++i) {
664 final ByteBuffer src = srcs[i];
665 if (src == null) {
666 throw new IllegalArgumentException("srcs[" + i + "] is null");
667 }
668 if (srcsLen == MAX_PLAINTEXT_LENGTH) {
669 continue;
670 }
671
672 srcsLen += src.remaining();
673 if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
674
675
676
677 srcsLen = MAX_PLAINTEXT_LENGTH;
678 }
679 }
680
681
682
683 if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
684 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
685 }
686 }
687
688
689 int bytesConsumed = 0;
690
691 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
692 for (; offset < endOffset; ++offset) {
693 final ByteBuffer src = srcs[offset];
694 final int remaining = src.remaining();
695 if (remaining == 0) {
696 continue;
697 }
698
699 final int bytesWritten;
700 if (jdkCompatibilityMode) {
701
702
703
704 bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
705 } else {
706
707
708
709 final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
710 if (availableCapacityForWrap <= 0) {
711 return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
712 bytesProduced);
713 }
714 bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
715 }
716
717 if (bytesWritten > 0) {
718 bytesConsumed += bytesWritten;
719
720
721 final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
722 bytesProduced += bioLengthBefore - pendingNow;
723 bioLengthBefore = pendingNow;
724
725 if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
726 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
727 }
728 } else {
729 int sslError = SSL.getError(ssl, bytesWritten);
730 if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
731
732 if (!receivedShutdown) {
733 closeAll();
734
735 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
736
737
738
739
740 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
741 status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
742 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
743 : FINISHED);
744 return newResult(hs, bytesConsumed, bytesProduced);
745 }
746
747 return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
748 } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
749
750
751
752 return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
753 } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
754
755
756
757
758
759
760
761
762
763
764
765
766 return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
767 } else {
768
769 throw shutdownWithError("SSL_write");
770 }
771 }
772 }
773 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
774 } finally {
775 SSL.bioClearByteBuffer(networkBIO);
776 if (bioReadCopyBuf == null) {
777 dst.position(dst.position() + bytesProduced);
778 } else {
779 assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
780 " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
781 dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
782 bioReadCopyBuf.release();
783 }
784 }
785 }
786 }
787
788 private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
789 return newResult(OK, hs, bytesConsumed, bytesProduced);
790 }
791
792 private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
793 int bytesConsumed, int bytesProduced) {
794
795
796
797 if (isOutboundDone()) {
798 if (isInboundDone()) {
799
800 hs = NOT_HANDSHAKING;
801
802
803 shutdown();
804 }
805 return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
806 }
807 return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
808 }
809
810 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
811 int bytesConsumed, int bytesProduced) throws SSLException {
812 return newResult(mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
813 bytesConsumed, bytesProduced);
814 }
815
816 private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
817 SSLEngineResult.HandshakeStatus hs,
818 int bytesConsumed, int bytesProduced) throws SSLException {
819 return newResult(status, mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
820 bytesConsumed, bytesProduced);
821 }
822
823
824
825
826 private SSLException shutdownWithError(String operations) {
827 String err = SSL.getLastError();
828 return shutdownWithError(operations, err);
829 }
830
831 private SSLException shutdownWithError(String operation, String err) {
832 if (logger.isDebugEnabled()) {
833 logger.debug("{} failed: OpenSSL error: {}", operation, err);
834 }
835
836
837 shutdown();
838 if (handshakeState == HandshakeState.FINISHED) {
839 return new SSLException(err);
840 }
841 return new SSLHandshakeException(err);
842 }
843
844 public final SSLEngineResult unwrap(
845 final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
846 final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
847
848
849 if (srcs == null) {
850 throw new NullPointerException("srcs");
851 }
852 if (srcsOffset >= srcs.length
853 || srcsOffset + srcsLength > srcs.length) {
854 throw new IndexOutOfBoundsException(
855 "offset: " + srcsOffset + ", length: " + srcsLength +
856 " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
857 }
858 if (dsts == null) {
859 throw new IllegalArgumentException("dsts is null");
860 }
861 if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
862 throw new IndexOutOfBoundsException(
863 "offset: " + dstsOffset + ", length: " + dstsLength +
864 " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
865 }
866 long capacity = 0;
867 final int dstsEndOffset = dstsOffset + dstsLength;
868 for (int i = dstsOffset; i < dstsEndOffset; i ++) {
869 ByteBuffer dst = dsts[i];
870 if (dst == null) {
871 throw new IllegalArgumentException("dsts[" + i + "] is null");
872 }
873 if (dst.isReadOnly()) {
874 throw new ReadOnlyBufferException();
875 }
876 capacity += dst.remaining();
877 }
878
879 final int srcsEndOffset = srcsOffset + srcsLength;
880 long len = 0;
881 for (int i = srcsOffset; i < srcsEndOffset; i++) {
882 ByteBuffer src = srcs[i];
883 if (src == null) {
884 throw new IllegalArgumentException("srcs[" + i + "] is null");
885 }
886 len += src.remaining();
887 }
888
889 synchronized (this) {
890 if (isInboundDone()) {
891 return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
892 }
893
894 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
895
896 if (handshakeState != HandshakeState.FINISHED) {
897 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
898
899 handshakeState = HandshakeState.STARTED_IMPLICITLY;
900 }
901
902 status = handshake();
903 if (status == NEED_WRAP) {
904 return NEED_WRAP_OK;
905 }
906
907 if (isInboundDone) {
908 return NEED_WRAP_CLOSED;
909 }
910 }
911
912 int sslPending = sslPending0();
913 int packetLength;
914
915
916
917
918 if (jdkCompatibilityMode) {
919 if (len < SSL_RECORD_HEADER_LENGTH) {
920 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
921 }
922
923 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
924 if (packetLength == SslUtils.NOT_ENCRYPTED) {
925 throw new NotSslRecordException("not an SSL/TLS record");
926 }
927
928 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
929 if (packetLengthDataOnly > capacity) {
930
931
932 if (packetLengthDataOnly > MAX_RECORD_SIZE) {
933
934
935
936
937
938 throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
939 session.getApplicationBufferSize());
940 } else {
941 session.tryExpandApplicationBufferSize(packetLengthDataOnly);
942 }
943 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
944 }
945
946 if (len < packetLength) {
947
948
949 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
950 }
951 } else if (len == 0 && sslPending <= 0) {
952 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
953 } else if (capacity == 0) {
954 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
955 } else {
956 packetLength = (int) min(MAX_VALUE, len);
957 }
958
959
960 assert srcsOffset < srcsEndOffset;
961
962
963 assert capacity > 0;
964
965
966 int bytesProduced = 0;
967 int bytesConsumed = 0;
968 try {
969 srcLoop:
970 for (;;) {
971 ByteBuffer src = srcs[srcsOffset];
972 int remaining = src.remaining();
973 final ByteBuf bioWriteCopyBuf;
974 int pendingEncryptedBytes;
975 if (remaining == 0) {
976 if (sslPending <= 0) {
977
978
979 if (++srcsOffset >= srcsEndOffset) {
980 break;
981 }
982 continue;
983 } else {
984 bioWriteCopyBuf = null;
985 pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
986 }
987 } else {
988
989
990 pendingEncryptedBytes = min(packetLength, remaining);
991 bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
992 }
993 try {
994 for (;;) {
995 ByteBuffer dst = dsts[dstsOffset];
996 if (!dst.hasRemaining()) {
997
998 if (++dstsOffset >= dstsEndOffset) {
999 break srcLoop;
1000 }
1001 continue;
1002 }
1003
1004 int bytesRead = readPlaintextData(dst);
1005
1006
1007
1008 int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1009 bytesConsumed += localBytesConsumed;
1010 packetLength -= localBytesConsumed;
1011 pendingEncryptedBytes -= localBytesConsumed;
1012 src.position(src.position() + localBytesConsumed);
1013
1014 if (bytesRead > 0) {
1015 bytesProduced += bytesRead;
1016
1017 if (!dst.hasRemaining()) {
1018 sslPending = sslPending0();
1019
1020 if (++dstsOffset >= dstsEndOffset) {
1021 return sslPending > 0 ?
1022 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1023 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1024 bytesConsumed, bytesProduced);
1025 }
1026 } else if (packetLength == 0 || jdkCompatibilityMode) {
1027
1028
1029 break srcLoop;
1030 }
1031 } else {
1032 int sslError = SSL.getError(ssl, bytesRead);
1033 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1034
1035
1036 break;
1037 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1038
1039 if (!receivedShutdown) {
1040 closeAll();
1041 }
1042 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1043 bytesConsumed, bytesProduced);
1044 } else {
1045 return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed,
1046 bytesProduced);
1047 }
1048 }
1049 }
1050
1051 if (++srcsOffset >= srcsEndOffset) {
1052 break;
1053 }
1054 } finally {
1055 if (bioWriteCopyBuf != null) {
1056 bioWriteCopyBuf.release();
1057 }
1058 }
1059 }
1060 } finally {
1061 SSL.bioClearByteBuffer(networkBIO);
1062 rejectRemoteInitiatedRenegotiation();
1063 }
1064
1065
1066 if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1067 closeAll();
1068 }
1069
1070 return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1071 }
1072 }
1073
1074 private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) throws SSLException {
1075 String errStr = SSL.getErrorString(err);
1076
1077
1078
1079
1080
1081 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1082 if (handshakeException == null && handshakeState != HandshakeState.FINISHED) {
1083
1084
1085 handshakeException = new SSLHandshakeException(errStr);
1086 }
1087 return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1088 }
1089 throw shutdownWithError("SSL_read", errStr);
1090 }
1091
1092 private void closeAll() throws SSLException {
1093 receivedShutdown = true;
1094 closeOutbound();
1095 closeInbound();
1096 }
1097
1098 private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1099
1100
1101
1102 if (!isDestroyed() && SSL.getHandshakeCount(ssl) > 1) {
1103
1104
1105 shutdown();
1106 throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1107 }
1108 }
1109
1110 public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1111 return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1112 }
1113
1114 private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1115 singleSrcBuffer[0] = src;
1116 return singleSrcBuffer;
1117 }
1118
1119 private void resetSingleSrcBuffer() {
1120 singleSrcBuffer[0] = null;
1121 }
1122
1123 private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1124 singleDstBuffer[0] = src;
1125 return singleDstBuffer;
1126 }
1127
1128 private void resetSingleDstBuffer() {
1129 singleDstBuffer[0] = null;
1130 }
1131
1132 @Override
1133 public final synchronized SSLEngineResult unwrap(
1134 final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1135 try {
1136 return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1137 } finally {
1138 resetSingleSrcBuffer();
1139 }
1140 }
1141
1142 @Override
1143 public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1144 try {
1145 return wrap(singleSrcBuffer(src), dst);
1146 } finally {
1147 resetSingleSrcBuffer();
1148 }
1149 }
1150
1151 @Override
1152 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1153 try {
1154 return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1155 } finally {
1156 resetSingleSrcBuffer();
1157 resetSingleDstBuffer();
1158 }
1159 }
1160
1161 @Override
1162 public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1163 try {
1164 return unwrap(singleSrcBuffer(src), dsts);
1165 } finally {
1166 resetSingleSrcBuffer();
1167 }
1168 }
1169
1170 @Override
1171 public final Runnable getDelegatedTask() {
1172
1173
1174 return null;
1175 }
1176
1177 @Override
1178 public final synchronized void closeInbound() throws SSLException {
1179 if (isInboundDone) {
1180 return;
1181 }
1182
1183 isInboundDone = true;
1184
1185 if (isOutboundDone()) {
1186
1187
1188 shutdown();
1189 }
1190
1191 if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1192 throw new SSLException(
1193 "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1194 }
1195 }
1196
1197 @Override
1198 public final synchronized boolean isInboundDone() {
1199 return isInboundDone;
1200 }
1201
1202 @Override
1203 public final synchronized void closeOutbound() {
1204 if (outboundClosed) {
1205 return;
1206 }
1207
1208 outboundClosed = true;
1209
1210 if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) {
1211 int mode = SSL.getShutdown(ssl);
1212 if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1213 doSSLShutdown();
1214 }
1215 } else {
1216
1217 shutdown();
1218 }
1219 }
1220
1221
1222
1223
1224
1225 private boolean doSSLShutdown() {
1226 if (SSL.isInInit(ssl) != 0) {
1227
1228
1229
1230
1231 return false;
1232 }
1233 int err = SSL.shutdownSSL(ssl);
1234 if (err < 0) {
1235 int sslErr = SSL.getError(ssl, err);
1236 if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1237 if (logger.isDebugEnabled()) {
1238 logger.debug("SSL_shutdown failed: OpenSSL error: {}", SSL.getLastError());
1239 }
1240
1241 shutdown();
1242 return false;
1243 }
1244 SSL.clearError();
1245 }
1246 return true;
1247 }
1248
1249 @Override
1250 public final synchronized boolean isOutboundDone() {
1251
1252
1253 return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1254 }
1255
1256 @Override
1257 public final String[] getSupportedCipherSuites() {
1258 return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(new String[OpenSsl.AVAILABLE_CIPHER_SUITES.size()]);
1259 }
1260
1261 @Override
1262 public final String[] getEnabledCipherSuites() {
1263 final String[] enabled;
1264 synchronized (this) {
1265 if (!isDestroyed()) {
1266 enabled = SSL.getCiphers(ssl);
1267 } else {
1268 return EmptyArrays.EMPTY_STRINGS;
1269 }
1270 }
1271 if (enabled == null) {
1272 return EmptyArrays.EMPTY_STRINGS;
1273 } else {
1274 synchronized (this) {
1275 for (int i = 0; i < enabled.length; i++) {
1276 String mapped = toJavaCipherSuite(enabled[i]);
1277 if (mapped != null) {
1278 enabled[i] = mapped;
1279 }
1280 }
1281 }
1282 return enabled;
1283 }
1284 }
1285
1286 @Override
1287 public final void setEnabledCipherSuites(String[] cipherSuites) {
1288 checkNotNull(cipherSuites, "cipherSuites");
1289
1290 final StringBuilder buf = new StringBuilder();
1291 for (String c: cipherSuites) {
1292 if (c == null) {
1293 break;
1294 }
1295
1296 String converted = CipherSuiteConverter.toOpenSsl(c);
1297 if (converted == null) {
1298 converted = c;
1299 }
1300
1301 if (!OpenSsl.isCipherSuiteAvailable(converted)) {
1302 throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')');
1303 }
1304
1305 buf.append(converted);
1306 buf.append(':');
1307 }
1308
1309 if (buf.length() == 0) {
1310 throw new IllegalArgumentException("empty cipher suites");
1311 }
1312 buf.setLength(buf.length() - 1);
1313
1314 final String cipherSuiteSpec = buf.toString();
1315
1316 synchronized (this) {
1317 if (!isDestroyed()) {
1318 try {
1319 SSL.setCipherSuites(ssl, cipherSuiteSpec);
1320 } catch (Exception e) {
1321 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1322 }
1323 } else {
1324 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1325 }
1326 }
1327 }
1328
1329 @Override
1330 public final String[] getSupportedProtocols() {
1331 return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(new String[OpenSsl.SUPPORTED_PROTOCOLS_SET.size()]);
1332 }
1333
1334 @Override
1335 public final String[] getEnabledProtocols() {
1336 List<String> enabled = new ArrayList<String>(6);
1337
1338 enabled.add(PROTOCOL_SSL_V2_HELLO);
1339
1340 int opts;
1341 synchronized (this) {
1342 if (!isDestroyed()) {
1343 opts = SSL.getOptions(ssl);
1344 } else {
1345 return enabled.toArray(new String[1]);
1346 }
1347 }
1348 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1, PROTOCOL_TLS_V1)) {
1349 enabled.add(PROTOCOL_TLS_V1);
1350 }
1351 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_1, PROTOCOL_TLS_V1_1)) {
1352 enabled.add(PROTOCOL_TLS_V1_1);
1353 }
1354 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
1355 enabled.add(PROTOCOL_TLS_V1_2);
1356 }
1357 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
1358 enabled.add(PROTOCOL_SSL_V2);
1359 }
1360 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv3, PROTOCOL_SSL_V3)) {
1361 enabled.add(PROTOCOL_SSL_V3);
1362 }
1363 return enabled.toArray(new String[enabled.size()]);
1364 }
1365
1366 private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1367
1368
1369 return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString);
1370 }
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381 @Override
1382 public final void setEnabledProtocols(String[] protocols) {
1383 if (protocols == null) {
1384
1385 throw new IllegalArgumentException();
1386 }
1387 int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1388 int maxProtocolIndex = 0;
1389 for (String p: protocols) {
1390 if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
1391 throw new IllegalArgumentException("Protocol " + p + " is not supported.");
1392 }
1393 if (p.equals(PROTOCOL_SSL_V2)) {
1394 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1395 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1396 }
1397 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1398 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1399 }
1400 } else if (p.equals(PROTOCOL_SSL_V3)) {
1401 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1402 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1403 }
1404 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1405 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1406 }
1407 } else if (p.equals(PROTOCOL_TLS_V1)) {
1408 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1409 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1410 }
1411 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1412 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1413 }
1414 } else if (p.equals(PROTOCOL_TLS_V1_1)) {
1415 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1416 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1417 }
1418 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1419 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1420 }
1421 } else if (p.equals(PROTOCOL_TLS_V1_2)) {
1422 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1423 minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1424 }
1425 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1426 maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1427 }
1428 }
1429 }
1430 synchronized (this) {
1431 if (!isDestroyed()) {
1432
1433 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
1434 SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2);
1435
1436 int opts = 0;
1437 for (int i = 0; i < minProtocolIndex; ++i) {
1438 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1439 }
1440 assert maxProtocolIndex != MAX_VALUE;
1441 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1442 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1443 }
1444
1445
1446 SSL.setOptions(ssl, opts);
1447 } else {
1448 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1449 }
1450 }
1451 }
1452
1453 @Override
1454 public final SSLSession getSession() {
1455 return session;
1456 }
1457
1458 @Override
1459 public final synchronized void beginHandshake() throws SSLException {
1460 switch (handshakeState) {
1461 case STARTED_IMPLICITLY:
1462 checkEngineClosed(BEGIN_HANDSHAKE_ENGINE_CLOSED);
1463
1464
1465
1466
1467
1468
1469
1470 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1471 calculateMaxWrapOverhead();
1472
1473 break;
1474 case STARTED_EXPLICITLY:
1475
1476 break;
1477 case FINISHED:
1478 throw RENEGOTIATION_UNSUPPORTED;
1479 case NOT_STARTED:
1480 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1481 handshake();
1482 calculateMaxWrapOverhead();
1483 break;
1484 default:
1485 throw new Error();
1486 }
1487 }
1488
1489 private void checkEngineClosed(SSLException cause) throws SSLException {
1490 if (isDestroyed()) {
1491 throw cause;
1492 }
1493 }
1494
1495 private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1496
1497 return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1498 }
1499
1500 private static boolean isEmpty(Object[] arr) {
1501 return arr == null || arr.length == 0;
1502 }
1503
1504 private static boolean isEmpty(byte[] cert) {
1505 return cert == null || cert.length == 0;
1506 }
1507
1508 private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1509 if (handshakeState == HandshakeState.FINISHED) {
1510 return FINISHED;
1511 }
1512 checkEngineClosed(HANDSHAKE_ENGINE_CLOSED);
1513
1514
1515
1516
1517
1518 SSLHandshakeException exception = handshakeException;
1519 if (exception != null) {
1520 if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1521
1522 return NEED_WRAP;
1523 }
1524
1525
1526 handshakeException = null;
1527 shutdown();
1528 throw exception;
1529 }
1530
1531
1532 engineMap.add(this);
1533 if (lastAccessed == -1) {
1534 lastAccessed = System.currentTimeMillis();
1535 }
1536
1537 if (!certificateSet && keyMaterialManager != null) {
1538 certificateSet = true;
1539 keyMaterialManager.setKeyMaterial(this);
1540 }
1541
1542 int code = SSL.doHandshake(ssl);
1543 if (code <= 0) {
1544
1545
1546 if (handshakeException != null) {
1547 exception = handshakeException;
1548 handshakeException = null;
1549 shutdown();
1550 throw exception;
1551 }
1552
1553 int sslError = SSL.getError(ssl, code);
1554 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1555 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
1556 } else {
1557
1558 throw shutdownWithError("SSL_do_handshake");
1559 }
1560 }
1561
1562 session.handshakeFinished();
1563 engineMap.remove(ssl);
1564 return FINISHED;
1565 }
1566
1567 private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
1568 throws SSLException {
1569 if (status == NOT_HANDSHAKING && handshakeState != HandshakeState.FINISHED) {
1570
1571
1572 return handshake();
1573 }
1574 return status;
1575 }
1576
1577 @Override
1578 public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
1579
1580 return needPendingStatus() ? pendingStatus(SSL.bioLengthNonApplication(networkBIO)) : NOT_HANDSHAKING;
1581 }
1582
1583 private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
1584
1585 return needPendingStatus() ? pendingStatus(pending) : NOT_HANDSHAKING;
1586 }
1587
1588 private boolean needPendingStatus() {
1589 return handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()
1590 && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone());
1591 }
1592
1593
1594
1595
1596 private String toJavaCipherSuite(String openSslCipherSuite) {
1597 if (openSslCipherSuite == null) {
1598 return null;
1599 }
1600
1601 String prefix = toJavaCipherSuitePrefix(SSL.getVersion(ssl));
1602 return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
1603 }
1604
1605
1606
1607
1608 private static String toJavaCipherSuitePrefix(String protocolVersion) {
1609 final char c;
1610 if (protocolVersion == null || protocolVersion.isEmpty()) {
1611 c = 0;
1612 } else {
1613 c = protocolVersion.charAt(0);
1614 }
1615
1616 switch (c) {
1617 case 'T':
1618 return "TLS";
1619 case 'S':
1620 return "SSL";
1621 default:
1622 return "UNKNOWN";
1623 }
1624 }
1625
1626 @Override
1627 public final void setUseClientMode(boolean clientMode) {
1628 if (clientMode != this.clientMode) {
1629 throw new UnsupportedOperationException();
1630 }
1631 }
1632
1633 @Override
1634 public final boolean getUseClientMode() {
1635 return clientMode;
1636 }
1637
1638 @Override
1639 public final void setNeedClientAuth(boolean b) {
1640 setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
1641 }
1642
1643 @Override
1644 public final boolean getNeedClientAuth() {
1645 return clientAuth == ClientAuth.REQUIRE;
1646 }
1647
1648 @Override
1649 public final void setWantClientAuth(boolean b) {
1650 setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
1651 }
1652
1653 @Override
1654 public final boolean getWantClientAuth() {
1655 return clientAuth == ClientAuth.OPTIONAL;
1656 }
1657
1658
1659
1660
1661
1662 @UnstableApi
1663 public final synchronized void setVerify(int verifyMode, int depth) {
1664 SSL.setVerify(ssl, verifyMode, depth);
1665 }
1666
1667 private void setClientAuth(ClientAuth mode) {
1668 if (clientMode) {
1669 return;
1670 }
1671 synchronized (this) {
1672 if (clientAuth == mode) {
1673
1674 return;
1675 }
1676 switch (mode) {
1677 case NONE:
1678 SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1679 break;
1680 case REQUIRE:
1681 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1682 break;
1683 case OPTIONAL:
1684 SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1685 break;
1686 default:
1687 throw new Error(mode.toString());
1688 }
1689 clientAuth = mode;
1690 }
1691 }
1692
1693 @Override
1694 public final void setEnableSessionCreation(boolean b) {
1695 if (b) {
1696 throw new UnsupportedOperationException();
1697 }
1698 }
1699
1700 @Override
1701 public final boolean getEnableSessionCreation() {
1702 return false;
1703 }
1704
1705 @Override
1706 public final synchronized SSLParameters getSSLParameters() {
1707 SSLParameters sslParameters = super.getSSLParameters();
1708
1709 int version = PlatformDependent.javaVersion();
1710 if (version >= 7) {
1711 sslParameters.setEndpointIdentificationAlgorithm(endPointIdentificationAlgorithm);
1712 Java7SslParametersUtils.setAlgorithmConstraints(sslParameters, algorithmConstraints);
1713 if (version >= 8) {
1714 if (sniHostNames != null) {
1715 Java8SslUtils.setSniHostNames(sslParameters, sniHostNames);
1716 }
1717 if (!isDestroyed()) {
1718 Java8SslUtils.setUseCipherSuitesOrder(
1719 sslParameters, (SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
1720 }
1721
1722 Java8SslUtils.setSNIMatchers(sslParameters, matchers);
1723 }
1724 }
1725 return sslParameters;
1726 }
1727
1728 @Override
1729 public final synchronized void setSSLParameters(SSLParameters sslParameters) {
1730 int version = PlatformDependent.javaVersion();
1731 if (version >= 7) {
1732 if (sslParameters.getAlgorithmConstraints() != null) {
1733 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
1734 }
1735
1736 if (version >= 8) {
1737 if (!isDestroyed()) {
1738 if (clientMode) {
1739 final List<String> sniHostNames = Java8SslUtils.getSniHostNames(sslParameters);
1740 for (String name: sniHostNames) {
1741 SSL.setTlsExtHostName(ssl, name);
1742 }
1743 this.sniHostNames = sniHostNames;
1744 }
1745 if (Java8SslUtils.getUseCipherSuitesOrder(sslParameters)) {
1746 SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1747 } else {
1748 SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1749 }
1750 }
1751 matchers = sslParameters.getSNIMatchers();
1752 }
1753
1754 final String endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
1755 final boolean endPointVerificationEnabled = endPointIdentificationAlgorithm != null &&
1756 !endPointIdentificationAlgorithm.isEmpty();
1757 SSL.setHostNameValidation(ssl, DEFAULT_HOSTNAME_VALIDATION_FLAGS,
1758 endPointVerificationEnabled ? getPeerHost() : null);
1759
1760
1761 if (clientMode && endPointVerificationEnabled) {
1762 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
1763 }
1764
1765 this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
1766 algorithmConstraints = sslParameters.getAlgorithmConstraints();
1767 }
1768 super.setSSLParameters(sslParameters);
1769 }
1770
1771 private boolean isDestroyed() {
1772 return destroyed != 0;
1773 }
1774
1775 final boolean checkSniHostnameMatch(String hostname) {
1776 return Java8SslUtils.checkSniHostnameMatch(matchers, hostname);
1777 }
1778
1779 @Override
1780 public String getNegotiatedApplicationProtocol() {
1781 return applicationProtocol;
1782 }
1783
1784 private final class OpenSslSession implements SSLSession {
1785 private final OpenSslSessionContext sessionContext;
1786
1787
1788
1789 private X509Certificate[] x509PeerCerts;
1790 private Certificate[] peerCerts;
1791 private String protocol;
1792 private String cipher;
1793 private byte[] id;
1794 private long creationTime;
1795 private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
1796
1797
1798 private Map<String, Object> values;
1799
1800 OpenSslSession(OpenSslSessionContext sessionContext) {
1801 this.sessionContext = sessionContext;
1802 }
1803
1804 @Override
1805 public byte[] getId() {
1806 synchronized (ReferenceCountedOpenSslEngine.this) {
1807 if (id == null) {
1808 return EmptyArrays.EMPTY_BYTES;
1809 }
1810 return id.clone();
1811 }
1812 }
1813
1814 @Override
1815 public SSLSessionContext getSessionContext() {
1816 return sessionContext;
1817 }
1818
1819 @Override
1820 public long getCreationTime() {
1821 synchronized (ReferenceCountedOpenSslEngine.this) {
1822 if (creationTime == 0 && !isDestroyed()) {
1823 creationTime = SSL.getTime(ssl) * 1000L;
1824 }
1825 }
1826 return creationTime;
1827 }
1828
1829 @Override
1830 public long getLastAccessedTime() {
1831 long lastAccessed = ReferenceCountedOpenSslEngine.this.lastAccessed;
1832
1833 return lastAccessed == -1 ? getCreationTime() : lastAccessed;
1834 }
1835
1836 @Override
1837 public void invalidate() {
1838 synchronized (ReferenceCountedOpenSslEngine.this) {
1839 if (!isDestroyed()) {
1840 SSL.setTimeout(ssl, 0);
1841 }
1842 }
1843 }
1844
1845 @Override
1846 public boolean isValid() {
1847 synchronized (ReferenceCountedOpenSslEngine.this) {
1848 if (!isDestroyed()) {
1849 return System.currentTimeMillis() - (SSL.getTimeout(ssl) * 1000L) < (SSL.getTime(ssl) * 1000L);
1850 }
1851 }
1852 return false;
1853 }
1854
1855 @Override
1856 public void putValue(String name, Object value) {
1857 if (name == null) {
1858 throw new NullPointerException("name");
1859 }
1860 if (value == null) {
1861 throw new NullPointerException("value");
1862 }
1863 Map<String, Object> values = this.values;
1864 if (values == null) {
1865
1866 values = this.values = new HashMap<String, Object>(2);
1867 }
1868 Object old = values.put(name, value);
1869 if (value instanceof SSLSessionBindingListener) {
1870 ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
1871 }
1872 notifyUnbound(old, name);
1873 }
1874
1875 @Override
1876 public Object getValue(String name) {
1877 if (name == null) {
1878 throw new NullPointerException("name");
1879 }
1880 if (values == null) {
1881 return null;
1882 }
1883 return values.get(name);
1884 }
1885
1886 @Override
1887 public void removeValue(String name) {
1888 if (name == null) {
1889 throw new NullPointerException("name");
1890 }
1891 Map<String, Object> values = this.values;
1892 if (values == null) {
1893 return;
1894 }
1895 Object old = values.remove(name);
1896 notifyUnbound(old, name);
1897 }
1898
1899 @Override
1900 public String[] getValueNames() {
1901 Map<String, Object> values = this.values;
1902 if (values == null || values.isEmpty()) {
1903 return EmptyArrays.EMPTY_STRINGS;
1904 }
1905 return values.keySet().toArray(new String[values.size()]);
1906 }
1907
1908 private void notifyUnbound(Object value, String name) {
1909 if (value instanceof SSLSessionBindingListener) {
1910 ((SSLSessionBindingListener) value).valueUnbound(new SSLSessionBindingEvent(this, name));
1911 }
1912 }
1913
1914
1915
1916
1917
1918 void handshakeFinished() throws SSLException {
1919 synchronized (ReferenceCountedOpenSslEngine.this) {
1920 if (!isDestroyed()) {
1921 id = SSL.getSessionId(ssl);
1922 cipher = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
1923 protocol = SSL.getVersion(ssl);
1924
1925 initPeerCerts();
1926 selectApplicationProtocol();
1927 calculateMaxWrapOverhead();
1928
1929 handshakeState = HandshakeState.FINISHED;
1930 } else {
1931 throw new SSLException("Already closed");
1932 }
1933 }
1934 }
1935
1936
1937
1938
1939
1940 private void initPeerCerts() {
1941
1942 byte[][] chain = SSL.getPeerCertChain(ssl);
1943 if (clientMode) {
1944 if (isEmpty(chain)) {
1945 peerCerts = EMPTY_CERTIFICATES;
1946 x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
1947 } else {
1948 peerCerts = new Certificate[chain.length];
1949 x509PeerCerts = new X509Certificate[chain.length];
1950 initCerts(chain, 0);
1951 }
1952 } else {
1953
1954
1955
1956
1957
1958 byte[] clientCert = SSL.getPeerCertificate(ssl);
1959 if (isEmpty(clientCert)) {
1960 peerCerts = EMPTY_CERTIFICATES;
1961 x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
1962 } else {
1963 if (isEmpty(chain)) {
1964 peerCerts = new Certificate[] {new OpenSslX509Certificate(clientCert)};
1965 x509PeerCerts = new X509Certificate[] {new OpenSslJavaxX509Certificate(clientCert)};
1966 } else {
1967 peerCerts = new Certificate[chain.length + 1];
1968 x509PeerCerts = new X509Certificate[chain.length + 1];
1969 peerCerts[0] = new OpenSslX509Certificate(clientCert);
1970 x509PeerCerts[0] = new OpenSslJavaxX509Certificate(clientCert);
1971 initCerts(chain, 1);
1972 }
1973 }
1974 }
1975 }
1976
1977 private void initCerts(byte[][] chain, int startPos) {
1978 for (int i = 0; i < chain.length; i++) {
1979 int certPos = startPos + i;
1980 peerCerts[certPos] = new OpenSslX509Certificate(chain[i]);
1981 x509PeerCerts[certPos] = new OpenSslJavaxX509Certificate(chain[i]);
1982 }
1983 }
1984
1985
1986
1987
1988 private void selectApplicationProtocol() throws SSLException {
1989 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
1990 List<String> protocols = apn.protocols();
1991 String applicationProtocol;
1992 switch (apn.protocol()) {
1993 case NONE:
1994 break;
1995
1996
1997 case ALPN:
1998 applicationProtocol = SSL.getAlpnSelected(ssl);
1999 if (applicationProtocol != null) {
2000 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2001 protocols, behavior, applicationProtocol);
2002 }
2003 break;
2004 case NPN:
2005 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2006 if (applicationProtocol != null) {
2007 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2008 protocols, behavior, applicationProtocol);
2009 }
2010 break;
2011 case NPN_AND_ALPN:
2012 applicationProtocol = SSL.getAlpnSelected(ssl);
2013 if (applicationProtocol == null) {
2014 applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2015 }
2016 if (applicationProtocol != null) {
2017 ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2018 protocols, behavior, applicationProtocol);
2019 }
2020 break;
2021 default:
2022 throw new Error();
2023 }
2024 }
2025
2026 private String selectApplicationProtocol(List<String> protocols,
2027 ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2028 String applicationProtocol) throws SSLException {
2029 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2030 return applicationProtocol;
2031 } else {
2032 int size = protocols.size();
2033 assert size > 0;
2034 if (protocols.contains(applicationProtocol)) {
2035 return applicationProtocol;
2036 } else {
2037 if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2038 return protocols.get(size - 1);
2039 } else {
2040 throw new SSLException("unknown protocol " + applicationProtocol);
2041 }
2042 }
2043 }
2044 }
2045
2046 @Override
2047 public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2048 synchronized (ReferenceCountedOpenSslEngine.this) {
2049 if (isEmpty(peerCerts)) {
2050 throw new SSLPeerUnverifiedException("peer not verified");
2051 }
2052 return peerCerts.clone();
2053 }
2054 }
2055
2056 @Override
2057 public Certificate[] getLocalCertificates() {
2058 if (localCerts == null) {
2059 return null;
2060 }
2061 return localCerts.clone();
2062 }
2063
2064 @Override
2065 public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2066 synchronized (ReferenceCountedOpenSslEngine.this) {
2067 if (isEmpty(x509PeerCerts)) {
2068 throw new SSLPeerUnverifiedException("peer not verified");
2069 }
2070 return x509PeerCerts.clone();
2071 }
2072 }
2073
2074 @Override
2075 public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2076 Certificate[] peer = getPeerCertificates();
2077
2078
2079 return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2080 }
2081
2082 @Override
2083 public Principal getLocalPrincipal() {
2084 Certificate[] local = localCerts;
2085 if (local == null || local.length == 0) {
2086 return null;
2087 }
2088 return ((java.security.cert.X509Certificate) local[0]).getIssuerX500Principal();
2089 }
2090
2091 @Override
2092 public String getCipherSuite() {
2093 synchronized (ReferenceCountedOpenSslEngine.this) {
2094 if (cipher == null) {
2095 return INVALID_CIPHER;
2096 }
2097 return cipher;
2098 }
2099 }
2100
2101 @Override
2102 public String getProtocol() {
2103 String protocol = this.protocol;
2104 if (protocol == null) {
2105 synchronized (ReferenceCountedOpenSslEngine.this) {
2106 if (!isDestroyed()) {
2107 protocol = SSL.getVersion(ssl);
2108 } else {
2109 protocol = StringUtil.EMPTY_STRING;
2110 }
2111 }
2112 }
2113 return protocol;
2114 }
2115
2116 @Override
2117 public String getPeerHost() {
2118 return ReferenceCountedOpenSslEngine.this.getPeerHost();
2119 }
2120
2121 @Override
2122 public int getPeerPort() {
2123 return ReferenceCountedOpenSslEngine.this.getPeerPort();
2124 }
2125
2126 @Override
2127 public int getPacketBufferSize() {
2128 return maxEncryptedPacketLength();
2129 }
2130
2131 @Override
2132 public int getApplicationBufferSize() {
2133 return applicationBufferSize;
2134 }
2135
2136
2137
2138
2139
2140
2141
2142 void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2143 if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2144 applicationBufferSize = MAX_RECORD_SIZE;
2145 }
2146 }
2147 }
2148 }