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

Side by Side Diff: net/http/http_auth_handler_ntlm_win.cc

Issue 173528: Use SSPI for NTLM authentication on Windows.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_auth_handler_ntlm_portable.cc ('k') | net/http/http_network_transaction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // See "SSPI Sample Application" at
6 // http://msdn.microsoft.com/en-us/library/aa918273.aspx
7 // and "NTLM Security Support Provider" at
8 // http://msdn.microsoft.com/en-us/library/aa923611.aspx.
9
10 #include "net/http/http_auth_handler_ntlm.h"
11
12 #include "base/logging.h"
13 #include "net/base/net_errors.h"
14
15 #pragma comment(lib, "secur32.lib")
16
17 namespace {
18
19 void ZapString(string16* s) {
20 memset(&(*s)[0], 0, s->length() * 2);
21 }
22
23 } // namespace
24
25 namespace net {
26
27 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() : max_token_len_(0) {
28 SecInvalidateHandle(&cred_);
29 SecInvalidateHandle(&ctxt_);
30 }
31
32 HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
33 ResetSecurityContext();
34 if (SecIsValidHandle(&cred_)) {
35 FreeCredentialsHandle(&cred_);
36 SecInvalidateHandle(&cred_);
37 }
38 ZapString(&password_);
39 }
40
41 int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
42 DCHECK_EQ("ntlm", scheme_) << "This is not ntlm scheme";
43
44 SEC_WCHAR* package = NTLMSP_NAME;
45 PSecPkgInfo pkg_info;
46 SECURITY_STATUS status;
47
48 // The following API call is required to get the maximum token length
49 // for the scheme.
50 // TODO(arindam): Move this (PSecPkgInfo) to a static function.
51 status = QuerySecurityPackageInfo(package, &pkg_info);
52 if (status != SEC_E_OK) {
53 LOG(ERROR) << "Security package " << package << " not found";
54 return ERR_UNEXPECTED;
55 }
56 max_token_len_ = pkg_info->cbMaxToken;
57 FreeContextBuffer(pkg_info);
58
59 SEC_WINNT_AUTH_IDENTITY identity;
60 identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
61 identity.User =
62 reinterpret_cast<USHORT*>(const_cast<wchar_t*>(username_.c_str()));
63 identity.UserLength = username_.size();
64 identity.Domain =
65 reinterpret_cast<USHORT*>(const_cast<wchar_t*>(domain_.c_str()));
66 identity.DomainLength = domain_.size();
67 identity.Password =
68 reinterpret_cast<USHORT*>(const_cast<wchar_t*>(password_.c_str()));
69 identity.PasswordLength = password_.size();
70
71 TimeStamp expiry; // Since the credentials handle doesn't expire, ignore
72 // the expiration time.
73
74 // Pass the username/password to get the credentials handle.
75 // Note: If the 5th argument is NULL, it uses the default cached credentials
76 // for the logged in user, which can be used for single sign-on.
77 status = AcquireCredentialsHandle(NULL, // pszPrincipal
78 package, // pszPackage
79 SECPKG_CRED_OUTBOUND, // fCredentialUse
80 NULL, // pvLogonID
81 &identity, // pAuthData
82 NULL, // pGetKeyFn (not used)
83 NULL, // pvGetKeyArgument (not used)
84 &cred_, // phCredential
85 &expiry); // ptsExpiry
86 if (status != SEC_E_OK)
87 return ERR_UNEXPECTED;
88
89 return OK;
90 }
91
92 int HttpAuthHandlerNTLM::GetNextToken(const void* in_token,
93 uint32 in_token_len,
94 void** out_token,
95 uint32* out_token_len) {
96 SECURITY_STATUS status;
97 TimeStamp expiry;
98
99 DWORD ctxt_attr;
100 CtxtHandle* ctxt_ptr;
101 SecBufferDesc in_buffer_desc, out_buffer_desc;
102 SecBufferDesc* in_buffer_desc_ptr;
103 SecBuffer in_buffer, out_buffer;
104
105 if (in_token) {
106 // Prepare input buffer.
107 in_buffer_desc.ulVersion = SECBUFFER_VERSION;
108 in_buffer_desc.cBuffers = 1;
109 in_buffer_desc.pBuffers = &in_buffer;
110 in_buffer.BufferType = SECBUFFER_TOKEN;
111 in_buffer.cbBuffer = in_token_len;
112 in_buffer.pvBuffer = const_cast<void*>(in_token);
113 ctxt_ptr = &ctxt_;
114 in_buffer_desc_ptr = &in_buffer_desc;
115 } else {
116 // If there is no input token, then we are starting a new authentication
117 // sequence. If we have already initialized our security context, then
118 // we're incorrectly reusing the auth handler for a new sequence.
119 if (SecIsValidHandle(&ctxt_)) {
120 LOG(ERROR) << "Cannot restart authentication sequence";
121 return ERR_UNEXPECTED;
122 }
123 ctxt_ptr = NULL;
124 in_buffer_desc_ptr = NULL;
125 }
126
127 // Prepare output buffer.
128 out_buffer_desc.ulVersion = SECBUFFER_VERSION;
129 out_buffer_desc.cBuffers = 1;
130 out_buffer_desc.pBuffers = &out_buffer;
131 out_buffer.BufferType = SECBUFFER_TOKEN;
132 out_buffer.cbBuffer = max_token_len_;
133 out_buffer.pvBuffer = malloc(out_buffer.cbBuffer);
134 if (!out_buffer.pvBuffer)
135 return ERR_OUT_OF_MEMORY;
136
137 // Name of the destination server. NULL for NTLM.
138 SEC_WCHAR* target = NULL;
139
140 // This returns a token that is passed to the remote server.
141 status = InitializeSecurityContext(&cred_, // phCredential
142 ctxt_ptr, // phContext
143 target, // pszTargetName
144 0, // fContextReq
145 0, // Reserved1 (must be 0)
146 SECURITY_NATIVE_DREP, // TargetDataRep
147 in_buffer_desc_ptr, // pInput
148 0, // Reserved2 (must be 0)
149 &ctxt_, // phNewContext
150 &out_buffer_desc, // pOutput
151 &ctxt_attr, // pfContextAttr
152 &expiry); // ptsExpiry
153 // On success, the function returns SEC_I_CONTINUE_NEEDED on the first call
154 // and SEC_E_OK on the second call. On failure, the function returns an
155 // error code.
156 if (status != SEC_I_CONTINUE_NEEDED && status != SEC_E_OK) {
157 LOG(ERROR) << "InitializeSecurityContext failed: " << status;
158 ResetSecurityContext();
159 free(out_buffer.pvBuffer);
160 return ERR_UNEXPECTED; // TODO(wtc): map error code.
161 }
162 if (!out_buffer.cbBuffer) {
163 free(out_buffer.pvBuffer);
164 out_buffer.pvBuffer = NULL;
165 }
166 *out_token = out_buffer.pvBuffer;
167 *out_token_len = out_buffer.cbBuffer;
168 return OK;
169 }
170
171 // Require identity on first pass instead of second.
172 bool HttpAuthHandlerNTLM::NeedsIdentity() {
173 return auth_data_.empty();
174 }
175
176 bool HttpAuthHandlerNTLM::IsFinalRound() {
177 return !auth_data_.empty();
178 }
179
180 void HttpAuthHandlerNTLM::ResetSecurityContext() {
181 if (SecIsValidHandle(&ctxt_)) {
182 DeleteSecurityContext(&ctxt_);
183 SecInvalidateHandle(&ctxt_);
184 }
185 }
186
187 } // namespace net
188
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_ntlm_portable.cc ('k') | net/http/http_network_transaction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698