/// <exception cref="System.IO.IOException"></exception> public virtual void Connect(HttpClientConnection conn, HttpRoute route, int connectTimeout , HttpContext context) { Args.NotNull(conn, "Connection"); Args.NotNull(route, "HTTP route"); Asserts.Check(conn == this.conn, "Connection not obtained from this manager"); HttpHost host; if (route.GetProxyHost() != null) { host = route.GetProxyHost(); } else { host = route.GetTargetHost(); } IPEndPoint localAddress = route.GetLocalSocketAddress(); this.connectionOperator.Connect(this.conn, host, localAddress, connectTimeout, this .socketConfig, context); }
/// <exception cref="Apache.Http.ProtocolException"></exception> internal virtual void RewriteRequestURI(HttpRequestWrapper request, HttpRoute route ) { try { URI uri = request.GetURI(); if (uri != null) { if (route.GetProxyHost() != null && !route.IsTunnelled()) { // Make sure the request URI is absolute if (!uri.IsAbsolute()) { HttpHost target = route.GetTargetHost(); uri = URIUtils.RewriteURI(uri, target, true); } else { uri = URIUtils.RewriteURI(uri); } } else { // Make sure the request URI is relative if (uri.IsAbsolute()) { uri = URIUtils.RewriteURI(uri, null, true); } else { uri = URIUtils.RewriteURI(uri); } } request.SetURI(uri); } } catch (URISyntaxException ex) { throw new ProtocolException("Invalid URI: " + request.GetRequestLine().GetUri(), ex); } }
private bool NeedAuthentication(AuthState targetAuthState, AuthState proxyAuthState , HttpRoute route, HttpResponse response, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); if (config.IsAuthenticationEnabled()) { HttpHost target = context.GetTargetHost(); if (target == null) { target = route.GetTargetHost(); } if (target.GetPort() < 0) { target = new HttpHost(target.GetHostName(), route.GetTargetHost().GetPort(), target .GetSchemeName()); } if (this.authenticator.IsAuthenticationRequested(target, response, this.targetAuthStrategy , targetAuthState, context)) { return(this.authenticator.HandleAuthChallenge(target, response, this.targetAuthStrategy , targetAuthState, context)); } HttpHost proxy = route.GetProxyHost(); if (this.authenticator.IsAuthenticationRequested(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { // if proxy is not set use target host instead if (proxy == null) { proxy = route.GetTargetHost(); } return(this.authenticator.HandleAuthChallenge(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)); } } return(false); }
/// <exception cref="Apache.Http.Auth.AuthenticationException"></exception> public override Header Authenticate(Credentials credentials, IHttpRequest request , HttpContext context) { Args.NotNull(request, "HTTP request"); switch (state) { case GGSSchemeBase.State.Uninitiated: { throw new AuthenticationException(GetSchemeName() + " authentication has not been initiated" ); } case GGSSchemeBase.State.Failed: { throw new AuthenticationException(GetSchemeName() + " authentication has failed"); } case GGSSchemeBase.State.ChallengeReceived: { try { HttpRoute route = (HttpRoute)context.GetAttribute(HttpClientContext.HttpRoute); if (route == null) { throw new AuthenticationException("Connection route is not available"); } HttpHost host; if (IsProxy()) { host = route.GetProxyHost(); if (host == null) { host = route.GetTargetHost(); } } else { host = route.GetTargetHost(); } string authServer; if (!this.stripPort && host.GetPort() > 0) { authServer = host.ToHostString(); } else { authServer = host.GetHostName(); } if (log.IsDebugEnabled()) { log.Debug("init " + authServer); } token = GenerateToken(token, authServer); state = GGSSchemeBase.State.TokenGenerated; } catch (GSSException gsse) { state = GGSSchemeBase.State.Failed; if (gsse.GetMajor() == GSSException.DefectiveCredential || gsse.GetMajor() == GSSException .CredentialsExpired) { throw new InvalidCredentialsException(gsse.Message, gsse); } if (gsse.GetMajor() == GSSException.NoCred) { throw new InvalidCredentialsException(gsse.Message, gsse); } if (gsse.GetMajor() == GSSException.DefectiveToken || gsse.GetMajor() == GSSException .DuplicateToken || gsse.GetMajor() == GSSException.OldToken) { throw new AuthenticationException(gsse.Message, gsse); } // other error throw new AuthenticationException(gsse.Message); } goto case GGSSchemeBase.State.TokenGenerated; } case GGSSchemeBase.State.TokenGenerated: { string tokenstr = Sharpen.Runtime.GetStringForBytes(base64codec.Encode(token)); if (log.IsDebugEnabled()) { log.Debug("Sending response '" + tokenstr + "' back to the auth server"); } CharArrayBuffer buffer = new CharArrayBuffer(32); if (IsProxy()) { buffer.Append(AUTH.ProxyAuthResp); } else { buffer.Append(AUTH.WwwAuthResp); } buffer.Append(": Negotiate "); buffer.Append(tokenstr); return(new BufferedHeader(buffer)); } default: { throw new InvalidOperationException("Illegal state: " + state); } } }
/// <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); }
/// <summary>Establishes the target route.</summary> /// <remarks>Establishes the target route.</remarks> /// <exception cref="Apache.Http.HttpException"></exception> /// <exception cref="System.IO.IOException"></exception> internal virtual void EstablishRoute(AuthState proxyAuthState, HttpClientConnection managedConn, HttpRoute route, IHttpRequest request, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); int timeout = config.GetConnectTimeout(); RouteTracker tracker = new RouteTracker(route); int step; do { HttpRoute fact = tracker.ToRoute(); step = this.routeDirector.NextStep(route, fact); switch (step) { case HttpRouteDirector.ConnectTarget: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); tracker.ConnectTarget(route.IsSecure()); break; } case HttpRouteDirector.ConnectProxy: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); HttpHost proxy = route.GetProxyHost(); tracker.ConnectProxy(proxy, false); break; } case HttpRouteDirector.TunnelTarget: { bool secure = CreateTunnelToTarget(proxyAuthState, managedConn, route, request, context ); this.log.Debug("Tunnel to target created."); tracker.TunnelTarget(secure); break; } case HttpRouteDirector.TunnelProxy: { // The most simple example for this case is a proxy chain // of two proxies, where P1 must be tunnelled to P2. // route: Source -> P1 -> P2 -> Target (3 hops) // fact: Source -> P1 -> Target (2 hops) int hop = fact.GetHopCount() - 1; // the hop to establish bool secure = CreateTunnelToProxy(route, hop, context); this.log.Debug("Tunnel to proxy created."); tracker.TunnelProxy(route.GetHopTarget(hop), secure); break; } case HttpRouteDirector.LayerProtocol: { this.connManager.Upgrade(managedConn, route, context); tracker.LayerProtocol(route.IsSecure()); break; } case HttpRouteDirector.Unreachable: { throw new HttpException("Unable to establish route: " + "planned = " + route + "; current = " + fact); } case HttpRouteDirector.Complete: { this.connManager.RouteComplete(managedConn, route, context); break; } default: { throw new InvalidOperationException("Unknown step indicator " + step + " from RouteDirector." ); } } }while (step > HttpRouteDirector.Complete); }