@Test public void testAuthenticationUserinfoInRequestFailure() throws Exception { this.localServer.register("*", new AuthHandler()); this.localServer.start(); HttpHost target = getServerHttp(); HttpGet httpget = new HttpGet("http://*****:*****@" + target.toHostString() + "/"); HttpResponse response = this.httpclient.execute(getServerHttp(), httpget); HttpEntity entity = response.getEntity(); Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatusLine().getStatusCode()); Assert.assertNotNull(entity); EntityUtils.consume(entity); }
/** * 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. * * @param route the route to establish * @param context the context for request execution * @return <code>true</code> if the tunnelled route is secure, <code>false</code> otherwise. The * implementation here always returns <code>false</code>, but derived classes may override. * @throws HttpException in case of a problem * @throws IOException in case of an IO problem */ protected boolean createTunnelToTarget(HttpRoute route, HttpContext context) throws HttpException, IOException { HttpHost proxy = route.getProxyHost(); HttpHost target = route.getTargetHost(); HttpResponse response = null; boolean done = false; while (!done) { done = true; if (!this.managedConn.isOpen()) { this.managedConn.open(route, context, this.params); } HttpRequest connect = createConnectRequest(route, context); String agent = HttpProtocolParams.getUserAgent(params); if (agent != null) { connect.addHeader(HTTP.USER_AGENT, agent); } connect.addHeader(HTTP.TARGET_HOST, target.toHostString()); AuthScheme authScheme = this.proxyAuthState.getAuthScheme(); AuthScope authScope = this.proxyAuthState.getAuthScope(); Credentials creds = this.proxyAuthState.getCredentials(); if (creds != null) { if (authScope != null || !authScheme.isConnectionBased()) { try { connect.addHeader(authScheme.authenticate(creds, connect)); } catch (AuthenticationException ex) { if (this.log.isErrorEnabled()) { this.log.error("Proxy authentication error: " + ex.getMessage()); } } } } response = requestExec.execute(connect, this.managedConn, context); int status = response.getStatusLine().getStatusCode(); if (status < 200) { throw new HttpException( "Unexpected response to CONNECT request: " + response.getStatusLine()); } CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER); if (credsProvider != null && HttpClientParams.isAuthenticating(params)) { if (this.proxyAuthHandler.isAuthenticationRequested(response, context)) { this.log.debug("Proxy requested authentication"); Map<String, Header> challenges = this.proxyAuthHandler.getChallenges(response, context); try { processChallenges( challenges, this.proxyAuthState, this.proxyAuthHandler, response, context); } catch (AuthenticationException ex) { if (this.log.isWarnEnabled()) { this.log.warn("Authentication error: " + ex.getMessage()); break; } } updateAuthState(this.proxyAuthState, proxy, credsProvider); if (this.proxyAuthState.getCredentials() != null) { done = false; // Retry request if (this.reuseStrategy.keepAlive(response, context)) { this.log.debug("Connection kept alive"); // Consume response content HttpEntity entity = response.getEntity(); if (entity != null) { entity.consumeContent(); } } else { this.managedConn.close(); } } } else { // Reset proxy auth scope this.proxyAuthState.setAuthScope(null); } } } int status = response.getStatusLine().getStatusCode(); if (status > 299) { // Buffer response content HttpEntity entity = response.getEntity(); if (entity != null) { response.setEntity(new BufferedHttpEntity(entity)); } this.managedConn.close(); throw new TunnelRefusedException( "CONNECT refused by proxy: " + response.getStatusLine(), response); } this.managedConn.markReusable(); // 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; } // createTunnelToTarget
@Override public Header authenticate( final Credentials credentials, final HttpRequest request, final HttpContext context) throws AuthenticationException { Args.notNull(request, "HTTP request"); switch (state) { case UNINITIATED: throw new AuthenticationException( getSchemeName() + " authentication has not been initiated"); case FAILED: throw new AuthenticationException(getSchemeName() + " authentication has failed"); case CHALLENGE_RECEIVED: try { final HttpRoute route = (HttpRoute) context.getAttribute(HttpClientContext.HTTP_ROUTE); 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(); } final 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 = State.TOKEN_GENERATED; } catch (final GSSException gsse) { state = State.FAILED; if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED) { throw new InvalidCredentialsException(gsse.getMessage(), gsse); } if (gsse.getMajor() == GSSException.NO_CRED) { throw new InvalidCredentialsException(gsse.getMessage(), gsse); } if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN || gsse.getMajor() == GSSException.DUPLICATE_TOKEN || gsse.getMajor() == GSSException.OLD_TOKEN) { throw new AuthenticationException(gsse.getMessage(), gsse); } // other error throw new AuthenticationException(gsse.getMessage()); } case TOKEN_GENERATED: final String tokenstr = new String(base64codec.encode(token)); if (log.isDebugEnabled()) { log.debug("Sending response '" + tokenstr + "' back to the auth server"); } final CharArrayBuffer buffer = new CharArrayBuffer(32); if (isProxy()) { buffer.append(AUTH.PROXY_AUTH_RESP); } else { buffer.append(AUTH.WWW_AUTH_RESP); } buffer.append(": Negotiate "); buffer.append(tokenstr); return new BufferedHeader(buffer); default: throw new IllegalStateException("Illegal state: " + state); } }