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

Unified 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, 7 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_auth_handler_negotiate_posix.cc
diff --git a/net/http/http_auth_handler_negotiate_posix.cc b/net/http/http_auth_handler_negotiate_posix.cc
index 270ee5ba172dce09c5e9892e9c31d85fb756b807..6ce3cd734f23a791e268bd6bf4a4ac1153e916ce 100644
--- a/net/http/http_auth_handler_negotiate_posix.cc
+++ b/net/http/http_auth_handler_negotiate_posix.cc
@@ -5,7 +5,11 @@
#include "net/http/http_auth_handler_negotiate.h"
#include "base/logging.h"
+#include "base/string_util.h"
+#include "net/base/address_family.h"
+#include "net/base/host_resolver.h"
#include "net/base/net_errors.h"
+#include "net/third_party/gssapi/gssapi.h"
namespace net {
@@ -16,33 +20,44 @@ namespace net {
// Negotiate without requiring conditional compilation.
HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
- URLSecurityManager* url_security_manager)
- : url_security_manager_(url_security_manager) {
+ GSSAPILibrary* library,
+ URLSecurityManager* url_security_manager,
+ bool disable_cname_lookup,
+ bool use_port)
+ : auth_gssapi_("Negotiate", GSS_C_NO_OID, library),
+ current_token_(NULL),
+ user_callback_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(resolve_cname_callback_(
+ this, &HttpAuthHandlerNegotiate::OnResolveCanonicalName)),
+ disable_cname_lookup_(disable_cname_lookup),
+ use_port_(use_port),
+ url_security_manager_(url_security_manager) {
}
HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
}
bool HttpAuthHandlerNegotiate::NeedsIdentity() {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return false;
+ return auth_gssapi_.NeedsIdentity();
}
bool HttpAuthHandlerNegotiate::IsFinalRound() {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return false;
+ return auth_gssapi_.IsFinalRound();
}
bool HttpAuthHandlerNegotiate::AllowsDefaultCredentials() {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return false;
+ if (target_ == HttpAuth::AUTH_PROXY)
+ return true;
+ if (!url_security_manager_)
+ return false;
+ return url_security_manager_->CanUseDefaultCredentials(origin_);
}
bool HttpAuthHandlerNegotiate::Init(HttpAuth::ChallengeTokenizer* tok) {
- return false;
+ scheme_ = "negotiate";
+ score_ = 4;
+ properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED;
+ return auth_gssapi_.ParseChallenge(tok);
}
int HttpAuthHandlerNegotiate::GenerateAuthToken(
@@ -51,34 +66,124 @@ int HttpAuthHandlerNegotiate::GenerateAuthToken(
const HttpRequestInfo* request,
const ProxyInfo* proxy,
std::string* auth_token) {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return ERR_NOT_IMPLEMENTED;
+ return auth_gssapi_.GenerateAuthToken(&username,
+ &password,
+ spn_,
+ request,
+ proxy,
+ auth_token);
}
int HttpAuthHandlerNegotiate::GenerateDefaultAuthToken(
const HttpRequestInfo* request,
const ProxyInfo* proxy,
std::string* auth_token) {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return ERR_NOT_IMPLEMENTED;
+ return auth_gssapi_.GenerateAuthToken(NULL, // username
+ NULL, // password
+ spn_,
+ request,
+ proxy,
+ auth_token);
}
bool HttpAuthHandlerNegotiate::NeedsCanonicalName() {
- return false;
+ if (!spn_.empty())
+ return false;
+ if (disable_cname_lookup_) {
+ spn_ = CreateSPN(address_list_, origin_);
+ address_list_.Reset();
+ return false;
+ }
+ return true;
}
-int HttpAuthHandlerNegotiate::ResolveCanonicalName(HostResolver* host_resolver,
+int HttpAuthHandlerNegotiate::ResolveCanonicalName(HostResolver* resolver,
CompletionCallback* callback,
const BoundNetLog& net_log) {
- NOTREACHED();
- LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
- return ERR_NOT_IMPLEMENTED;
+ // TODO(cbentzel): Add reverse DNS lookup for numeric addresses.
+ DCHECK(!single_resolve_.get());
+ DCHECK(!disable_cname_lookup_);
+ DCHECK(callback);
+
+ HostResolver::RequestInfo info(origin_.host(), 0);
+ info.set_host_resolver_flags(HOST_RESOLVER_CANONNAME);
+ single_resolve_.reset(new SingleRequestHostResolver(resolver));
+ int rv = single_resolve_->Resolve(info, &address_list_,
+ &resolve_cname_callback_,
+ net_log);
+ if (rv == ERR_IO_PENDING) {
+ user_callback_ = callback;
+ return rv;
+ }
+ OnResolveCanonicalName(rv);
+ // Always return OK. OnResolveCanonicalName logs the error code if not
+ // OK and attempts to use the original origin_ hostname rather than failing
+ // the auth attempt completely.
+ return OK;
+}
+
+void HttpAuthHandlerNegotiate::OnResolveCanonicalName(int result) {
+ if (result != OK) {
+ // Even in the error case, try to use origin_.host instead of
+ // passing the failure on to the caller.
+ LOG(INFO) << "Problem finding canonical name for SPN for host "
+ << origin_.host() << ": " << ErrorToString(result);
+ result = OK;
+ }
+ spn_ = CreateSPN(address_list_, origin_);
+ address_list_.Reset();
+ if (user_callback_) {
+ CompletionCallback* callback = user_callback_;
+ user_callback_ = NULL;
+ callback->Run(result);
+ }
+}
+
+std::wstring HttpAuthHandlerNegotiate::CreateSPN(
+ const AddressList& address_list, const GURL& origin) {
+ // Kerberos SPNs are in the form HTTP/<host>:<port>
+ // http://msdn.microsoft.com/en-us/library/ms677601%28VS.85%29.aspx
+ //
+ // However, reality differs from the specification. A good description of
+ // the problems can be found here:
+ // http://blog.michelbarneveld.nl/michel/archive/2009/11/14/the-reason-why-kb911149-and-kb908209-are-not-the-soluton.aspx
+ //
+ // Typically the <host> portion should be the canonical FQDN for the service.
+ // If this could not be resolved, the original hostname in the URL will be
+ // attempted instead. However, some intranets register SPNs using aliases
+ // for the same canonical DNS name to allow multiple web services to reside
+ // on the same host machine without requiring different ports. IE6 and IE7
+ // have hotpatches that allow the default behavior to be overridden.
+ // http://support.microsoft.com/kb/911149
+ // http://support.microsoft.com/kb/938305
+ //
+ // According to the spec, the <port> option should be included if it is a
+ // non-standard port (i.e. not 80 or 443 in the HTTP case). However,
+ // historically browsers have not included the port, even on non-standard
+ // ports. IE6 required a hotpatch and a registry setting to enable
+ // including non-standard ports, and IE7 and IE8 also require the same
+ // registry setting, but no hotpatch. Firefox does not appear to have an
+ // option to include non-standard ports as of 3.6.
+ // http://support.microsoft.com/kb/908209
+ //
+ // Without any command-line flags, Chrome matches the behavior of Firefox
+ // and IE. Users can override the behavior so aliases are allowed and
+ // non-standard ports are included.
+ int port = origin.EffectiveIntPort();
+ std::string server;
+ if (!address_list.GetCanonicalName(&server))
+ server = origin.host();
+ if (port != 80 && port != 443 && use_port_) {
+ return ASCIIToWide(StringPrintf("HTTP/%s:%d", server.c_str(), port));
+ } else {
+ return ASCIIToWide(StringPrintf("HTTP/%s", server.c_str()));
+ }
}
HttpAuthHandlerNegotiate::Factory::Factory()
- : disable_cname_lookup_(false), use_port_(false) {
+ : disable_cname_lookup_(false),
+ use_port_(false),
+ gssapi_library_(GSSAPILibrary::GetDefault()) {
}
HttpAuthHandlerNegotiate::Factory::~Factory() {
@@ -91,7 +196,16 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler(
CreateReason reason,
int digest_nonce_count,
scoped_refptr<HttpAuthHandler>* handler) {
- return ERR_UNSUPPORTED_AUTH_SCHEME;
+ // TODO(cbentzel): Move towards model of parsing in the factory
+ // method and only constructing when valid.
+ scoped_refptr<HttpAuthHandler> tmp_handler(
+ new HttpAuthHandlerNegotiate(gssapi_library_,
+ url_security_manager(),
+ disable_cname_lookup_, use_port_));
+ if (!tmp_handler->InitFromChallenge(challenge, target, origin))
+ return ERR_INVALID_RESPONSE;
+ handler->swap(tmp_handler);
+ return OK;
}
} // namespace net
« 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