blob: 1b13f78216a3a24876ca0ac9cb065a4ab33eb2d8 [file] [log] [blame]
// 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_ntlm.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "net/base/net_errors.h"
#include "net/base/network_interfaces.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_auth_preferences.h"
namespace net {
namespace {
uint64_t GetMSTime() {
return base::Time::Now().since_origin().InMicroseconds() * 10;
void GenerateRandom(uint8_t* output, size_t n) {
base::RandBytes(output, n);
} // namespace
// static
HttpAuthHandlerNTLM::GetMSTimeProc HttpAuthHandlerNTLM::get_ms_time_proc_ =
// static
HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom;
// static
HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::get_host_name_proc_ =
const HttpAuthPreferences* http_auth_preferences)
: ntlm_client_(ntlm::NtlmFeatures(
http_auth_preferences ? http_auth_preferences->NtlmV2Enabled()
: true)) {}
bool HttpAuthHandlerNTLM::NeedsIdentity() {
// This gets called for each round-trip. Only require identity on
// the first call (when auth_data_ is empty). On subsequent calls,
// we use the initially established identity.
return auth_data_.empty();
bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
// Default credentials are not supported in the portable implementation of
// NTLM, but are supported in the SSPI implementation.
return false;
int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
return OK;
HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() = default;
// static
HttpAuthHandlerNTLM::GetMSTimeProc HttpAuthHandlerNTLM::SetGetMSTimeProc(
GetMSTimeProc proc) {
GetMSTimeProc old_proc = get_ms_time_proc_;
get_ms_time_proc_ = proc;
return old_proc;
// static
HttpAuthHandlerNTLM::SetGenerateRandomProc(GenerateRandomProc proc) {
GenerateRandomProc old_proc = generate_random_proc_;
generate_random_proc_ = proc;
return old_proc;
// static
HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::SetHostNameProc(
HostNameProc proc) {
HostNameProc old_proc = get_host_name_proc_;
get_host_name_proc_ = proc;
return old_proc;
HttpAuthHandlerNTLM::Factory::Factory() = default;
HttpAuthHandlerNTLM::Factory::~Factory() = default;
std::vector<uint8_t> HttpAuthHandlerNTLM::GetNextToken(
base::span<const uint8_t> in_token) {
// If in_token is non-empty, then assume it contains a challenge message,
// and generate the Authenticate message in reply. Otherwise return the
// Negotiate message.
if (in_token.empty()) {
return ntlm_client_.GetNegotiateMessage();
std::string hostname = get_host_name_proc_();
if (hostname.empty())
return {};
uint8_t client_challenge[8];
generate_random_proc_(client_challenge, 8);
uint64_t client_time = get_ms_time_proc_();
return ntlm_client_.GenerateAuthenticateMessage(
domain_, credentials_.username(), credentials_.password(), hostname,
channel_bindings_, CreateSPN(origin_), client_time, client_challenge,
int HttpAuthHandlerNTLM::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 (reason == CREATE_PREEMPTIVE)
// TODO(cbentzel): Move towards model of parsing in the factory
// method and only constructing when valid.
// NOTE: Default credentials are not supported for the portable implementation
// of NTLM.
std::unique_ptr<HttpAuthHandler> tmp_handler(
new HttpAuthHandlerNTLM(http_auth_preferences()));
if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
return OK;
} // namespace net