@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);
  }
示例#2
0
  /**
   * 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
示例#3
0
  @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);
    }
  }