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; }
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; }