public virtual bool HandleAuthChallenge(HttpHost host, HttpResponse response, AuthenticationStrategy authStrategy, AuthState authState, HttpContext context) { try { if (this.log.IsDebugEnabled()) { this.log.Debug(host.ToHostString() + " requested authentication"); } IDictionary <string, Header> challenges = authStrategy.GetChallenges(host, response , context); if (challenges.IsEmpty()) { this.log.Debug("Response contains no authentication challenges"); return(false); } AuthScheme authScheme = authState.GetAuthScheme(); switch (authState.GetState()) { case AuthProtocolState.Failure: { return(false); } case AuthProtocolState.Success: { authState.Reset(); break; } case AuthProtocolState.Challenged: case AuthProtocolState.Handshake: { if (authScheme == null) { this.log.Debug("Auth scheme is null"); authStrategy.AuthFailed(host, null, context); authState.Reset(); authState.SetState(AuthProtocolState.Failure); return(false); } goto case AuthProtocolState.Unchallenged; } case AuthProtocolState.Unchallenged: { if (authScheme != null) { string id = authScheme.GetSchemeName(); Header challenge = challenges.Get(id.ToLower(CultureInfo.InvariantCulture)); if (challenge != null) { this.log.Debug("Authorization challenge processed"); authScheme.ProcessChallenge(challenge); if (authScheme.IsComplete()) { this.log.Debug("Authentication failed"); authStrategy.AuthFailed(host, authState.GetAuthScheme(), context); authState.Reset(); authState.SetState(AuthProtocolState.Failure); return(false); } else { authState.SetState(AuthProtocolState.Handshake); return(true); } } else { authState.Reset(); } } } } // Retry authentication with a different scheme Queue <AuthOption> authOptions = authStrategy.Select(challenges, host, response, context ); if (authOptions != null && !authOptions.IsEmpty()) { if (this.log.IsDebugEnabled()) { this.log.Debug("Selected authentication options: " + authOptions); } authState.SetState(AuthProtocolState.Challenged); authState.Update(authOptions); return(true); } else { return(false); } } catch (MalformedChallengeException ex) { if (this.log.IsWarnEnabled()) { this.log.Warn("Malformed challenge: " + ex.Message); } authState.Reset(); return(false); } }
/// <summary> /// Creates a HttpHostConnectException based on original /// <see cref="System.IO.IOException">System.IO.IOException</see> /// . /// </summary> /// <since>4.3</since> public HttpHostConnectException(IOException cause, HttpHost host, params IPAddress [] remoteAddresses) : base("Connect to " + (host != null ? host.ToHostString() : "remote host") + (remoteAddresses != null && remoteAddresses.Length > 0 ? " " + Arrays.AsList(remoteAddresses) : string.Empty) + ((cause != null && cause.Message != null) ? " failed: " + cause.Message : " refused")) { this.host = host; Sharpen.Extensions.InitCause(this, cause); }
/// <summary>Creates a tunnel to the target server.</summary> /// <remarks> /// Creates a tunnel to the target server. /// The connection must be established to the (last) proxy. /// A CONNECT request for tunnelling through the proxy will /// be created and sent, the response received and checked. /// This method does <i>not</i> update the connection with /// information about the tunnel, that is left to the caller. /// </remarks> /// <exception cref="Apache.Http.HttpException"></exception> /// <exception cref="System.IO.IOException"></exception> private bool CreateTunnelToTarget(AuthState proxyAuthState, HttpClientConnection managedConn, HttpRoute route, IHttpRequest request, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); int timeout = config.GetConnectTimeout(); HttpHost target = route.GetTargetHost(); HttpHost proxy = route.GetProxyHost(); HttpResponse response; string authority = target.ToHostString(); IHttpRequest connect = new BasicHttpRequest("CONNECT", authority, request.GetProtocolVersion ()); this.requestExecutor.PreProcess(connect, this.proxyHttpProcessor, context); for (; ;) { if (!managedConn.IsOpen()) { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); } connect.RemoveHeaders(AUTH.ProxyAuthResp); this.authenticator.GenerateAuthResponse(connect, proxyAuthState, context); response = this.requestExecutor.Execute(connect, managedConn, context); int status = response.GetStatusLine().GetStatusCode(); if (status < 200) { throw new HttpException("Unexpected response to CONNECT request: " + response.GetStatusLine ()); } if (config.IsAuthenticationEnabled()) { if (this.authenticator.IsAuthenticationRequested(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { if (this.authenticator.HandleAuthChallenge(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { // Retry request if (this.reuseStrategy.KeepAlive(response, context)) { this.log.Debug("Connection kept alive"); // Consume response content HttpEntity entity = response.GetEntity(); EntityUtils.Consume(entity); } else { managedConn.Close(); } } else { break; } } else { break; } } } int status_1 = response.GetStatusLine().GetStatusCode(); if (status_1 > 299) { // Buffer response content HttpEntity entity = response.GetEntity(); if (entity != null) { response.SetEntity(new BufferedHttpEntity(entity)); } managedConn.Close(); throw new TunnelRefusedException("CONNECT refused by proxy: " + response.GetStatusLine (), response); } // How to decide on security of the tunnelled connection? // The socket factory knows only about the segment to the proxy. // Even if that is secure, the hop to the target may be insecure. // Leave it to derived classes, consider insecure by default here. return(false); }