Home | History | Annotate | Download | only in http
      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