1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.io.ssl;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.ClosedChannelException;
24 import java.util.Arrays;
25 import java.util.concurrent.Executor;
26 import javax.net.ssl.SSLEngine;
27 import javax.net.ssl.SSLEngineResult;
28 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
29 import javax.net.ssl.SSLEngineResult.Status;
30 import javax.net.ssl.SSLException;
31
32 import org.eclipse.jetty.io.AbstractConnection;
33 import org.eclipse.jetty.io.AbstractEndPoint;
34 import org.eclipse.jetty.io.ByteBufferPool;
35 import org.eclipse.jetty.io.Connection;
36 import org.eclipse.jetty.io.EndPoint;
37 import org.eclipse.jetty.io.EofException;
38 import org.eclipse.jetty.io.FillInterest;
39 import org.eclipse.jetty.io.RuntimeIOException;
40 import org.eclipse.jetty.io.SelectChannelEndPoint;
41 import org.eclipse.jetty.io.WriteFlusher;
42 import org.eclipse.jetty.util.BufferUtil;
43 import org.eclipse.jetty.util.Callback;
44 import org.eclipse.jetty.util.log.Log;
45 import org.eclipse.jetty.util.log.Logger;
46
47 /**
48 * A Connection that acts as an interceptor between an EndPoint providing SSL encrypted data
49 * and another consumer of an EndPoint (typically an {@link Connection} like HttpConnection) that
50 * wants unencrypted data.
51 * <p>
52 * The connector uses an {@link EndPoint} (typically {@link SelectChannelEndPoint}) as
53 * it's source/sink of encrypted data. It then provides an endpoint via {@link #getDecryptedEndPoint()} to
54 * expose a source/sink of unencrypted data to another connection (eg HttpConnection).
55 * <p>
56 * The design of this class is based on a clear separation between the passive methods, which do not block nor schedule any
57 * asynchronous callbacks, and active methods that do schedule asynchronous callbacks.
58 * <p>
59 * The passive methods are {@link DecryptedEndPoint#fill(ByteBuffer)} and {@link DecryptedEndPoint#flush(ByteBuffer...)}. They make best
60 * effort attempts to progress the connection using only calls to the encrypted {@link EndPoint#fill(ByteBuffer)} and {@link EndPoint#flush(ByteBuffer...)}
61 * methods. They will never block nor schedule any readInterest or write callbacks. If a fill/flush cannot progress either because
62 * of network congestion or waiting for an SSL handshake message, then the fill/flush will simply return with zero bytes filled/flushed.
63 * Specifically, if a flush cannot proceed because it needs to receive a handshake message, then the flush will attempt to fill bytes from the
64 * encrypted endpoint, but if insufficient bytes are read it will NOT call {@link EndPoint#fillInterested(Callback)}.
65 * <p>
66 * It is only the active methods : {@link DecryptedEndPoint#fillInterested(Callback)} and
67 * {@link DecryptedEndPoint#write(Callback, ByteBuffer...)} that may schedule callbacks by calling the encrypted
68 * {@link EndPoint#fillInterested(Callback)} and {@link EndPoint#write(Callback, ByteBuffer...)}
69 * methods. For normal data handling, the decrypted fillInterest method will result in an encrypted fillInterest and a decrypted
70 * write will result in an encrypted write. However, due to SSL handshaking requirements, it is also possible for a decrypted fill
71 * to call the encrypted write and for the decrypted flush to call the encrypted fillInterested methods.
72 * <p>
73 * MOST IMPORTANTLY, the encrypted callbacks from the active methods (#onFillable() and WriteFlusher#completeWrite()) do no filling or flushing
74 * themselves. Instead they simple make the callbacks to the decrypted callbacks, so that the passive encrypted fill/flush will
75 * be called again and make another best effort attempt to progress the connection.
76 *
77 */
78 public class SslConnection extends AbstractConnection
79 {
80 private static final Logger LOG = Log.getLogger(SslConnection.class);
81 private static final boolean DEBUG = LOG.isDebugEnabled(); // Easy for the compiler to remove the code if DEBUG==false
82 private static final ByteBuffer __FILL_CALLED_FLUSH= BufferUtil.allocate(0);
83 private static final ByteBuffer __FLUSH_CALLED_FILL= BufferUtil.allocate(0);
84 private final ByteBufferPool _bufferPool;
85 private final SSLEngine _sslEngine;
86 private final DecryptedEndPoint _decryptedEndPoint;
87 private ByteBuffer _decryptedInput;
88 private ByteBuffer _encryptedInput;
89 private ByteBuffer _encryptedOutput;
90 private final boolean _encryptedDirectBuffers = false;
91 private final boolean _decryptedDirectBuffers = false;
92 private final Runnable _runCompletWrite = new Runnable()
93 {
94 @Override
95 public void run()
96 {
97 _decryptedEndPoint.getWriteFlusher().completeWrite();
98 }
99 };
100 private boolean _renegotiationAllowed;
101
102 public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
103 {
104 // This connection does not execute calls to onfillable, so they will be called by the selector thread.
105 // onfillable does not block and will only wakeup another thread to do the actual reading and handling.
106 super(endPoint, executor, !EXECUTE_ONFILLABLE);
107 this._bufferPool = byteBufferPool;
108 this._sslEngine = sslEngine;
109 this._decryptedEndPoint = newDecryptedEndPoint();
110 }
111
112 protected DecryptedEndPoint newDecryptedEndPoint()
113 {
114 return new DecryptedEndPoint();
115 }
116
117 public SSLEngine getSSLEngine()
118 {
119 return _sslEngine;
120 }
121
122 public DecryptedEndPoint getDecryptedEndPoint()
123 {
124 return _decryptedEndPoint;
125 }
126
127 public boolean isRenegotiationAllowed()
128 {
129 return _renegotiationAllowed;
130 }
131
132 public void setRenegotiationAllowed(boolean renegotiationAllowed)
133 {
134 this._renegotiationAllowed = renegotiationAllowed;
135 }
136
137 @Override
138 public void onOpen()
139 {
140 try
141 {
142 // Begin the handshake
143 _sslEngine.beginHandshake();
144 super.onOpen();
145 getDecryptedEndPoint().getConnection().onOpen();
146 }
147 catch (SSLException x)
148 {
149 getEndPoint().close();
150 throw new RuntimeIOException(x);
151 }
152 }
153
154 @Override
155 public void onClose()
156 {
157 _decryptedEndPoint.getConnection().onClose();
158 super.onClose();
159 }
160
161 @Override
162 public void close()
163 {
164 getDecryptedEndPoint().getConnection().close();
165 }
166
167 @Override
168 public void onFillable()
169 {
170 // onFillable means that there are encrypted bytes ready to be filled.
171 // however we do not fill them here on this callback, but instead wakeup
172 // the decrypted readInterest and/or writeFlusher so that they will attempt
173 // to do the fill and/or flush again and these calls will do the actually
174 // filling.
175
176 if (DEBUG)
177 LOG.debug("onFillable enter {}", _decryptedEndPoint);
178
179 // We have received a close handshake, close the end point to send FIN.
180 if (_decryptedEndPoint.isInputShutdown())
181 _decryptedEndPoint.close();
182
183 // wake up whoever is doing the fill or the flush so they can
184 // do all the filling, unwrapping, wrapping and flushing
185 _decryptedEndPoint.getFillInterest().fillable();
186
187 // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
188 synchronized(_decryptedEndPoint)
189 {
190 if (_decryptedEndPoint._flushRequiresFillToProgress)
191 {
192 _decryptedEndPoint._flushRequiresFillToProgress = false;
193 getExecutor().execute(_runCompletWrite);
194 }
195 }
196
197 if (DEBUG)
198 LOG.debug("onFillable exit {}", _decryptedEndPoint);
199 }
200
201 @Override
202 public void onFillInterestedFailed(Throwable cause)
203 {
204 // this means that the fill interest in encrypted bytes has failed.
205 // However we do not handle that here on this callback, but instead wakeup
206 // the decrypted readInterest and/or writeFlusher so that they will attempt
207 // to do the fill and/or flush again and these calls will do the actually
208 // handle the cause.
209 _decryptedEndPoint.getFillInterest().onFail(cause);
210
211 boolean failFlusher = false;
212 synchronized(_decryptedEndPoint)
213 {
214 if (_decryptedEndPoint._flushRequiresFillToProgress)
215 {
216 _decryptedEndPoint._flushRequiresFillToProgress = false;
217 failFlusher = true;
218 }
219 }
220 if (failFlusher)
221 _decryptedEndPoint.getWriteFlusher().onFail(cause);
222 }
223
224 @Override
225 public String toString()
226 {
227 ByteBuffer b = _encryptedInput;
228 int ei=b==null?-1:b.remaining();
229 b = _encryptedOutput;
230 int eo=b==null?-1:b.remaining();
231 b = _decryptedInput;
232 int di=b==null?-1:b.remaining();
233
234 return String.format("SslConnection@%x{%s,eio=%d/%d,di=%d} -> %s",
235 hashCode(),
236 _sslEngine.getHandshakeStatus(),
237 ei,eo,di,
238 _decryptedEndPoint.getConnection());
239 }
240
241 public class DecryptedEndPoint extends AbstractEndPoint
242 {
243 private boolean _fillRequiresFlushToProgress;
244 private boolean _flushRequiresFillToProgress;
245 private boolean _cannotAcceptMoreAppDataToFlush;
246 private boolean _handshaken;
247 private boolean _underFlown;
248
249 private final Callback _writeCallback = new Callback()
250 {
251 @Override
252 public void succeeded()
253 {
254 // This means that a write of encrypted data has completed. Writes are done
255 // only if there is a pending writeflusher or a read needed to write
256 // data. In either case the appropriate callback is passed on.
257 boolean fillable = false;
258 synchronized (DecryptedEndPoint.this)
259 {
260 if (DEBUG)
261 LOG.debug("write.complete {}", SslConnection.this.getEndPoint());
262
263 releaseEncryptedOutputBuffer();
264
265 _cannotAcceptMoreAppDataToFlush = false;
266
267 if (_fillRequiresFlushToProgress)
268 {
269 _fillRequiresFlushToProgress = false;
270 fillable = true;
271 }
272 }
273 if (fillable)
274 getFillInterest().fillable();
275 getExecutor().execute(_runCompletWrite);
276 }
277
278 @Override
279 public void failed(final Throwable x)
280 {
281 // This means that a write of data has failed. Writes are done
282 // only if there is an active writeflusher or a read needed to write
283 // data. In either case the appropriate callback is passed on.
284 boolean fail_filler = false;
285 synchronized (DecryptedEndPoint.this)
286 {
287 if (DEBUG)
288 LOG.debug("{} write.failed", SslConnection.this, x);
289 BufferUtil.clear(_encryptedOutput);
290 releaseEncryptedOutputBuffer();
291
292 _cannotAcceptMoreAppDataToFlush = false;
293
294 if (_fillRequiresFlushToProgress)
295 {
296 _fillRequiresFlushToProgress = false;
297 fail_filler = true;
298 }
299 }
300
301 final boolean filler_failed=fail_filler;
302
303 failedCallback(new Callback()
304 {
305 @Override
306 public void succeeded()
307 {
308 }
309
310 @Override
311 public void failed(Throwable x)
312 {
313 if (filler_failed)
314 getFillInterest().onFail(x);
315 getWriteFlusher().onFail(x);
316 }
317
318 },x);
319 }
320 };
321
322 public DecryptedEndPoint()
323 {
324 super(null,getEndPoint().getLocalAddress(), getEndPoint().getRemoteAddress());
325 setIdleTimeout(getEndPoint().getIdleTimeout());
326 }
327
328 @Override
329 protected FillInterest getFillInterest()
330 {
331 return super.getFillInterest();
332 }
333
334 @Override
335 public void setIdleTimeout(long idleTimeout)
336 {
337 super.setIdleTimeout(idleTimeout);
338 getEndPoint().setIdleTimeout(idleTimeout);
339 }
340
341 @Override
342 protected WriteFlusher getWriteFlusher()
343 {
344 return super.getWriteFlusher();
345 }
346
347 @Override
348 protected void onIncompleteFlush()
349 {
350 // This means that the decrypted endpoint write method was called and not
351 // all data could be wrapped. So either we need to write some encrypted data,
352 // OR if we are handshaking we need to read some encrypted data OR
353 // if neither then we should just try the flush again.
354 boolean try_again = false;
355 synchronized (DecryptedEndPoint.this)
356 {
357 if (DEBUG)
358 LOG.debug("onIncompleteFlush {}", getEndPoint());
359 // If we have pending output data,
360 if (BufferUtil.hasContent(_encryptedOutput))
361 {
362 // write it
363 _cannotAcceptMoreAppDataToFlush = true;
364 getEndPoint().write(_writeCallback, _encryptedOutput);
365 }
366 // If we are handshaking and need to read,
367 else if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP)
368 {
369 // check if we are actually read blocked in order to write
370 _flushRequiresFillToProgress = true;
371 SslConnection.this.fillInterested();
372 }
373 else
374 {
375 // We can get here because the WriteFlusher might not see progress
376 // when it has just flushed the encrypted data, but not consumed anymore
377 // of the application buffers. This is mostly avoided by another iteration
378 // within DecryptedEndPoint flush(), but I cannot convince myself that
379 // this is never ever the case.
380 try_again = true;
381 }
382 }
383
384
385 if (try_again)
386 {
387 // If the output is closed,
388 if (isOutputShutdown())
389 {
390 // don't bother writing, just notify of close
391 getWriteFlusher().onClose();
392 }
393 // Else,
394 else
395 {
396 // try to flush what is pending
397 // because this is a special case (see above) we could probably
398 // avoid the dispatch, but best to be sure
399 getExecutor().execute(_runCompletWrite);
400 }
401 }
402 }
403
404 @Override
405 protected boolean needsFill() throws IOException
406 {
407 // This means that the decrypted data consumer has called the fillInterested
408 // method on the DecryptedEndPoint, so we have to work out if there is
409 // decrypted data to be filled or what callbacks to setup to be told when there
410 // might be more encrypted data available to attempt another call to fill
411
412 synchronized (DecryptedEndPoint.this)
413 {
414 // Do we already have some app data, then app can fill now so return true
415 if (BufferUtil.hasContent(_decryptedInput))
416 return true;
417
418 // If we have no encrypted data to decrypt OR we have some, but it is not enough
419 if (BufferUtil.isEmpty(_encryptedInput) || _underFlown)
420 {
421 // We are not ready to read data
422
423 // Are we actually write blocked?
424 if (_fillRequiresFlushToProgress)
425 {
426 // we must be blocked trying to write before we can read
427
428 // Do we have data to write
429 if (BufferUtil.hasContent(_encryptedOutput))
430 {
431 // write it
432 _cannotAcceptMoreAppDataToFlush = true;
433 getEndPoint().write(_writeCallback, _encryptedOutput);
434 }
435 else
436 {
437 // we have already written the net data
438 // pretend we are readable so the wrap is done by next readable callback
439 _fillRequiresFlushToProgress = false;
440 return true;
441 }
442 }
443 else
444 {
445 // Normal readable callback
446 // Get called back on onfillable when then is more data to fill
447 SslConnection.this.fillInterested();
448 }
449
450 return false;
451 }
452 else
453 {
454 // We are ready to read data
455 return true;
456 }
457 }
458 }
459
460 @Override
461 public void setConnection(Connection connection)
462 {
463 if (connection instanceof AbstractConnection)
464 {
465 AbstractConnection a = (AbstractConnection)connection;
466 if (a.getInputBufferSize()<_sslEngine.getSession().getApplicationBufferSize())
467 a.setInputBufferSize(_sslEngine.getSession().getApplicationBufferSize());
468 }
469 super.setConnection(connection);
470 }
471
472 public SslConnection getSslConnection()
473 {
474 return SslConnection.this;
475 }
476
477 @Override
478 public synchronized int fill(ByteBuffer buffer) throws IOException
479 {
480 if (DEBUG)
481 LOG.debug("{} fill enter", SslConnection.this);
482 try
483 {
484 // Do we already have some decrypted data?
485 if (BufferUtil.hasContent(_decryptedInput))
486 return BufferUtil.append(buffer,_decryptedInput);
487
488 // We will need a network buffer
489 if (_encryptedInput == null)
490 _encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
491 else
492 BufferUtil.compact(_encryptedInput);
493
494 // We also need an app buffer, but can use the passed buffer if it is big enough
495 ByteBuffer app_in;
496 if (BufferUtil.space(buffer) > _sslEngine.getSession().getApplicationBufferSize())
497 app_in = buffer;
498 else if (_decryptedInput == null)
499 app_in = _decryptedInput = _bufferPool.acquire(_sslEngine.getSession().getApplicationBufferSize(), _decryptedDirectBuffers);
500 else
501 app_in = _decryptedInput;
502
503 // loop filling and unwrapping until we have something
504 while (true)
505 {
506 // Let's try reading some encrypted data... even if we have some already.
507 int net_filled = getEndPoint().fill(_encryptedInput);
508 if (DEBUG)
509 LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled);
510
511 decryption: while (true)
512 {
513 // Let's unwrap even if we have no net data because in that
514 // case we want to fall through to the handshake handling
515 int pos = BufferUtil.flipToFill(app_in);
516 SSLEngineResult unwrapResult;
517 try
518 {
519 unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
520 }
521 finally
522 {
523 BufferUtil.flipToFlush(app_in, pos);
524 }
525 if (DEBUG)
526 LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
527
528 HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
529 HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus();
530 Status unwrapResultStatus = unwrapResult.getStatus();
531
532 // Extra check on unwrapResultStatus == OK with zero length buffer is due
533 // to SSL client on android (see bug #454773)
534 _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW || unwrapResultStatus == Status.OK && unwrapResult.bytesConsumed()==0 && unwrapResult.bytesProduced()==0;
535
536 if (_underFlown)
537 {
538 if (net_filled < 0)
539 closeInbound();
540 if (net_filled <= 0)
541 return net_filled;
542 }
543
544 switch (unwrapResultStatus)
545 {
546 case CLOSED:
547 {
548 switch (handshakeStatus)
549 {
550 case NOT_HANDSHAKING:
551 {
552 // We were not handshaking, so just tell the app we are closed
553 return -1;
554 }
555 case NEED_TASK:
556 {
557 _sslEngine.getDelegatedTask().run();
558 continue;
559 }
560 case NEED_WRAP:
561 {
562 // We need to send some handshake data (probably the close handshake).
563 // We return -1 so that the application can drive the close by flushing
564 // or shutting down the output.
565 return -1;
566 }
567 case NEED_UNWRAP:
568 {
569 // We expected to read more, but we got closed.
570 // Return -1 to indicate to the application to drive the close.
571 return -1;
572 }
573 default:
574 {
575 throw new IllegalStateException();
576 }
577 }
578 }
579 case BUFFER_UNDERFLOW:
580 case OK:
581 {
582 if (unwrapHandshakeStatus == HandshakeStatus.FINISHED && !_handshaken)
583 {
584 _handshaken = true;
585 if (DEBUG)
586 LOG.debug("{} {} handshake completed", SslConnection.this,
587 _sslEngine.getUseClientMode() ? "client-side" : "resumed session server-side");
588 }
589
590 // Check whether renegotiation is allowed
591 if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
592 {
593 if (DEBUG)
594 LOG.debug("{} renegotiation denied", SslConnection.this);
595 closeInbound();
596 return -1;
597 }
598
599 // If bytes were produced, don't bother with the handshake status;
600 // pass the decrypted data to the application, which will perform
601 // another call to fill() or flush().
602 if (unwrapResult.bytesProduced() > 0)
603 {
604 if (app_in == buffer)
605 return unwrapResult.bytesProduced();
606 return BufferUtil.append(buffer,_decryptedInput);
607 }
608
609 switch (handshakeStatus)
610 {
611 case NOT_HANDSHAKING:
612 {
613 if (_underFlown)
614 break decryption;
615 continue;
616 }
617 case NEED_TASK:
618 {
619 _sslEngine.getDelegatedTask().run();
620 continue;
621 }
622 case NEED_WRAP:
623 {
624 // If we are called from flush()
625 // return to let it do the wrapping.
626 if (buffer == __FLUSH_CALLED_FILL)
627 return 0;
628
629 _fillRequiresFlushToProgress = true;
630 flush(__FILL_CALLED_FLUSH);
631 if (BufferUtil.isEmpty(_encryptedOutput))
632 {
633 // The flush wrote all the encrypted bytes so continue to fill
634 _fillRequiresFlushToProgress = false;
635 continue;
636 }
637 else
638 {
639 // The flush did not complete, return from fill()
640 // and let the write completion mechanism to kick in.
641 return 0;
642 }
643 }
644 case NEED_UNWRAP:
645 {
646 if (_underFlown)
647 break decryption;
648 continue;
649 }
650 default:
651 {
652 throw new IllegalStateException();
653 }
654 }
655 }
656 default:
657 {
658 throw new IllegalStateException();
659 }
660 }
661 }
662 }
663 }
664 catch (Exception e)
665 {
666 getEndPoint().close();
667 throw e;
668 }
669 finally
670 {
671 // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
672 if (_flushRequiresFillToProgress)
673 {
674 _flushRequiresFillToProgress = false;
675 getExecutor().execute(_runCompletWrite);
676 }
677
678 if (_encryptedInput != null && !_encryptedInput.hasRemaining())
679 {
680 _bufferPool.release(_encryptedInput);
681 _encryptedInput = null;
682 }
683 if (_decryptedInput != null && !_decryptedInput.hasRemaining())
684 {
685 _bufferPool.release(_decryptedInput);
686 _decryptedInput = null;
687 }
688 if (DEBUG)
689 LOG.debug("{} fill exit", SslConnection.this);
690 }
691 }
692
693 private void closeInbound()
694 {
695 try
696 {
697 _sslEngine.closeInbound();
698 }
699 catch (SSLException x)
700 {
701 LOG.ignore(x);
702 }
703 }
704
705 @Override
706 public synchronized boolean flush(ByteBuffer... appOuts) throws IOException
707 {
708 // The contract for flush does not require that all appOuts bytes are written
709 // or even that any appOut bytes are written! If the connection is write block
710 // or busy handshaking, then zero bytes may be taken from appOuts and this method
711 // will return 0 (even if some handshake bytes were flushed and filled).
712 // it is the applications responsibility to call flush again - either in a busy loop
713 // or better yet by using EndPoint#write to do the flushing.
714
715 if (DEBUG)
716 LOG.debug("{} flush enter {}", SslConnection.this, Arrays.toString(appOuts));
717 int consumed=0;
718 try
719 {
720 if (_cannotAcceptMoreAppDataToFlush)
721 {
722 if (_sslEngine.isOutboundDone())
723 throw new EofException(new ClosedChannelException());
724 return false;
725 }
726
727 // We will need a network buffer
728 if (_encryptedOutput == null)
729 _encryptedOutput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
730
731 while (true)
732 {
733 // We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer
734 BufferUtil.compact(_encryptedOutput);
735 int pos = BufferUtil.flipToFill(_encryptedOutput);
736 SSLEngineResult wrapResult;
737 try
738 {
739 wrapResult=_sslEngine.wrap(appOuts, _encryptedOutput);
740 }
741 finally
742 {
743 BufferUtil.flipToFlush(_encryptedOutput, pos);
744 }
745
746 if (DEBUG)
747 LOG.debug("{} wrap {}", SslConnection.this, wrapResult);
748 if (wrapResult.bytesConsumed()>0)
749 consumed+=wrapResult.bytesConsumed();
750 Status wrapResultStatus = wrapResult.getStatus();
751
752 boolean allConsumed=true;
753 for (ByteBuffer b : appOuts)
754 if (BufferUtil.hasContent(b))
755 allConsumed=false;
756
757 // and deal with the results returned from the sslEngineWrap
758 switch (wrapResultStatus)
759 {
760 case CLOSED:
761 // The SSL engine has close, but there may be close handshake that needs to be written
762 if (BufferUtil.hasContent(_encryptedOutput))
763 {
764 _cannotAcceptMoreAppDataToFlush = true;
765 getEndPoint().flush(_encryptedOutput);
766 getEndPoint().shutdownOutput();
767 // If we failed to flush the close handshake then we will just pretend that
768 // the write has progressed normally and let a subsequent call to flush
769 // (or WriteFlusher#onIncompleteFlushed) to finish writing the close handshake.
770 // The caller will find out about the close on a subsequent flush or fill.
771 if (BufferUtil.hasContent(_encryptedOutput))
772 return false;
773 }
774 // otherwise we have written, and the caller will close the underlying connection
775 else
776 {
777 getEndPoint().shutdownOutput();
778 }
779 return allConsumed;
780
781 case BUFFER_UNDERFLOW:
782 throw new IllegalStateException();
783
784 default:
785 if (DEBUG)
786 LOG.debug("{} {} {}", this, wrapResultStatus, BufferUtil.toDetailString(_encryptedOutput));
787
788 if (wrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED && !_handshaken)
789 {
790 _handshaken = true;
791 if (DEBUG)
792 LOG.debug("{} {} handshake completed", SslConnection.this, "server-side");
793 }
794
795 HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
796
797 // Check whether renegotiation is allowed
798 if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
799 {
800 if (DEBUG)
801 LOG.debug("{} renegotiation denied", SslConnection.this);
802 getEndPoint().shutdownOutput();
803 return allConsumed;
804 }
805
806 // if we have net bytes, let's try to flush them
807 if (BufferUtil.hasContent(_encryptedOutput))
808 if (!getEndPoint().flush(_encryptedOutput))
809 getEndPoint().flush(_encryptedOutput); // one retry
810
811 // But we also might have more to do for the handshaking state.
812 switch (handshakeStatus)
813 {
814 case NOT_HANDSHAKING:
815 // If we have not consumed all and had just finished handshaking, then we may
816 // have just flushed the last handshake in the encrypted buffers, so we should
817 // try again.
818 if (!allConsumed && wrapResult.getHandshakeStatus()==HandshakeStatus.FINISHED && BufferUtil.isEmpty(_encryptedOutput))
819 continue;
820
821 // Return true if we consumed all the bytes and encrypted are all flushed
822 return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
823
824 case NEED_TASK:
825 // run the task and continue
826 _sslEngine.getDelegatedTask().run();
827 continue;
828
829 case NEED_WRAP:
830 // Hey we just wrapped! Oh well who knows what the sslEngine is thinking, so continue and we will wrap again
831 continue;
832
833 case NEED_UNWRAP:
834 // Ah we need to fill some data so we can write.
835 // So if we were not called from fill and the app is not reading anyway
836 if (appOuts[0]!=__FILL_CALLED_FLUSH && !getFillInterest().isInterested())
837 {
838 // Tell the onFillable method that there might be a write to complete
839 _flushRequiresFillToProgress = true;
840 fill(__FLUSH_CALLED_FILL);
841 // Check if after the fill() we need to wrap again
842 if (handshakeStatus == HandshakeStatus.NEED_WRAP)
843 continue;
844 }
845 return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
846
847 case FINISHED:
848 throw new IllegalStateException();
849 }
850 }
851 }
852 }
853 finally
854 {
855 if (DEBUG)
856 LOG.debug("{} flush exit, consumed {}", SslConnection.this, consumed);
857 releaseEncryptedOutputBuffer();
858 }
859 }
860
861 private void releaseEncryptedOutputBuffer()
862 {
863 if (!Thread.holdsLock(DecryptedEndPoint.this))
864 throw new IllegalStateException();
865 if (_encryptedOutput != null && !_encryptedOutput.hasRemaining())
866 {
867 _bufferPool.release(_encryptedOutput);
868 _encryptedOutput = null;
869 }
870 }
871
872 @Override
873 public void shutdownOutput()
874 {
875 boolean ishut = isInputShutdown();
876 boolean oshut = isOutputShutdown();
877 if (DEBUG)
878 LOG.debug("{} shutdownOutput: oshut={}, ishut={}", SslConnection.this, oshut, ishut);
879 if (ishut)
880 {
881 // Aggressively close, since inbound close alert has already been processed
882 // and the TLS specification allows to close the connection directly, which
883 // is what most other implementations expect: a FIN rather than a TLS close
884 // reply. If a TLS close reply is sent, most implementations send a RST.
885 getEndPoint().close();
886 }
887 else if (!oshut)
888 {
889 try
890 {
891 _sslEngine.closeOutbound();
892 flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
893 SslConnection.this.fillInterested(); // seek reply FIN or RST or close handshake
894 }
895 catch (Exception e)
896 {
897 LOG.ignore(e);
898 getEndPoint().close();
899 }
900 }
901 }
902
903 @Override
904 public boolean isOutputShutdown()
905 {
906 return _sslEngine.isOutboundDone() || getEndPoint().isOutputShutdown();
907 }
908
909 @Override
910 public void close()
911 {
912 super.close();
913 // First send the TLS Close Alert, then the FIN
914 shutdownOutput();
915 getEndPoint().close();
916 }
917
918 @Override
919 public boolean isOpen()
920 {
921 return getEndPoint().isOpen();
922 }
923
924 @Override
925 public Object getTransport()
926 {
927 return getEndPoint();
928 }
929
930 @Override
931 public boolean isInputShutdown()
932 {
933 return _sslEngine.isInboundDone();
934 }
935
936 @Override
937 public String toString()
938 {
939 return super.toString()+"->"+getEndPoint().toString();
940 }
941 }
942 }