| Index: net/http/http_auth_controller_unittest.cc
|
| diff --git a/net/http/http_auth_controller_unittest.cc b/net/http/http_auth_controller_unittest.cc
|
| index 1235156a38a5bd52b87aa88944aeed666900cb07..e90e578e67b27f22a570b04174512d50bf19e3e5 100644
|
| --- a/net/http/http_auth_controller_unittest.cc
|
| +++ b/net/http/http_auth_controller_unittest.cc
|
| @@ -4,18 +4,30 @@
|
|
|
| #include "net/http/http_auth_controller.h"
|
|
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/base/test_completion_callback.h"
|
| +#include "net/dns/mock_host_resolver.h"
|
| +#include "net/http/http_auth.h"
|
| #include "net/http/http_auth_cache.h"
|
| #include "net/http/http_auth_challenge_tokenizer.h"
|
| +#include "net/http/http_auth_filter.h"
|
| +#include "net/http/http_auth_handler.h"
|
| +#include "net/http/http_auth_handler_factory.h"
|
| #include "net/http/http_auth_handler_mock.h"
|
| #include "net/http/http_request_info.h"
|
| #include "net/http/http_response_headers.h"
|
| +#include "net/http/http_response_info.h"
|
| #include "net/http/http_util.h"
|
| +#include "net/http/mock_allow_url_security_manager.h"
|
| #include "net/log/net_log.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| +using ::testing::ValuesIn;
|
| +
|
| namespace net {
|
|
|
| namespace {
|
| @@ -49,6 +61,10 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode,
|
| int handler_rv,
|
| int expected_controller_rv,
|
| SchemeState scheme_state) {
|
| + SCOPED_TRACE(::testing::Message()
|
| + << "run_mode:" << run_mode << " handler_rv:" << handler_rv
|
| + << " expected_controller_rv:" << expected_controller_rv
|
| + << " scheme_state:" << scheme_state);
|
| BoundNetLog dummy_log;
|
| HttpAuthCache dummy_auth_cache;
|
|
|
| @@ -56,10 +72,11 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode,
|
| request.method = "GET";
|
| request.url = GURL("http://example.com");
|
|
|
| - scoped_refptr<HttpResponseHeaders> headers(HeadersFromString(
|
| + HttpResponseInfo response;
|
| + response.headers = HeadersFromString(
|
| "HTTP/1.1 407\r\n"
|
| "Proxy-Authenticate: MOCK foo\r\n"
|
| - "\r\n"));
|
| + "\r\n");
|
|
|
| HttpAuthHandlerMock::Factory auth_handler_factory;
|
| scoped_ptr<HttpAuthHandlerMock> auth_handler(new HttpAuthHandlerMock());
|
| @@ -72,20 +89,22 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode,
|
| new HttpAuthController(HttpAuth::AUTH_PROXY,
|
| GURL("http://example.com"),
|
| &dummy_auth_cache, &auth_handler_factory));
|
| - ASSERT_EQ(OK,
|
| - controller->HandleAuthChallenge(headers, false, false, dummy_log));
|
| + TestCompletionCallback completion_callback;
|
| + int result = controller->HandleAuthChallenge(
|
| + response, completion_callback.callback(), dummy_log);
|
| + ASSERT_EQ(OK, completion_callback.GetResult(result));
|
| ASSERT_TRUE(controller->HaveAuthHandler());
|
| + EXPECT_FALSE(controller->HaveAuth());
|
| controller->ResetAuth(
|
| AuthCredentials(base::ASCIIToUTF16("a"), base::ASCIIToUTF16("b")));
|
| EXPECT_TRUE(controller->HaveAuth());
|
|
|
| TestCompletionCallback callback;
|
| - EXPECT_EQ((run_mode == RUN_HANDLER_ASYNC)? ERR_IO_PENDING:
|
| - expected_controller_rv,
|
| - controller->MaybeGenerateAuthToken(&request, callback.callback(),
|
| - dummy_log));
|
| + result = controller->MaybeGenerateAuthToken(&request, callback.callback(),
|
| + dummy_log);
|
| if (run_mode == RUN_HANDLER_ASYNC)
|
| - EXPECT_EQ(expected_controller_rv, callback.WaitForResult());
|
| + ASSERT_EQ(ERR_IO_PENDING, result);
|
| + EXPECT_EQ(expected_controller_rv, callback.GetResult(result));
|
| EXPECT_EQ((scheme_state == SCHEME_IS_DISABLED),
|
| controller->IsAuthSchemeDisabled("mock"));
|
| }
|
| @@ -95,24 +114,30 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode,
|
| // If an HttpAuthHandler returns an error code that indicates a
|
| // permanent error, the HttpAuthController should disable the scheme
|
| // used and retry the request.
|
| -TEST(HttpAuthControllerTest, PermanentErrors) {
|
| -
|
| - // Run a synchronous handler that returns
|
| - // ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS. We expect a return value
|
| - // of OK from the controller so we can retry the request.
|
| +TEST(HttpAuthControllerTest, PermanentErrors_Sync) {
|
| RunSingleRoundAuthTest(RUN_HANDLER_SYNC,
|
| ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS,
|
| OK, SCHEME_IS_DISABLED);
|
| +}
|
|
|
| - // Now try an async handler that returns
|
| - // ERR_MISSING_AUTH_CREDENTIALS. Async and sync handlers invoke
|
| - // different code paths in HttpAuthController when generating
|
| - // tokens.
|
| +// Similar to the above test. Now try an async handler that returns
|
| +// ERR_MISSING_AUTH_CREDENTIALS. Async and sync handlers invoke different code
|
| +// paths in HttpAuthController when generating tokens.
|
| +TEST(HttpAuthControllerTest, PermanentErrors_Async) {
|
| RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_MISSING_AUTH_CREDENTIALS, OK,
|
| SCHEME_IS_DISABLED);
|
| +}
|
|
|
| - // If a non-permanent error is returned by the handler, then the
|
| - // controller should report it unchanged.
|
| +// If a non-permanent error is returned by the handler, then the controller
|
| +// should leave the scheme enabled.
|
| +TEST(HttpAuthControllerTest, NonPermanentErrors_Sync) {
|
| + RunSingleRoundAuthTest(RUN_HANDLER_SYNC, ERR_INVALID_AUTH_CREDENTIALS,
|
| + ERR_INVALID_AUTH_CREDENTIALS, SCHEME_IS_ENABLED);
|
| +}
|
| +
|
| +// If a non-permanent error is returned by the handler, then the controller
|
| +// should leave the scheme enabled.
|
| +TEST(HttpAuthControllerTest, NonPermanentErrors_Async) {
|
| RunSingleRoundAuthTest(RUN_HANDLER_ASYNC, ERR_INVALID_AUTH_CREDENTIALS,
|
| ERR_INVALID_AUTH_CREDENTIALS, SCHEME_IS_ENABLED);
|
| }
|
| @@ -127,11 +152,12 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
|
| request.url = GURL("http://example.com");
|
|
|
| HttpRequestHeaders request_headers;
|
| - scoped_refptr<HttpResponseHeaders> headers(
|
| - HeadersFromString("HTTP/1.1 401\r\n"
|
| - "WWW-Authenticate: Ernie\r\n"
|
| - "WWW-Authenticate: Bert\r\n"
|
| - "\r\n"));
|
| + HttpResponseInfo response;
|
| + response.headers = HeadersFromString(
|
| + "HTTP/1.1 401\r\n"
|
| + "WWW-Authenticate: Ernie\r\n"
|
| + "WWW-Authenticate: Bert\r\n"
|
| + "\r\n");
|
|
|
| HttpAuthHandlerMock::Factory auth_handler_factory;
|
|
|
| @@ -148,16 +174,17 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
|
| new HttpAuthController(HttpAuth::AUTH_SERVER,
|
| GURL("http://example.com"),
|
| &dummy_auth_cache, &auth_handler_factory));
|
| - ASSERT_EQ(OK,
|
| - controller->HandleAuthChallenge(headers, false, false, dummy_log));
|
| + TestCompletionCallback completion_calback;
|
| + int rv = controller->HandleAuthChallenge(
|
| + response, completion_calback.callback(), dummy_log);
|
| + ASSERT_EQ(OK, completion_calback.GetResult(rv));
|
| ASSERT_TRUE(controller->HaveAuthHandler());
|
| - controller->ResetAuth(AuthCredentials());
|
| EXPECT_TRUE(controller->HaveAuth());
|
| EXPECT_FALSE(auth_handler_factory.HaveAuthHandlers());
|
|
|
| // Should only succeed if we are using the "Ernie" MockHandler.
|
| - EXPECT_EQ(OK, controller->MaybeGenerateAuthToken(
|
| - &request, CompletionCallback(), dummy_log));
|
| + ASSERT_EQ(OK, controller->MaybeGenerateAuthToken(
|
| + &request, completion_calback.callback(), dummy_log));
|
| controller->AddAuthorizationHeader(&request_headers);
|
|
|
| // Handlers for the second attempt. Neither should be used to generate a
|
| @@ -182,9 +209,12 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
|
|
|
| // Once a token is generated, simulate the receipt of a server response
|
| // indicating that the authentication attempt was rejected.
|
| - ASSERT_EQ(OK,
|
| - controller->HandleAuthChallenge(headers, false, false, dummy_log));
|
| + TestCompletionCallback completion_calback_rejected;
|
| + rv = controller->HandleAuthChallenge(
|
| + response, completion_calback_rejected.callback(), dummy_log);
|
| + ASSERT_EQ(OK, completion_calback_rejected.GetResult(rv));
|
| ASSERT_TRUE(controller->HaveAuthHandler());
|
| + EXPECT_FALSE(controller->HaveAuth());
|
| controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"),
|
| base::string16()));
|
| EXPECT_TRUE(controller->HaveAuth());
|
| @@ -193,7 +223,445 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) {
|
|
|
| // Should only succeed if we are using the "Bert" MockHandler.
|
| EXPECT_EQ(OK, controller->MaybeGenerateAuthToken(
|
| - &request, CompletionCallback(), dummy_log));
|
| + &request, completion_calback.callback(), dummy_log));
|
| }
|
|
|
| +namespace {
|
| +
|
| +struct ChallengeResponse {
|
| + const char* const response_headers = nullptr;
|
| + const char* const authorization_header = nullptr;
|
| +
|
| + ChallengeResponse(const char* const response_headers,
|
| + const char* const authorization_header)
|
| + : response_headers(response_headers),
|
| + authorization_header(authorization_header) {}
|
| +};
|
| +
|
| +struct MockAuthHandler {
|
| + std::string scheme;
|
| + int init_rv = OK;
|
| + int generate_rv = OK;
|
| +
|
| + MockAuthHandler(const std::string& scheme, int int_rv, int generate_rv)
|
| + : scheme(scheme), init_rv(int_rv), generate_rv(generate_rv) {}
|
| +};
|
| +
|
| +struct ChallengeResponseTestCase {
|
| + std::vector<ChallengeResponse> rounds;
|
| + std::vector<MockAuthHandler> handlers;
|
| + bool run_handler_async = false;
|
| +
|
| + ChallengeResponseTestCase& WithChallengeResponse(
|
| + const char* response_headers,
|
| + const char* authorization_header) {
|
| + rounds.push_back(ChallengeResponse(response_headers, authorization_header));
|
| + return *this;
|
| + }
|
| +
|
| + ChallengeResponseTestCase& WithHandler(const base::StringPiece& scheme,
|
| + int init_rv,
|
| + int generate_rv) {
|
| + handlers.push_back(
|
| + MockAuthHandler(scheme.as_string(), init_rv, generate_rv));
|
| + return *this;
|
| + }
|
| +};
|
| +
|
| +std::vector<ChallengeResponseTestCase> SyncAndAsync(
|
| + const ChallengeResponseTestCase& test_case) {
|
| + std::vector<ChallengeResponseTestCase> test_cases;
|
| + ChallengeResponseTestCase test_case_copy = test_case;
|
| +
|
| + test_case_copy.run_handler_async = false;
|
| + test_cases.push_back(test_case_copy);
|
| +
|
| + test_case_copy.run_handler_async = true;
|
| + test_cases.push_back(test_case_copy);
|
| + return test_cases;
|
| +}
|
| +
|
| +class HttpAuthControllerTest
|
| + : public ::testing::TestWithParam<ChallengeResponseTestCase> {};
|
| +
|
| +} // namespace
|
| +
|
| +TEST_P(HttpAuthControllerTest, Run) {
|
| + const ChallengeResponseTestCase& params = GetParam();
|
| + BoundNetLog dummy_log;
|
| + HttpAuthCache dummy_auth_cache;
|
| + GURL url("http://example.com");
|
| + HttpAuthHandlerMock::Factory auth_factory;
|
| +
|
| + for (const auto& handler : params.handlers) {
|
| + scoped_ptr<HttpAuthHandlerMock> mock_handler(new HttpAuthHandlerMock);
|
| + mock_handler->set_expected_auth_scheme(handler.scheme);
|
| + mock_handler->set_expect_multiple_challenges(handler.scheme == "ntlm" ||
|
| + handler.scheme == "negotiate");
|
| + mock_handler->SetInitExpectation(params.run_handler_async, handler.init_rv);
|
| + mock_handler->SetGenerateExpectation(params.run_handler_async,
|
| + handler.generate_rv);
|
| + auth_factory.AddMockHandler(mock_handler.Pass(),
|
| + HttpAuthHandlerCreateReason::CHALLENGE);
|
| + }
|
| +
|
| + HttpRequestInfo request_info;
|
| +
|
| + scoped_refptr<HttpAuthController> auth_controller(new HttpAuthController(
|
| + HttpAuth::AUTH_SERVER, url, &dummy_auth_cache, &auth_factory));
|
| + for (const auto& round : params.rounds) {
|
| + if (!round.response_headers)
|
| + break;
|
| + HttpResponseInfo response_info;
|
| + response_info.headers = HeadersFromString(round.response_headers);
|
| + TestCompletionCallback callback;
|
| +
|
| + int result = auth_controller->HandleAuthChallenge(
|
| + response_info, callback.callback(), dummy_log);
|
| + EXPECT_EQ(OK, callback.GetResult(result));
|
| +
|
| + if (!auth_controller->HaveAuthHandler()) {
|
| + EXPECT_STREQ("", round.authorization_header);
|
| + continue;
|
| + }
|
| +
|
| + if (!auth_controller->HaveAuth()) {
|
| + auth_controller->ResetAuth(
|
| + AuthCredentials(base::ASCIIToUTF16("a"), base::ASCIIToUTF16("b")));
|
| + }
|
| +
|
| + result = auth_controller->MaybeGenerateAuthToken(
|
| + &request_info, callback.callback(), dummy_log);
|
| + EXPECT_EQ(OK, callback.GetResult(result));
|
| + HttpRequestHeaders headers;
|
| + auth_controller->AddAuthorizationHeader(&headers);
|
| + std::string authorization_header;
|
| + headers.GetHeader(
|
| + HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_SERVER),
|
| + &authorization_header);
|
| + EXPECT_STREQ(round.authorization_header, authorization_header.c_str());
|
| + }
|
| +
|
| + EXPECT_FALSE(auth_factory.HaveAuthHandlers());
|
| +}
|
| +
|
| +// Picks Basic because that's the only supported scheme.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + PickSupportedScheme,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse(
|
| + "HTTP/1.1 401\n"
|
| + "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
|
| + "www-authenticate: Basic realm=\"BasicRealm\"\n",
|
| + "basic auth_token,realm=\"BasicRealm\"")
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// No supported schemes.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + NoSupportedSchemes,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(ChallengeResponseTestCase().WithChallengeResponse(
|
| + "HTTP/1.1 401\n"
|
| + "Y: Digest realm=\"FooBar\", nonce=\"aaaaaaaaaa\"\n"
|
| + "www-authenticate: Fake realm=\"FooBar\"\n",
|
| + ""))));
|
| +
|
| +// Pick Digest over Basic.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + DigestOverBasic,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse(
|
| + "HTTP/1.1 401\n"
|
| + "www-authenticate: Basic realm=\"FooBar\"\n"
|
| + "www-authenticate: Fake realm=\"FooBar\"\n"
|
| + "www-authenticate: nonce=\"aaaaaaaaaa\"\n"
|
| + "www-authenticate: Digest realm=\"DigestRealm\", "
|
| + "nonce=\"aaaaaaaaaa\"\n",
|
| + "digest auth_token,realm=\"DigestRealm\", nonce=\"aaaaaaaaaa\"")
|
| + .WithHandler("digest", OK, OK))));
|
| +
|
| +// Handle an empty header correctly.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + EmptyHeader,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(ChallengeResponseTestCase().WithChallengeResponse(
|
| + "HTTP/1.1 401\n"
|
| + "Y: Digest realm=\"X\", nonce=\"aaaaaaaaaa\"\n"
|
| + "www-authenticate:\n",
|
| + ""))));
|
| +
|
| +// NTLM appears earlier in the list, Negotiate is preferred.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + NegotiateOverNTLM,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: NTLM\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK))));
|
| +
|
| +// Two rounds. Basic isn't connection oriented and will use up a new handler
|
| +// for the second challenge.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + SecondChallengeForBasic,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic second_round\n",
|
| + "basic auth_token,second_round")
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// Correctly deal with a missing challenge for the second round.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + SecondChallengeIsMissing,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n", ""))));
|
| +
|
| +// Correctly deal with an empty challenge for the second round.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + SecondChallengeIsEmpty,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate:\n",
|
| + ""))));
|
| +
|
| +// The second round introduces a preferred scheme.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + SecondChallengeHasPreferredScheme,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic second_round\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK))));
|
| +
|
| +// If there are two challenges, then the auth controller should pick the first
|
| +// one.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultipleChallengesForSameScheme,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic second_round_1\n"
|
| + "WWW-Authenticate: Basic second_round_2\n",
|
| + "basic auth_token,second_round_1")
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// As above, but the handler will reject the first challenge of the second
|
| +// round. The auth controller should use the second challenge instead.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + RejectChallengeForTheSameSchemeInSingleResponse,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic first_round\n",
|
| + "basic auth_token,first_round")
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic second_round_1\n"
|
| + "WWW-Authenticate: Basic second_round_2\n",
|
| + "basic auth_token,second_round_2")
|
| + .WithHandler("basic", OK, OK)
|
| + .WithHandler("basic", ERR_INVALID_AUTH_CREDENTIALS, OK)
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// Connection based schemes will treat new auth challenges for the same scheme
|
| +// as acceptance and continuance of the current handshake if there's a
|
| +// parameter.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_Continuations,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate foo\n",
|
| + "negotiate continuation,foo"))));
|
| +
|
| +// As above, but picks the first challenge for the second round.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_ContinuationsWithMultipleChallenges,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate foo\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate continuation,foo"))));
|
| +
|
| +// As above. The first challenge in the second round counts as a rejection, so
|
| +// the controller should create a new handler and restart the handshake.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_ContinuationsWithMultipleChallengesAndRejection,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n"
|
| + "WWW-Authenticate: Negotiate continuation\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK))));
|
| +
|
| +// Multiround authentication with rejection. The rejection comes in the form of
|
| +// an empty challenge for the same scheme.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_RejectionViaEmptyChallenge,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK))));
|
| +
|
| +// Multiround authentication with rejection. The rejection comes in the form of
|
| +// a response with no challenge for the original scheme.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_RejectionViaSchemeChange,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic foo\n",
|
| + "basic auth_token,foo")
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// Dealing with empty and missing second round challenges for connection
|
| +// oriented schemes.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_EmptySecondChallenge,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate:\n",
|
| + ""))));
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_MissingSecondChallenge,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n", ""))));
|
| +
|
| +// Should pick matching challenge even if other challenges are present.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_PicksCorrectChallenge,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n",
|
| + "negotiate auth_token")
|
| + .WithHandler("negotiate", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic foo\n"
|
| + "WWW-Authenticate: Negotiate bar\n",
|
| + "negotiate continuation,bar"))));
|
| +INSTANTIATE_TEST_CASE_P(
|
| + MultiRoundAuth_PicksCorrectChallengeWithPreferredChallenge,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(
|
| + SyncAndAsync(ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: NTLM\n",
|
| + "ntlm auth_token")
|
| + .WithHandler("ntlm", OK, OK)
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Negotiate\n"
|
| + "WWW-Authenticate: NTLM bar\n",
|
| + "ntlm continuation,bar"))));
|
| +
|
| +// If an auth handler fails to initialize, the controller should try the next
|
| +// suitable challenge.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + FallThroughInvalidHeaders,
|
| + HttpAuthControllerTest,
|
| + ValuesIn(SyncAndAsync(
|
| + ChallengeResponseTestCase()
|
| + .WithChallengeResponse("HTTP/1.1 401\n"
|
| + "WWW-Authenticate: Basic abc;\n"
|
| + "WWW-Authenticate: Digest abc;\n"
|
| + "WWW-Authenticate: Basic valid",
|
| + "basic auth_token,valid")
|
| + // The first challenge chosen is Digest. But the handler fails.
|
| + .WithHandler("digest", ERR_INVALID_AUTH_CREDENTIALS, OK)
|
| + // Next the controller tries the first Basic challenge, which also
|
| + // fails.
|
| + .WithHandler("basic", ERR_INVALID_AUTH_CREDENTIALS, OK)
|
| + // Finally, the second Basic challenge succeeds.
|
| + .WithHandler("basic", OK, OK))));
|
| +
|
| +// Identities are used in the correct order.
|
| +TEST(HttpAuthControllerTest, IdentityPriorityOrder) {}
|
| +
|
| +// Identities from abstract sources should be available to a new handler if the
|
| +// server changes authentication scheme or if all identity sources were
|
| +// exhausted for a handler.
|
| +TEST(HttpAuthControllerTest, IdentityReuseAcrossHandlers) {}
|
| +
|
| } // namespace net
|
|
|