/*
   * Create and size the buffers appropriately.
   */
  private void createBuffers() {

    /*
     * We'll assume the buffer sizes are the same
     * between client and server.
     */
    SSLSession session = clientEngine.getSession();
    int appBufferMax = session.getApplicationBufferSize();
    int netBufferMax = session.getPacketBufferSize();

    /*
     * We'll make the input buffers a bit bigger than the max needed
     * size, so that unwrap()s following a successful data transfer
     * won't generate BUFFER_OVERFLOWS.
     *
     * We'll use a mix of direct and indirect ByteBuffers for
     * tutorial purposes only.  In reality, only use direct
     * ByteBuffers when they give a clear performance enhancement.
     */
    clientIn = ByteBuffer.allocate(appBufferMax + 50);
    serverIn = ByteBuffer.allocate(appBufferMax + 50);

    cTOs = ByteBuffer.allocateDirect(netBufferMax);
    sTOc = ByteBuffer.allocateDirect(netBufferMax);

    clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
    serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());
  }
  private void createBuffers() {

    SSLSession session = sslStateMachine.sslEngine.getSession();
    appBufferMax = session.getApplicationBufferSize();
    netBufferMax = session.getPacketBufferSize();

    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      logger.logDebug("appBufferMax=" + appBufferMax + " netBufferMax=" + netBufferMax);
    }
  }
 public SSLSocketChannelWrapper(SSLContext sslContext, SocketChannel sc, boolean client)
     throws Exception {
   super(sc);
   sslEngine = sslContext.createSSLEngine();
   sslEngine.setUseClientMode(client);
   sslEngine.setEnableSessionCreation(true);
   SSLSession session = sslEngine.getSession();
   in = ByteBuffer.allocate(64 * 1024);
   emptyBuffer = ByteBuffer.allocate(0);
   int netBufferMax = session.getPacketBufferSize();
   netOutBuffer = ByteBuffer.allocate(netBufferMax);
   netInBuffer = ByteBuffer.allocate(netBufferMax);
 }
Example #4
0
  /**
   * Close the {@link SSLEngine} attached to this channel
   *
   * @throws Exception
   */
  private void handleClose() throws Exception {
    if (sslEngine.isOutboundDone()) {
      return;
    }
    sslEngine.closeOutbound();

    SSLSession session = getSSLSession();
    int packetBufferSize = Math.max(session.getPacketBufferSize(), MIN_BUFFER_SIZE);

    this.netOutBuffer =
        (this.netOutBuffer == null)
            ? ByteBuffer.allocateDirect(packetBufferSize)
            : this.netOutBuffer.compact();
    this.netInBuffer =
        (this.netInBuffer == null)
            ? ByteBuffer.allocateDirect(packetBufferSize)
            : this.netInBuffer.compact();

    while (!sslEngine.isOutboundDone()) {
      // Get close message
      SSLEngineResult res = sslEngine.wrap(this.netInBuffer, this.netOutBuffer);

      switch (res.getStatus()) {
        case OK:
          // Execute tasks if we need to
          tryTasks();
          while (this.netOutBuffer.hasRemaining()) {
            if (this.channel.write(this.netOutBuffer).get() < 0) {
              break;
            }
            this.netOutBuffer.compact();
          }
          break;
        case BUFFER_OVERFLOW:
          ByteBuffer tmp =
              ByteBuffer.allocateDirect(packetBufferSize + this.netOutBuffer.capacity());
          this.netOutBuffer.flip();
          tmp.put(this.netOutBuffer);
          this.netOutBuffer = tmp;

          break;
        case BUFFER_UNDERFLOW:
          // Cannot happens in case of wrap
        case CLOSED:
          // Already closed, so return
          break;
      }
    }
  }
Example #5
0
  /**
   * Execute a handshake with the client socket channel
   *
   * @throws Exception
   */
  private void doHandshake() throws Exception {

    SSLSession session = getSSLSession();
    int packetBufferSize = Math.max(session.getPacketBufferSize(), MIN_BUFFER_SIZE);
    // Create byte buffers to use for holding application data
    initBuffers(packetBufferSize);

    ByteBuffer clientNetData = ByteBuffer.allocateDirect(packetBufferSize);
    ByteBuffer clientAppData = ByteBuffer.allocateDirect(packetBufferSize);

    // Begin handshake
    sslEngine.beginHandshake();
    handshakeStatus = sslEngine.getHandshakeStatus();
    int i = 1;
    boolean read = true;
    // Process handshaking message
    while (!handshakeComplete) {

      switch (handshakeStatus) {
        case NEED_UNWRAP:
          int nBytes = 0;
          if (read) {
            clientAppData.clear();
            nBytes = this.channel.read(this.netInBuffer).get();
          }
          if (nBytes < 0) {
            throw new IOException(MESSAGES.errorUnwrappingHandshake());
          } else {
            boolean cont = false;
            // Loop while we can perform pure SSLEngine data
            do {
              // Prepare the buffer with the incoming data
              this.netInBuffer.flip();
              // Call unwrap
              SSLEngineResult res = sslEngine.unwrap(this.netInBuffer, clientAppData);
              // Compact the buffer, this is an optional method,
              // wonder what would happen if we didn't
              this.netInBuffer.compact();
              // Read in the status
              handshakeStatus = res.getHandshakeStatus();
              if (res.getStatus() == SSLEngineResult.Status.OK) {
                // Execute tasks if we need to
                tryTasks();
                read = true;
              } else if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
                read = true;
              } else if (res.getStatus() == Status.BUFFER_OVERFLOW) {
                ByteBuffer tmp = ByteBuffer.allocateDirect(packetBufferSize * (++i));

                if (clientAppData.position() > 0) {
                  clientAppData.flip();
                }
                tmp.put(clientAppData);
                clientAppData = tmp;
                read = false;
              }
              // Perform another unwrap?
              cont =
                  res.getStatus() == SSLEngineResult.Status.OK
                      && handshakeStatus == HandshakeStatus.NEED_UNWRAP;
            } while (cont);
          }

          break;
        case NEED_WRAP:
          clientNetData.compact();
          this.netOutBuffer.clear();
          SSLEngineResult res = sslEngine.wrap(clientNetData, this.netOutBuffer);
          handshakeStatus = res.getHandshakeStatus();
          this.netOutBuffer.flip();

          if (res.getStatus() == Status.OK) {
            // Execute tasks if we need to
            tryTasks();
            // Send the handshaking data to client
            while (this.netOutBuffer.hasRemaining()) {
              if (this.channel.write(this.netOutBuffer).get() < 0) {
                // Handle closed channel
                throw new IOException(MESSAGES.errorWrappingHandshake());
              }
            }
          } else {
            // Wrap should always work with our buffers
            throw new IOException(
                MESSAGES.errorWrappingHandshakeStatus(res.getStatus().toString()));
          }

          break;
        case NEED_TASK:
          handshakeStatus = tasks();

          break;
        case NOT_HANDSHAKING:
          throw new SSLHandshakeException(MESSAGES.notHandshaking());
        case FINISHED:
          handshakeComplete = true;
          break;
      }
    }

    this.handshakeComplete = (handshakeStatus == HandshakeStatus.FINISHED);
  }