1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/http/http_auth.h" 6 7 #include <algorithm> 8 9 #include "base/basictypes.h" 10 #include "base/strings/string_tokenizer.h" 11 #include "base/strings/string_util.h" 12 #include "net/base/net_errors.h" 13 #include "net/http/http_auth_challenge_tokenizer.h" 14 #include "net/http/http_auth_handler.h" 15 #include "net/http/http_auth_handler_factory.h" 16 #include "net/http/http_request_headers.h" 17 #include "net/http/http_response_headers.h" 18 #include "net/http/http_util.h" 19 20 namespace net { 21 22 HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {} 23 24 // static 25 void HttpAuth::ChooseBestChallenge( 26 HttpAuthHandlerFactory* http_auth_handler_factory, 27 const HttpResponseHeaders* headers, 28 Target target, 29 const GURL& origin, 30 const std::set<Scheme>& disabled_schemes, 31 const BoundNetLog& net_log, 32 scoped_ptr<HttpAuthHandler>* handler) { 33 DCHECK(http_auth_handler_factory); 34 DCHECK(handler->get() == NULL); 35 36 // Choose the challenge whose authentication handler gives the maximum score. 37 scoped_ptr<HttpAuthHandler> best; 38 const std::string header_name = GetChallengeHeaderName(target); 39 std::string cur_challenge; 40 void* iter = NULL; 41 while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) { 42 scoped_ptr<HttpAuthHandler> cur; 43 int rv = http_auth_handler_factory->CreateAuthHandlerFromString( 44 cur_challenge, target, origin, net_log, &cur); 45 if (rv != OK) { 46 VLOG(1) << "Unable to create AuthHandler. Status: " 47 << ErrorToString(rv) << " Challenge: " << cur_challenge; 48 continue; 49 } 50 if (cur.get() && (!best.get() || best->score() < cur->score()) && 51 (disabled_schemes.find(cur->auth_scheme()) == disabled_schemes.end())) 52 best.swap(cur); 53 } 54 handler->swap(best); 55 } 56 57 // static 58 HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse( 59 HttpAuthHandler* handler, 60 const HttpResponseHeaders* headers, 61 Target target, 62 const std::set<Scheme>& disabled_schemes, 63 std::string* challenge_used) { 64 DCHECK(handler); 65 DCHECK(headers); 66 DCHECK(challenge_used); 67 challenge_used->clear(); 68 HttpAuth::Scheme current_scheme = handler->auth_scheme(); 69 if (disabled_schemes.find(current_scheme) != disabled_schemes.end()) 70 return HttpAuth::AUTHORIZATION_RESULT_REJECT; 71 std::string current_scheme_name = SchemeToString(current_scheme); 72 const std::string header_name = GetChallengeHeaderName(target); 73 void* iter = NULL; 74 std::string challenge; 75 HttpAuth::AuthorizationResult authorization_result = 76 HttpAuth::AUTHORIZATION_RESULT_INVALID; 77 while (headers->EnumerateHeader(&iter, header_name, &challenge)) { 78 HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); 79 if (!LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str())) 80 continue; 81 authorization_result = handler->HandleAnotherChallenge(&props); 82 if (authorization_result != HttpAuth::AUTHORIZATION_RESULT_INVALID) { 83 *challenge_used = challenge; 84 return authorization_result; 85 } 86 } 87 // Finding no matches is equivalent to rejection. 88 return HttpAuth::AUTHORIZATION_RESULT_REJECT; 89 } 90 91 // static 92 std::string HttpAuth::GetChallengeHeaderName(Target target) { 93 switch (target) { 94 case AUTH_PROXY: 95 return "Proxy-Authenticate"; 96 case AUTH_SERVER: 97 return "WWW-Authenticate"; 98 default: 99 NOTREACHED(); 100 return std::string(); 101 } 102 } 103 104 // static 105 std::string HttpAuth::GetAuthorizationHeaderName(Target target) { 106 switch (target) { 107 case AUTH_PROXY: 108 return HttpRequestHeaders::kProxyAuthorization; 109 case AUTH_SERVER: 110 return HttpRequestHeaders::kAuthorization; 111 default: 112 NOTREACHED(); 113 return std::string(); 114 } 115 } 116 117 // static 118 std::string HttpAuth::GetAuthTargetString(Target target) { 119 switch (target) { 120 case AUTH_PROXY: 121 return "proxy"; 122 case AUTH_SERVER: 123 return "server"; 124 default: 125 NOTREACHED(); 126 return std::string(); 127 } 128 } 129 130 // static 131 const char* HttpAuth::SchemeToString(Scheme scheme) { 132 static const char* const kSchemeNames[] = { 133 "basic", 134 "digest", 135 "ntlm", 136 "negotiate", 137 "spdyproxy", 138 "mock", 139 }; 140 COMPILE_ASSERT(arraysize(kSchemeNames) == AUTH_SCHEME_MAX, 141 http_auth_scheme_names_incorrect_size); 142 if (scheme < AUTH_SCHEME_BASIC || scheme >= AUTH_SCHEME_MAX) { 143 NOTREACHED(); 144 return "invalid_scheme"; 145 } 146 return kSchemeNames[scheme]; 147 } 148 149 } // namespace net 150