コード例 #1
0
  private boolean exitAfterHandlingConnect( //
      final Channel channel, //
      final NettyResponseFuture<?> future, //
      final Request request, //
      ProxyServer proxyServer, //
      int statusCode, //
      HttpRequest httpRequest)
      throws IOException {

    if (future.isKeepAlive()) future.attachChannel(channel, true);

    Uri requestUri = request.getUri();
    logger.debug("Connecting to proxy {} for scheme {}", proxyServer, requestUri.getScheme());

    channelManager.upgradeProtocol(channel.pipeline(), requestUri);
    future.setReuseChannel(true);
    future.setConnectAllowed(false);
    requestSender.drainChannelAndExecuteNextRequest(
        channel, future, new RequestBuilder(future.getTargetRequest()).build());

    return true;
  }
コード例 #2
0
  private boolean exitAfterHandling407( //
      Channel channel, //
      NettyResponseFuture<?> future, //
      HttpResponse response, //
      Request request, //
      int statusCode, //
      ProxyServer proxyServer, //
      HttpRequest httpRequest) {

    if (future.getInProxyAuth().getAndSet(true)) {
      logger.info("Can't handle 407 as auth was already performed");
      return false;
    }

    Realm proxyRealm = future.getProxyRealm();

    if (proxyRealm == null) {
      logger.info("Can't handle 407 as there's no proxyRealm");
      return false;
    }

    List<String> proxyAuthHeaders = response.headers().getAll(HttpHeaders.Names.PROXY_AUTHENTICATE);

    if (proxyAuthHeaders.isEmpty()) {
      logger.info("Can't handle 407 as response doesn't contain Proxy-Authenticate headers");
      return false;
    }

    // FIXME what's this???
    future.setChannelState(ChannelState.NEW);
    HttpHeaders requestHeaders = new DefaultHttpHeaders(false).add(request.getHeaders());

    switch (proxyRealm.getScheme()) {
      case BASIC:
        if (getHeaderWithPrefix(proxyAuthHeaders, "Basic") == null) {
          logger.info(
              "Can't handle 407 with Basic realm as Proxy-Authenticate headers don't match");
          return false;
        }

        if (proxyRealm.isUsePreemptiveAuth()) {
          // FIXME do we need this, as future.getAndSetAuth
          // was tested above?
          // auth was already performed, most likely auth
          // failed
          logger.info(
              "Can't handle 407 with Basic realm as auth was preemptive and already performed");
          return false;
        }

        // FIXME do we want to update the realm, or directly
        // set the header?
        Realm newBasicRealm =
            realm(proxyRealm) //
                .setUsePreemptiveAuth(true) //
                .build();
        future.setProxyRealm(newBasicRealm);
        break;

      case DIGEST:
        String digestHeader = getHeaderWithPrefix(proxyAuthHeaders, "Digest");
        if (digestHeader == null) {
          logger.info(
              "Can't handle 407 with Digest realm as Proxy-Authenticate headers don't match");
          return false;
        }
        Realm newDigestRealm =
            realm(proxyRealm) //
                .setUri(request.getUri()) //
                .setMethodName(request.getMethod()) //
                .setUsePreemptiveAuth(true) //
                .parseProxyAuthenticateHeader(digestHeader) //
                .build();
        future.setProxyRealm(newDigestRealm);
        break;

      case NTLM:
        String ntlmHeader = getHeaderWithPrefix(proxyAuthHeaders, "NTLM");
        if (ntlmHeader == null) {
          logger.info("Can't handle 407 with NTLM realm as Proxy-Authenticate headers don't match");
          return false;
        }
        ntlmProxyChallenge(ntlmHeader, request, proxyRealm, requestHeaders, future);
        Realm newNtlmRealm =
            realm(proxyRealm) //
                .setUsePreemptiveAuth(true) //
                .build();
        future.setProxyRealm(newNtlmRealm);
        break;

      case KERBEROS:
      case SPNEGO:
        if (getHeaderWithPrefix(proxyAuthHeaders, "Negociate") == null) {
          logger.info(
              "Can't handle 407 with Kerberos or Spnego realm as Proxy-Authenticate headers don't match");
          return false;
        }
        try {
          kerberosProxyChallenge(
              channel, proxyAuthHeaders, request, proxyServer, proxyRealm, requestHeaders, future);

        } catch (SpnegoEngineException e) {
          // FIXME
          String ntlmHeader2 = getHeaderWithPrefix(proxyAuthHeaders, "NTLM");
          if (ntlmHeader2 != null) {
            logger.warn("Kerberos/Spnego proxy auth failed, proceeding with NTLM");
            ntlmChallenge(ntlmHeader2, request, requestHeaders, proxyRealm, future);
            Realm newNtlmRealm2 =
                realm(proxyRealm) //
                    .setScheme(AuthScheme.NTLM) //
                    .setUsePreemptiveAuth(true) //
                    .build();
            future.setProxyRealm(newNtlmRealm2);
          } else {
            requestSender.abort(channel, future, e);
            return false;
          }
        }
        break;
      default:
        throw new IllegalStateException("Invalid Authentication scheme " + proxyRealm.getScheme());
    }

    RequestBuilder nextRequestBuilder =
        new RequestBuilder(future.getCurrentRequest()).setHeaders(requestHeaders);
    if (future.getCurrentRequest().getUri().isSecured()) {
      nextRequestBuilder.setMethod(CONNECT);
    }
    final Request nextRequest = nextRequestBuilder.build();

    logger.debug("Sending proxy authentication to {}", request.getUri());
    if (future.isKeepAlive() //
        && HttpHeaders.isKeepAlive(httpRequest) //
        && HttpHeaders.isKeepAlive(response) //
        // support broken Proxy-Connection
        && !response.headers().contains("Proxy-Connection", HttpHeaders.Values.CLOSE, true) //
        && !HttpHeaders.isTransferEncodingChunked(httpRequest) //
        && !HttpHeaders.isTransferEncodingChunked(response)) {
      future.setConnectAllowed(true);
      future.setReuseChannel(true);
      requestSender.drainChannelAndExecuteNextRequest(channel, future, nextRequest);
    } else {
      channelManager.closeChannel(channel);
      requestSender.sendNextRequest(nextRequest, future);
    }

    return true;
  }