1 // Copyright (c) 2010 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_handler_basic.h" 6 7 #include <string> 8 9 #include "base/base64.h" 10 #include "base/string_util.h" 11 #include "base/utf_string_conversions.h" 12 #include "net/base/net_errors.h" 13 #include "net/http/http_auth.h" 14 15 namespace net { 16 17 // Note that if a realm was not specified, we will default it to ""; 18 // so specifying 'Basic realm=""' is equivalent to 'Basic'. 19 // 20 // This is more generous than RFC 2617, which is pretty clear in the 21 // production of challenge that realm is required. 22 // 23 // We allow it to be compatibility with certain embedded webservers that don't 24 // include a realm (see http://crbug.com/20984.) 25 bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) { 26 auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC; 27 score_ = 1; 28 properties_ = 0; 29 return ParseChallenge(challenge); 30 } 31 32 bool HttpAuthHandlerBasic::ParseChallenge( 33 HttpAuth::ChallengeTokenizer* challenge) { 34 // Verify the challenge's auth-scheme. 35 if (!LowerCaseEqualsASCII(challenge->scheme(), "basic")) 36 return false; 37 38 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); 39 40 // Extract the realm (may be missing). 41 std::string realm; 42 while (parameters.GetNext()) { 43 if (LowerCaseEqualsASCII(parameters.name(), "realm")) 44 realm = parameters.value(); 45 } 46 47 if (!parameters.valid()) 48 return false; 49 50 realm_ = realm; 51 return true; 52 } 53 54 HttpAuth::AuthorizationResult HttpAuthHandlerBasic::HandleAnotherChallenge( 55 HttpAuth::ChallengeTokenizer* challenge) { 56 // Basic authentication is always a single round, so any responses 57 // should be treated as a rejection. However, if the new challenge 58 // is for a different realm, then indicate the realm change. 59 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs(); 60 std::string realm; 61 while (parameters.GetNext()) { 62 if (LowerCaseEqualsASCII(parameters.name(), "realm")) 63 realm = parameters.value(); 64 } 65 return (realm_ != realm)? 66 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM: 67 HttpAuth::AUTHORIZATION_RESULT_REJECT; 68 } 69 70 int HttpAuthHandlerBasic::GenerateAuthTokenImpl( 71 const string16* username, 72 const string16* password, 73 const HttpRequestInfo*, 74 CompletionCallback*, 75 std::string* auth_token) { 76 // TODO(eroman): is this the right encoding of username/password? 77 std::string base64_username_password; 78 if (!base::Base64Encode(UTF16ToUTF8(*username) + ":" + UTF16ToUTF8(*password), 79 &base64_username_password)) { 80 LOG(ERROR) << "Unexpected problem Base64 encoding."; 81 return ERR_UNEXPECTED; 82 } 83 *auth_token = "Basic " + base64_username_password; 84 return OK; 85 } 86 87 HttpAuthHandlerBasic::Factory::Factory() { 88 } 89 90 HttpAuthHandlerBasic::Factory::~Factory() { 91 } 92 93 int HttpAuthHandlerBasic::Factory::CreateAuthHandler( 94 HttpAuth::ChallengeTokenizer* challenge, 95 HttpAuth::Target target, 96 const GURL& origin, 97 CreateReason reason, 98 int digest_nonce_count, 99 const BoundNetLog& net_log, 100 scoped_ptr<HttpAuthHandler>* handler) { 101 // TODO(cbentzel): Move towards model of parsing in the factory 102 // method and only constructing when valid. 103 scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerBasic()); 104 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) 105 return ERR_INVALID_RESPONSE; 106 handler->swap(tmp_handler); 107 return OK; 108 } 109 110 } // namespace net 111