// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/http_auth_controller.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "net/base/auth.h"
#include "net/base/url_util.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_source_type.h"
#include "net/log/net_log_with_source.h"
#include "url/scheme_host_port.h"

namespace net {

namespace {

base::Value::Dict ControllerParamsToValue(HttpAuth::Target target,
                                          const GURL& url) {
  base::Value::Dict params;
  params.Set("target", HttpAuth::GetAuthTargetString(target));
  params.Set("url", url.spec());
  return params;
}

}  // namespace

HttpAuthController::HttpAuthController(
    HttpAuth::Target target,
    const GURL& auth_url,
    const NetworkAnonymizationKey& network_anonymization_key,
    HttpAuthCache* http_auth_cache,
    HttpAuthHandlerFactory* http_auth_handler_factory,
    HostResolver* host_resolver)
    : target_(target),
      auth_url_(auth_url),
      auth_scheme_host_port_(auth_url),
      auth_path_(auth_url.path()),
      network_anonymization_key_(network_anonymization_key),
      http_auth_cache_(http_auth_cache),
      http_auth_handler_factory_(http_auth_handler_factory),
      host_resolver_(host_resolver) {
  DCHECK(target != HttpAuth::AUTH_PROXY || auth_path_ == "/");
  DCHECK(auth_scheme_host_port_.IsValid());
}

HttpAuthController::~HttpAuthController() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (net_log_.source().IsValid())
    net_log_.EndEvent(NetLogEventType::AUTH_CONTROLLER);
}

void HttpAuthController::BindToCallingNetLog(
    const NetLogWithSource& caller_net_log) {
  if (!net_log_.source().IsValid()) {
    net_log_ = NetLogWithSource::Make(caller_net_log.net_log(),
                                      NetLogSourceType::HTTP_AUTH_CONTROLLER);
    net_log_.BeginEvent(NetLogEventType::AUTH_CONTROLLER, [&] {
      return ControllerParamsToValue(target_, auth_url_);
    });
  }
  caller_net_log.AddEventReferencingSource(
      NetLogEventType::AUTH_BOUND_TO_CONTROLLER, net_log_.source());
}

int HttpAuthController::MaybeGenerateAuthToken(
    const HttpRequestInfo* request,
    CompletionOnceCallback callback,
    const NetLogWithSource& caller_net_log) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!auth_info_);
  bool needs_auth = HaveAuth() || SelectPreemptiveAuth(caller_net_log);
  if (!needs_auth)
    return OK;
  net_log_.BeginEventReferencingSource(NetLogEventType::AUTH_GENERATE_TOKEN,
                                       caller_net_log.source());
  const AuthCredentials* credentials = nullptr;
  if (identity_.source != HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS)
    credentials = &identity_.credentials;
  DCHECK(auth_token_.empty());
  DCHECK(callback_.is_null());
  int rv = handler_->GenerateAuthToken(
      credentials, request,
      base::BindOnce(&HttpAuthController::OnGenerateAuthTokenDone,
                     base::Unretained(this)),
      &auth_token_);

  if (rv == ERR_IO_PENDING) {
    callback_ = std::move(callback);
    return rv;
  }

  return HandleGenerateTokenResult(rv);
}

bool HttpAuthController::SelectPreemptiveAuth(
    const NetLogWithSource& caller_net_log) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!HaveAuth());
  DCHECK(identity_.invalid);

  // Don't do preemptive authorization if the URL contains a username:password,
  // since we must first be challenged in order to use the URL's identity.
  if (auth_url_.has_username())
    return false;

  // SelectPreemptiveAuth() is on the critical path for each request, so it
  // is expected to be fast. LookupByPath() is fast in the common case, since
  // the number of http auth cache entries is expected to be very small.
  // (For most users in fact, it will be 0.)
  HttpAuthCache::Entry* entry = http_auth_cache_->LookupByPath(
      auth_scheme_host_port_, target_, network_anonymization_key_, auth_path_);
  if (!entry)
    return false;

  BindToCallingNetLog(caller_net_log);

  // Try to create a handler using the previous auth challenge.
  std::unique_ptr<HttpAuthHandler> handler_preemptive;
  int rv_create =
      http_auth_handler_factory_->CreatePreemptiveAuthHandlerFromString(
          entry->auth_challenge(), target_, network_anonymization_key_,
          auth_scheme_host_port_, entry->IncrementNonceCount(), net_log_,
          host_resolver_, &handler_preemptive);
  if (rv_create != OK)
    return false;

  // Set the state
  identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
  identity_.invalid = false;
  identity_.credentials = entry->credentials();
  handler_.swap(handler_preemptive);
  return true;
}

void HttpAuthController::AddAuthorizationHeader(
    HttpRequestHeaders* authorization_headers) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(HaveAuth());
  // auth_token_ can be empty if we encountered a permanent error with
  // the auth scheme and want to retry.
  if (!auth_token_.empty()) {
    authorization_headers->SetHeader(
        HttpAuth::GetAuthorizationHeaderName(target_), auth_token_);
    auth_token_.clear();
  }
}

int HttpAuthController::HandleAuthChallenge(
    scoped_refptr<HttpResponseHeaders> headers,
    const SSLInfo& ssl_info,
    bool do_not_send_server_auth,
    bool establishing_tunnel,
    const NetLogWithSource& caller_net_log) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(headers.get());
  DCHECK(auth_scheme_host_port_.IsValid());
  DCHECK(!auth_info_);

  BindToCallingNetLog(caller_net_log);
  net_log_.BeginEventReferencingSource(NetLogEventType::AUTH_HANDLE_CHALLENGE,
                                       caller_net_log.source());

  // Give the existing auth handler first try at the authentication headers.
  // This will also evict the entry in the HttpAuthCache if the previous
  // challenge appeared to be rejected, or is using a stale nonce in the Digest
  // case.
  if (HaveAuth()) {
    std::string challenge_used;
    HttpAuth::AuthorizationResult result = HttpAuth::HandleChallengeResponse(
        handler_.get(), *headers, target_, disabled_schemes_, &challenge_used);
    switch (result) {
      case HttpAuth::AUTHORIZATION_RESULT_ACCEPT:
        break;
      case HttpAuth::AUTHORIZATION_RESULT_INVALID:
        InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
        break;
      case HttpAuth::AUTHORIZATION_RESULT_REJECT:
        InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
        break;
      case HttpAuth::AUTHORIZATION_RESULT_STALE:
        if (http_auth_cache_->UpdateStaleChallenge(
                auth_scheme_host_port_, target_, handler_->realm(),
                handler_->auth_scheme(), network_anonymization_key_,
                challenge_used)) {
          InvalidateCurrentHandler(INVALIDATE_HANDLER);
        } else {
          // It's possible that a server could incorrectly issue a stale
          // response when the entry is not in the cache. Just evict the
          // current value from the cache.
          InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
        }
        break;
      case HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM:
        // If the server changes the authentication realm in a
        // subsequent challenge, invalidate cached credentials for the
        // previous realm.  If the server rejects a preemptive
        // authorization and requests credentials for a different
        // realm, we keep the cached credentials.
        InvalidateCurrentHandler(
            (identity_.source == HttpAuth::IDENT_SRC_PATH_LOOKUP) ?
            INVALIDATE_HANDLER :
            INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
        break;
      default:
        NOTREACHED();
        break;
    }
  }

  identity_.invalid = true;
  bool can_send_auth = (target_ != HttpAuth::AUTH_SERVER ||
                        !do_not_send_server_auth);

  do {
    if (!handler_.get() && can_send_auth) {
      // Find the best authentication challenge that we support.
      HttpAuth::ChooseBestChallenge(
          http_auth_handler_factory_, *headers, ssl_info,
          network_anonymization_key_, target_, auth_scheme_host_port_,
          disabled_schemes_, net_log_, host_resolver_, &handler_);
    }

    if (!handler_.get()) {
      if (establishing_tunnel) {
        // We are establishing a tunnel, we can't show the error page because an
        // active network attacker could control its contents.  Instead, we just
        // fail to establish the tunnel.
        DCHECK_EQ(target_, HttpAuth::AUTH_PROXY);
        net_log_.EndEventWithNetErrorCode(
            NetLogEventType::AUTH_HANDLE_CHALLENGE, ERR_PROXY_AUTH_UNSUPPORTED);
        return ERR_PROXY_AUTH_UNSUPPORTED;
      }
      // We found no supported challenge -- let the transaction continue so we
      // end up displaying the error page.
      net_log_.EndEvent(NetLogEventType::AUTH_HANDLE_CHALLENGE);
      return OK;
    }

    if (handler_->NeedsIdentity()) {
      // Pick a new auth identity to try, by looking to the URL and auth cache.
      // If an identity to try is found, it is saved to identity_.
      SelectNextAuthIdentityToTry();
    } else {
      // Proceed with the existing identity or a null identity.
      identity_.invalid = false;
    }

    // From this point on, we are restartable.

    if (identity_.invalid) {
      // We have exhausted all identity possibilities.
      if (!handler_->AllowsExplicitCredentials()) {
        // If the handler doesn't accept explicit credentials, then we need to
        // choose a different auth scheme.
        InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_DISABLE_SCHEME);
      } else {
        // Pass the challenge information back to the client.
        PopulateAuthChallenge();
      }
    }

    // If we get here and we don't have a handler_, that's because we
    // invalidated it due to not having any viable identities to use with it. Go
    // back and try again.
    // TODO(asanka): Instead we should create a priority list of
    //     <handler,identity> and iterate through that.
  } while(!handler_.get());
  net_log_.EndEvent(NetLogEventType::AUTH_HANDLE_CHALLENGE);
  return OK;
}

void HttpAuthController::ResetAuth(const AuthCredentials& credentials) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(identity_.invalid || credentials.Empty());

  if (identity_.invalid) {
    // Update the credentials.
    identity_.source = HttpAuth::IDENT_SRC_EXTERNAL;
    identity_.invalid = false;
    identity_.credentials = credentials;

    // auth_info_ is no longer necessary.
    auth_info_ = absl::nullopt;
  }

  DCHECK(identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP);

  // Add the auth entry to the cache before restarting. We don't know whether
  // the identity is valid yet, but if it is valid we want other transactions
  // to know about it. If an entry for (origin, handler->realm()) already
  // exists, we update it.
  //
  // If identity_.source is HttpAuth::IDENT_SRC_NONE or
  // HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS, identity_ contains no
  // identity because identity is not required yet or we're using default
  // credentials.
  //
  // TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
  // round 1 and round 2, which is redundant but correct.  It would be nice
  // to add an auth entry to the cache only once, preferrably in round 1.
  // See http://crbug.com/21015.
  switch (identity_.source) {
    case HttpAuth::IDENT_SRC_NONE:
    case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS:
      break;
    default:
      http_auth_cache_->Add(auth_scheme_host_port_, target_, handler_->realm(),
                            handler_->auth_scheme(), network_anonymization_key_,
                            handler_->challenge(), identity_.credentials,
                            auth_path_);
      break;
  }
}

bool HttpAuthController::HaveAuthHandler() const {
  return handler_.get() != nullptr;
}

bool HttpAuthController::HaveAuth() const {
  return handler_.get() && !identity_.invalid;
}

bool HttpAuthController::NeedsHTTP11() const {
  return handler_ && handler_->is_connection_based();
}

void HttpAuthController::InvalidateCurrentHandler(
    InvalidateHandlerAction action) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(handler_.get());

  switch (action) {
    case INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS:
      InvalidateRejectedAuthFromCache();
      break;

    case INVALIDATE_HANDLER_AND_DISABLE_SCHEME:
      DisableAuthScheme(handler_->auth_scheme());
      break;

    case INVALIDATE_HANDLER:
      PrepareIdentityForReuse();
      break;
  }

  handler_.reset();
  identity_ = HttpAuth::Identity();
}

void HttpAuthController::InvalidateRejectedAuthFromCache() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(HaveAuth());

  // Clear the cache entry for the identity we just failed on.
  // Note: we require the credentials to match before invalidating
  // since the entry in the cache may be newer than what we used last time.
  http_auth_cache_->Remove(auth_scheme_host_port_, target_, handler_->realm(),
                           handler_->auth_scheme(), network_anonymization_key_,
                           identity_.credentials);
}

void HttpAuthController::PrepareIdentityForReuse() {
  if (identity_.invalid)
    return;

  switch (identity_.source) {
    case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS:
      DCHECK(default_credentials_used_);
      default_credentials_used_ = false;
      break;

    case HttpAuth::IDENT_SRC_URL:
      DCHECK(embedded_identity_used_);
      embedded_identity_used_ = false;
      break;

    case HttpAuth::IDENT_SRC_NONE:
    case HttpAuth::IDENT_SRC_PATH_LOOKUP:
    case HttpAuth::IDENT_SRC_REALM_LOOKUP:
    case HttpAuth::IDENT_SRC_EXTERNAL:
      break;
  }
}

bool HttpAuthController::SelectNextAuthIdentityToTry() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(handler_.get());
  DCHECK(identity_.invalid);

  // Try to use the username:password encoded into the URL first.
  if (target_ == HttpAuth::AUTH_SERVER && auth_url_.has_username() &&
      !embedded_identity_used_) {
    identity_.source = HttpAuth::IDENT_SRC_URL;
    identity_.invalid = false;
    // Extract the username:password from the URL.
    std::u16string username;
    std::u16string password;
    GetIdentityFromURL(auth_url_, &username, &password);
    identity_.credentials.Set(username, password);
    embedded_identity_used_ = true;
    // TODO(eroman): If the password is blank, should we also try combining
    // with a password from the cache?
    UMA_HISTOGRAM_BOOLEAN("net.HttpIdentSrcURL", true);
    return true;
  }

  // Check the auth cache for a realm entry.
  HttpAuthCache::Entry* entry = http_auth_cache_->Lookup(
      auth_scheme_host_port_, target_, handler_->realm(),
      handler_->auth_scheme(), network_anonymization_key_);

  if (entry) {
    identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
    identity_.invalid = false;
    identity_.credentials = entry->credentials();
    return true;
  }

  // Use default credentials (single sign-on) if they're allowed and this is the
  // first attempt at using an identity. Do not allow multiple times as it will
  // infinite loop. We use default credentials after checking the auth cache so
  // that if single sign-on doesn't work, we won't try default credentials for
  // future transactions.
  if (!default_credentials_used_ && handler_->AllowsDefaultCredentials()) {
    identity_.source = HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS;
    identity_.invalid = false;
    default_credentials_used_ = true;
    return true;
  }

  return false;
}

void HttpAuthController::PopulateAuthChallenge() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Populates response_.auth_challenge with the authentication challenge info.
  // This info is consumed by URLRequestHttpJob::GetAuthChallengeInfo().

  auth_info_ = AuthChallengeInfo();
  auth_info_->is_proxy = (target_ == HttpAuth::AUTH_PROXY);
  auth_info_->challenger = auth_scheme_host_port_;
  auth_info_->scheme = HttpAuth::SchemeToString(handler_->auth_scheme());
  auth_info_->realm = handler_->realm();
  auth_info_->path = auth_path_;
  auth_info_->challenge = handler_->challenge();
}

int HttpAuthController::HandleGenerateTokenResult(int result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  net_log_.EndEventWithNetErrorCode(NetLogEventType::AUTH_GENERATE_TOKEN,
                                    result);
  switch (result) {
    // Occurs if the credential handle is found to be invalid at the point it is
    // exercised (i.e. GenerateAuthToken stage). We are going to consider this
    // to be an error that invalidates the identity but not necessarily the
    // scheme. Doing so allows a different identity to be used with the same
    // scheme. See https://crbug.com/648366.
    case ERR_INVALID_HANDLE:

    // If the GenerateAuthToken call fails with this error, this means that the
    // handler can no longer be used. However, the authentication scheme is
    // considered still usable. This allows a scheme that attempted and failed
    // to use default credentials to recover and use explicit credentials.
    //
    // The current handler may be tied to external state that is no longer
    // valid, hence should be discarded. Since the scheme is still valid, a new
    // handler can be created for the current scheme.
    case ERR_INVALID_AUTH_CREDENTIALS:
      InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
      auth_token_.clear();
      return OK;

    // Occurs with GSSAPI, if the user has not already logged in.
    case ERR_MISSING_AUTH_CREDENTIALS:
      // Usually, GSSAPI doesn't allow explicit credentials and the scheme
      // cannot succeed anymore hence it gets disabled. However, on ChromeOS
      // it's not the case so we invalidate the current handler and can ask for
      // explicit credentials later. (See b/260522530).
      if (!handler_->AllowsExplicitCredentials()) {
        InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_DISABLE_SCHEME);
      } else {
        InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_CACHED_CREDENTIALS);
      }
      auth_token_.clear();
      return OK;

    // Can occur with GSSAPI or SSPI if the underlying library reports
    // a permanent error.
    case ERR_UNSUPPORTED_AUTH_SCHEME:

    // These two error codes represent failures we aren't handling.
    case ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS:
    case ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS:

    // Can be returned by SSPI if the authenticating authority or
    // target is not known.
    case ERR_MISCONFIGURED_AUTH_ENVIRONMENT:

      // In these cases, disable the current scheme as it cannot
      // succeed.
      InvalidateCurrentHandler(INVALIDATE_HANDLER_AND_DISABLE_SCHEME);
      auth_token_.clear();
      return OK;

    default:
      return result;
  }
}

void HttpAuthController::OnGenerateAuthTokenDone(int result) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  result = HandleGenerateTokenResult(result);
  if (!callback_.is_null()) {
    std::move(callback_).Run(result);
  }
}

void HttpAuthController::TakeAuthInfo(
    absl::optional<AuthChallengeInfo>* other) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  auth_info_.swap(*other);
}

bool HttpAuthController::IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return disabled_schemes_.find(scheme) != disabled_schemes_.end();
}

void HttpAuthController::DisableAuthScheme(HttpAuth::Scheme scheme) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  disabled_schemes_.insert(scheme);
}

void HttpAuthController::DisableEmbeddedIdentity() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  embedded_identity_used_ = true;
}

void HttpAuthController::OnConnectionClosed() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  InvalidateCurrentHandler(INVALIDATE_HANDLER);
}

}  // namespace net
