Exemplo n.º 1
0
  /**
   * Handle a SOCKS v5 response from the proxy server.
   *
   * @param nextFilter the next filter
   * @param buf the buffered data received
   * @param step the current step in the authentication process
   */
  protected void handleResponse(final NextFilter nextFilter, final IoBuffer buf, int step)
      throws Exception {
    int len = 2;
    if (step == SocksProxyConstants.SOCKS5_GREETING_STEP) {
      // Send greeting message
      byte method = buf.get(1);

      if (method == SocksProxyConstants.NO_ACCEPTABLE_AUTH_METHOD) {
        throw new IllegalStateException(
            "No acceptable authentication method to use with " + "the socks proxy server");
      }

      getSession().setAttribute(SELECTED_AUTH_METHOD, method);

    } else if (step == SocksProxyConstants.SOCKS5_AUTH_STEP) {
      // Authentication to the SOCKS server
      byte method = (Byte) getSession().getAttribute(Socks5LogicHandler.SELECTED_AUTH_METHOD);

      if (method == SocksProxyConstants.GSSAPI_AUTH) {
        int oldPos = buf.position();

        if (buf.get(0) != 0x01) {
          throw new IllegalStateException("Authentication failed");
        }
        if (buf.get(1) == 0xFF) {
          throw new IllegalStateException(
              "Authentication failed: GSS API Security Context Failure");
        }

        if (buf.remaining() >= 2) {
          byte[] size = new byte[2];
          buf.get(size);
          int s = ByteUtilities.makeIntFromByte2(size);
          if (buf.remaining() >= s) {
            byte[] token = new byte[s];
            buf.get(token);
            getSession().setAttribute(GSS_TOKEN, token);
            len = 0;
          } else {
            // buf.position(oldPos);
            return;
          }
        } else {
          buf.position(oldPos);
          return;
        }
      } else if (buf.get(1) != SocksProxyConstants.V5_REPLY_SUCCEEDED) {
        throw new IllegalStateException("Authentication failed");
      }

    } else if (step == SocksProxyConstants.SOCKS5_REQUEST_STEP) {
      // Send the request
      byte addressType = buf.get(3);
      len = 6;
      if (addressType == SocksProxyConstants.IPV6_ADDRESS_TYPE) {
        len += 16;
      } else if (addressType == SocksProxyConstants.IPV4_ADDRESS_TYPE) {
        len += 4;
      } else if (addressType == SocksProxyConstants.DOMAIN_NAME_ADDRESS_TYPE) {
        len += 1 + (buf.get(4));
      } else {
        throw new IllegalStateException("Unknwon address type");
      }

      if (buf.remaining() >= len) {
        // handle response
        byte status = buf.get(1);
        LOGGER.debug("  response status: {}", SocksProxyConstants.getReplyCodeAsString(status));

        if (status == SocksProxyConstants.V5_REPLY_SUCCEEDED) {
          buf.position(buf.position() + len);
          setHandshakeComplete();
          return;
        }

        throw new Exception(
            "Proxy handshake failed - Code: 0x" + ByteUtilities.asHex(new byte[] {status}));
      }

      return;
    }

    if (len > 0) {
      buf.position(buf.position() + len);
    }

    // Move to the handshaking next step if not in the middle of
    // the authentication process
    boolean isAuthenticating = false;
    if (step == SocksProxyConstants.SOCKS5_AUTH_STEP) {
      byte method = (Byte) getSession().getAttribute(Socks5LogicHandler.SELECTED_AUTH_METHOD);
      if (method == SocksProxyConstants.GSSAPI_AUTH) {
        GSSContext ctx = (GSSContext) getSession().getAttribute(GSS_CONTEXT);
        if (ctx == null || !ctx.isEstablished()) {
          isAuthenticating = true;
        }
      }
    }

    if (!isAuthenticating) {
      getSession().setAttribute(HANDSHAKE_STEP, ++step);
    }

    doHandshake(nextFilter);
  }