summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-29 18:02:36 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-29 18:02:36 +0000
commitd7f166387b66955c2e5b967a3cc7467fad072e73 (patch)
tree7a5c47a5e65f90afb2eca5bbb4c0d6c08f5dc625 /net
parent5452d7e80ce2df298e15e6a5e17effcb26a51bf2 (diff)
downloadchromium_src-d7f166387b66955c2e5b967a3cc7467fad072e73.zip
chromium_src-d7f166387b66955c2e5b967a3cc7467fad072e73.tar.gz
chromium_src-d7f166387b66955c2e5b967a3cc7467fad072e73.tar.bz2
On Windows, use IInternetSecurityManager to determine if it's OK
to send the default credentials to a server, without prompting the user for permission, for HTTP NTLM or Negotiate authentication. It is always OK to send the default credentials to a proxy without prompting the user. Rename the AllowDefaultCredentials method of HttpAuthHandler to SupportsDefaultCredentials and redefine it to simply return if the authentication scheme supports the use of default credentials, as opposed to whether we may use the default credentials for a particular server or proxy. This CL contains the changes by cbentzel in http://codereview.chromium.org/1082001. R=cbentzel,cpu,stoyan BUG=29596 TEST=none Review URL: http://codereview.chromium.org/1343003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_auth.h90
-rw-r--r--net/http/http_auth_handler.h12
-rw-r--r--net/http/http_auth_handler_negotiate.h2
-rw-r--r--net/http/http_auth_handler_negotiate_posix.cc2
-rw-r--r--net/http/http_auth_handler_negotiate_win.cc13
-rw-r--r--net/http/http_auth_handler_ntlm.h2
-rw-r--r--net/http/http_auth_handler_ntlm_portable.cc2
-rw-r--r--net/http/http_auth_handler_ntlm_win.cc23
-rw-r--r--net/http/http_network_session.cc11
-rw-r--r--net/http/http_network_session.h6
-rw-r--r--net/http/http_network_transaction.cc90
-rw-r--r--net/http/http_network_transaction.h9
-rw-r--r--net/http/url_security_manager.h34
-rw-r--r--net/http/url_security_manager_posix.cc25
-rw-r--r--net/http/url_security_manager_win.cc101
-rw-r--r--net/net.gyp3
16 files changed, 321 insertions, 104 deletions
diff --git a/net/http/http_auth.h b/net/http/http_auth.h
index 76deca8..8d1ecc5 100644
--- a/net/http/http_auth.h
+++ b/net/http/http_auth.h
@@ -19,49 +19,53 @@ class HttpResponseHeaders;
class HttpAuth {
public:
- // Http authentication can be done the the proxy server, origin server,
- // or both. This enum tracks who the target is.
- enum Target {
- AUTH_NONE = -1,
- // We depend on the valid targets (!= AUTH_NONE) being usable as indexes
- // in an array, so start from 0.
- AUTH_PROXY = 0,
- AUTH_SERVER = 1,
- };
-
- // Describes where the identity used for authentication came from.
- enum IdentitySource {
- // Came from nowhere -- the identity is not initialized.
- IDENT_SRC_NONE,
-
- // The identity came from the auth cache, by doing a path-based
- // lookup (premptive authorization).
- IDENT_SRC_PATH_LOOKUP,
-
- // The identity was extracted from a URL of the form:
- // http://<username>:<password>@host:port
- IDENT_SRC_URL,
-
- // The identity was retrieved from the auth cache, by doing a
- // realm lookup.
- IDENT_SRC_REALM_LOOKUP,
-
- // The identity was provided by RestartWithAuth -- it likely
- // came from a prompt (or maybe the password manager).
- IDENT_SRC_EXTERNAL,
- };
-
- // Helper structure used by HttpNetworkTransaction to track
- // the current identity being used for authorization.
- struct Identity {
- Identity() : source(IDENT_SRC_NONE), invalid(true) { }
-
- IdentitySource source;
- bool invalid;
- // TODO(wtc): |username| and |password| should be string16.
- std::wstring username;
- std::wstring password;
- };
+ // Http authentication can be done the the proxy server, origin server,
+ // or both. This enum tracks who the target is.
+ enum Target {
+ AUTH_NONE = -1,
+ // We depend on the valid targets (!= AUTH_NONE) being usable as indexes
+ // in an array, so start from 0.
+ AUTH_PROXY = 0,
+ AUTH_SERVER = 1,
+ };
+
+ // Describes where the identity used for authentication came from.
+ enum IdentitySource {
+ // Came from nowhere -- the identity is not initialized.
+ IDENT_SRC_NONE,
+
+ // The identity came from the auth cache, by doing a path-based
+ // lookup (premptive authorization).
+ IDENT_SRC_PATH_LOOKUP,
+
+ // The identity was extracted from a URL of the form:
+ // http://<username>:<password>@host:port
+ IDENT_SRC_URL,
+
+ // The identity was retrieved from the auth cache, by doing a
+ // realm lookup.
+ IDENT_SRC_REALM_LOOKUP,
+
+ // The identity was provided by RestartWithAuth -- it likely
+ // came from a prompt (or maybe the password manager).
+ IDENT_SRC_EXTERNAL,
+
+ // The identity used the default credentials for the computer,
+ // on schemes that support single sign-on.
+ IDENT_SRC_DEFAULT_CREDENTIALS,
+ };
+
+ // Helper structure used by HttpNetworkTransaction to track
+ // the current identity being used for authorization.
+ struct Identity {
+ Identity() : source(IDENT_SRC_NONE), invalid(true) { }
+
+ IdentitySource source;
+ bool invalid;
+ // TODO(wtc): |username| and |password| should be string16.
+ std::wstring username;
+ std::wstring password;
+ };
// Get the name of the header containing the auth challenge
// (either WWW-Authenticate or Proxy-Authenticate).
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h
index dc0543e..d2eae13 100644
--- a/net/http/http_auth_handler.h
+++ b/net/http/http_auth_handler.h
@@ -74,10 +74,12 @@ class HttpAuthHandler : public base::RefCounted<HttpAuthHandler> {
// single-round schemes.
virtual bool IsFinalRound() { return true; }
- // Returns whether the default credentials may be used for the |origin| passed
- // into |InitFromChallenge|. If true, the user does not need to be prompted
- // for username and password to establish credentials.
- virtual bool AllowDefaultCredentials() { return false; }
+ // Returns whether the authentication scheme supports the use of default
+ // credentials. If true, the user does not need to be prompted for
+ // username and password to establish credentials.
+ // NOTE: SSO is a potential security risk.
+ // TODO(cbentzel): Add a pointer to Firefox documentation about risk.
+ virtual bool SupportsDefaultCredentials() { return false; }
// TODO(cbentzel): Separate providing credentials from generating the
// authentication token in the API.
@@ -96,7 +98,7 @@ class HttpAuthHandler : public base::RefCounted<HttpAuthHandler> {
// The return value is an error code. If the code is not |OK|, the value of
// |*auth_token| is unspecified.
// |auth_token| is a return value and must be non-NULL.
- // This should only be called after |AllowDefaultCredentials| returns true.
+ // This should only be called if |SupportsDefaultCredentials| returns true.
virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
const ProxyInfo* proxy,
std::string* auth_token) = 0;
diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h
index 4577d9c..f34664c 100644
--- a/net/http/http_auth_handler_negotiate.h
+++ b/net/http/http_auth_handler_negotiate.h
@@ -65,7 +65,7 @@ class HttpAuthHandlerNegotiate : public HttpAuthHandler {
virtual bool IsFinalRound();
- virtual bool AllowDefaultCredentials();
+ virtual bool SupportsDefaultCredentials();
virtual int GenerateAuthToken(const std::wstring& username,
const std::wstring& password,
diff --git a/net/http/http_auth_handler_negotiate_posix.cc b/net/http/http_auth_handler_negotiate_posix.cc
index ab69267..2b96597 100644
--- a/net/http/http_auth_handler_negotiate_posix.cc
+++ b/net/http/http_auth_handler_negotiate_posix.cc
@@ -31,7 +31,7 @@ bool HttpAuthHandlerNegotiate::IsFinalRound() {
return false;
}
-bool HttpAuthHandlerNegotiate::AllowDefaultCredentials() {
+bool HttpAuthHandlerNegotiate::SupportsDefaultCredentials() {
NOTREACHED();
LOG(ERROR) << ErrorToString(ERR_NOT_IMPLEMENTED);
return false;
diff --git a/net/http/http_auth_handler_negotiate_win.cc b/net/http/http_auth_handler_negotiate_win.cc
index c09beb0..d710c69 100644
--- a/net/http/http_auth_handler_negotiate_win.cc
+++ b/net/http/http_auth_handler_negotiate_win.cc
@@ -51,17 +51,8 @@ bool HttpAuthHandlerNegotiate::IsFinalRound() {
return auth_sspi_.IsFinalRound();
}
-bool HttpAuthHandlerNegotiate::AllowDefaultCredentials() {
- // NOTE: Temporarily disabled. SSO is a potential security risk.
- // TODO(cbentzel): Add a pointer to Firefox documentation about risk.
-
- // TODO(cbentzel): Add a blanket command line flag to enable/disable?
- // TODO(cbentzel): Add a whitelist regexp command line flag?
- // TODO(cbentzel): Resolve the origin_ (helpful if doing already) and see if
- // it is in private IP space?
- // TODO(cbentzel): Compare origin_ to this machine's hostname and allow if
- // it matches at least two or three layers deep?
- return false;
+bool HttpAuthHandlerNegotiate::SupportsDefaultCredentials() {
+ return true;
}
int HttpAuthHandlerNegotiate::GenerateDefaultAuthToken(
diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h
index aebb5c4..542bf92 100644
--- a/net/http/http_auth_handler_ntlm.h
+++ b/net/http/http_auth_handler_ntlm.h
@@ -103,7 +103,7 @@ class HttpAuthHandlerNTLM : public HttpAuthHandler {
virtual bool IsFinalRound();
- virtual bool AllowDefaultCredentials();
+ virtual bool SupportsDefaultCredentials();
virtual int GenerateAuthToken(const std::wstring& username,
const std::wstring& password,
diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc
index 6cbf16a..5872131 100644
--- a/net/http/http_auth_handler_ntlm_portable.cc
+++ b/net/http/http_auth_handler_ntlm_portable.cc
@@ -658,7 +658,7 @@ bool HttpAuthHandlerNTLM::IsFinalRound() {
return !auth_data_.empty();
}
-bool HttpAuthHandlerNTLM::AllowDefaultCredentials() {
+bool HttpAuthHandlerNTLM::SupportsDefaultCredentials() {
// Default credentials are not supported in the portable implementation of
// NTLM, but are supported in the SSPI implementation.
return false;
diff --git a/net/http/http_auth_handler_ntlm_win.cc b/net/http/http_auth_handler_ntlm_win.cc
index 2de3411..2aa9c0d 100644
--- a/net/http/http_auth_handler_ntlm_win.cc
+++ b/net/http/http_auth_handler_ntlm_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -36,17 +36,8 @@ bool HttpAuthHandlerNTLM::IsFinalRound() {
return auth_sspi_.IsFinalRound();
}
-bool HttpAuthHandlerNTLM::AllowDefaultCredentials() {
- // NOTE: Temporarily disabled. SSO is a potential security risk with NTLM.
- // TODO(cbentzel): Add a pointer to Firefox documentation about risk.
-
- // TODO(cbentzel): Add a blanket command line flag to enable/disable?
- // TODO(cbentzel): Add a whitelist regexp command line flag?
- // TODO(cbentzel): Resolve the origin_ (helpful if doing already) and see if
- // it is in private IP space?
- // TODO(cbentzel): Compare origin_ to this machine's hostname and allow if
- // it matches at least two or three layers deep?
- return false;
+bool HttpAuthHandlerNTLM::SupportsDefaultCredentials() {
+ return true;
}
int HttpAuthHandlerNTLM::GenerateDefaultAuthToken(
@@ -54,16 +45,16 @@ int HttpAuthHandlerNTLM::GenerateDefaultAuthToken(
const ProxyInfo* proxy,
std::string* auth_token) {
return auth_sspi_.GenerateAuthToken(
- NULL, // username
- NULL, // password
+ NULL, // username
+ NULL, // password
origin_,
request,
proxy,
auth_token);
}
-HttpAuthHandlerNTLM::Factory::Factory() :
- max_token_length_(0),
+HttpAuthHandlerNTLM::Factory::Factory()
+ : max_token_length_(0),
first_creation_(true),
is_unsupported_(false),
sspi_library_(SSPILibrary::GetDefault()) {
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index d7dbe94..66b7854 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/http/url_security_manager.h"
#include "net/spdy/spdy_session_pool.h"
namespace net {
@@ -54,6 +55,14 @@ HttpNetworkSession::HttpNetworkSession(
HttpNetworkSession::~HttpNetworkSession() {
}
+URLSecurityManager* HttpNetworkSession::GetURLSecurityManager() {
+ // Create the URL security manager lazily in the first call.
+ // This is called on a single thread.
+ if (!url_security_manager_.get())
+ url_security_manager_.reset(URLSecurityManager::Create());
+ return url_security_manager_.get();
+}
+
// static
void HttpNetworkSession::set_max_sockets_per_group(int socket_count) {
DCHECK(0 < socket_count);
@@ -73,4 +82,4 @@ void HttpNetworkSession::ReplaceTCPSocketPool() {
network_change_notifier_);
}
-} // namespace net
+} // namespace net
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 5b2cb97..fcfaac4 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -6,6 +6,7 @@
#define NET_HTTP_HTTP_NETWORK_SESSION_H_
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_client_auth_cache.h"
#include "net/base/ssl_config_service.h"
@@ -21,6 +22,7 @@ class ClientSocketFactory;
class HttpAuthHandlerFactory;
class SpdySessionPool;
class NetworkChangeNotifier;
+class URLSecurityManager;
// This class holds session objects used by HttpNetworkTransaction objects.
class HttpNetworkSession : public base::RefCounted<HttpNetworkSession> {
@@ -65,6 +67,9 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession> {
return http_auth_handler_factory_;
}
+ // Returns a pointer to the URL security manager.
+ URLSecurityManager* GetURLSecurityManager();
+
// Replace the current socket pool with a new one. This effectively
// abandons the current pool. This is only used for debugging.
void ReplaceTCPSocketPool();
@@ -106,6 +111,7 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession> {
scoped_refptr<SSLConfigService> ssl_config_service_;
scoped_refptr<SpdySessionPool> spdy_session_pool_;
HttpAuthHandlerFactory* http_auth_handler_factory_;
+ scoped_ptr<URLSecurityManager> url_security_manager_;
};
} // namespace net
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 218f26d..57cf773 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -29,6 +29,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/http/url_security_manager.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
@@ -219,6 +220,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
using_spdy_(false),
alternate_protocol_mode_(kUnspecified),
embedded_identity_used_(false),
+ default_credentials_used_(false),
read_buf_len_(0),
next_state_(STATE_NONE) {
session->ssl_config_service()->GetSSLConfig(&ssl_config_);
@@ -335,20 +337,25 @@ void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) {
// to know about it. If an entry for (origin, handler->realm()) already
// exists, we update it.
//
- // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE,
- // auth_identity_[target] contains no identity because identity is not
- // required yet.
+ // If auth_identity_[target].source is HttpAuth::IDENT_SRC_NONE or
+ // HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS, auth_identity_[target] contains
+ // no identity because identity is not required yet or we're using default
+ // credentials.
//
// TODO(wtc): For NTLM_SSPI, we add the same auth entry to the cache in
// round 1 and round 2, which is redundant but correct. It would be nice
// to add an auth entry to the cache only once, preferrably in round 1.
// See http://crbug.com/21015.
- bool has_auth_identity =
- auth_identity_[target].source != HttpAuth::IDENT_SRC_NONE;
- if (has_auth_identity) {
- session_->auth_cache()->Add(AuthOrigin(target), auth_handler_[target],
- auth_identity_[target].username, auth_identity_[target].password,
- AuthPath(target));
+ switch (auth_identity_[target].source) {
+ case HttpAuth::IDENT_SRC_NONE:
+ case HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS:
+ break;
+ default:
+ session_->auth_cache()->Add(
+ AuthOrigin(target), auth_handler_[target],
+ auth_identity_[target].username, auth_identity_[target].password,
+ AuthPath(target));
+ break;
}
bool keep_alive = false;
@@ -1610,12 +1617,17 @@ std::string HttpNetworkTransaction::BuildAuthorizationHeader(
// Add a Authorization/Proxy-Authorization header line.
std::string auth_token;
- int rv = auth_handler_[target]->GenerateAuthToken(
- auth_identity_[target].username,
- auth_identity_[target].password,
- request_,
- &proxy_info_,
- &auth_token);
+ int rv;
+ if (auth_identity_[target].source ==
+ HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS) {
+ rv = auth_handler_[target]->GenerateDefaultAuthToken(
+ request_, &proxy_info_, &auth_token);
+ } else {
+ rv = auth_handler_[target]->GenerateAuthToken(
+ auth_identity_[target].username,
+ auth_identity_[target].password,
+ request_, &proxy_info_, &auth_token);
+ }
if (rv == OK)
return HttpAuth::GetAuthorizationHeaderName(target) +
": " + auth_token + "\r\n";
@@ -1694,9 +1706,25 @@ bool HttpNetworkTransaction::SelectPreemptiveAuth(HttpAuth::Target target) {
auth_handler_[target] = entry->handler();
return true;
}
+
+ // TODO(cbentzel): Preemptively use default credentials if they have worked
+ // for the origin/path in the past to save a round trip.
+
return false;
}
+bool HttpNetworkTransaction::CanUseDefaultCredentials(
+ HttpAuth::Target target,
+ const GURL& auth_origin) const {
+ if (target == HttpAuth::AUTH_PROXY)
+ return true;
+
+ URLSecurityManager* security_manager = session_->GetURLSecurityManager();
+ if (!security_manager)
+ return false;
+ return security_manager->CanUseDefaultCredentials(auth_origin);
+}
+
bool HttpNetworkTransaction::SelectNextAuthIdentityToTry(
HttpAuth::Target target,
const GURL& auth_origin) {
@@ -1733,19 +1761,33 @@ bool HttpNetworkTransaction::SelectNextAuthIdentityToTry(
// is the same realm that we have a cached identity for. However if
// we use that identity, it would get sent over the wire in
// clear text (which isn't what the user agreed to when entering it).
- if (entry->handler()->scheme() != auth_handler_[target]->scheme()) {
- LOG(WARNING) << "The scheme of realm " << auth_handler_[target]->realm()
- << " has changed from " << entry->handler()->scheme()
- << " to " << auth_handler_[target]->scheme();
- return false;
+ if (entry->handler()->scheme() == auth_handler_[target]->scheme()) {
+ auth_identity_[target].source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
+ auth_identity_[target].invalid = false;
+ auth_identity_[target].username = entry->username();
+ auth_identity_[target].password = entry->password();
+ return true;
}
-
- auth_identity_[target].source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
+ LOG(WARNING) << "The scheme of realm " << auth_handler_[target]->realm()
+ << " has changed from " << entry->handler()->scheme()
+ << " to " << auth_handler_[target]->scheme();
+ // Fall through.
+ }
+
+ // Use default credentials (single sign on) if this is the first attempt
+ // at identity. Do not allow multiple times as it will infinite loop.
+ // We use default credentials after checking the auth cache so that if
+ // single sign-on doesn't work, we won't try default credentials for future
+ // transactions.
+ if (auth_handler_[target]->SupportsDefaultCredentials() &&
+ !default_credentials_used_ &&
+ CanUseDefaultCredentials(target, auth_origin)) {
+ auth_identity_[target].source = HttpAuth::IDENT_SRC_DEFAULT_CREDENTIALS;
auth_identity_[target].invalid = false;
- auth_identity_[target].username = entry->username();
- auth_identity_[target].password = entry->password();
+ default_credentials_used_ = true;
return true;
}
+
return false;
}
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index ca4e882..159f75d 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -237,6 +237,11 @@ class HttpNetworkTransaction : public HttpTransaction {
void InvalidateRejectedAuthFromCache(HttpAuth::Target target,
const GURL& auth_origin);
+ // Returns true if we can use the default credentials for the
+ // authentication.
+ bool CanUseDefaultCredentials(HttpAuth::Target target,
+ const GURL& auth_origin) const;
+
// Sets auth_identity_[target] to the next identity that the transaction
// should try. It chooses candidates by searching the auth cache
// and the URL for a username:password. Returns true if an identity
@@ -335,6 +340,10 @@ class HttpNetworkTransaction : public HttpTransaction {
// preventing an infinite auth restart loop.
bool embedded_identity_used_;
+ // True if default credentials have already been tried for this transaction
+ // in response to an HTTP authentication challenge.
+ bool default_credentials_used_;
+
SSLConfig ssl_config_;
std::string request_headers_;
diff --git a/net/http/url_security_manager.h b/net/http/url_security_manager.h
new file mode 100644
index 0000000..7309fef
--- /dev/null
+++ b/net/http/url_security_manager.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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.
+
+#ifndef NET_HTTP_URL_SECURITY_MANAGER_H_
+#define NET_HTTP_URL_SECURITY_MANAGER_H_
+
+class GURL;
+
+namespace net {
+
+// The URL security manager controls the policies (allow, deny, prompt user)
+// regarding URL actions (e.g., sending the default credentials to a server).
+//
+// On Windows, we honor the WinINet/IE settings and group policy related to
+// URL Security Zones. See the Microsoft Knowledge Base article 182569
+// "Internet Explorer security zones registry entries for advanced users"
+// (http://support.microsoft.com/kb/182569) for more info on these registry
+// keys.
+class URLSecurityManager {
+ public:
+ virtual ~URLSecurityManager() {}
+
+ // Creates a platform-dependent instance of URLSecurityManager.
+ static URLSecurityManager* Create();
+
+ // Returns true if we can send the default credentials to the server at
+ // |auth_origin| for HTTP NTLM or Negotiate authentication.
+ virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const = 0;
+};
+
+} // namespace net
+
+#endif // NET_HTTP_URL_SECURITY_MANAGER_H_
diff --git a/net/http/url_security_manager_posix.cc b/net/http/url_security_manager_posix.cc
new file mode 100644
index 0000000..84bae9f
--- /dev/null
+++ b/net/http/url_security_manager_posix.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 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/url_security_manager.h"
+
+#include "googleurl/src/gurl.h"
+
+namespace net {
+
+class URLSecurityManagerDefault : public URLSecurityManager {
+ public:
+ // URLSecurityManager methods:
+ virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const {
+ // TODO(wtc): use command-line whitelist.
+ return false;
+ }
+};
+
+// static
+URLSecurityManager* URLSecurityManager::Create() {
+ return new URLSecurityManagerDefault;
+}
+
+} // namespace net
diff --git a/net/http/url_security_manager_win.cc b/net/http/url_security_manager_win.cc
new file mode 100644
index 0000000..b3abb05
--- /dev/null
+++ b/net/http/url_security_manager_win.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 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/url_security_manager.h"
+
+#include <urlmon.h>
+#pragma comment(lib, "urlmon.lib")
+
+#include "base/scoped_comptr_win.h"
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+
+// The Windows implementation of URLSecurityManager uses WinINet/IE's
+// URL security zone manager. See the MSDN page "URL Security Zones" at
+// http://msdn.microsoft.com/en-us/library/ms537021(VS.85).aspx for more
+// info on the Internet Security Manager and Internet Zone Manager objects.
+
+namespace net {
+
+class URLSecurityManagerWin : public URLSecurityManager {
+ public:
+ URLSecurityManagerWin();
+
+ // URLSecurityManager methods:
+ virtual bool CanUseDefaultCredentials(const GURL& auth_origin) const;
+
+ private:
+ ScopedComPtr<IInternetSecurityManager> security_manager_;
+};
+
+URLSecurityManagerWin::URLSecurityManagerWin() {
+ HRESULT hr = CoInternetCreateSecurityManager(NULL,
+ security_manager_.Receive(),
+ NULL);
+ DCHECK(SUCCEEDED(hr));
+}
+
+
+bool URLSecurityManagerWin::CanUseDefaultCredentials(
+ const GURL& auth_origin) const {
+ if (!security_manager_) {
+ NOTREACHED(); // The code in the constructor failed.
+ return false;
+ }
+
+ std::wstring url_w = ASCIIToWide(auth_origin.spec());
+ DWORD policy = 0;
+ HRESULT hr;
+ hr = security_manager_->ProcessUrlAction(url_w.c_str(),
+ URLACTION_CREDENTIALS_USE,
+ reinterpret_cast<BYTE*>(&policy),
+ sizeof(policy), NULL, 0,
+ PUAF_NOUI, 0);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "IInternetSecurityManager::ProcessUrlAction failed: " << hr;
+ return false;
+ }
+
+ // Four possible policies for URLACTION_CREDENTIALS_USE. See the MSDN page
+ // "About URL Security Zones" at
+ // http://msdn.microsoft.com/en-us/library/ms537183(VS.85).aspx
+ switch (policy) {
+ case URLPOLICY_CREDENTIALS_SILENT_LOGON_OK:
+ return true;
+ case URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT: {
+ // This policy means "prompt the user for permission if the resource is
+ // not located in the Intranet zone". TODO(wtc): Note that it's
+ // prompting for permission (to use the default credentials), as opposed
+ // to prompting the user to enter a user name and password.
+
+ // URLZONE_LOCAL_MACHINE 0
+ // URLZONE_INTRANET 1
+ // URLZONE_TRUSTED 2
+ // URLZONE_INTERNET 3
+ // URLZONE_UNTRUSTED 4
+ DWORD zone = 0;
+ hr = security_manager_->MapUrlToZone(url_w.c_str(), &zone, 0);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "IInternetSecurityManager::MapUrlToZone failed: " << hr;
+ return false;
+ }
+ return zone <= URLZONE_INTRANET;
+ }
+ case URLPOLICY_CREDENTIALS_MUST_PROMPT_USER:
+ return false;
+ case URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY:
+ // TODO(wtc): we should fail the authentication.
+ return false;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+// static
+URLSecurityManager* URLSecurityManager::Create() {
+ return new URLSecurityManagerWin;
+}
+
+} // namespace net
diff --git a/net/net.gyp b/net/net.gyp
index 34e77fc..177f69f 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -365,6 +365,9 @@
'http/http_stream_parser.h',
'http/http_transaction.h',
'http/http_transaction_factory.h',
+ 'http/url_security_manager.h',
+ 'http/url_security_manager_posix.cc',
+ 'http/url_security_manager_win.cc',
'http/http_util.cc',
'http/http_util_icu.cc',
'http/http_util.h',