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