@SuppressWarnings("unchecked")
  @Override
  public SMTPClientFuture<FutureResult<me.normanmaurer.niosmtp.transport.FutureResult.Void>>
      startTLS() {
    if (!isEncrypted()) {
      final SMTPClientFutureImpl<FutureResult<me.normanmaurer.niosmtp.transport.FutureResult.Void>>
          future =
              new SMTPClientFutureImpl<
                  FutureResult<me.normanmaurer.niosmtp.transport.FutureResult.Void>>(false);

      SslHandler sslHandler = new SslHandler(engine, false);
      channel.getPipeline().addFirst(SSL_HANDLER_KEY, sslHandler);
      sslHandler
          .handshake()
          .addListener(
              new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture cfuture) throws Exception {
                  if (cfuture.isSuccess()) {
                    future.setResult(FutureResult.createVoid());
                  } else {
                    future.setResult(FutureResult.create(cfuture.getCause()));
                  }
                }
              });

      return future;
    } else {
      return new ReadySMTPClientFuture<
          FutureResult<me.normanmaurer.niosmtp.transport.FutureResult.Void>>(
          this, FutureResult.create(STARTTLS_EXCEPTION));
    }
  }
예제 #2
0
  @Override
  public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
    // Get the SslHandler in the current pipeline.
    // We added it in SecureChatPipelineFactory.
    final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);

    // Get notified when SSL handshake is done.
    ChannelFuture handshakeFuture = sslHandler.handshake();
    handshakeFuture.addListener(new SslLister(sslHandler));
  }
예제 #3
0
  private void handleRenegotiation(HandshakeStatus handshakeStatus) {
    if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING
        || handshakeStatus == HandshakeStatus.FINISHED) {
      // Not handshaking
      return;
    }

    if (!handshaken) {
      // Not renegotiation
      return;
    }

    final boolean renegotiate;
    synchronized (handshakeLock) {
      if (handshaking) {
        // Renegotiation in progress or failed already.
        // i.e. Renegotiation check has been done already below.
        return;
      }

      if (engine.isInboundDone() || engine.isOutboundDone()) {
        // Not handshaking but closing.
        return;
      }

      if (isEnableRenegotiation()) {
        // Continue renegotiation.
        renegotiate = true;
      } else {
        // Do not renegotiate.
        renegotiate = false;
        // Prevent reentrance of this method.
        handshaking = true;
      }
    }

    if (renegotiate) {
      // Renegotiate.
      handshake();
    } else {
      // Raise an exception.
      fireExceptionCaught(
          ctx, new SSLException("renegotiation attempted by peer; " + "closing the connection"));

      // Close the connection to stop renegotiation.
      Channels.close(ctx, succeededFuture(ctx.getChannel()));
    }
  }
예제 #4
0
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {

      final NioSocketChannel ch = (NioSocketChannel) e.getChannel();
      NioWorker worker = ch.getWorker();

      // Choose a handler
      final HandlerHolder handler = handlerManager.chooseHandler(worker);

      if (handler == null) {
        // Ignore
        return;
      }

      if (tcpHelper.isSSL()) {
        SslHandler sslHandler = (SslHandler) ch.getPipeline().get("ssl");

        ChannelFuture fut = sslHandler.handshake();
        fut.addListener(
            new ChannelFutureListener() {

              public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()) {
                  connected(ch, handler);
                } else {
                  log.error(
                      "Client from origin "
                          + ch.getRemoteAddress()
                          + " failed to connect over ssl");
                }
              }
            });

      } else {
        connected(ch, handler);
      }
    }
예제 #5
0
  private ChannelBuffer unwrap(
      ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, int offset, int length)
      throws SSLException {
    ByteBuffer inNetBuf = buffer.toByteBuffer(offset, length);
    ByteBuffer outAppBuf = bufferPool.acquire();

    try {
      boolean needsWrap = false;
      loop:
      for (; ; ) {
        SSLEngineResult result;
        synchronized (handshakeLock) {
          if (!handshaken
              && !handshaking
              && !engine.getUseClientMode()
              && !engine.isInboundDone()
              && !engine.isOutboundDone()) {
            handshake();
          }

          try {
            result = engine.unwrap(inNetBuf, outAppBuf);
          } catch (SSLException e) {
            throw e;
          }

          final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
          handleRenegotiation(handshakeStatus);
          switch (handshakeStatus) {
            case NEED_UNWRAP:
              if (inNetBuf.hasRemaining() && !engine.isInboundDone()) {
                break;
              } else {
                break loop;
              }
            case NEED_WRAP:
              wrapNonAppData(ctx, channel);
              break;
            case NEED_TASK:
              runDelegatedTasks();
              break;
            case FINISHED:
              setHandshakeSuccess(channel);
              needsWrap = true;
              break loop;
            case NOT_HANDSHAKING:
              needsWrap = true;
              break loop;
            default:
              throw new IllegalStateException("Unknown handshake status: " + handshakeStatus);
          }
        }
      }

      if (needsWrap) {
        // wrap() acquires pendingUnencryptedWrites first and then
        // handshakeLock.  If handshakeLock is already hold by the
        // current thread, calling wrap() will lead to a dead lock
        // i.e. pendingUnencryptedWrites -> handshakeLock vs.
        //      handshakeLock -> pendingUnencryptedLock -> handshakeLock
        //
        // There is also a same issue between pendingEncryptedWrites
        // and pendingUnencryptedWrites.
        if (!Thread.holdsLock(handshakeLock)
            && !pendingEncryptedWritesLock.isHeldByCurrentThread()) {
          wrap(ctx, channel);
        }
      }

      outAppBuf.flip();

      if (outAppBuf.hasRemaining()) {
        ChannelBuffer frame = ChannelBuffers.buffer(outAppBuf.remaining());
        frame.writeBytes(outAppBuf.array(), 0, frame.capacity());
        return frame;
      } else {
        return null;
      }
    } catch (SSLException e) {
      setHandshakeFailure(channel, e);
      throw e;
    } finally {
      bufferPool.release(outAppBuf);
    }
  }