NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / net / spdyproxy / http_auth_handler_spdyproxy.cc
blob207fc312e897be7b218714d9ba23012a6642c159
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "base/i18n/icu_string_conversions.h"
12 #include "base/metrics/histogram.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_auth.h"
17 #include "net/http/http_request_info.h"
19 namespace spdyproxy {
21 using net::AuthCredentials;
22 using net::BoundNetLog;
23 using net::CompletionCallback;
24 using net::HttpAuth;
25 using net::HttpAuthHandler;
26 using net::HttpAuthHandlerFactory;
27 using net::HttpRequestInfo;
28 using net::HttpUtil;
30 HttpAuthHandlerSpdyProxy::Factory::Factory(
31 const std::vector<GURL>& authorized_spdyproxy_origins) {
32 for (unsigned int i = 0; i < authorized_spdyproxy_origins.size(); ++i) {
33 if (authorized_spdyproxy_origins[i].possibly_invalid_spec().empty()) {
34 VLOG(1) << "SpdyProxy auth without configuring authorized origin.";
35 return;
38 authorized_spdyproxy_origins_ = authorized_spdyproxy_origins;
41 HttpAuthHandlerSpdyProxy::Factory::~Factory() {
44 int HttpAuthHandlerSpdyProxy::Factory::CreateAuthHandler(
45 HttpAuth::ChallengeTokenizer* challenge,
46 HttpAuth::Target target,
47 const GURL& origin,
48 CreateReason reason,
49 int digest_nonce_count,
50 const BoundNetLog& net_log,
51 scoped_ptr<HttpAuthHandler>* handler) {
52 // If a spdyproxy auth proxy has not been set, refuse all requests to use this
53 // auth handler.
54 if (authorized_spdyproxy_origins_.empty())
55 return net::ERR_UNSUPPORTED_AUTH_SCHEME;
57 // We ensure that this authentication handler is used only with an authorized
58 // SPDY proxy, since otherwise a user's authentication token can be
59 // sniffed by a malicious proxy that presents an appropriate challenge.
60 const GURL origin_origin = origin.GetOrigin();
61 if (!(std::find(authorized_spdyproxy_origins_.begin(),
62 authorized_spdyproxy_origins_.end(),
63 origin_origin) != authorized_spdyproxy_origins_.end())) {
64 UMA_HISTOGRAM_COUNTS("Net.UnexpectedSpdyProxyAuth", 1);
65 VLOG(1) << "SpdyProxy auth request with an unexpected config."
66 << " origin: " << origin_origin.possibly_invalid_spec();
67 return net::ERR_UNSUPPORTED_AUTH_SCHEME;
70 scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerSpdyProxy());
71 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
72 return net::ERR_INVALID_RESPONSE;
73 handler->swap(tmp_handler);
74 return net::OK;
77 HttpAuth::AuthorizationResult
78 HttpAuthHandlerSpdyProxy::HandleAnotherChallenge(
79 HttpAuth::ChallengeTokenizer* challenge) {
80 // SpdyProxy authentication is always a single round, so any responses
81 // should be treated as a rejection.
82 return HttpAuth::AUTHORIZATION_RESULT_REJECT;
85 bool HttpAuthHandlerSpdyProxy::NeedsIdentity() {
86 return true;
89 bool HttpAuthHandlerSpdyProxy::AllowsDefaultCredentials() {
90 return false;
93 bool HttpAuthHandlerSpdyProxy::AllowsExplicitCredentials() {
94 return true;
97 HttpAuthHandlerSpdyProxy::~HttpAuthHandlerSpdyProxy() {}
99 bool HttpAuthHandlerSpdyProxy::Init(
100 HttpAuth::ChallengeTokenizer* challenge) {
101 auth_scheme_ = HttpAuth::AUTH_SCHEME_SPDYPROXY;
102 score_ = 5;
103 properties_ = ENCRYPTS_IDENTITY;
104 return ParseChallenge(challenge);
107 int HttpAuthHandlerSpdyProxy::GenerateAuthTokenImpl(
108 const AuthCredentials* credentials, const HttpRequestInfo* request,
109 const CompletionCallback&, std::string* auth_token) {
110 DCHECK(credentials);
111 if (credentials->password().length() == 0) {
112 DVLOG(1) << "Received a SpdyProxy auth token request without an "
113 << "available token.";
114 return -1;
116 *auth_token = "SpdyProxy ps=\"" + ps_token_ + "\", sid=\"" +
117 base::UTF16ToUTF8(credentials->password()) + "\"";
118 return net::OK;
121 bool HttpAuthHandlerSpdyProxy::ParseChallenge(
122 HttpAuth::ChallengeTokenizer* challenge) {
124 // Verify the challenge's auth-scheme.
125 if (!LowerCaseEqualsASCII(challenge->scheme(), "spdyproxy")) {
126 VLOG(1) << "Parsed challenge without SpdyProxy type";
127 return false;
130 HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
132 // Loop through all the properties.
133 while (parameters.GetNext()) {
134 // FAIL -- couldn't parse a property.
135 if (!ParseChallengeProperty(parameters.name(),
136 parameters.value()))
137 return false;
139 // Check if tokenizer failed.
140 if (!parameters.valid())
141 return false;
143 // Check that the required properties were provided.
144 if (realm_.empty())
145 return false;
147 if (ps_token_.empty())
148 return false;
150 return true;
153 bool HttpAuthHandlerSpdyProxy::ParseChallengeProperty(
154 const std::string& name, const std::string& value) {
155 if (LowerCaseEqualsASCII(name, "realm")) {
156 std::string realm;
157 if (!base::ConvertToUtf8AndNormalize(value, base::kCodepageLatin1, &realm))
158 return false;
159 realm_ = realm;
160 } else if (LowerCaseEqualsASCII(name, "ps")) {
161 ps_token_ = value;
162 } else {
163 VLOG(1) << "Skipping unrecognized SpdyProxy auth property, " << name;
165 return true;
168 } // namespace spdyproxy