Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1003)

Side by Side Diff: net/http/http_auth_handler_negotiate_posix.cc

Issue 2268002: Implemented mid-level Negotiate protocol for Posix. (Closed)
Patch Set: Merged with trunk. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/http/http_auth_handler_negotiate.h ('k') | net/http/http_auth_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_auth_handler_negotiate.h" 5 #include "net/http/http_auth_handler_negotiate.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/string_util.h"
9 #include "net/base/address_family.h"
10 #include "net/base/host_resolver.h"
8 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
12 #include "net/third_party/gssapi/gssapi.h"
9 13
10 namespace net { 14 namespace net {
11 15
12 // TODO(ahendrickson): Implement via GSSAPI. 16 // TODO(ahendrickson): Implement via GSSAPI.
13 17
14 // TODO(cbentzel): Negotiate authentication protocol is not supported on Posix 18 // TODO(cbentzel): Negotiate authentication protocol is not supported on Posix
15 // systems currently. These stubs make the main HTTP Authentication code bypass 19 // systems currently. These stubs make the main HTTP Authentication code bypass
16 // Negotiate without requiring conditional compilation. 20 // Negotiate without requiring conditional compilation.
17 21
18 HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate( 22 HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
19 URLSecurityManager* url_security_manager) 23 GSSAPILibrary* library,
20 : url_security_manager_(url_security_manager) { 24 URLSecurityManager* url_security_manager,
25 bool disable_cname_lookup,
26 bool use_port)
27 : auth_gssapi_("Negotiate", GSS_C_NO_OID, library),
28 current_token_(NULL),
29 user_callback_(NULL),
30 ALLOW_THIS_IN_INITIALIZER_LIST(resolve_cname_callback_(
31 this, &HttpAuthHandlerNegotiate::OnResolveCanonicalName)),
32 disable_cname_lookup_(disable_cname_lookup),
33 use_port_(use_port),
34 url_security_manager_(url_security_manager) {
21 } 35 }
22 36
23 HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() { 37 HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
24 } 38 }
25 39
26 bool HttpAuthHandlerNegotiate::NeedsIdentity() { 40 bool HttpAuthHandlerNegotiate::NeedsIdentity() {
27 NOTREACHED(); 41 return auth_gssapi_.NeedsIdentity();
28 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
29 return false;
30 } 42 }
31 43
32 bool HttpAuthHandlerNegotiate::IsFinalRound() { 44 bool HttpAuthHandlerNegotiate::IsFinalRound() {
33 NOTREACHED(); 45 return auth_gssapi_.IsFinalRound();
34 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
35 return false;
36 } 46 }
37 47
38 bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() { 48 bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
39 NOTREACHED(); 49 if (target_ == HttpAuth::AUTH_PROXY)
40 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED); 50 return true;
41 return false; 51 if (!url_security_manager_)
52 return false;
53 return url_security_manager_->CanUseDefaultCredentials(origin_);
42 } 54 }
43 55
44 bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* tok) { 56 bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* tok) {
45 return false; 57 scheme_ = "negotiate";
58 score_ = 4;
59 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
60 return auth_gssapi_.ParseChallenge(tok);
46 } 61 }
47 62
48 int HttpAuthHandlerNegotiate::GenerateAuthToken( 63 int HttpAuthHandlerNegotiate::GenerateAuthToken(
49 const std::wstring& username, 64 const std::wstring& username,
50 const std::wstring& password, 65 const std::wstring& password,
51 const HttpRequestInfo* request, 66 const HttpRequestInfo* request,
52 const ProxyInfo* proxy, 67 const ProxyInfo* proxy,
53 std::string* auth_token) { 68 std::string* auth_token) {
54 NOTREACHED(); 69 return auth_gssapi_.GenerateAuthToken(&username,
55 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED); 70 &password,
56 return ERR_NOT_IMPLEMENTED; 71 spn_,
72 request,
73 proxy,
74 auth_token);
57 } 75 }
58 76
59 int HttpAuthHandlerNegotiate::GenerateDefaultAuthToken( 77 int HttpAuthHandlerNegotiate::GenerateDefaultAuthToken(
60 const HttpRequestInfo* request, 78 const HttpRequestInfo* request,
61 const ProxyInfo* proxy, 79 const ProxyInfo* proxy,
62 std::string* auth_token) { 80 std::string* auth_token) {
63 NOTREACHED(); 81 return auth_gssapi_.GenerateAuthToken(NULL, // username
64 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED); 82 NULL, // password
65 return ERR_NOT_IMPLEMENTED; 83 spn_,
84 request,
85 proxy,
86 auth_token);
66 } 87 }
67 88
68 bool HttpAuthHandlerNegotiate::NeedsCanonicalName() { 89 bool HttpAuthHandlerNegotiate::NeedsCanonicalName() {
69 return false; 90 if (!spn_.empty())
91 return false;
92 if (disable_cname_lookup_) {
93 spn_ = CreateSPN(address_list_, origin_);
94 address_list_.Reset();
95 return false;
96 }
97 return true;
70 } 98 }
71 99
72 int HttpAuthHandlerNegotiate::ResolveCanonicalName(HostResolver* host_resolver, 100 int HttpAuthHandlerNegotiate::ResolveCanonicalName(HostResolver* resolver,
73 CompletionCallback* callback, 101 CompletionCallback* callback,
74 const BoundNetLog& net_log) { 102 const BoundNetLog& net_log) {
75 NOTREACHED(); 103 // TODO(cbentzel): Add reverse DNS lookup for numeric addresses.
76 LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED); 104 DCHECK(!single_resolve_.get());
77 return ERR_NOT_IMPLEMENTED; 105 DCHECK(!disable_cname_lookup_);
106 DCHECK(callback);
107
108 HostResolver::RequestInfo info(origin_.host(), 0);
109 info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME);
110 single_resolve_.reset(new SingleRequestHostResolver(resolver));
111 int rv = single_resolve_->Resolve(info, &address_list_,
112 &resolve_cname_callback_,
113 net_log);
114 if (rv == ERR_IO_PENDING) {
115 user_callback_ = callback;
116 return rv;
117 }
118 OnResolveCanonicalName(rv);
119 // Always return OK. OnResolveCanonicalName logs the error code if not
120 // OK and attempts to use the original origin_ hostname rather than failing
121 // the auth attempt completely.
122 return OK;
123 }
124
125 void HttpAuthHandlerNegotiate::OnResolveCanonicalName(int result) {
126 if (result != OK) {
127 // Even in the error case, try to use origin_.host instead of
128 // passing the failure on to the caller.
129 LOG(INFO) << "Problem finding canonical name for SPN for host "
130 << origin_.host() << ": " << ErrorToString(result);
131 result = OK;
132 }
133 spn_ = CreateSPN(address_list_, origin_);
134 address_list_.Reset();
135 if (user_callback_) {
136 CompletionCallback* callback = user_callback_;
137 user_callback_ = NULL;
138 callback->Run(result);
139 }
140 }
141
142 std::wstring HttpAuthHandlerNegotiate::CreateSPN(
143 const AddressList& address_list, const GURL& origin) {
144 // Kerberos SPNs are in the form HTTP/<host>:<port>
145 // http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx
146 //
147 // However, reality differs from the specification. A good description of
148 // the problems can be found here:
149 // http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-k b911149-and-kb908209-are-not-the-soluton.aspx
150 //
151 // Typically the <host> portion should be the canonical FQDN for the service.
152 // If this could not be resolved, the original hostname in the URL will be
153 // attempted instead. However, some intranets register SPNs using aliases
154 // for the same canonical DNS name to allow multiple web services to reside
155 // on the same host machine without requiring different ports. IE6 and IE7
156 // have hotpatches that allow the default behavior to be overridden.
157 // http://support.microsoft.com/kb/911149
158 // http://support.microsoft.com/kb/938305
159 //
160 // According to the spec, the <port> option should be included if it is a
161 // non-standard port (i.e. not 80 or 443 in the HTTP case). However,
162 // historically browsers have not included the port, even on non-standard
163 // ports. IE6 required a hotpatch and a registry setting to enable
164 // including non-standard ports, and IE7 and IE8 also require the same
165 // registry setting, but no hotpatch. Firefox does not appear to have an
166 // option to include non-standard ports as of 3.6.
167 // http://support.microsoft.com/kb/908209
168 //
169 // Without any command-line flags, Chrome matches the behavior of Firefox
170 // and IE. Users can override the behavior so aliases are allowed and
171 // non-standard ports are included.
172 int port = origin.EffectiveIntPort();
173 std::string server;
174 if (!address_list.GetCanonicalName(&server))
175 server = origin.host();
176 if (port != 80 && port != 443 && use_port_) {
177 return ASCIIToWide(StringPrintf("HTTP/%s:%d", server.c_str(), port));
178 } else {
179 return ASCIIToWide(StringPrintf("HTTP/%s", server.c_str()));
180 }
78 } 181 }
79 182
80 HttpAuthHandlerNegotiate::Factory::Factory() 183 HttpAuthHandlerNegotiate::Factory::Factory()
81 : disable_cname_lookup_(false), use_port_(false) { 184 : disable_cname_lookup_(false),
185 use_port_(false),
186 gssapi_library_(GSSAPILibrary::GetDefault()) {
82 } 187 }
83 188
84 HttpAuthHandlerNegotiate::Factory::~Factory() { 189 HttpAuthHandlerNegotiate::Factory::~Factory() {
85 } 190 }
86 191
87 int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( 192 int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
88 HttpAuth::ChallengeTokenizer* challenge, 193 HttpAuth::ChallengeTokenizer* challenge,
89 HttpAuth::Target target, 194 HttpAuth::Target target,
90 const GURL& origin, 195 const GURL& origin,
91 CreateReason reason, 196 CreateReason reason,
92 int digest_nonce_count, 197 int digest_nonce_count,
93 scoped_refptr<HttpAuthHandler>* handler) { 198 scoped_refptr<HttpAuthHandler>* handler) {
94 return ERR_UNSUPPORTED_AUTH_SCHEME; 199 // TODO(cbentzel): Move towards model of parsing in the factory
200 // method and only constructing when valid.
201 scoped_refptr<HttpAuthHandler> tmp_handler(
202 new HttpAuthHandlerNegotiate(gssapi_library_,
203 url_security_manager(),
204 disable_cname_lookup_, use_port_));
205 if (!tmp_handler->InitFromChallenge(challenge, target, origin))
206 return ERR_INVALID_RESPONSE;
207 handler->swap(tmp_handler);
208 return OK;
95 } 209 }
96 210
97 } // namespace net 211 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_negotiate.h ('k') | net/http/http_auth_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698