// Copyright (c) 2011 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_factory.h"

#include <memory>

#include "build/build_config.h"
#include "net/base/net_errors.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_auth_scheme.h"
#include "net/http/mock_allow_http_auth_preferences.h"
#include "net/http/url_security_manager.h"
#include "net/log/net_log_values.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
#include "net/net_buildflags.h"
#include "net/ssl/ssl_info.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/scheme_host_port.h"

using net::test::IsError;
using net::test::IsOk;

namespace net {

namespace {

class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
 public:
  explicit MockHttpAuthHandlerFactory(int return_code) :
      return_code_(return_code) {}
  ~MockHttpAuthHandlerFactory() override = default;

  int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
                        HttpAuth::Target target,
                        const SSLInfo& ssl_info,
                        const NetworkIsolationKey& network_isolation_key,
                        const url::SchemeHostPort& scheme_host_port,
                        CreateReason reason,
                        int nonce_count,
                        const NetLogWithSource& net_log,
                        HostResolver* host_resolver,
                        std::unique_ptr<HttpAuthHandler>* handler) override {
    handler->reset();
    return return_code_;
  }

 private:
  int return_code_;
};

}  // namespace

TEST(HttpAuthHandlerFactoryTest, RegistryFactory) {
  SSLInfo null_ssl_info;
  HttpAuthHandlerRegistryFactory registry_factory;
  url::SchemeHostPort scheme_host_port(GURL("https://www.google.com"));
  const int kBasicReturnCode = -1;
  MockHttpAuthHandlerFactory* mock_factory_basic =
      new MockHttpAuthHandlerFactory(kBasicReturnCode);

  const int kDigestReturnCode = -2;
  MockHttpAuthHandlerFactory* mock_factory_digest =
      new MockHttpAuthHandlerFactory(kDigestReturnCode);

  const int kDigestReturnCodeReplace = -3;
  MockHttpAuthHandlerFactory* mock_factory_digest_replace =
      new MockHttpAuthHandlerFactory(kDigestReturnCodeReplace);

  auto host_resovler = std::make_unique<MockHostResolver>();
  std::unique_ptr<HttpAuthHandler> handler;

  // No schemes should be supported in the beginning.
  EXPECT_EQ(
      ERR_UNSUPPORTED_AUTH_SCHEME,
      registry_factory.CreateAuthHandlerFromString(
          "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));

  // Test what happens with a single scheme.
  registry_factory.RegisterSchemeFactory("Basic", mock_factory_basic);
  EXPECT_EQ(
      kBasicReturnCode,
      registry_factory.CreateAuthHandlerFromString(
          "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));
  EXPECT_EQ(
      ERR_UNSUPPORTED_AUTH_SCHEME,
      registry_factory.CreateAuthHandlerFromString(
          "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));

  // Test multiple schemes
  registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest);
  EXPECT_EQ(
      kBasicReturnCode,
      registry_factory.CreateAuthHandlerFromString(
          "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));
  EXPECT_EQ(
      kDigestReturnCode,
      registry_factory.CreateAuthHandlerFromString(
          "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));

  // Test case-insensitivity
  EXPECT_EQ(
      kBasicReturnCode,
      registry_factory.CreateAuthHandlerFromString(
          "basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));

  // Test replacement of existing auth scheme
  registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest_replace);
  EXPECT_EQ(
      kBasicReturnCode,
      registry_factory.CreateAuthHandlerFromString(
          "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));
  EXPECT_EQ(
      kDigestReturnCodeReplace,
      registry_factory.CreateAuthHandlerFromString(
          "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
          scheme_host_port, NetLogWithSource(), host_resovler.get(), &handler));
}

TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
  std::unique_ptr<HostResolver> host_resolver(new MockHostResolver());
  MockAllowHttpAuthPreferences http_auth_preferences;
  std::unique_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
      HttpAuthHandlerFactory::CreateDefault());
  http_auth_handler_factory->SetHttpAuthPreferences(kNegotiateAuthScheme,
                                                    &http_auth_preferences);
  url::SchemeHostPort server_scheme_host_port(GURL("http://www.example.com"));
  url::SchemeHostPort proxy_scheme_host_port(
      GURL("http://cache.example.com:3128"));
  SSLInfo null_ssl_info;
  {
    std::unique_ptr<HttpAuthHandler> handler;
    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
        "Basic realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info,
        NetworkIsolationKey(), server_scheme_host_port, NetLogWithSource(),
        host_resolver.get(), &handler);
    EXPECT_THAT(rv, IsOk());
    ASSERT_FALSE(handler.get() == nullptr);
    EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme());
    EXPECT_STREQ("FooBar", handler->realm().c_str());
    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
    EXPECT_FALSE(handler->encrypts_identity());
    EXPECT_FALSE(handler->is_connection_based());
  }
  {
    std::unique_ptr<HttpAuthHandler> handler;
    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
        "UNSUPPORTED realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info,
        NetworkIsolationKey(), server_scheme_host_port, NetLogWithSource(),
        host_resolver.get(), &handler);
    EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME));
    EXPECT_TRUE(handler.get() == nullptr);
  }
  {
    std::unique_ptr<HttpAuthHandler> handler;
    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
        "Digest realm=\"FooBar\", nonce=\"xyz\"", HttpAuth::AUTH_PROXY,
        null_ssl_info, NetworkIsolationKey(), proxy_scheme_host_port,
        NetLogWithSource(), host_resolver.get(), &handler);
    EXPECT_THAT(rv, IsOk());
    ASSERT_FALSE(handler.get() == nullptr);
    EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme());
    EXPECT_STREQ("FooBar", handler->realm().c_str());
    EXPECT_EQ(HttpAuth::AUTH_PROXY, handler->target());
    EXPECT_TRUE(handler->encrypts_identity());
    EXPECT_FALSE(handler->is_connection_based());
  }
  {
    std::unique_ptr<HttpAuthHandler> handler;
    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
        "NTLM", HttpAuth::AUTH_SERVER, null_ssl_info, NetworkIsolationKey(),
        server_scheme_host_port, NetLogWithSource(), host_resolver.get(),
        &handler);
    EXPECT_THAT(rv, IsOk());
    ASSERT_FALSE(handler.get() == nullptr);
    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme());
    EXPECT_STREQ("", handler->realm().c_str());
    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
    EXPECT_TRUE(handler->encrypts_identity());
    EXPECT_TRUE(handler->is_connection_based());
  }
  {
    std::unique_ptr<HttpAuthHandler> handler;
    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
        "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info,
        NetworkIsolationKey(), server_scheme_host_port, NetLogWithSource(),
        host_resolver.get(), &handler);
// Note the default factory doesn't support Kerberos on Android
#if BUILDFLAG(USE_KERBEROS) && !BUILDFLAG(IS_ANDROID)
    EXPECT_THAT(rv, IsOk());
    ASSERT_FALSE(handler.get() == nullptr);
    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NEGOTIATE, handler->auth_scheme());
    EXPECT_STREQ("", handler->realm().c_str());
    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
    EXPECT_TRUE(handler->encrypts_identity());
    EXPECT_TRUE(handler->is_connection_based());
#else
    EXPECT_THAT(rv, IsError(ERR_UNSUPPORTED_AUTH_SCHEME));
    EXPECT_TRUE(handler.get() == nullptr);
#endif  // BUILDFLAG(USE_KERBEROS) && !BUILDFLAG(IS_ANDROID)
  }
}

TEST(HttpAuthHandlerFactoryTest, BasicFactoryRespectsHTTPEnabledPref) {
  std::unique_ptr<HostResolver> host_resolver(new MockHostResolver());
  std::unique_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
      HttpAuthHandlerFactory::CreateDefault());

  // Set the Preference that blocks Basic Auth over HTTP on all of the
  // factories. It shouldn't impact any behavior except for the Basic factory.
  MockAllowHttpAuthPreferences http_auth_preferences;
  http_auth_preferences.set_basic_over_http_enabled(false);
  http_auth_handler_factory->SetHttpAuthPreferences(kBasicAuthScheme,
                                                    &http_auth_preferences);
  http_auth_handler_factory->SetHttpAuthPreferences(kDigestAuthScheme,
                                                    &http_auth_preferences);
  http_auth_handler_factory->SetHttpAuthPreferences(kNtlmAuthScheme,
                                                    &http_auth_preferences);
  http_auth_handler_factory->SetHttpAuthPreferences(kNegotiateAuthScheme,
                                                    &http_auth_preferences);

  url::SchemeHostPort nonsecure_scheme_host_port(
      GURL("http://www.example.com"));
  url::SchemeHostPort secure_scheme_host_port(GURL("https://www.example.com"));
  SSLInfo null_ssl_info;

  const HttpAuth::Target kTargets[] = {HttpAuth::AUTH_SERVER,
                                       HttpAuth::AUTH_PROXY};
  struct TestCase {
    int expected_net_error;
    const url::SchemeHostPort scheme_host_port;
    const char* challenge;
  } const kTestCases[] = {
    // Challenges that result in success results.
    {OK, secure_scheme_host_port, "Basic realm=\"FooBar\""},
    {OK, secure_scheme_host_port, "Digest realm=\"FooBar\", nonce=\"xyz\""},
    {OK, nonsecure_scheme_host_port, "Digest realm=\"FooBar\", nonce=\"xyz\""},
    {OK, secure_scheme_host_port, "Ntlm"},
    {OK, nonsecure_scheme_host_port, "Ntlm"},
#if BUILDFLAG(USE_KERBEROS) && !BUILDFLAG(IS_ANDROID)
    {OK, secure_scheme_host_port, "Negotiate"},
    {OK, nonsecure_scheme_host_port, "Negotiate"},
#endif
    // Challenges that result in error results.
    {ERR_UNSUPPORTED_AUTH_SCHEME, nonsecure_scheme_host_port,
     "Basic realm=\"FooBar\""},
  };

  for (const auto target : kTargets) {
    for (const TestCase& test_case : kTestCases) {
      std::unique_ptr<HttpAuthHandler> handler;
      int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
          test_case.challenge, target, null_ssl_info, NetworkIsolationKey(),
          test_case.scheme_host_port, NetLogWithSource(), host_resolver.get(),
          &handler);
      EXPECT_THAT(rv, IsError(test_case.expected_net_error));
    }
  }
}

TEST(HttpAuthHandlerFactoryTest, LogCreateAuthHandlerResults) {
  std::unique_ptr<HostResolver> host_resolver(new MockHostResolver());
  std::unique_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
      HttpAuthHandlerFactory::CreateDefault());
  url::SchemeHostPort scheme_host_port(GURL("http://www.example.com"));
  SSLInfo null_ssl_info;
  RecordingNetLogObserver net_log_observer;

  net::NetLogCaptureMode capture_modes[] = {
      NetLogCaptureMode::kDefault, NetLogCaptureMode::kIncludeSensitive};

  struct TestCase {
    int expected_net_error;
    const char* challenge;
    const net::HttpAuth::Target auth_target;
    const char* expected_scheme;
  } test_cases[] = {
      // Challenges that result in success results.
      {OK, "Basic realm=\"FooBar\"", HttpAuth::AUTH_SERVER, "Basic"},
      {OK, "Basic realm=\"FooBar\"", HttpAuth::AUTH_PROXY, "Basic"},
      {OK, "Digest realm=\"FooBar\", nonce=\"xyz\"", HttpAuth::AUTH_SERVER,
       "Digest"},
      // Challenges that result in error results.
      {ERR_INVALID_RESPONSE, "", HttpAuth::AUTH_SERVER, ""},
      {ERR_INVALID_RESPONSE, "Digest realm=\"no_nonce\"", HttpAuth::AUTH_SERVER,
       "Digest"},
      {ERR_UNSUPPORTED_AUTH_SCHEME, "UNSUPPORTED realm=\"FooBar\"",
       HttpAuth::AUTH_SERVER, "UNSUPPORTED"},
      {ERR_UNSUPPORTED_AUTH_SCHEME, "invalid\xff\x0a", HttpAuth::AUTH_SERVER,
       "%ESCAPED:\xE2\x80\x8B invalid%FF\n"},
      {ERR_UNSUPPORTED_AUTH_SCHEME, "UNSUPPORTED2 realm=\"FooBar\"",
       HttpAuth::AUTH_PROXY, "UNSUPPORTED2"}};

  // For each level of capture sensitivity...
  for (auto capture_mode : capture_modes) {
    net_log_observer.SetObserverCaptureMode(capture_mode);

    // ... evaluate the expected results for each test case.
    for (auto test_case : test_cases) {
      std::unique_ptr<HttpAuthHandler> handler;
      int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
          test_case.challenge, test_case.auth_target, null_ssl_info,
          NetworkIsolationKey(), scheme_host_port,
          NetLogWithSource::Make(NetLogSourceType::NONE), host_resolver.get(),
          &handler);
      EXPECT_THAT(rv, IsError(test_case.expected_net_error));
      auto entries = net_log_observer.GetEntriesWithType(
          NetLogEventType::AUTH_HANDLER_CREATE_RESULT);
      ASSERT_EQ(1u, entries.size());
      const std::string* scheme = entries[0].params.FindStringKey("scheme");
      ASSERT_NE(nullptr, scheme);
      EXPECT_STRCASEEQ(test_case.expected_scheme, scheme->data());
      absl::optional<int> net_error = entries[0].params.FindIntKey("net_error");
      if (test_case.expected_net_error) {
        ASSERT_TRUE(net_error.has_value());
        EXPECT_EQ(test_case.expected_net_error, net_error.value());
      } else {
        ASSERT_FALSE(net_error.has_value());
      }

      // The challenge should be logged only when sensitive logging is enabled.
      const std::string* challenge =
          entries[0].params.FindStringKey("challenge");
      if (capture_mode == NetLogCaptureMode::kDefault) {
        ASSERT_EQ(nullptr, challenge);
      } else {
        ASSERT_NE(nullptr, challenge);
        EXPECT_EQ(net::NetLogStringValue(test_case.challenge).GetString(),
                  challenge->data());
      }

      net_log_observer.Clear();
    }
  }
}

}  // namespace net
