Commit 310ef922 authored by Asanka Herath's avatar Asanka Herath Committed by Commit Bot

[net/auth] Add NetLog support to Posix GSSAPI implementation.

This change uses the plumbing introduced in prior CLs to perform
detailed logging of GSSAPI library invocations.

R=eroman@chromium.org

Bug: 884313
Change-Id: Id010fda54f32691a092edd97385470502d18d15f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1698942
Commit-Queue: Asanka Herath <asanka@chromium.org>
Reviewed-by: default avatarMaks Orlovich <morlovich@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarEric Roman <eroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680116}
parent 29d3cc04
......@@ -695,7 +695,7 @@ void NetworkServiceClient::OnGenerateHttpNegotiateAuthToken(
auth_negotiate->set_can_delegate(can_delegate);
auto auth_token = std::make_unique<std::string>();
auth_negotiate_raw->GenerateAuthToken(
auth_negotiate_raw->GenerateAuthTokenAndroid(
nullptr, spn, std::string(), auth_token.get(),
base::BindOnce(&FinishGenerateNegotiateAuthToken,
std::move(auth_negotiate), std::move(auth_token),
......
......@@ -16,6 +16,7 @@
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/http_auth_multi_round_parse.h"
#include "net/http/http_auth_preferences.h"
#include "net/log/net_log_with_source.h"
#include "net/net_jni_headers/HttpNegotiateAuthenticator_jni.h"
using base::android::AttachCurrentThread;
......@@ -69,7 +70,7 @@ HttpAuthNegotiateAndroid::HttpAuthNegotiateAndroid(
HttpAuthNegotiateAndroid::~HttpAuthNegotiateAndroid() {
}
bool HttpAuthNegotiateAndroid::Init() {
bool HttpAuthNegotiateAndroid::Init(const NetLogWithSource& net_log) {
return true;
}
......@@ -92,11 +93,22 @@ HttpAuth::AuthorizationResult HttpAuthNegotiateAndroid::ParseChallenge(
&decoded_auth_token);
}
int HttpAuthNegotiateAndroid::GenerateAuthTokenAndroid(
const AuthCredentials* credentials,
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
net::CompletionOnceCallback callback) {
return GenerateAuthToken(credentials, spn, channel_bindings, auth_token,
NetLogWithSource(), std::move(callback));
}
int HttpAuthNegotiateAndroid::GenerateAuthToken(
const AuthCredentials* credentials,
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
net::CompletionOnceCallback callback) {
if (GetAuthAndroidNegotiateAccountType().empty()) {
// This can happen if there is a policy change, removing the account type,
......
......@@ -74,7 +74,7 @@ class NET_EXPORT_PRIVATE HttpAuthNegotiateAndroid
~HttpAuthNegotiateAndroid() override;
// HttpNegotiateAuthSystem implementation:
bool Init() override;
bool Init(const NetLogWithSource& net_log) override;
bool NeedsIdentity() const override;
bool AllowsExplicitCredentials() const override;
HttpAuth::AuthorizationResult ParseChallenge(
......@@ -83,9 +83,20 @@ class NET_EXPORT_PRIVATE HttpAuthNegotiateAndroid
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) override;
void SetDelegation(HttpAuth::DelegationType delegation_type) override;
// Unlike the platform agnostic GenerateAuthToken(), the Android specific
// version doesn't require a NetLogWithSource. The call is made across service
// boundaries, so currently the goings-on within the GenerateAuthToken()
// handler is outside the scope of the NetLog.
int GenerateAuthTokenAndroid(const AuthCredentials* credentials,
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
CompletionOnceCallback callback);
bool can_delegate() const { return can_delegate_; }
void set_can_delegate(bool can_delegate) { can_delegate_ = can_delegate; }
......
......@@ -11,6 +11,7 @@
#include "net/base/test_completion_callback.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/mock_allow_http_auth_preferences.h"
#include "net/log/net_log_with_source.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
......@@ -32,12 +33,12 @@ TEST(HttpAuthNegotiateAndroidTest, GenerateAuthToken) {
prefs.set_auth_android_negotiate_account_type(
"org.chromium.test.DummySpnegoAuthenticator");
HttpAuthNegotiateAndroid auth(&prefs);
EXPECT_TRUE(auth.Init());
EXPECT_TRUE(auth.Init(NetLogWithSource()));
TestCompletionCallback callback;
EXPECT_EQ(OK, callback.GetResult(
auth.GenerateAuthToken(nullptr, "Dummy", std::string(),
&auth_token, callback.callback())));
EXPECT_EQ(OK, callback.GetResult(auth.GenerateAuthToken(
nullptr, "Dummy", std::string(), &auth_token,
NetLogWithSource(), callback.callback())));
EXPECT_EQ("Negotiate DummyToken", auth_token);
......
This diff is collapsed.
......@@ -43,7 +43,7 @@ class NET_EXPORT_PRIVATE GSSAPILibrary {
// Initializes the library, including any necessary dynamic libraries.
// This is done separately from construction (which happens at startup time)
// in order to delay work until the class is actually needed.
virtual bool Init() = 0;
virtual bool Init(const NetLogWithSource& net_log) = 0;
// These methods match the ones in the GSSAPI library.
virtual OM_uint32 import_name(
......@@ -116,7 +116,7 @@ class NET_EXPORT_PRIVATE GSSAPISharedLibrary : public GSSAPILibrary {
~GSSAPISharedLibrary() override;
// GSSAPILibrary methods:
bool Init() override;
bool Init(const NetLogWithSource& net_log) override;
OM_uint32 import_name(OM_uint32* minor_status,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
......@@ -171,12 +171,14 @@ class NET_EXPORT_PRIVATE GSSAPISharedLibrary : public GSSAPILibrary {
private:
FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup);
bool InitImpl();
bool InitImpl(const NetLogWithSource& net_log);
// Finds a usable dynamic library for GSSAPI and loads it. The criteria are:
// 1. The library must exist.
// 2. The library must export the functions we need.
base::NativeLibrary LoadSharedLibrary();
bool BindMethods(base::NativeLibrary lib);
base::NativeLibrary LoadSharedLibrary(const NetLogWithSource& net_log);
bool BindMethods(base::NativeLibrary lib,
base::StringPiece library_name,
const NetLogWithSource& net_log);
bool initialized_ = false;
......@@ -207,7 +209,7 @@ class ScopedSecurityContext {
gss_ctx_id_t* receive() { return &security_context_; }
private:
gss_ctx_id_t security_context_;
gss_ctx_id_t security_context_ = GSS_C_NO_CONTEXT;
GSSAPILibrary* gssapi_lib_;
DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext);
......@@ -223,7 +225,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI : public HttpNegotiateAuthSystem {
~HttpAuthGSSAPI() override;
// HttpNegotiateAuthSystem implementation:
bool Init() override;
bool Init(const NetLogWithSource& net_log) override;
bool NeedsIdentity() const override;
bool AllowsExplicitCredentials() const override;
HttpAuth::AuthorizationResult ParseChallenge(
......@@ -232,6 +234,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI : public HttpNegotiateAuthSystem {
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) override;
void SetDelegation(HttpAuth::DelegationType delegation_type) override;
......@@ -239,7 +242,8 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI : public HttpNegotiateAuthSystem {
int GetNextSecurityToken(const std::string& spn,
const std::string& channel_bindings,
gss_buffer_t in_token,
gss_buffer_t out_token);
gss_buffer_t out_token,
const NetLogWithSource& net_log);
std::string scheme_;
gss_OID gss_oid_;
......
......@@ -16,6 +16,9 @@
#include "net/base/net_errors.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/mock_gssapi_library_posix.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_util.h"
#include "net/net_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -86,30 +89,74 @@ void UnexpectedCallback(int result) {
} // namespace
TEST(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup) {
BoundTestNetLog log;
// TODO(ahendrickson): Manipulate the libraries and paths to test each of the
// libraries we expect, and also whether or not they have the interface
// functions we want.
std::unique_ptr<GSSAPILibrary> gssapi(new GSSAPISharedLibrary(std::string()));
DCHECK(gssapi.get());
EXPECT_TRUE(gssapi.get()->Init());
EXPECT_TRUE(gssapi.get()->Init(log.bound()));
// Should've logged a AUTH_LIBRARY_LOAD event, but not
// AUTH_LIBRARY_BIND_FAILED.
auto entries = log.GetEntries();
auto offset = ExpectLogContainsSomewhere(
entries, 0u, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::BEGIN);
offset = ExpectLogContainsSomewhereAfter(entries, offset,
NetLogEventType::AUTH_LIBRARY_LOAD,
NetLogEventPhase::END);
ASSERT_LT(offset, entries.size());
auto& entry = entries[offset];
const std::string* library_name = entry.params.FindStringKey("library_name");
const std::string* load_result = entry.params.FindStringPath("load_result");
ASSERT_TRUE(library_name);
EXPECT_FALSE(library_name->empty());
EXPECT_FALSE(load_result); // No load_result since it succeeded.
}
TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryMissing) {
BoundTestNetLog log;
std::unique_ptr<GSSAPILibrary> gssapi(
new GSSAPISharedLibrary("/this/library/does/not/exist"));
EXPECT_FALSE(gssapi.get()->Init());
EXPECT_FALSE(gssapi.get()->Init(log.bound()));
auto entries = log.GetEntries();
auto offset = ExpectLogContainsSomewhere(
entries, 0, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::END);
ASSERT_LT(offset, entries.size());
auto& entry = entries[offset];
const std::string* load_result = entry.params.FindStringKey("load_result");
ASSERT_TRUE(load_result);
EXPECT_FALSE(load_result->empty());
}
TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryExists) {
BoundTestNetLog log;
base::FilePath module;
ASSERT_TRUE(base::PathService::Get(base::DIR_MODULE, &module));
auto basename = base::GetNativeLibraryName("test_gssapi");
module = module.AppendASCII(basename);
auto gssapi = std::make_unique<GSSAPISharedLibrary>(module.value());
EXPECT_TRUE(gssapi.get()->Init());
EXPECT_TRUE(gssapi.get()->Init(log.bound()));
auto entries = log.GetEntries();
auto offset = ExpectLogContainsSomewhere(
entries, 0, NetLogEventType::AUTH_LIBRARY_LOAD, NetLogEventPhase::END);
ASSERT_LT(offset, entries.size());
auto& entry = entries[offset];
const std::string* load_result = entry.params.FindStringKey("load_result");
const std::string* library_name = entry.params.FindStringKey("library_name");
EXPECT_FALSE(load_result);
ASSERT_TRUE(library_name);
EXPECT_EQ(*library_name, module.AsUTF8Unsafe());
}
TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryMethodsMissing) {
BoundTestNetLog log;
base::FilePath module;
ASSERT_TRUE(base::PathService::Get(base::DIR_MODULE, &module));
auto basename = base::GetNativeLibraryName("test_badgssapi");
......@@ -124,18 +171,25 @@ TEST(HttpAuthGSSAPIPOSIXTest, CustomLibraryMethodsMissing) {
//
// To resolve this issue, make sure that //net:test_badgssapi target in
// //net/BUILD.gn should have an empty `deps` and an empty `libs`.
EXPECT_FALSE(gssapi.get()->Init());
// Logs something like "gss_import_name" during loading process.
// TODO(asanka): Once GSSAPI library loading starts emitting NetLogs verify
// that the missing method is correctly identified.
EXPECT_FALSE(gssapi.get()->Init(log.bound()));
auto entries = log.GetEntries();
auto offset = ExpectLogContainsSomewhere(
entries, 0, NetLogEventType::AUTH_LIBRARY_BIND_FAILED,
NetLogEventPhase::NONE);
ASSERT_LT(offset, entries.size());
auto& entry = entries[offset];
const std::string* method = entry.params.FindStringKey("method");
ASSERT_TRUE(method);
EXPECT_EQ(*method, "gss_import_name");
}
TEST(HttpAuthGSSAPIPOSIXTest, GSSAPICycle) {
std::unique_ptr<test::MockGSSAPILibrary> mock_library(
new test::MockGSSAPILibrary);
DCHECK(mock_library.get());
mock_library->Init();
mock_library->Init(NetLogWithSource());
const char kAuthResponse[] = "Mary had a little lamb";
test::GssContextMockImpl context1(
"localhost", // Source name
......@@ -231,6 +285,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_FirstRound) {
}
TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
BoundTestNetLog log;
// The first round should just have "Negotiate", and the second round should
// have a valid base64 token associated with it.
test::MockGSSAPILibrary mock_library;
......@@ -245,15 +300,30 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
// Generate an auth token and create another thing.
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(
OK, auth_gssapi.GenerateAuthToken(nullptr, "HTTP/intranet.google.com",
std::string(), &auth_token, log.bound(),
base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
second_challenge_text.end());
EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
auth_gssapi.ParseChallenge(&second_challenge));
auto entries = log.GetEntries();
auto offset = ExpectLogContainsSomewhere(
entries, 0, NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX,
NetLogEventPhase::END);
// There should be two of these.
offset = ExpectLogContainsSomewhere(
entries, offset, NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX,
NetLogEventPhase::END);
ASSERT_LT(offset, entries.size());
const std::string* source =
entries[offset].params.FindStringPath("context.source.name");
ASSERT_TRUE(source);
EXPECT_EQ("localhost", *source);
}
TEST(HttpAuthGSSAPITest, ParseChallenge_UnexpectedTokenFirstRound) {
......@@ -283,9 +353,10 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) {
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(OK,
auth_gssapi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(), &auth_token,
NetLogWithSource(), base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
second_challenge_text.end());
......@@ -307,9 +378,10 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) {
EstablishInitialContext(&mock_library);
std::string auth_token;
EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(OK,
auth_gssapi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(), &auth_token,
NetLogWithSource(), base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
second_challenge_text.end());
......@@ -332,7 +404,7 @@ TEST(HttpAuthGSSAPITest, OidToValue_Known) {
{
"oid" : "GSS_C_NT_ANONYMOUS",
"length": 6,
"bytes" : "0x0000: 2b06 0105 0603 +.....\n"
"bytes" : "KwYBBQYD"
}
)");
ASSERT_TRUE(expected.has_value());
......@@ -345,7 +417,7 @@ TEST(HttpAuthGSSAPITest, OidToValue_Unknown) {
auto expected = base::JSONReader::Read(R"(
{
"length": 6,
"bytes" : "0x0000: 2b06 0105 0605 +.....\n"
"bytes" : "KwYBBQYF"
}
)");
ASSERT_TRUE(expected.has_value());
......
......@@ -131,7 +131,7 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
if (!http_auth_preferences()->AllowGssapiLibraryLoad())
return ERR_UNSUPPORTED_AUTH_SCHEME;
#endif
if (!auth_library_->Init()) {
if (!auth_library_->Init(net_log)) {
is_unsupported_ = true;
return ERR_UNSUPPORTED_AUTH_SCHEME;
}
......@@ -185,7 +185,7 @@ bool HttpAuthHandlerNegotiate::AllowsExplicitCredentials() {
bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge,
const SSLInfo& ssl_info) {
#if defined(OS_POSIX)
if (!auth_system_->Init()) {
if (!auth_system_->Init(net_log())) {
VLOG(1) << "can't initialize GSSAPI library";
return false;
}
......@@ -387,7 +387,7 @@ 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_,
credentials, spn_, channel_bindings_, auth_token_, net_log(),
base::BindOnce(&HttpAuthHandlerNegotiate::OnIOComplete,
base::Unretained(this)));
}
......
......@@ -426,7 +426,7 @@ class TestAuthSystem : public HttpNegotiateAuthSystem {
~TestAuthSystem() override = default;
// HttpNegotiateAuthSystem implementation:
bool Init() override { return true; }
bool Init(const NetLogWithSource&) override { return true; }
bool NeedsIdentity() const override { return true; }
bool AllowsExplicitCredentials() const override { return true; }
......@@ -439,6 +439,7 @@ class TestAuthSystem : public HttpNegotiateAuthSystem {
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
net::CompletionOnceCallback callback) override {
*auth_token = kFakeToken;
return net::OK;
......
......@@ -41,7 +41,7 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
std::string* auth_token) {
#if defined(NTLM_SSPI)
return auth_sspi_.GenerateAuthToken(credentials, CreateSPN(origin_),
channel_bindings_, auth_token,
channel_bindings_, auth_token, net_log(),
std::move(callback));
#else // !defined(NTLM_SSPI)
// TODO(cbentzel): Shouldn't be hitting this case.
......
......@@ -263,7 +263,7 @@ HttpAuthSSPI::~HttpAuthSSPI() {
}
}
bool HttpAuthSSPI::Init() {
bool HttpAuthSSPI::Init(const NetLogWithSource&) {
return true;
}
......@@ -300,6 +300,7 @@ int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource&,
CompletionOnceCallback /*callback*/) {
// Initial challenge.
if (!SecIsValidHandle(&cred_)) {
......
......@@ -116,7 +116,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI : public HttpNegotiateAuthSystem {
~HttpAuthSSPI() override;
// HttpNegotiateAuthSystem implementation:
bool Init() override;
bool Init(const NetLogWithSource& net_log) override;
bool NeedsIdentity() const override;
bool AllowsExplicitCredentials() const override;
HttpAuth::AuthorizationResult ParseChallenge(
......@@ -125,6 +125,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI : public HttpNegotiateAuthSystem {
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) override;
void SetDelegation(HttpAuth::DelegationType delegation_type) override;
......
......@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "net/http/http_auth_sspi_win.h"
#include "base/bind.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/mock_sspi_library_win.h"
#include "net/log/net_log_with_source.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -96,9 +98,10 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
// Generate an auth token and create another thing.
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(OK,
auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(), &auth_token,
NetLogWithSource(), base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
......@@ -133,9 +136,10 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
auth_sspi.ParseChallenge(&first_challenge));
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(OK,
auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(), &auth_token,
NetLogWithSource(), base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
second_challenge_text.end());
......@@ -156,9 +160,10 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
auth_sspi.ParseChallenge(&first_challenge));
std::string auth_token;
EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(),
&auth_token, base::BindOnce(&UnexpectedCallback)));
EXPECT_EQ(OK,
auth_sspi.GenerateAuthToken(
nullptr, "HTTP/intranet.google.com", std::string(), &auth_token,
NetLogWithSource(), base::BindOnce(&UnexpectedCallback)));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(),
second_challenge_text.end());
......
......@@ -13,12 +13,13 @@ namespace net {
class AuthCredentials;
class HttpAuthChallengeTokenizer;
class NetLogWithSource;
class NET_EXPORT_PRIVATE HttpNegotiateAuthSystem {
public:
virtual ~HttpNegotiateAuthSystem() = default;
virtual bool Init() = 0;
virtual bool Init(const NetLogWithSource& net_log) = 0;
// True if authentication needs the identity of the user from Chrome.
virtual bool NeedsIdentity() const = 0;
......@@ -57,6 +58,7 @@ class NET_EXPORT_PRIVATE HttpNegotiateAuthSystem {
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) = 0;
// Sets the delegation type allowed on the Kerberos ticket. This allows
......
......@@ -253,7 +253,7 @@ void MockGSSAPILibrary::ExpectSecurityContext(
expected_security_queries_.push_back(security_query);
}
bool MockGSSAPILibrary::Init() {
bool MockGSSAPILibrary::Init(const NetLogWithSource&) {
return true;
}
......
......@@ -113,7 +113,7 @@ class MockGSSAPILibrary : public GSSAPILibrary {
// Initializes the library, including any necessary dynamic libraries.
// This is done separately from construction (which happens at startup time)
// in order to delay work until the class is actually needed.
bool Init() override;
bool Init(const NetLogWithSource& net_log) override;
// These methods match the ones in the GSSAPI library.
OM_uint32 import_name(OM_uint32* minor_status,
......
......@@ -2169,6 +2169,79 @@ EVENT_TYPE(SOCKS5_HANDSHAKE_READ)
// ------------------------------------------------------------------------
// HTTP Authentication
// ------------------------------------------------------------------------
//
// Structure of common GSSAPI / SSPI values.
// -----------------------------------------
// For convenience some structured GSSAPI/SSPI values are serialized
// consistently across different events. They are explained below.
//
// ** GSSAPI Status:
//
// A major/minor status code returned by a GSSAPI function. The major status
// code indicates the GSSAPI level error, while the minor code provides a
// mechanism specific error code if a specific GSSAPI mechanism was involved in
// the error.
//
// The status value has the following structure:
// {
// "function": <name of GSSAPI function that returned the error>
// "major_status": {
// "status" : <status value as a number>,
// "message": [
// <list of strings hopefully explaining what that number means>
// ]
// },
// "minor_status": {
// "status" : <status value as a number>,
// "message": [
// <list of strings hopefully explaining what that number means>
// ]
// }
// }
//
// ** OID:
//
// An ASN.1 OID that's used for GSSAPI is serialized thusly:
// {
// "oid": <symbolic name of OID if it is known>
// "length": <length in bytes of serialized OID>,
// "bytes": <serialized bytes of OID encoded via NetLogBinaryValue()>
// }
//
// ** GSS Display Name:
//
// A serialization of GSSAPI principal name to something that can be consumed by
// humans. If the encoding of the string is not UTF-8 (since there's no
// requirement that they use any specific encoding) the field is serialized
// using NetLogBinaryValue().
// {
// "name" : <GSSAPI principal name>
// "type" : <OID indicating type of name. See OID above.>
// "error": <If the display name lookup operation failed, then this field
// contains the error in the form of a GSSAPI Status.>
// }
//
// ** GSSAPI Context Description
//
// A serialization of the GSSAPI context. It takes the following form:
// {
// "source" : <GSS Display Name for the source of the authentication
// attempt. In practice this is always the user's identity.>
// "target" : <GSS Display Name for the target of the authentication
// attempt. This the target server or proxy service
// principal.>
// "open" : <Boolean indicating whether the context is "open", which
// means that the handshake is still in progress. In
// particular, the flags, lifetime, and mechanism fields are
// not considered final until "open" is false.
// "lifetime": <A decimal string indicating the lifetime in seconds of the
// authentication context. The identity as established by this
// handshake is only valid for this long since the time at
// which it was established.>
// "mechanism":<OID indicating inner authentication mechanism.>
// "flags" :<Flags. See RFC 2744 Section 5.19 for meanings. Flag
// bitmasks can be found in RFC 2744 Appendix A.>
// }
// Lifetime event for HttpAuthController.
//
......@@ -2212,11 +2285,56 @@ EVENT_TYPE(AUTH_GENERATE_TOKEN)
// }
EVENT_TYPE(AUTH_HANDLE_CHALLENGE)
// An attempt was made to load an authentication library.
//
// If the request succeeded, the parameters are:
// {
// "library_name": <Name of library>
// }
// Otherwise, the parameters are:
// {
// "library_name": <Name of library>
// "load_error": <An error string>
// }
EVENT_TYPE(AUTH_LIBRARY_LOAD)
// A required method was not found while attempting to load an authentication
// library.
//
// Parameters are:
// {
// "library_name": <Name of the library where the method lookup failed>
// "method": <Name of method that was not found>
// }
EVENT_TYPE(AUTH_LIBRARY_BIND_FAILED)
// Construction of the GSSAPI service principal name.
//
// Parameters:
// {
// "spn": <Service principal name as a string>
// "status": <GSSAPI Status. See GSSAPI Status above. This is field is only
// logged if the operation failed.>
// }
EVENT_TYPE(AUTH_LIBRARY_IMPORT_NAME)
// Initialize security context.
//
// This operation involves invoking an external library which may perform disk,
// IPC, and network IO as a part of its work.
//
// The END phase has the following parameters.
// {
// "context": <GSSAPI Context Description>,
// "status": <GSSAPI Status if the operation failed>
// }
EVENT_TYPE(AUTH_LIBRARY_INIT_SEC_CTX)
// The channel bindings generated for the connection.
// {
// "token": <Hex encoded RFC 5929 'tls-server-endpoint' channel binding
// token. Could be empty if one could not be generated (e.g.
// because the underlying channel was not TLS>
// "token": <Hex encoded RFC 5929 'tls-server-endpoint' channel binding
// token. Could be empty if one could not be generated (e.g.
// because the underlying channel was not TLS.)>
// }
EVENT_TYPE(AUTH_CHANNEL_BINDINGS)
......
......@@ -150,7 +150,9 @@ class NetworkServiceAuthNegotiateAndroid : public net::HttpNegotiateAuthSystem {
~NetworkServiceAuthNegotiateAndroid() override = default;
// HttpNegotiateAuthSystem implementation:
bool Init() override { return auth_negotiate_.Init(); }
bool Init(const net::NetLogWithSource& net_log) override {
return auth_negotiate_.Init(net_log);
}
bool NeedsIdentity() const override {
return auth_negotiate_.NeedsIdentity();
......@@ -169,6 +171,7 @@ class NetworkServiceAuthNegotiateAndroid : public net::HttpNegotiateAuthSystem {
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const net::NetLogWithSource& net_log,
net::CompletionOnceCallback callback) override {
network_service_->client()->OnGenerateHttpNegotiateAuthToken(
auth_negotiate_.server_auth_token(), auth_negotiate_.can_delegate(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment