diff options
author | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 14:56:56 +0000 |
---|---|---|
committer | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 14:56:56 +0000 |
commit | 7da0b3399c137070e5e5b9403428c98f52b9e2c5 (patch) | |
tree | 44045ed03614d156f9cc49f9404a3f0820d67d8b /net/http | |
parent | 50ada2e97cc6f1c1e0f1bf7ee33ff64a0d28d79a (diff) | |
download | chromium_src-7da0b3399c137070e5e5b9403428c98f52b9e2c5.zip chromium_src-7da0b3399c137070e5e5b9403428c98f52b9e2c5.tar.gz chromium_src-7da0b3399c137070e5e5b9403428c98f52b9e2c5.tar.bz2 |
Abstracted and moved common SSPI functionality.
The NTLM and Negotiate authentication schemes follow very similar code paths when using the SSPI API on Windows.
BUG=29862
TEST=New unittest, plus manual NTLM Authentication testing.
Review URL: http://codereview.chromium.org/505048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35791 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_auth_handler_ntlm_win.cc | 51 | ||||
-rwxr-xr-x | net/http/http_auth_sspi_win.cc | 77 | ||||
-rwxr-xr-x | net/http/http_auth_sspi_win.h | 47 | ||||
-rwxr-xr-x | net/http/http_auth_sspi_win_unittest.cc | 26 |
4 files changed, 156 insertions, 45 deletions
diff --git a/net/http/http_auth_handler_ntlm_win.cc b/net/http/http_auth_handler_ntlm_win.cc index 7970740..0f40236 100644 --- a/net/http/http_auth_handler_ntlm_win.cc +++ b/net/http/http_auth_handler_ntlm_win.cc @@ -13,6 +13,7 @@ #include "base/string_util.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" +#include "net/http/http_auth_sspi_win.h" #pragma comment(lib, "secur32.lib") @@ -43,52 +44,12 @@ HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() { int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() { DCHECK_EQ("ntlm", scheme_) << "This is not ntlm scheme"; - SEC_WCHAR* package = NTLMSP_NAME; - PSecPkgInfo pkg_info; - SECURITY_STATUS status; - - // The following API call is required to get the maximum token length - // for the scheme. - // TODO(arindam): Move this (PSecPkgInfo) to a static function. - status = QuerySecurityPackageInfo(package, &pkg_info); - if (status != SEC_E_OK) { - LOG(ERROR) << "Security package " << package << " not found"; - return ERR_UNEXPECTED; + int rv = DetermineMaxTokenLength(NTLMSP_NAME, &max_token_len_); + if (rv != OK) { + return rv; } - max_token_len_ = pkg_info->cbMaxToken; - FreeContextBuffer(pkg_info); - - SEC_WINNT_AUTH_IDENTITY identity; - identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - identity.User = - reinterpret_cast<USHORT*>(const_cast<wchar_t*>(username_.c_str())); - identity.UserLength = username_.size(); - identity.Domain = - reinterpret_cast<USHORT*>(const_cast<wchar_t*>(domain_.c_str())); - identity.DomainLength = domain_.size(); - identity.Password = - reinterpret_cast<USHORT*>(const_cast<wchar_t*>(password_.c_str())); - identity.PasswordLength = password_.size(); - - TimeStamp expiry; // Since the credentials handle doesn't expire, ignore - // the expiration time. - - // Pass the username/password to get the credentials handle. - // Note: If the 5th argument is NULL, it uses the default cached credentials - // for the logged in user, which can be used for single sign-on. - status = AcquireCredentialsHandle(NULL, // pszPrincipal - package, // pszPackage - SECPKG_CRED_OUTBOUND, // fCredentialUse - NULL, // pvLogonID - &identity, // pAuthData - NULL, // pGetKeyFn (not used) - NULL, // pvGetKeyArgument (not used) - &cred_, // phCredential - &expiry); // ptsExpiry - if (status != SEC_E_OK) - return ERR_UNEXPECTED; - - return OK; + rv = AcquireCredentials(NTLMSP_NAME, domain_, username_, password_, &cred_); + return rv; } int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc new file mode 100755 index 0000000..ff3ec82 --- /dev/null +++ b/net/http/http_auth_sspi_win.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2009 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_sspi_win.h" + +#include "base/logging.h" +#include "net/base/net_errors.h" + +namespace net { + +void SplitDomainAndUser(const std::wstring& combined, + std::wstring* domain, + std::wstring* user) { + size_t backslash_idx = combined.find(L'\\'); + if (backslash_idx == std::wstring::npos) { + domain->clear(); + *user = combined; + } else { + *domain = combined.substr(0, backslash_idx); + *user = combined.substr(backslash_idx + 1); + } +} + +int DetermineMaxTokenLength(const std::wstring& package, + ULONG* max_token_length) { + PSecPkgInfo pkg_info; + SECURITY_STATUS status = QuerySecurityPackageInfo( + const_cast<wchar_t *>(package.c_str()), &pkg_info); + if (status != SEC_E_OK) { + LOG(ERROR) << "Security package " << package << " not found"; + return ERR_UNEXPECTED; + } + *max_token_length = pkg_info->cbMaxToken; + FreeContextBuffer(pkg_info); + return OK; +} + +int AcquireCredentials(const SEC_WCHAR* package, + const std::wstring& domain, + const std::wstring& user, + const std::wstring& password, + CredHandle* cred) { + SEC_WINNT_AUTH_IDENTITY identity; + identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + identity.User = + reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(user.c_str())); + identity.UserLength = user.size(); + identity.Domain = + reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(domain.c_str())); + identity.DomainLength = domain.size(); + identity.Password = + reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(password.c_str())); + identity.PasswordLength = password.size(); + + TimeStamp expiry; + + // Pass the username/password to get the credentials handle. + // Note: If the 5th argument is NULL, it uses the default cached credentials + // for the logged in user, which can be used for single sign-on. + SECURITY_STATUS status = AcquireCredentialsHandle( + NULL, // pszPrincipal + const_cast<SEC_WCHAR*>(package), // pszPackage + SECPKG_CRED_OUTBOUND, // fCredentialUse + NULL, // pvLogonID + &identity, // pAuthData + NULL, // pGetKeyFn (not used) + NULL, // pvGetKeyArgument (not used) + cred, // phCredential + &expiry); // ptsExpiry + + if (status != SEC_E_OK) + return ERR_UNEXPECTED; + return OK; +} + +} // namespace net diff --git a/net/http/http_auth_sspi_win.h b/net/http/http_auth_sspi_win.h new file mode 100755 index 0000000..d58678b --- /dev/null +++ b/net/http/http_auth_sspi_win.h @@ -0,0 +1,47 @@ +// Copyright (c) 2009 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. + +// This file contains common routines used by NTLM and Negotiate authentication +// using the SSPI API on Windows. + +#ifndef NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ +#define NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ + +// security.h needs to be included for CredHandle. Unfortunately CredHandle +// is a typedef and can't be forward declared. +#define SECURITY_WIN32 1 +#include <windows.h> +#include <security.h> + +#include <string> + +namespace net { + +// Splits |combined| into domain and username. +// If |combined| is of form "FOO\bar", |domain| will contain "FOO" and |user| +// will contain "bar". +// If |combined| is of form "bar", |domain| will be empty and |user| will +// contain "bar". +// |domain| and |user| must be non-NULL. +void SplitDomainAndUser(const std::wstring& combined, + std::wstring* domain, + std::wstring* user); + +// Determines the max token length for a particular SSPI package. +// If the return value is not OK, than the value of max_token_length +// is undefined. +// |max_token_length| must be non-NULL. +int DetermineMaxTokenLength(const std::wstring& package, + ULONG* max_token_length); + +// Acquire credentials for a user. +int AcquireCredentials(const SEC_WCHAR* package, + const std::wstring& domain, + const std::wstring& user, + const std::wstring& password, + CredHandle* cred); +} // namespace net + +#endif // NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ + diff --git a/net/http/http_auth_sspi_win_unittest.cc b/net/http/http_auth_sspi_win_unittest.cc new file mode 100755 index 0000000..b421ca9 --- /dev/null +++ b/net/http/http_auth_sspi_win_unittest.cc @@ -0,0 +1,26 @@ +// Copyright (c) 2009 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 "base/basictypes.h" +#include "net/http/http_auth_sspi_win.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +void MatchDomainUserAfterSplit(const std::wstring& combined, + const std::wstring& expected_domain, + const std::wstring& expected_user) { + std::wstring actual_domain; + std::wstring actual_user; + SplitDomainAndUser(combined, &actual_domain, &actual_user); + EXPECT_EQ(expected_domain, actual_domain); + EXPECT_EQ(expected_user, actual_user); +} + +TEST(HttpAuthHandlerSspiWinTest, SplitUserAndDomain) { + MatchDomainUserAfterSplit(L"foobar", L"", L"foobar"); + MatchDomainUserAfterSplit(L"FOO\\bar", L"FOO", L"bar"); +} + +} // namespace net |