| Index: net/http/http_auth_handler_ntlm_win.cc
|
| ===================================================================
|
| --- net/http/http_auth_handler_ntlm_win.cc (revision 0)
|
| +++ net/http/http_auth_handler_ntlm_win.cc (revision 0)
|
| @@ -0,0 +1,192 @@
|
| +// 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_handler_ntlm.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "net/base/net_errors.h"
|
| +
|
| +#if !defined(NDEBUG)
|
| +#define CASE_(_x) case _x: return # _x;
|
| +static const char *MapErrorCode(int rc) {
|
| + switch (rc) {
|
| + CASE_(SEC_E_OK)
|
| + CASE_(SEC_I_CONTINUE_NEEDED)
|
| + CASE_(SEC_I_COMPLETE_NEEDED)
|
| + CASE_(SEC_I_COMPLETE_AND_CONTINUE)
|
| + CASE_(SEC_E_INCOMPLETE_MESSAGE)
|
| + CASE_(SEC_I_INCOMPLETE_CREDENTIALS)
|
| + CASE_(SEC_E_INVALID_HANDLE)
|
| + CASE_(SEC_E_TARGET_UNKNOWN)
|
| + CASE_(SEC_E_LOGON_DENIED)
|
| + CASE_(SEC_E_INTERNAL_ERROR)
|
| + CASE_(SEC_E_NO_CREDENTIALS)
|
| + CASE_(SEC_E_NO_AUTHENTICATING_AUTHORITY)
|
| + CASE_(SEC_E_INSUFFICIENT_MEMORY)
|
| + CASE_(SEC_E_INVALID_TOKEN)
|
| + }
|
| + return "<unknown>";
|
| +}
|
| +#else
|
| +#define MapErrorCode(x) (x)
|
| +#endif
|
| +
|
| +namespace net {
|
| +
|
| +HttpAuthHandlerNTLM::HttpAuthHandlerNTLM()
|
| + : max_token_len_(0) {
|
| + memset(&cred_, 0, sizeof(cred_));
|
| + memset(&ctxt_, 0, sizeof(ctxt_));
|
| +}
|
| +
|
| +HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
|
| + ResetSecurityContext();
|
| + if (cred_.dwLower || cred_.dwUpper) {
|
| + FreeCredentialHandle(&cred_);
|
| + memset(&cred_, 0, sizeof(cred_));
|
| + }
|
| + ZapString(&password_);
|
| +}
|
| +
|
| +int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
|
| + DCHECK_EQ("ntlm", scheme_) << "This is not ntlm scheme";
|
| +
|
| + SEC_WCHAR *package = L"NTLM";
|
| + PSecPkgInfo pinfo;
|
| + TimeStamp use_before;
|
| + SECURITY_STATUS rc;
|
| +
|
| + // The following API call is required to get the maximum token length
|
| + // for the scheme.
|
| + // TODO(arindam): Can we move this (PSecPkgInfo) to a static function ?
|
| + rc = QuerySecurityPackageInfo(package, &pinfo);
|
| + if (rc != SEC_E_OK) {
|
| + LOG(ERROR) << package << " not found";
|
| + return ERR_UNEXPECTED;
|
| + }
|
| + max_token_len_ = pinfo->cbMaxToken;
|
| + FreeContextBuffer(pinfo);
|
| +
|
| + SEC_WINNT_AUTH_IDENTITY identity;
|
| + identity.Domain =
|
| + reinterpret_cast<USHORT*>(const_cast<wchar_t*>(domain_.data()));
|
| + identity.DomainLength = domain_.size();
|
| + identity.User =
|
| + reinterpret_cast<USHORT*>(const_cast<wchar_t*>(username_.data()));
|
| + identity.UserLength = username_.size();
|
| + identity.Password =
|
| + reinterpret_cast<USHORT*>(const_cast<wchar_t*>(password_.data()));
|
| + identity.PasswordLength = password_.size();
|
| + identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
| +
|
| + LOG(ERROR) << "Calling Acquire Creds Handle";
|
| +
|
| + // Pass the username/password to get the credentials.
|
| + // Note: If params 1 and 5 are NULL, it gets the credentials for the
|
| + // logged in user which can be used for single sign-on.
|
| + rc = AcquireCredentialsHandle(const_cast<wchar_t*>(username_.c_str()),
|
| + package, // pszPackage
|
| + SECPKG_CRED_OUTBOUND, // fCredentialUse
|
| + NULL, // pvLogonID
|
| + &identity, // pAuthData (login information)
|
| + NULL, // pGetKeyFn (always NULL)
|
| + NULL, // pvGetKeyArgument (always NULL)
|
| + &cred_, // phCredential
|
| + &use_before); // ptsExpiry
|
| + if (rc != SEC_E_OK)
|
| + return ERR_UNEXPECTED;
|
| +
|
| + return OK;
|
| +}
|
| +
|
| +int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
|
| + uint32 in_token_len,
|
| + void** out_token,
|
| + uint32* out_token_len) {
|
| + SECURITY_STATUS rc;
|
| + TimeStamp ignored;
|
| +
|
| + DWORD ctx_attr, ctx_req = 0;
|
| + CtxtHandle *ctx_in;
|
| + SecBufferDesc ibd, obd;
|
| + SecBuffer ib, ob;
|
| +
|
| + if (in_token) {
|
| + ib.BufferType = SECBUFFER_TOKEN;
|
| + ib.cbBuffer = in_token_len;
|
| + ib.pvBuffer = const_cast<void*>(in_token);
|
| + ibd.ulVersion = SECBUFFER_VERSION;
|
| + ibd.cBuffers = 1;
|
| + ibd.pBuffers = &ib;
|
| + ctx_in = &ctxt_;
|
| + } 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 in trouble because it means that the
|
| + // first sequence failed. We need to bail or else we might end up in
|
| + // an infinite loop.
|
| + if (ctxt_.dwLower || ctxt_.dwUpper) {
|
| + LOG(ERROR) <<"Cannot restart authentication sequence";
|
| + return ERR_INVALID_RESPONSE;
|
| + }
|
| + ctx_in = NULL;
|
| + }
|
| +
|
| + obd.ulVersion = SECBUFFER_VERSION;
|
| + obd.cBuffers = 1;
|
| + obd.pBuffers = &ob;
|
| + ob.BufferType = SECBUFFER_TOKEN;
|
| + ob.cbBuffer = max_token_len_;
|
| + ob.pvBuffer = malloc(ob.cbBuffer);
|
| + if (!ob.pvBuffer)
|
| + return ERR_UNEXPECTED;
|
| + memset(ob.pvBuffer, 0, ob.cbBuffer);
|
| +
|
| + SEC_WCHAR *sn = NULL; // Package is NTLM.
|
| +
|
| + LOG(ERROR) << "Sending Another Token";
|
| +
|
| + // This returns a token that is passed to the remote server.
|
| + rc = InitializeSecurityContext(&cred_, // phCredential
|
| + ctx_in, // phContext (NULL on first call)
|
| + sn, // pszTargetName
|
| + ctx_req, // fContextReq
|
| + 0, // reserved NULL
|
| + SECURITY_NATIVE_DREP, // TargetDataRep
|
| + in_token ? &ibd : NULL, // pInput
|
| + 0, // reserved NULl
|
| + &ctxt_, // phNewContext
|
| + &obd, // pOutput
|
| + &ctx_attr, // pfContextAttr
|
| + &ignored); // ptsExpiry
|
| + if (rc == SEC_I_CONTINUE_NEEDED || rc == SEC_E_OK) {
|
| + if (!ob.cbBuffer) {
|
| + free(ob.pvBuffer);
|
| + ob.pvBuffer = NULL;
|
| + }
|
| + *out_token = ob.pvBuffer;
|
| + *out_token_len = ob.cbBuffer;
|
| + return OK;
|
| + } else {
|
| + LOG(ERROR) << "InitializeSecurityContext failed " << MapErrorCode(rc);
|
| + ResetSecurityContext();
|
| + free(ob.pvBuffer);
|
| + return ERR_UNEXPECTED;
|
| + }
|
| +}
|
| +
|
| +// Require identity on first pass instead of second.
|
| +bool HttpAuthHandlerNTLM::NeedsIdentity() {
|
| + return !auth_data_.empty();
|
| +}
|
| +
|
| +void HttpAuthHandlerNTLM::ResetSecurityContext() {
|
| + if (ctxt_.dwLower || ctxt_.dwUpper) {
|
| + DeleteSecurityContext(&ctxt_);
|
| + memset(&ctxt_, 0, sizeof(ctxt_));
|
| + }
|
| +}
|
| +
|
| +} // namespace net
|
| +
|
|
|
| Property changes on: net\http\http_auth_handler_ntlm_win.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|