1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/http/http_auth_handler_basic.h"
#include <string>
#include "base/base64.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth.h"
namespace net {
namespace {
// Parses a realm from an auth challenge, and converts to UTF8-encoding.
// Returns whether the realm is invalid or the parameters are invalid.
//
// Note that if a realm was not specified, we will default it to "";
// so specifying 'Basic realm=""' is equivalent to 'Basic'.
//
// This is more generous than RFC 2617, which is pretty clear in the
// production of challenge that realm is required.
//
// We allow it to be compatibility with certain embedded webservers that don't
// include a realm (see http://crbug.com/20984.)
//
// The over-the-wire realm is encoded as ISO-8859-1 (aka Latin-1).
//
// TODO(cbentzel): Realm may need to be decoded using RFC 2047 rules as
// well, see http://crbug.com/25790.
bool ParseRealm(const HttpAuth::ChallengeTokenizer& tokenizer,
std::string* realm) {
CHECK(realm);
realm->clear();
HttpUtil::NameValuePairsIterator parameters = tokenizer.param_pairs();
while (parameters.GetNext()) {
if (!LowerCaseEqualsASCII(parameters.name(), "realm"))
continue;
if (!base::ConvertToUtf8AndNormalize(
parameters.value(), base::kCodepageLatin1, realm))
return false;
}
return parameters.valid();
}
} // namespace
bool HttpAuthHandlerBasic::Init(HttpAuth::ChallengeTokenizer* challenge) {
auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC;
score_ = 1;
properties_ = 0;
return ParseChallenge(challenge);
}
bool HttpAuthHandlerBasic::ParseChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
// Verify the challenge's auth-scheme.
if (!LowerCaseEqualsASCII(challenge->scheme(), "basic"))
return false;
std::string realm;
if (!ParseRealm(*challenge, &realm))
return false;
realm_ = realm;
return true;
}
HttpAuth::AuthorizationResult HttpAuthHandlerBasic::HandleAnotherChallenge(
HttpAuth::ChallengeTokenizer* challenge) {
// Basic authentication is always a single round, so any responses
// should be treated as a rejection. However, if the new challenge
// is for a different realm, then indicate the realm change.
std::string realm;
if (!ParseRealm(*challenge, &realm))
return HttpAuth::AUTHORIZATION_RESULT_INVALID;
return (realm_ != realm)?
HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM:
HttpAuth::AUTHORIZATION_RESULT_REJECT;
}
int HttpAuthHandlerBasic::GenerateAuthTokenImpl(
const AuthCredentials* credentials,
const HttpRequestInfo*,
OldCompletionCallback*,
std::string* auth_token) {
DCHECK(credentials);
// TODO(eroman): is this the right encoding of username/password?
std::string base64_username_password;
if (!base::Base64Encode(
UTF16ToUTF8(credentials->username()) + ":" +
UTF16ToUTF8(credentials->password()),
&base64_username_password)) {
LOG(ERROR) << "Unexpected problem Base64 encoding.";
return ERR_UNEXPECTED;
}
*auth_token = "Basic " + base64_username_password;
return OK;
}
HttpAuthHandlerBasic::Factory::Factory() {
}
HttpAuthHandlerBasic::Factory::~Factory() {
}
int HttpAuthHandlerBasic::Factory::CreateAuthHandler(
HttpAuth::ChallengeTokenizer* challenge,
HttpAuth::Target target,
const GURL& origin,
CreateReason reason,
int digest_nonce_count,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler) {
// TODO(cbentzel): Move towards model of parsing in the factory
// method and only constructing when valid.
scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerBasic());
if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
return OK;
}
} // namespace net
|