1 //
2 // ========================================================================
3 // Copyright (c) 1995-2013 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 // commented out for now as it might cause native code being stuck in preClose0.
112 // See: https://java.net/jira/browse/GRIZZLY-547
113
114 // if (endPoint instanceof SocketBased)
115 // {
116 // try
117 // {
118 // ((SocketBased)endPoint).getSocket().setSoLinger(true, 30000);
119 // }
120 // catch (SocketException e)
121 // {
122 // throw new RuntimeIOException(e);
123 // }
124 // }
125 }
126
127 protected DecryptedEndPoint newDecryptedEndPoint()
128 {
129 return new DecryptedEndPoint();
130 }
131
132 public SSLEngine getSSLEngine()
133 {
134 return _sslEngine;
135 }
136
137 public DecryptedEndPoint getDecryptedEndPoint()
138 {
139 return _decryptedEndPoint;
140 }
141
142 public boolean isRenegotiationAllowed()
143 {
144 return _renegotiationAllowed;
145 }
146
147 public void setRenegotiationAllowed(boolean renegotiationAllowed)
148 {
149 this._renegotiationAllowed = renegotiationAllowed;
150 }
151
152 @Override
153 public void onOpen()
154 {
155 try
156 {
157 // Begin the handshake
158 _sslEngine.beginHandshake();
159 super.onOpen();
160 getDecryptedEndPoint().getConnection().onOpen();
161 }
162 catch (SSLException x)
163 {
164 getEndPoint().close();
165 throw new RuntimeIOException(x);
166 }
167 }
168
169 @Override
170 public void onClose()
171 {
172 _decryptedEndPoint.getConnection().onClose();
173 super.onClose();
174 }
175
176 @Override
177 public void close()
178 {
179 getDecryptedEndPoint().getConnection().close();
180 }
181
182 @Override
183 public void onFillable()
184 {
185 // onFillable means that there are encrypted bytes ready to be filled.
186 // however we do not fill them here on this callback, but instead wakeup
187 // the decrypted readInterest and/or writeFlusher so that they will attempt
188 // to do the fill and/or flush again and these calls will do the actually
189 // filling.
190
191 if (DEBUG)
192 LOG.debug("onFillable enter {}", _decryptedEndPoint);
193
194 // We have received a close handshake, close the end point to send FIN.
195 if (_decryptedEndPoint.isInputShutdown())
196 _decryptedEndPoint.close();
197
198 // wake up whoever is doing the fill or the flush so they can
199 // do all the filling, unwrapping, wrapping and flushing
200 _decryptedEndPoint.getFillInterest().fillable();
201
202 // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
203 synchronized(_decryptedEndPoint)
204 {
205 if (_decryptedEndPoint._flushRequiresFillToProgress)
206 {
207 _decryptedEndPoint._flushRequiresFillToProgress = false;
208 getExecutor().execute(_runCompletWrite);
209 }
210 }
211
212 if (DEBUG)
213 LOG.debug("onFillable exit {}", _decryptedEndPoint);
214 }
215
216 @Override
217 public void onFillInterestedFailed(Throwable cause)
218 {
219 // this means that the fill interest in encrypted bytes has failed.
220 // However we do not handle that here on this callback, but instead wakeup
221 // the decrypted readInterest and/or writeFlusher so that they will attempt
222 // to do the fill and/or flush again and these calls will do the actually
223 // handle the cause.
224 _decryptedEndPoint.getFillInterest().onFail(cause);
225
226 boolean failFlusher = false;
227 synchronized(_decryptedEndPoint)
228 {
229 if (_decryptedEndPoint._flushRequiresFillToProgress)
230 {
231 _decryptedEndPoint._flushRequiresFillToProgress = false;
232 failFlusher = true;
233 }
234 }
235 if (failFlusher)
236 _decryptedEndPoint.getWriteFlusher().onFail(cause);
237 }
238
239 @Override
240 public String toString()
241 {
242 ByteBuffer b = _encryptedInput;
243 int ei=b==null?-1:b.remaining();
244 b = _encryptedOutput;
245 int eo=b==null?-1:b.remaining();
246 b = _decryptedInput;
247 int di=b==null?-1:b.remaining();
248
249 return String.format("SslConnection@%x{%s,eio=%d/%d,di=%d} -> %s",
250 hashCode(),
251 _sslEngine.getHandshakeStatus(),
252 ei,eo,di,
253 _decryptedEndPoint.getConnection());
254 }
255
256 public class DecryptedEndPoint extends AbstractEndPoint
257 {
258 private boolean _fillRequiresFlushToProgress;
259 private boolean _flushRequiresFillToProgress;
260 private boolean _cannotAcceptMoreAppDataToFlush;
261 private boolean _handshaken;
262 private boolean _underFlown;
263
264 private final Callback _writeCallback = new Callback()
265 {
266 @Override
267 public void succeeded()
268 {
269 // This means that a write of encrypted data has completed. Writes are done
270 // only if there is a pending writeflusher or a read needed to write
271 // data. In either case the appropriate callback is passed on.
272 boolean fillable = false;
273 synchronized (DecryptedEndPoint.this)
274 {
275 if (DEBUG)
276 LOG.debug("write.complete {}", SslConnection.this.getEndPoint());
277
278 releaseEncryptedOutputBuffer();
279
280 _cannotAcceptMoreAppDataToFlush = false;
281
282 if (_fillRequiresFlushToProgress)
283 {
284 _fillRequiresFlushToProgress = false;
285 fillable = true;
286 }
287 }
288 if (fillable)
289 getFillInterest().fillable();
290 getExecutor().execute(_runCompletWrite);
291 }
292
293 @Override
294 public void failed(final Throwable x)
295 {
296 // This means that a write of data has failed. Writes are done
297 // only if there is an active writeflusher or a read needed to write
298 // data. In either case the appropriate callback is passed on.
299 boolean fail_filler = false;
300 synchronized (DecryptedEndPoint.this)
301 {
302 if (DEBUG)
303 LOG.debug("{} write.failed", SslConnection.this, x);
304 BufferUtil.clear(_encryptedOutput);
305 releaseEncryptedOutputBuffer();
306
307 _cannotAcceptMoreAppDataToFlush = false;
308
309 if (_fillRequiresFlushToProgress)
310 {
311 _fillRequiresFlushToProgress = false;
312 fail_filler = true;
313 }
314 }
315
316 final boolean filler_failed=fail_filler;
317
318 getExecutor().execute(new Runnable()
319 {
320 @Override
321 public void run()
322 {
323
324 if (filler_failed)
325 getFillInterest().onFail(x);
326 getWriteFlusher().onFail(x);
327 }
328 });
329 }
330 };
331
332 public DecryptedEndPoint()
333 {
334 super(null,getEndPoint().getLocalAddress(), getEndPoint().getRemoteAddress());
335 setIdleTimeout(getEndPoint().getIdleTimeout());
336 }
337
338 @Override
339 protected FillInterest getFillInterest()
340 {
341 return super.getFillInterest();
342 }
343
344 @Override
345 public void setIdleTimeout(long idleTimeout)
346 {
347 super.setIdleTimeout(idleTimeout);
348 getEndPoint().setIdleTimeout(idleTimeout);
349 }
350
351 @Override
352 protected WriteFlusher getWriteFlusher()
353 {
354 return super.getWriteFlusher();
355 }
356
357 @Override
358 protected void onIncompleteFlush()
359 {
360 // This means that the decrypted endpoint write method was called and not
361 // all data could be wrapped. So either we need to write some encrypted data,
362 // OR if we are handshaking we need to read some encrypted data OR
363 // if neither then we should just try the flush again.
364 boolean flush = false;
365 synchronized (DecryptedEndPoint.this)
366 {
367 if (DEBUG)
368 LOG.debug("onIncompleteFlush {}", getEndPoint());
369 // If we have pending output data,
370 if (BufferUtil.hasContent(_encryptedOutput))
371 {
372 // write it
373 _cannotAcceptMoreAppDataToFlush = true;
374 getEndPoint().write(_writeCallback, _encryptedOutput);
375 }
376 // If we are handshaking and need to read,
377 else if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP)
378 {
379 // check if we are actually read blocked in order to write
380 _flushRequiresFillToProgress = true;
381 SslConnection.this.fillInterested();
382 }
383 else
384 {
385 flush = true;
386 }
387 }
388 if (flush)
389 {
390 // If the output is closed,
391 if (isOutputShutdown())
392 {
393 // don't bother writing, just notify of close
394 getWriteFlusher().onClose();
395 }
396 // Else,
397 else
398 {
399 // try to flush what is pending
400 getWriteFlusher().completeWrite();
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.flipPutFlip(_decryptedInput, buffer);
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 = _sslEngine.unwrap(_encryptedInput, app_in);
518 BufferUtil.flipToFlush(app_in, pos);
519 if (DEBUG)
520 LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
521
522 HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
523 HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus();
524 Status unwrapResultStatus = unwrapResult.getStatus();
525
526 _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW;
527
528 if (_underFlown)
529 {
530 if (net_filled < 0)
531 closeInbound();
532 if (net_filled <= 0)
533 return net_filled;
534 }
535
536 switch (unwrapResultStatus)
537 {
538 case CLOSED:
539 {
540 switch (handshakeStatus)
541 {
542 case NOT_HANDSHAKING:
543 {
544 // We were not handshaking, so just tell the app we are closed
545 return -1;
546 }
547 case NEED_TASK:
548 {
549 _sslEngine.getDelegatedTask().run();
550 continue;
551 }
552 case NEED_WRAP:
553 {
554 // We need to send some handshake data (probably the close handshake).
555 // We return -1 so that the application can drive the close by flushing
556 // or shutting down the output.
557 return -1;
558 }
559 default:
560 {
561 throw new IllegalStateException();
562 }
563 }
564 }
565 case BUFFER_UNDERFLOW:
566 case OK:
567 {
568 if (unwrapHandshakeStatus == HandshakeStatus.FINISHED && !_handshaken)
569 {
570 _handshaken = true;
571 if (DEBUG)
572 LOG.debug("{} {} handshake completed", SslConnection.this,
573 _sslEngine.getUseClientMode() ? "client-side" : "resumed session server-side");
574 }
575
576 // Check whether renegotiation is allowed
577 if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
578 {
579 if (DEBUG)
580 LOG.debug("{} renegotiation denied", SslConnection.this);
581 closeInbound();
582 return -1;
583 }
584
585 // If bytes were produced, don't bother with the handshake status;
586 // pass the decrypted data to the application, which will perform
587 // another call to fill() or flush().
588 if (unwrapResult.bytesProduced() > 0)
589 {
590 if (app_in == buffer)
591 return unwrapResult.bytesProduced();
592 return BufferUtil.flipPutFlip(_decryptedInput, buffer);
593 }
594
595 switch (handshakeStatus)
596 {
597 case NOT_HANDSHAKING:
598 {
599 if (_underFlown)
600 break decryption;
601 continue;
602 }
603 case NEED_TASK:
604 {
605 _sslEngine.getDelegatedTask().run();
606 continue;
607 }
608 case NEED_WRAP:
609 {
610 // If we are called from flush()
611 // return to let it do the wrapping.
612 if (buffer == __FLUSH_CALLED_FILL)
613 return 0;
614
615 _fillRequiresFlushToProgress = true;
616 flush(__FILL_CALLED_FLUSH);
617 if (BufferUtil.isEmpty(_encryptedOutput))
618 {
619 // The flush wrote all the encrypted bytes so continue to fill
620 _fillRequiresFlushToProgress = false;
621 continue;
622 }
623 else
624 {
625 // The flush did not complete, return from fill()
626 // and let the write completion mechanism to kick in.
627 return 0;
628 }
629 }
630 case NEED_UNWRAP:
631 {
632 if (_underFlown)
633 break decryption;
634 continue;
635 }
636 default:
637 {
638 throw new IllegalStateException();
639 }
640 }
641 }
642 default:
643 {
644 throw new IllegalStateException();
645 }
646 }
647 }
648 }
649 }
650 catch (SSLException e)
651 {
652 getEndPoint().close();
653 throw new EofException(e);
654 }
655 catch (Exception e)
656 {
657 getEndPoint().close();
658 throw e;
659 }
660 finally
661 {
662 // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
663 if (_flushRequiresFillToProgress)
664 {
665 _flushRequiresFillToProgress = false;
666 getExecutor().execute(_runCompletWrite);
667 }
668
669 if (_encryptedInput != null && !_encryptedInput.hasRemaining())
670 {
671 _bufferPool.release(_encryptedInput);
672 _encryptedInput = null;
673 }
674 if (_decryptedInput != null && !_decryptedInput.hasRemaining())
675 {
676 _bufferPool.release(_decryptedInput);
677 _decryptedInput = null;
678 }
679 if (DEBUG)
680 LOG.debug("{} fill exit", SslConnection.this);
681 }
682 }
683
684 private void closeInbound()
685 {
686 try
687 {
688 _sslEngine.closeInbound();
689 }
690 catch (SSLException x)
691 {
692 LOG.ignore(x);
693 }
694 }
695
696 @Override
697 public synchronized boolean flush(ByteBuffer... appOuts) throws IOException
698 {
699 // The contract for flush does not require that all appOuts bytes are written
700 // or even that any appOut bytes are written! If the connection is write block
701 // or busy handshaking, then zero bytes may be taken from appOuts and this method
702 // will return 0 (even if some handshake bytes were flushed and filled).
703 // it is the applications responsibility to call flush again - either in a busy loop
704 // or better yet by using EndPoint#write to do the flushing.
705
706 if (DEBUG)
707 LOG.debug("{} flush enter {}", SslConnection.this, Arrays.toString(appOuts));
708 int consumed=0;
709 try
710 {
711 if (_cannotAcceptMoreAppDataToFlush)
712 {
713 if (_sslEngine.isOutboundDone())
714 throw new EofException(new ClosedChannelException());
715 return false;
716 }
717
718 // We will need a network buffer
719 if (_encryptedOutput == null)
720 _encryptedOutput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
721
722 while (true)
723 {
724 // We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer
725 BufferUtil.compact(_encryptedOutput);
726 int pos = BufferUtil.flipToFill(_encryptedOutput);
727 SSLEngineResult wrapResult = _sslEngine.wrap(appOuts, _encryptedOutput);
728 if (DEBUG)
729 LOG.debug("{} wrap {}", SslConnection.this, wrapResult);
730 BufferUtil.flipToFlush(_encryptedOutput, pos);
731 if (wrapResult.bytesConsumed()>0)
732 consumed+=wrapResult.bytesConsumed();
733
734 boolean allConsumed=true;
735 // clear empty buffers to prevent position creeping up the buffer
736 for (ByteBuffer b : appOuts)
737 {
738 if (BufferUtil.isEmpty(b))
739 BufferUtil.clear(b);
740 else
741 allConsumed=false;
742 }
743
744 Status wrapResultStatus = wrapResult.getStatus();
745
746 // and deal with the results returned from the sslEngineWrap
747 switch (wrapResultStatus)
748 {
749 case CLOSED:
750 // The SSL engine has close, but there may be close handshake that needs to be written
751 if (BufferUtil.hasContent(_encryptedOutput))
752 {
753 _cannotAcceptMoreAppDataToFlush = true;
754 getEndPoint().flush(_encryptedOutput);
755 getEndPoint().shutdownOutput();
756 // If we failed to flush the close handshake then we will just pretend that
757 // the write has progressed normally and let a subsequent call to flush
758 // (or WriteFlusher#onIncompleteFlushed) to finish writing the close handshake.
759 // The caller will find out about the close on a subsequent flush or fill.
760 if (BufferUtil.hasContent(_encryptedOutput))
761 return false;
762 }
763 // otherwise we have written, and the caller will close the underlying connection
764 else
765 {
766 getEndPoint().shutdownOutput();
767 }
768 return allConsumed;
769
770 case BUFFER_UNDERFLOW:
771 throw new IllegalStateException();
772
773 default:
774 if (DEBUG)
775 LOG.debug("{} {} {}", this, wrapResultStatus, BufferUtil.toDetailString(_encryptedOutput));
776
777 if (wrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED && !_handshaken)
778 {
779 _handshaken = true;
780 if (DEBUG)
781 LOG.debug("{} {} handshake completed", SslConnection.this, "server-side");
782 }
783
784 HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
785
786 // Check whether renegotiation is allowed
787 if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
788 {
789 if (DEBUG)
790 LOG.debug("{} renegotiation denied", SslConnection.this);
791 shutdownOutput();
792 return allConsumed;
793 }
794
795 // if we have net bytes, let's try to flush them
796 if (BufferUtil.hasContent(_encryptedOutput))
797 getEndPoint().flush(_encryptedOutput);
798
799 // But we also might have more to do for the handshaking state.
800 switch (handshakeStatus)
801 {
802 case NOT_HANDSHAKING:
803 // Return with the number of bytes consumed (which may be 0)
804 return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
805
806 case NEED_TASK:
807 // run the task and continue
808 _sslEngine.getDelegatedTask().run();
809 continue;
810
811 case NEED_WRAP:
812 // Hey we just wrapped! Oh well who knows what the sslEngine is thinking, so continue and we will wrap again
813 continue;
814
815 case NEED_UNWRAP:
816 // Ah we need to fill some data so we can write.
817 // So if we were not called from fill and the app is not reading anyway
818 if (appOuts[0]!=__FILL_CALLED_FLUSH && !getFillInterest().isInterested())
819 {
820 // Tell the onFillable method that there might be a write to complete
821 _flushRequiresFillToProgress = true;
822 fill(__FLUSH_CALLED_FILL);
823 // Check if after the fill() we need to wrap again
824 if (handshakeStatus == HandshakeStatus.NEED_WRAP)
825 continue;
826 }
827 return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
828
829 case FINISHED:
830 throw new IllegalStateException();
831 }
832 }
833 }
834 }
835 catch (Exception e)
836 {
837 getEndPoint().close();
838 throw e;
839 }
840 finally
841 {
842 if (DEBUG)
843 LOG.debug("{} flush exit, consumed {}", SslConnection.this, consumed);
844 releaseEncryptedOutputBuffer();
845 }
846 }
847
848 private void releaseEncryptedOutputBuffer()
849 {
850 if (!Thread.holdsLock(DecryptedEndPoint.this))
851 throw new IllegalStateException();
852 if (_encryptedOutput != null && !_encryptedOutput.hasRemaining())
853 {
854 _bufferPool.release(_encryptedOutput);
855 _encryptedOutput = null;
856 }
857 }
858
859 @Override
860 public void shutdownOutput()
861 {
862 boolean ishut = isInputShutdown();
863 boolean oshut = isOutputShutdown();
864 if (DEBUG)
865 LOG.debug("{} shutdownOutput: oshut={}, ishut={}", SslConnection.this, oshut, ishut);
866 if (ishut)
867 {
868 // Aggressively close, since inbound close alert has already been processed
869 // and the TLS specification allows to close the connection directly, which
870 // is what most other implementations expect: a FIN rather than a TLS close
871 // reply. If a TLS close reply is sent, most implementations send a RST.
872 getEndPoint().close();
873 }
874 else if (!oshut)
875 {
876 try
877 {
878 _sslEngine.closeOutbound();
879 flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
880 SslConnection.this.fillInterested(); // seek reply FIN or RST or close handshake
881 }
882 catch (Exception e)
883 {
884 LOG.ignore(e);
885 getEndPoint().close();
886 }
887 }
888 }
889
890 @Override
891 public boolean isOutputShutdown()
892 {
893 return _sslEngine.isOutboundDone() || getEndPoint().isOutputShutdown();
894 }
895
896 @Override
897 public void close()
898 {
899 // First send the TLS Close Alert, then the FIN
900 shutdownOutput();
901 getEndPoint().close();
902 }
903
904 @Override
905 public boolean isOpen()
906 {
907 return getEndPoint().isOpen();
908 }
909
910 @Override
911 public Object getTransport()
912 {
913 return getEndPoint();
914 }
915
916 @Override
917 public boolean isInputShutdown()
918 {
919 return _sslEngine.isInboundDone();
920 }
921
922 @Override
923 public String toString()
924 {
925 return super.toString()+"->"+getEndPoint().toString();
926 }
927 }
928 }