예제 #1
0
  protected boolean handleSSLHandshake2() throws IOException {
    // We need to make sure the handshake process finished as a whole
    //		boolean proceed = false;
    SSLEngineResult engineResult = null;
    isHanshakeDone = false;
    while (true) {
      switch (engine.getHandshakeStatus()) {
        case NOT_HANDSHAKING:
        case FINISHED:
          isHanshakeDone = true;
          return true;
        case NEED_TASK:
          Executor exec = Executors.newSingleThreadExecutor();
          Runnable task;
          while ((task = engine.getDelegatedTask()) != null) {
            exec.execute(task);
          }
          continue;
        case NEED_WRAP:
          // We need to call a wrap on the engine
          appSendBuffer.flip();
          engineResult = engine.wrap(appSendBuffer, netSendBuffer);
          appSendBuffer.compact();
          if (engineResult.getStatus() == Status.BUFFER_OVERFLOW
              || engineResult.getStatus()
                  == Status
                      .OK) { // The enigne sys we need to flush the current buffer into the network
            // So just set the selector to the write mode
            channel.register(selector, SelectionKey.OP_WRITE);
            selector.wakeup();
            // System.out.println("Handshake wants to do a write ");
            return false;
          } else if (engineResult.getStatus() == Status.CLOSED) {
            throw new IOException("Connection closed");
          } else {
            continue;
          }

        case NEED_UNWRAP:
          // We need to call unwarap method of the engine
          netRecvBuffer.flip();
          engineResult = engine.unwrap(netRecvBuffer, appRecvBuffer);
          netRecvBuffer.compact();
          // System.out.println(engine.isInboundDone());
          if (engineResult.getStatus() == Status.BUFFER_UNDERFLOW) {
            if (!engine.isInboundDone()) {
              channel.register(selector, SelectionKey.OP_READ);
              selector.wakeup();
              // System.out.println("Handshake wants to do a read ");
              return false;
            } else continue;
          } else if (engineResult.getStatus() == Status.CLOSED) {
            throw new IOException("Connection closed");
          } else {
            continue;
          }
      }
    }
  }
예제 #2
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()));
    }
  }
예제 #3
0
  private void closeOutboundAndChannel(
      final ChannelHandlerContext context, final ChannelStateEvent e) throws SSLException {
    if (!e.getChannel().isConnected()) {
      context.sendDownstream(e);
      return;
    }

    unwrap(context, e.getChannel(), ChannelBuffers.EMPTY_BUFFER, 0, 0);
    if (!engine.isInboundDone()) {
      if (sentCloseNotify.compareAndSet(false, true)) {
        engine.closeOutbound();
        ChannelFuture closeNotifyFuture = wrapNonAppData(context, e.getChannel());
        closeNotifyFuture.addListener(new ClosingChannelFutureListener(context, e));
        return;
      }
    }

    context.sendDownstream(e);
  }
예제 #4
0
 /**
  * Close engines by sending "close outbound" message from one SSLEngine to another.
  *
  * @param fromEngine - Sending engine.
  * @param toEngine - Receiving engine.
  * @throws SSLException - thrown on engine errors.
  */
 public static void closeEngines(SSLEngine fromEngine, SSLEngine toEngine) throws SSLException {
   String from = null;
   String to = null;
   ByteBuffer app;
   if (fromEngine.getUseClientMode() && !toEngine.getUseClientMode()) {
     from = "Client";
     to = "Server";
   } else if (toEngine.getUseClientMode() && !fromEngine.getUseClientMode()) {
     from = "Server";
     to = "Client";
   } else {
     throw new Error("Both engines are in the same mode");
   }
   System.out.println("=============================================");
   System.out.println("Trying to close engines from " + from + " to " + to);
   // Sending close outbound request to peer
   fromEngine.closeOutbound();
   app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
   net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
   doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
   app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
   net = doWrap(toEngine, to, 0, app, SSLEngineResult.Status.CLOSED);
   doUnWrap(fromEngine, from, net, SSLEngineResult.Status.CLOSED);
   if (!toEngine.isInboundDone()) {
     throw new AssertionError(
         from + " sent close request to " + to + ", but " + to + "did not close inbound.");
   }
   // Executing close inbound
   fromEngine.closeInbound();
   app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
   net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
   doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
   if (!toEngine.isOutboundDone()) {
     throw new AssertionError(
         from + "sent close request to " + to + ", but " + to + "did not close outbound.");
   }
   System.out.println("Successful closing from " + from + " to " + to);
 }
예제 #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);
    }
  }
예제 #6
0
 private static boolean isEngineClosed(SSLEngine engine) {
   return (engine.isOutboundDone() && engine.isInboundDone());
 }