diff options
author | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-21 21:38:05 +0000 |
---|---|---|
committer | cbentzel@chromium.org <cbentzel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-21 21:38:05 +0000 |
commit | 4fd4a6da1114c4df949d0bf0281b4ecbfbb73534 (patch) | |
tree | 0367c2b9f0a2f7f22185fbc69f2df6ccbee5f6e9 | |
parent | 7106ae5055a009e1ca53f0fc5ee6bb6b0c925c9f (diff) | |
download | chromium_src-4fd4a6da1114c4df949d0bf0281b4ecbfbb73534.zip chromium_src-4fd4a6da1114c4df949d0bf0281b4ecbfbb73534.tar.gz chromium_src-4fd4a6da1114c4df949d0bf0281b4ecbfbb73534.tar.bz2 |
Added WWW-Authenticate Negotate support using shared HttpAuthSspi.
BUG=29862
TEST=None
Review URL: http://codereview.chromium.org/551015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36785 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/http/http_auth.cc | 3 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate.h | 53 | ||||
-rwxr-xr-x | net/http/http_auth_handler_negotiate_posix.cc | 45 | ||||
-rw-r--r-- | net/http/http_auth_handler_negotiate_win.cc | 57 | ||||
-rwxr-xr-x[-rw-r--r--] | net/http/http_auth_handler_ntlm.cc | 20 | ||||
-rw-r--r-- | net/http/http_auth_handler_ntlm.h | 9 | ||||
-rw-r--r-- | net/http/http_auth_handler_ntlm_win.cc | 121 | ||||
-rw-r--r--[-rwxr-xr-x] | net/http/http_auth_sspi_win.cc | 209 | ||||
-rwxr-xr-x | net/http/http_auth_sspi_win.h | 47 | ||||
-rw-r--r--[-rwxr-xr-x] | net/http/http_auth_sspi_win_unittest.cc | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | net/net.gyp | 3 |
11 files changed, 441 insertions, 126 deletions
diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc index ba9b1ea..aa97640 100644 --- a/net/http/http_auth.cc +++ b/net/http/http_auth.cc @@ -10,6 +10,7 @@ #include "base/string_util.h" #include "net/http/http_auth_handler_basic.h" #include "net/http/http_auth_handler_digest.h" +#include "net/http/http_auth_handler_negotiate.h" #include "net/http/http_auth_handler_ntlm.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" @@ -67,6 +68,8 @@ void HttpAuth::CreateAuthHandler(const std::string& challenge, tmp_handler = new HttpAuthHandlerBasic(); } else if (LowerCaseEqualsASCII(props.scheme(), "digest")) { tmp_handler = new HttpAuthHandlerDigest(); + } else if (LowerCaseEqualsASCII(props.scheme(), "negotiate")) { + tmp_handler = new HttpAuthHandlerNegotiate(); } else if (LowerCaseEqualsASCII(props.scheme(), "ntlm")) { tmp_handler = new HttpAuthHandlerNTLM(); } diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h new file mode 100644 index 0000000..eb4d11f --- /dev/null +++ b/net/http/http_auth_handler_negotiate.h @@ -0,0 +1,53 @@ +// 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_HTTP_AUTH_HANDLER_NEGOTIATE_H_ +#define NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_ + +#include "build/build_config.h" + +#include <string> + +#include "net/http/http_auth_handler.h" + +#if defined(OS_WIN) +#include "net/http/http_auth_sspi_win.h" +#endif + +namespace net { + +// Handler for WWW-Authenticate: Negotiate protocol. +// +// See http://tools.ietf.org/html/rfc4178 and http://tools.ietf.org/html/rfc4559 +// for more information about the protocol. + +class HttpAuthHandlerNegotiate : public HttpAuthHandler { + public: + HttpAuthHandlerNegotiate(); + + virtual bool NeedsIdentity(); + + virtual bool IsFinalRound(); + + virtual std::string GenerateCredentials(const std::wstring& username, + const std::wstring& password, + const HttpRequestInfo* request, + const ProxyInfo* proxy); + + + protected: + virtual bool Init(std::string::const_iterator challenge_begin, + std::string::const_iterator challenge_end); + + private: + ~HttpAuthHandlerNegotiate(); + +#if defined(OS_WIN) + HttpAuthSSPI auth_sspi_; +#endif +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_ diff --git a/net/http/http_auth_handler_negotiate_posix.cc b/net/http/http_auth_handler_negotiate_posix.cc new file mode 100755 index 0000000..169689d --- /dev/null +++ b/net/http/http_auth_handler_negotiate_posix.cc @@ -0,0 +1,45 @@ +// 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/http_auth_handler_negotiate.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+// TODO(cbentzel): Negotiate authentication protocol is not supported on Posix
+// systems currently. These stubs make the main HTTP Authentication code bypass
+// Negotiate without requiring conditional compilation.
+
+HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate() {
+}
+
+HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
+}
+
+bool HttpAuthHandlerNegotiate::NeedsIdentity() {
+ NOTREACHED();
+ return false;
+}
+
+bool HttpAuthHandlerNegotiate::IsFinalRound() {
+ NOTREACHED();
+ return false;
+}
+
+bool HttpAuthHandlerNegotiate::Init(std::string::const_iterator challenge_begin,
+ std::string::const_iterator challenge_end) {
+ return false;
+}
+
+std::string HttpAuthHandlerNegotiate::GenerateCredentials(
+ const std::wstring& username,
+ const std::wstring& password,
+ const HttpRequestInfo* request,
+ const ProxyInfo* proxy) {
+ NOTREACHED();
+ return std::string();
+}
+
+} // namespace net
diff --git a/net/http/http_auth_handler_negotiate_win.cc b/net/http/http_auth_handler_negotiate_win.cc new file mode 100644 index 0000000..782cb5c --- /dev/null +++ b/net/http/http_auth_handler_negotiate_win.cc @@ -0,0 +1,57 @@ +// 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/http_auth_handler_negotiate.h" + +#include "net/base/net_errors.h" + +namespace net { + +HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate() : + auth_sspi_("Negotiate", NEGOSSP_NAME) { +} + +HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() { +} + +std::string HttpAuthHandlerNegotiate::GenerateCredentials( + const std::wstring& username, + const std::wstring& password, + const HttpRequestInfo* request, + const ProxyInfo* proxy) { + std::string auth_credentials; + + int rv = auth_sspi_.GenerateCredentials( + username, + password, + origin_, + request, + proxy, + &auth_credentials); + if (rv == OK) + return auth_credentials; + return std::string(); +} + +// The Negotiate challenge header looks like: +// WWW-Authenticate: NEGOTIATE auth-data +bool HttpAuthHandlerNegotiate::Init( + std::string::const_iterator challenge_begin, + std::string::const_iterator challenge_end) { + scheme_ = "negotiate"; + score_ = 4; + properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; + return auth_sspi_.ParseChallenge(challenge_begin, challenge_end); +} + +// Require identity on first pass instead of second. +bool HttpAuthHandlerNegotiate::NeedsIdentity() { + return auth_sspi_.NeedsIdentity(); +} + +bool HttpAuthHandlerNegotiate::IsFinalRound() { + return auth_sspi_.IsFinalRound(); +} + +} // namespace net diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc index 3dcf9b4..6e10e79 100644..100755 --- a/net/http/http_auth_handler_ntlm.cc +++ b/net/http/http_auth_handler_ntlm.cc @@ -15,6 +15,20 @@ std::string HttpAuthHandlerNTLM::GenerateCredentials( const std::wstring& password, const HttpRequestInfo* request, const ProxyInfo* proxy) { +#if defined(NTLM_SSPI) + std::string auth_credentials; + + int rv = auth_sspi_.GenerateCredentials( + username, + password, + origin_, + request, + proxy, + &auth_credentials); + if (rv == OK) + return auth_credentials; + return std::string(); +#else // !defined(NTLM_SSPI) // TODO(wtc): See if we can use char* instead of void* for in_buf and // out_buf. This change will need to propagate to GetNextToken, // GenerateType1Msg, and GenerateType3Msg, and perhaps further. @@ -76,6 +90,7 @@ std::string HttpAuthHandlerNTLM::GenerateCredentials( if (!ok) return std::string(); return std::string("NTLM ") + encode_output; +#endif } // The NTLM challenge header looks like: @@ -86,6 +101,10 @@ bool HttpAuthHandlerNTLM::ParseChallenge( scheme_ = "ntlm"; score_ = 3; properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; + +#if defined(NTLM_SSPI) + return auth_sspi_.ParseChallenge(challenge_begin, challenge_end); +#else auth_data_.clear(); // Verify the challenge's auth-scheme. @@ -103,6 +122,7 @@ bool HttpAuthHandlerNTLM::ParseChallenge( auth_data_.assign(challenge_begin, challenge_end); return true; +#endif } } // namespace net diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h index ca2b234..c3bda62 100644 --- a/net/http/http_auth_handler_ntlm.h +++ b/net/http/http_auth_handler_ntlm.h @@ -19,6 +19,7 @@ #define SECURITY_WIN32 1 #include <windows.h> #include <security.h> +#include "net/http/http_auth_sspi_win.h" #endif #include <string> @@ -105,7 +106,7 @@ class HttpAuthHandlerNTLM : public HttpAuthHandler { uint32* out_token_len); #if defined(NTLM_SSPI) - void ResetSecurityContext(); + HttpAuthSSPI auth_sspi_; #endif #if defined(NTLM_PORTABLE) @@ -120,12 +121,6 @@ class HttpAuthHandlerNTLM : public HttpAuthHandler { // The base64-encoded string following "NTLM" in the "WWW-Authenticate" or // "Proxy-Authenticate" response header. std::string auth_data_; - -#if defined(NTLM_SSPI) - ULONG max_token_len_; - CredHandle cred_; - CtxtHandle ctxt_; -#endif }; } // namespace net diff --git a/net/http/http_auth_handler_ntlm_win.cc b/net/http/http_auth_handler_ntlm_win.cc index 0f40236..fba9c1b 100644 --- a/net/http/http_auth_handler_ntlm_win.cc +++ b/net/http/http_auth_handler_ntlm_win.cc @@ -17,138 +17,23 @@ #pragma comment(lib, "secur32.lib") -namespace { - -void ZapString(string16* s) { - memset(&(*s)[0], 0, s->length() * 2); -} - -} // namespace - namespace net { -HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() : max_token_len_(0) { - SecInvalidateHandle(&cred_); - SecInvalidateHandle(&ctxt_); +HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() : auth_sspi_("NTLM", NTLMSP_NAME) { } HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() { - ResetSecurityContext(); - if (SecIsValidHandle(&cred_)) { - FreeCredentialsHandle(&cred_); - SecInvalidateHandle(&cred_); - } - ZapString(&password_); -} - -int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() { - DCHECK_EQ("ntlm", scheme_) << "This is not ntlm scheme"; - - int rv = DetermineMaxTokenLength(NTLMSP_NAME, &max_token_len_); - if (rv != OK) { - return rv; - } - rv = AcquireCredentials(NTLMSP_NAME, domain_, username_, password_, &cred_); - return rv; -} - -int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, - uint32 in_token_len, - void** out_token, - uint32* out_token_len) { - SECURITY_STATUS status; - TimeStamp expiry; - - DWORD ctxt_attr; - CtxtHandle* ctxt_ptr; - SecBufferDesc in_buffer_desc, out_buffer_desc; - SecBufferDesc* in_buffer_desc_ptr; - SecBuffer in_buffer, out_buffer; - - if (in_token) { - // Prepare input buffer. - in_buffer_desc.ulVersion = SECBUFFER_VERSION; - in_buffer_desc.cBuffers = 1; - in_buffer_desc.pBuffers = &in_buffer; - in_buffer.BufferType = SECBUFFER_TOKEN; - in_buffer.cbBuffer = in_token_len; - in_buffer.pvBuffer = const_cast<void*>(in_token); - ctxt_ptr = &ctxt_; - in_buffer_desc_ptr = &in_buffer_desc; - } else { - // If there is no input token, then we are starting a new authentication - // sequence. If we have already initialized our security context, then - // we're incorrectly reusing the auth handler for a new sequence. - if (SecIsValidHandle(&ctxt_)) { - LOG(ERROR) << "Cannot restart authentication sequence"; - return ERR_UNEXPECTED; - } - ctxt_ptr = NULL; - in_buffer_desc_ptr = NULL; - } - - // Prepare output buffer. - out_buffer_desc.ulVersion = SECBUFFER_VERSION; - out_buffer_desc.cBuffers = 1; - out_buffer_desc.pBuffers = &out_buffer; - out_buffer.BufferType = SECBUFFER_TOKEN; - out_buffer.cbBuffer = max_token_len_; - out_buffer.pvBuffer = malloc(out_buffer.cbBuffer); - if (!out_buffer.pvBuffer) - return ERR_OUT_OF_MEMORY; - - // The service principal name of the destination server. See - // http://msdn.microsoft.com/en-us/library/ms677949%28VS.85%29.aspx - std::wstring target(L"HTTP/"); - target.append(ASCIIToWide(GetHostAndPort(origin_))); - wchar_t* target_name = const_cast<wchar_t*>(target.c_str()); - - // This returns a token that is passed to the remote server. - status = InitializeSecurityContext(&cred_, // phCredential - ctxt_ptr, // phContext - target_name, // pszTargetName - 0, // fContextReq - 0, // Reserved1 (must be 0) - SECURITY_NATIVE_DREP, // TargetDataRep - in_buffer_desc_ptr, // pInput - 0, // Reserved2 (must be 0) - &ctxt_, // phNewContext - &out_buffer_desc, // pOutput - &ctxt_attr, // pfContextAttr - &expiry); // ptsExpiry - // On success, the function returns SEC_I_CONTINUE_NEEDED on the first call - // and SEC_E_OK on the second call. On failure, the function returns an - // error code. - if (status != SEC_I_CONTINUE_NEEDED && status != SEC_E_OK) { - LOG(ERROR) << "InitializeSecurityContext failed: " << status; - ResetSecurityContext(); - free(out_buffer.pvBuffer); - return ERR_UNEXPECTED; // TODO(wtc): map error code. - } - if (!out_buffer.cbBuffer) { - free(out_buffer.pvBuffer); - out_buffer.pvBuffer = NULL; - } - *out_token = out_buffer.pvBuffer; - *out_token_len = out_buffer.cbBuffer; - return OK; } // Require identity on first pass instead of second. bool HttpAuthHandlerNTLM::NeedsIdentity() { - return auth_data_.empty(); + return auth_sspi_.NeedsIdentity(); } bool HttpAuthHandlerNTLM::IsFinalRound() { - return !auth_data_.empty(); + return auth_sspi_.IsFinalRound(); } -void HttpAuthHandlerNTLM::ResetSecurityContext() { - if (SecIsValidHandle(&ctxt_)) { - DeleteSecurityContext(&ctxt_); - SecInvalidateHandle(&ctxt_); - } -} } // namespace net diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc index ff3ec82..00861e5 100755..100644 --- a/net/http/http_auth_sspi_win.cc +++ b/net/http/http_auth_sspi_win.cc @@ -2,13 +2,222 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// See "SSPI Sample Application" at +// http://msdn.microsoft.com/en-us/library/aa918273.aspx + #include "net/http/http_auth_sspi_win.h" +#include "base/base64.h" #include "base/logging.h" +#include "base/string_util.h" #include "net/base/net_errors.h" +#include "net/base/net_util.h" +#include "net/http/http_auth.h" namespace net { +HttpAuthSSPI::HttpAuthSSPI(const std::string& scheme, + SEC_WCHAR* security_package) + : scheme_(scheme), + security_package_(security_package), + max_token_length_(0) { + SecInvalidateHandle(&cred_); + SecInvalidateHandle(&ctxt_); +} + +HttpAuthSSPI::~HttpAuthSSPI() { + ResetSecurityContext(); + if (SecIsValidHandle(&cred_)) { + FreeCredentialsHandle(&cred_); + SecInvalidateHandle(&cred_); + } +} + +bool HttpAuthSSPI::NeedsIdentity() const { + return decoded_server_auth_token_.empty(); +} + +bool HttpAuthSSPI::IsFinalRound() const { + return !decoded_server_auth_token_.empty(); +} + +void HttpAuthSSPI::ResetSecurityContext() { + if (SecIsValidHandle(&ctxt_)) { + DeleteSecurityContext(&ctxt_); + SecInvalidateHandle(&ctxt_); + } +} + +bool HttpAuthSSPI::ParseChallenge(std::string::const_iterator challenge_begin, + std::string::const_iterator challenge_end) { + // Verify the challenge's auth-scheme. + HttpAuth::ChallengeTokenizer challenge_tok(challenge_begin, challenge_end); + if (!challenge_tok.valid() || + !LowerCaseEqualsASCII(challenge_tok.scheme(), + StringToLowerASCII(scheme_).c_str())) + return false; + // Extract the auth-data. We can't use challenge_tok.GetNext() because + // auth-data is base64-encoded and may contain '=' padding at the end, + // which would be mistaken for a name=value pair. + challenge_begin += scheme_.length(); // Skip over scheme name. + HttpUtil::TrimLWS(&challenge_begin, &challenge_end); + std::string encoded_auth_token(challenge_begin, challenge_end); + int encoded_length = encoded_auth_token.length(); + // Strip off any padding. + // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.) + // + // Our base64 decoder requires that the length be a multiple of 4. + while (encoded_length > 0 && encoded_length % 4 != 0 && + encoded_auth_token[encoded_length - 1] == '=') + encoded_length--; + encoded_auth_token.erase(encoded_length); + + std::string decoded_auth_token; + bool rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token); + if (rv) { + decoded_server_auth_token_ = decoded_auth_token; + } + return rv; +} + +int HttpAuthSSPI::GenerateCredentials(const std::wstring& username, + const std::wstring& password, + const GURL& origin, + const HttpRequestInfo* request, + const ProxyInfo* proxy, + std::string* out_credentials) { + // |username| may be in the form "DOMAIN\user". Parse it into the two + // components. + std::wstring domain; + std::wstring user; + SplitDomainAndUser(username, &domain, &user); + + // Initial challenge. + if (!IsFinalRound()) { + int rv = OnFirstRound(domain, user, password); + if (rv != OK) + return rv; + } + + void* out_buf; + int out_buf_len; + int rv = GetNextSecurityToken( + origin, + static_cast<void *>(const_cast<char *>( + decoded_server_auth_token_.c_str())), + decoded_server_auth_token_.length(), + &out_buf, + &out_buf_len); + if (rv != OK) + return rv; + + // Base64 encode data in output buffer and prepend the scheme. + std::string encode_input(static_cast<char*>(out_buf), out_buf_len); + std::string encode_output; + bool ok = base::Base64Encode(encode_input, &encode_output); + // OK, we are done with |out_buf| + free(out_buf); + if (!ok) + return rv; + *out_credentials = scheme_ + " " + encode_output; + return OK; +} + +int HttpAuthSSPI::OnFirstRound(const std::wstring& domain, + const std::wstring& user, + const std::wstring& password) { + int rv = DetermineMaxTokenLength(security_package_, &max_token_length_); + if (rv != OK) { + return rv; + } + rv = AcquireCredentials(security_package_, domain, user, password, &cred_); + return rv; +} + +int HttpAuthSSPI::GetNextSecurityToken( + const GURL& origin, + const void * in_token, + int in_token_len, + void** out_token, + int* out_token_len) { + SECURITY_STATUS status; + TimeStamp expiry; + + DWORD ctxt_attr; + CtxtHandle* ctxt_ptr; + SecBufferDesc in_buffer_desc, out_buffer_desc; + SecBufferDesc* in_buffer_desc_ptr; + SecBuffer in_buffer, out_buffer; + + if (in_token_len > 0) { + // Prepare input buffer. + in_buffer_desc.ulVersion = SECBUFFER_VERSION; + in_buffer_desc.cBuffers = 1; + in_buffer_desc.pBuffers = &in_buffer; + in_buffer.BufferType = SECBUFFER_TOKEN; + in_buffer.cbBuffer = in_token_len; + in_buffer.pvBuffer = const_cast<void*>(in_token); + ctxt_ptr = &ctxt_; + in_buffer_desc_ptr = &in_buffer_desc; + } else { + // If there is no input token, then we are starting a new authentication + // sequence. If we have already initialized our security context, then + // we're incorrectly reusing the auth handler for a new sequence. + if (SecIsValidHandle(&ctxt_)) { + LOG(ERROR) << "Cannot restart authentication sequence"; + return ERR_UNEXPECTED; + } + ctxt_ptr = NULL; + in_buffer_desc_ptr = NULL; + } + + // Prepare output buffer. + out_buffer_desc.ulVersion = SECBUFFER_VERSION; + out_buffer_desc.cBuffers = 1; + out_buffer_desc.pBuffers = &out_buffer; + out_buffer.BufferType = SECBUFFER_TOKEN; + out_buffer.cbBuffer = max_token_length_; + out_buffer.pvBuffer = malloc(out_buffer.cbBuffer); + if (!out_buffer.pvBuffer) + return ERR_OUT_OF_MEMORY; + + // The service principal name of the destination server. See + // http://msdn.microsoft.com/en-us/library/ms677949%28VS.85%29.aspx + std::wstring target(L"HTTP/"); + target.append(ASCIIToWide(GetHostAndPort(origin))); + wchar_t* target_name = const_cast<wchar_t*>(target.c_str()); + + // This returns a token that is passed to the remote server. + status = InitializeSecurityContext(&cred_, // phCredential + ctxt_ptr, // phContext + target_name, // pszTargetName + 0, // fContextReq + 0, // Reserved1 (must be 0) + SECURITY_NATIVE_DREP, // TargetDataRep + in_buffer_desc_ptr, // pInput + 0, // Reserved2 (must be 0) + &ctxt_, // phNewContext + &out_buffer_desc, // pOutput + &ctxt_attr, // pfContextAttr + &expiry); // ptsExpiry + // On success, the function returns SEC_I_CONTINUE_NEEDED on the first call + // and SEC_E_OK on the second call. On failure, the function returns an + // error code. + if (status != SEC_I_CONTINUE_NEEDED && status != SEC_E_OK) { + LOG(ERROR) << "InitializeSecurityContext failed: " << status; + ResetSecurityContext(); + free(out_buffer.pvBuffer); + return ERR_UNEXPECTED; // TODO(wtc): map error code. + } + if (!out_buffer.cbBuffer) { + free(out_buffer.pvBuffer); + out_buffer.pvBuffer = NULL; + } + *out_token = out_buffer.pvBuffer; + *out_token_len = out_buffer.cbBuffer; + return OK; +} + void SplitDomainAndUser(const std::wstring& combined, std::wstring* domain, std::wstring* user) { diff --git a/net/http/http_auth_sspi_win.h b/net/http/http_auth_sspi_win.h index d58678b..4d340aa 100755 --- a/net/http/http_auth_sspi_win.h +++ b/net/http/http_auth_sspi_win.h @@ -16,8 +16,53 @@ #include <string> +class GURL; + namespace net { +class HttpRequestInfo; +class ProxyInfo; + +class HttpAuthSSPI { + public: + HttpAuthSSPI(const std::string& scheme, + SEC_WCHAR* security_package); + ~HttpAuthSSPI(); + + bool NeedsIdentity() const; + bool IsFinalRound() const; + + bool ParseChallenge(std::string::const_iterator challenge_begin, + std::string::const_iterator challenge_end); + + int GenerateCredentials(const std::wstring& username, + const std::wstring& password, + const GURL& origin, + const HttpRequestInfo* request, + const ProxyInfo* proxy, + std::string* out_credentials); + + private: + int OnFirstRound(const std::wstring& domain, + const std::wstring& user, + const std::wstring& password); + + int GetNextSecurityToken( + const GURL& origin, + const void* in_token, + int in_token_len, + void** out_token, + int* out_token_len); + + void ResetSecurityContext(); + std::string scheme_; + SEC_WCHAR* security_package_; + std::string decoded_server_auth_token_; + ULONG max_token_length_; + CredHandle cred_; + CtxtHandle ctxt_; +}; + // Splits |combined| into domain and username. // If |combined| is of form "FOO\bar", |domain| will contain "FOO" and |user| // will contain "bar". @@ -41,7 +86,7 @@ int AcquireCredentials(const SEC_WCHAR* package, const std::wstring& user, const std::wstring& password, CredHandle* cred); -} // namespace net +} // 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 index b421ca9..b421ca9 100755..100644 --- a/net/http/http_auth_sspi_win_unittest.cc +++ b/net/http/http_auth_sspi_win_unittest.cc diff --git a/net/net.gyp b/net/net.gyp index 3812e11..f16ebab 100644..100755 --- a/net/net.gyp +++ b/net/net.gyp @@ -336,6 +336,9 @@ 'http/http_auth_handler_basic.h', 'http/http_auth_handler_digest.cc', 'http/http_auth_handler_digest.h', + 'http/http_auth_handler_negotiate.h', + 'http/http_auth_handler_negotiate_posix.cc', + 'http/http_auth_handler_negotiate_win.cc', 'http/http_auth_handler_ntlm.cc', 'http/http_auth_handler_ntlm.h', 'http/http_auth_handler_ntlm_portable.cc', |