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 15namespace 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.) 25bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) { 26 auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC; 27 score_ = 1; 28 properties_ = 0; 29 return ParseChallenge(challenge); 30} 31 32bool 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 54HttpAuth::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 70int 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 87HttpAuthHandlerBasic::Factory::Factory() { 88} 89 90HttpAuthHandlerBasic::Factory::~Factory() { 91} 92 93int 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