// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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_handler_negotiate.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_util.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_preferences.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/ssl/ssl_info.h"

namespace net {

using DelegationType = HttpAuth::DelegationType;

namespace {

std::unique_ptr<base::Value> NetLogParameterChannelBindings(
    const std::string& channel_binding_token,
    NetLogCaptureMode capture_mode) {
  std::unique_ptr<base::DictionaryValue> dict;
  if (!capture_mode.include_socket_bytes())
    return std::move(dict);

  dict.reset(new base::DictionaryValue());
  dict->SetString("token", base::HexEncode(channel_binding_token.data(),
                                           channel_binding_token.size()));
  return std::move(dict);
}

// Uses |negotiate_auth_system_factory| to create the auth system, otherwise
// creates the default auth system for each platform.
std::unique_ptr<HttpNegotiateAuthSystem> CreateAuthSystem(
#if !defined(OS_ANDROID)
    HttpAuthHandlerNegotiate::AuthLibrary* auth_library,
#endif
#if defined(OS_WIN)
    ULONG max_token_length,
#endif
    const HttpAuthPreferences* prefs,
    HttpAuthHandlerFactory::NegotiateAuthSystemFactory
        negotiate_auth_system_factory) {
  if (negotiate_auth_system_factory)
    return negotiate_auth_system_factory.Run(prefs);
#if defined(OS_ANDROID)
  return std::make_unique<net::android::HttpAuthNegotiateAndroid>(prefs);
#elif defined(OS_WIN)
  return std::make_unique<HttpAuthSSPI>(auth_library, "Negotiate", NEGOSSP_NAME,
                                        max_token_length);
#elif defined(OS_POSIX)
  return std::make_unique<HttpAuthGSSAPI>(auth_library, "Negotiate",
                                          CHROME_GSS_SPNEGO_MECH_OID_DESC);
#endif
}

}  // namespace

HttpAuthHandlerNegotiate::Factory::Factory(
    NegotiateAuthSystemFactory negotiate_auth_system_factory)
    : negotiate_auth_system_factory_(negotiate_auth_system_factory) {}

HttpAuthHandlerNegotiate::Factory::~Factory() = default;

#if !defined(OS_ANDROID) && defined(OS_POSIX)
const std::string& HttpAuthHandlerNegotiate::Factory::GetLibraryNameForTesting()
    const {
  return auth_library_->GetLibraryNameForTesting();
}
#endif  // !defined(OS_ANDROID) && defined(OS_POSIX)

int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
    HttpAuthChallengeTokenizer* challenge,
    HttpAuth::Target target,
    const SSLInfo& ssl_info,
    const GURL& origin,
    CreateReason reason,
    int digest_nonce_count,
    const NetLogWithSource& net_log,
    HostResolver* host_resolver,
    std::unique_ptr<HttpAuthHandler>* handler) {
#if defined(OS_WIN)
  if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
    return ERR_UNSUPPORTED_AUTH_SCHEME;
  if (max_token_length_ == 0) {
    int rv = DetermineMaxTokenLength(auth_library_.get(), NEGOSSP_NAME,
                                     &max_token_length_);
    if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
      is_unsupported_ = true;
    if (rv != OK)
      return rv;
  }
  // TODO(cbentzel): Move towards model of parsing in the factory
  //                 method and only constructing when valid.
  std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate(
      CreateAuthSystem(auth_library_.get(), max_token_length_,
                       http_auth_preferences(), negotiate_auth_system_factory_),
      http_auth_preferences(), host_resolver));
#elif defined(OS_ANDROID)
  if (is_unsupported_ || !http_auth_preferences() ||
      http_auth_preferences()->AuthAndroidNegotiateAccountType().empty() ||
      reason == CREATE_PREEMPTIVE)
    return ERR_UNSUPPORTED_AUTH_SCHEME;
  // TODO(cbentzel): Move towards model of parsing in the factory
  //                 method and only constructing when valid.
  std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate(
      CreateAuthSystem(http_auth_preferences(), negotiate_auth_system_factory_),
      http_auth_preferences(), host_resolver));
#elif defined(OS_POSIX)
  if (is_unsupported_ || !allow_gssapi_library_load_)
    return ERR_UNSUPPORTED_AUTH_SCHEME;
  if (!auth_library_->Init()) {
    is_unsupported_ = true;
    return ERR_UNSUPPORTED_AUTH_SCHEME;
  }
  // TODO(ahendrickson): Move towards model of parsing in the factory
  //                     method and only constructing when valid.
  std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate(
      CreateAuthSystem(auth_library_.get(), http_auth_preferences(),
                       negotiate_auth_system_factory_),
      http_auth_preferences(), host_resolver));
#endif
  if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
                                      net_log))
    return ERR_INVALID_RESPONSE;
  handler->swap(tmp_handler);
  return OK;
}

HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
    std::unique_ptr<HttpNegotiateAuthSystem> auth_system,
    const HttpAuthPreferences* prefs,
    HostResolver* resolver)
    : auth_system_(std::move(auth_system)),
      resolver_(resolver),
      already_called_(false),
      has_credentials_(false),
      auth_token_(nullptr),
      next_state_(STATE_NONE),
      http_auth_preferences_(prefs) {}

HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() = default;

HttpAuth::AuthorizationResult HttpAuthHandlerNegotiate::HandleAnotherChallenge(
    HttpAuthChallengeTokenizer* challenge) {
  return auth_system_->ParseChallenge(challenge);
}

// Require identity on first pass instead of second.
bool HttpAuthHandlerNegotiate::NeedsIdentity() {
  return auth_system_->NeedsIdentity();
}

bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
  if (target_ == HttpAuth::AUTH_PROXY)
    return true;
  if (!http_auth_preferences_)
    return false;
  return http_auth_preferences_->CanUseDefaultCredentials(origin_);
}

bool HttpAuthHandlerNegotiate::AllowsExplicitCredentials() {
  return auth_system_->AllowsExplicitCredentials();
}

// The Negotiate challenge header looks like:
//   WWW-Authenticate: NEGOTIATE auth-data
bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge,
                                    const SSLInfo& ssl_info) {
#if defined(OS_POSIX)
  if (!auth_system_->Init()) {
    VLOG(1) << "can't initialize GSSAPI library";
    return false;
  }
  // GSSAPI does not provide a way to enter username/password to
  // obtain a TGT. If the default credentials are not allowed for
  // a particular site (based on whitelist), fall back to a
  // different scheme.
  if (!AllowsDefaultCredentials())
    return false;
#endif
  auth_system_->SetDelegation(GetDelegationType());
  auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE;
  score_ = 4;
  properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;

  HttpAuth::AuthorizationResult auth_result =
      auth_system_->ParseChallenge(challenge);
  if (auth_result != HttpAuth::AUTHORIZATION_RESULT_ACCEPT)
    return false;

  // Try to extract channel bindings.
  if (ssl_info.is_valid())
    x509_util::GetTLSServerEndPointChannelBinding(*ssl_info.cert,
                                                  &channel_bindings_);
  if (!channel_bindings_.empty())
    net_log_.AddEvent(
        NetLogEventType::AUTH_CHANNEL_BINDINGS,
        base::Bind(&NetLogParameterChannelBindings, channel_bindings_));
  return true;
}

int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl(
    const AuthCredentials* credentials,
    const HttpRequestInfo* request,
    CompletionOnceCallback callback,
    std::string* auth_token) {
  DCHECK(callback_.is_null());
  DCHECK(auth_token_ == nullptr);
  auth_token_ = auth_token;
  if (already_called_) {
    DCHECK((!has_credentials_ && credentials == nullptr) ||
           (has_credentials_ && credentials->Equals(credentials_)));
    next_state_ = STATE_GENERATE_AUTH_TOKEN;
  } else {
    already_called_ = true;
    if (credentials) {
      has_credentials_ = true;
      credentials_ = *credentials;
    }
    next_state_ = STATE_RESOLVE_CANONICAL_NAME;
  }
  int rv = DoLoop(OK);
  if (rv == ERR_IO_PENDING)
    callback_ = std::move(callback);
  return rv;
}

std::string HttpAuthHandlerNegotiate::CreateSPN(const std::string& server,
                                                const GURL& origin) {
  // Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI,
  // and in the form HTTP@<host>:<port> through GSSAPI
  //   http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx
  //
  // However, reality differs from the specification. A good description of
  // the problems can be found here:
  //   http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-kb911149-and-kb908209-are-not-the-soluton.aspx
  //
  // Typically the <host> portion should be the canonical FQDN for the service.
  // If this could not be resolved, the original hostname in the URL will be
  // attempted instead. However, some intranets register SPNs using aliases
  // for the same canonical DNS name to allow multiple web services to reside
  // on the same host machine without requiring different ports. IE6 and IE7
  // have hotpatches that allow the default behavior to be overridden.
  //   http://support.microsoft.com/kb/911149
  //   http://support.microsoft.com/kb/938305
  //
  // According to the spec, the <port> option should be included if it is a
  // non-standard port (i.e. not 80 or 443 in the HTTP case). However,
  // historically browsers have not included the port, even on non-standard
  // ports. IE6 required a hotpatch and a registry setting to enable
  // including non-standard ports, and IE7 and IE8 also require the same
  // registry setting, but no hotpatch. Firefox does not appear to have an
  // option to include non-standard ports as of 3.6.
  //   http://support.microsoft.com/kb/908209
  //
  // Without any command-line flags, Chrome matches the behavior of Firefox
  // and IE. Users can override the behavior so aliases are allowed and
  // non-standard ports are included.
  int port = origin.EffectiveIntPort();
#if defined(OS_WIN)
  static const char kSpnSeparator = '/';
#elif defined(OS_POSIX)
  static const char kSpnSeparator = '@';
#endif
  if (port != 80 && port != 443 &&
      (http_auth_preferences_ &&
       http_auth_preferences_->NegotiateEnablePort())) {
    return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(),
                              port);
  } else {
    return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str());
  }
}

void HttpAuthHandlerNegotiate::OnIOComplete(int result) {
  int rv = DoLoop(result);
  if (rv != ERR_IO_PENDING)
    DoCallback(rv);
}

void HttpAuthHandlerNegotiate::DoCallback(int rv) {
  DCHECK(rv != ERR_IO_PENDING);
  DCHECK(!callback_.is_null());
  base::ResetAndReturn(&callback_).Run(rv);
}

int HttpAuthHandlerNegotiate::DoLoop(int result) {
  DCHECK(next_state_ != STATE_NONE);

  int rv = result;
  do {
    State state = next_state_;
    next_state_ = STATE_NONE;
    switch (state) {
      case STATE_RESOLVE_CANONICAL_NAME:
        DCHECK_EQ(OK, rv);
        rv = DoResolveCanonicalName();
        break;
      case STATE_RESOLVE_CANONICAL_NAME_COMPLETE:
        rv = DoResolveCanonicalNameComplete(rv);
        break;
      case STATE_GENERATE_AUTH_TOKEN:
        DCHECK_EQ(OK, rv);
        rv = DoGenerateAuthToken();
        break;
      case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
        rv = DoGenerateAuthTokenComplete(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = ERR_FAILED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);

  return rv;
}

int HttpAuthHandlerNegotiate::DoResolveCanonicalName() {
  next_state_ = STATE_RESOLVE_CANONICAL_NAME_COMPLETE;
  if ((http_auth_preferences_ &&
       http_auth_preferences_->NegotiateDisableCnameLookup()) ||
      !resolver_)
    return OK;

  // TODO(cbentzel): Add reverse DNS lookup for numeric addresses.
  HostResolver::ResolveHostParameters parameters;
  parameters.include_canonical_name = true;
  resolve_host_request_ = resolver_->CreateRequest(
      HostPortPair(origin_.host(), 0), net_log_, parameters);
  return resolve_host_request_->Start(base::BindOnce(
      &HttpAuthHandlerNegotiate::OnIOComplete, base::Unretained(this)));
}

int HttpAuthHandlerNegotiate::DoResolveCanonicalNameComplete(int rv) {
  DCHECK_NE(ERR_IO_PENDING, rv);
  std::string server = origin_.host();
  if (resolve_host_request_) {
    if (rv == OK) {
      DCHECK(resolve_host_request_->GetAddressResults());
      const std::string& canonical_name =
          resolve_host_request_->GetAddressResults().value().canonical_name();
      if (!canonical_name.empty())
        server = canonical_name;
    } else {
      // Even in the error case, try to use origin_.host instead of
      // passing the failure on to the caller.
      VLOG(1) << "Problem finding canonical name for SPN for host "
              << origin_.host() << ": " << ErrorToString(rv);
      rv = OK;
    }
  }

  next_state_ = STATE_GENERATE_AUTH_TOKEN;
  spn_ = CreateSPN(server, origin_);
  resolve_host_request_ = nullptr;
  return rv;
}

int HttpAuthHandlerNegotiate::DoGenerateAuthToken() {
  next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
  AuthCredentials* credentials = has_credentials_ ? &credentials_ : nullptr;
  return auth_system_->GenerateAuthToken(
      credentials, spn_, channel_bindings_, auth_token_,
      base::BindOnce(&HttpAuthHandlerNegotiate::OnIOComplete,
                     base::Unretained(this)));
}

int HttpAuthHandlerNegotiate::DoGenerateAuthTokenComplete(int rv) {
  DCHECK_NE(ERR_IO_PENDING, rv);
  auth_token_ = nullptr;
  return rv;
}

DelegationType HttpAuthHandlerNegotiate::GetDelegationType() const {
  if (!http_auth_preferences_)
    return DelegationType::kNone;

  // TODO(cbentzel): Should delegation be allowed on proxies?
  if (target_ == HttpAuth::AUTH_PROXY)
    return DelegationType::kNone;

  return http_auth_preferences_->GetDelegationType(origin_);
}

}  // namespace net
