Fix multi-round authentication.

In the case of Negotiate, authentication can look like

C: GET
S: 401, WWW-Authenticate: Negotiate

C: GET, WWW-Authorization: Negotiate <client_token_1>
S: 401, WWW-Authenticate: Negotiate <server_token_1>

C: GET, WWW-Authorization: Negotiate <client_token_2>
S: 401, WWW-Authenticate: Negotiate <server_token_2>

on that third challenge, the handler was reported as being in "the final round" and this was treated as a rejection of the authentication attempt. After that, the new challenge token was used by a new auth handler that hadn't established a security context, and an ERR_INVALID_HANDLE would be returned.

This CL also does some prep work to correctly handle the "stale=true" value for Digest authentication, but I decided to defer the HttpAuthCache changes needed for that to a separate CL since this was large enough.

BUG=53282
TEST=net_unittests. Unfortunately, I haven't been able to set up a proxy/server to do more than two auth challenges, but this does happen in the wild.

Review URL: http://codereview.chromium.org/3360017

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59188 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/http/http_auth_handler_digest_unittest.cc b/net/http/http_auth_handler_digest_unittest.cc
index 5129001..8026613 100644
--- a/net/http/http_auth_handler_digest_unittest.cc
+++ b/net/http/http_auth_handler_digest_unittest.cc
@@ -291,4 +291,34 @@
   }
 }
 
+TEST(HttpAuthHandlerDigest, HandleAnotherChallenge_Failed) {
+  scoped_ptr<HttpAuthHandlerDigest::Factory> factory(
+      new HttpAuthHandlerDigest::Factory());
+  scoped_ptr<HttpAuthHandler> handler;
+  std::string default_challenge =
+      "Digest realm=\"Oblivion\", nonce=\"nonce-value\"";
+  GURL origin("intranet.google.com");
+  int rv = factory->CreateAuthHandlerFromString(
+      default_challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(),
+      &handler);
+  EXPECT_EQ(OK, rv);
+
+  HttpAuth::ChallengeTokenizer tok_default(default_challenge.begin(),
+                                           default_challenge.end());
+  EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
+            handler->HandleAnotherChallenge(&tok_default));
+
+  std::string stale_challenge = default_challenge + ", stale=true";
+  HttpAuth::ChallengeTokenizer tok_stale(stale_challenge.begin(),
+                                         stale_challenge.end());
+  EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_STALE,
+            handler->HandleAnotherChallenge(&tok_stale));
+
+  std::string stale_false_challenge = default_challenge + ", stale=false";
+  HttpAuth::ChallengeTokenizer tok_stale_false(stale_false_challenge.begin(),
+                                               stale_false_challenge.end());
+  EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
+            handler->HandleAnotherChallenge(&tok_stale_false));
+}
+
 } // namespace net