ReactOS 0.4.15-dev-7958-gcd0bb1a
ntlm.c
Go to the documentation of this file.
1/*
2 * Copyright 2005, 2006 Kai Blin
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 * This file implements the NTLM security provider.
19 */
20
21#include "precomp.h"
22
23#include <assert.h>
24#include <stdio.h>
25#include <wincred.h>
26#include <lm.h>
27
28#include "hmac_md5.h"
29
30#include <wine/unicode.h>
31#include <wine/debug.h>
34
35#define NTLM_MAX_BUF 1904
36#define MIN_NTLM_AUTH_MAJOR_VERSION 3
37#define MIN_NTLM_AUTH_MINOR_VERSION 0
38#ifndef __REACTOS__
39#define MIN_NTLM_AUTH_MICRO_VERSION 25
40#else
41#define MIN_NTLM_AUTH_MICRO_VERSION 23
42#endif
43
44static CHAR ntlm_auth[] = "ntlm_auth";
45
46/***********************************************************************
47 * QueryCredentialsAttributesA
48 */
50 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
51{
53
54 TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
55
56 if(ulAttribute == SECPKG_ATTR_NAMES)
57 {
58 FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
60 }
61 else
63
64 return ret;
65}
66
67/***********************************************************************
68 * QueryCredentialsAttributesW
69 */
71 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
72{
74
75 TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
76
77 if(ulAttribute == SECPKG_ATTR_NAMES)
78 {
79 FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
81 }
82 else
84
85 return ret;
86}
87
88static char *ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
89{
90 static const char username_arg[] = "--username=";
91 char *user;
92 int unixcp_size;
93
95 userW, userW_length, NULL, 0, NULL, NULL) + sizeof(username_arg);
96 user = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
97 if (!user) return NULL;
98 memcpy(user, username_arg, sizeof(username_arg) - 1);
100 user + sizeof(username_arg) - 1,
101 unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
102 user[unixcp_size - 1] = '\0';
103 return user;
104}
105
106static char *ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
107{
108 static const char domain_arg[] = "--domain=";
109 char *domain;
110 int unixcp_size;
111
113 domainW, domainW_length, NULL, 0, NULL, NULL) + sizeof(domain_arg);
114 domain = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
115 if (!domain) return NULL;
116 memcpy(domain, domain_arg, sizeof(domain_arg) - 1);
118 domainW_length, domain + sizeof(domain_arg) - 1,
119 unixcp_size - sizeof(domain) + 1, NULL, NULL);
120 domain[unixcp_size - 1] = '\0';
121 return domain;
122}
123
124/***********************************************************************
125 * AcquireCredentialsHandleW
126 */
128 SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
129 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
130 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
131{
133 PNtlmCredentials ntlm_cred;
136
137 TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
138 debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
139 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
140
141 switch(fCredentialUse)
142 {
144 ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred));
145 if (!ntlm_cred)
147 else
148 {
149 ntlm_cred->mode = NTLM_SERVER;
150 ntlm_cred->username_arg = NULL;
151 ntlm_cred->domain_arg = NULL;
152 ntlm_cred->password = NULL;
153 ntlm_cred->pwlen = 0;
154 ntlm_cred->no_cached_credentials = 0;
155
156 phCredential->dwUpper = fCredentialUse;
157 phCredential->dwLower = (ULONG_PTR)ntlm_cred;
158 ret = SEC_E_OK;
159 }
160 break;
162 {
163 auth_data = pAuthData;
164 ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred));
165 if (!ntlm_cred)
166 {
168 break;
169 }
170 ntlm_cred->mode = NTLM_CLIENT;
171 ntlm_cred->username_arg = NULL;
172 ntlm_cred->domain_arg = NULL;
173 ntlm_cred->password = NULL;
174 ntlm_cred->pwlen = 0;
175 ntlm_cred->no_cached_credentials = 0;
176
177 if(pAuthData != NULL)
178 {
179 int domain_len = 0, user_len = 0, password_len = 0;
180
181 if (auth_data->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
182 {
183 if (auth_data->DomainLength)
184 {
185 domain_len = MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Domain,
186 auth_data->DomainLength, NULL, 0);
187 domain = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * domain_len);
188 if(!domain)
189 {
191 break;
192 }
193 MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Domain, auth_data->DomainLength,
194 domain, domain_len);
195 }
196
197 if (auth_data->UserLength)
198 {
199 user_len = MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->User,
200 auth_data->UserLength, NULL, 0);
201 user = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * user_len);
202 if(!user)
203 {
205 break;
206 }
207 MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->User, auth_data->UserLength,
208 user, user_len);
209 }
210
211 if (auth_data->PasswordLength)
212 {
213 password_len = MultiByteToWideChar(CP_ACP, 0,(char *)auth_data->Password,
214 auth_data->PasswordLength, NULL, 0);
215 password = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * password_len);
216 if(!password)
217 {
219 break;
220 }
221 MultiByteToWideChar(CP_ACP, 0, (char *)auth_data->Password, auth_data->PasswordLength,
222 password, password_len);
223 }
224 }
225 else
226 {
227 domain = auth_data->Domain;
228 domain_len = auth_data->DomainLength;
229
230 user = auth_data->User;
231 user_len = auth_data->UserLength;
232
233 password = auth_data->Password;
234 password_len = auth_data->PasswordLength;
235 }
236
237 TRACE("Username is %s\n", debugstr_wn(user, user_len));
238 TRACE("Domain name is %s\n", debugstr_wn(domain, domain_len));
239
240 ntlm_cred->username_arg = ntlm_GetUsernameArg(user, user_len);
241 ntlm_cred->domain_arg = ntlm_GetDomainArg(domain, domain_len);
242
243 if(password_len != 0)
244 {
246 password_len, NULL, 0, NULL, NULL);
247
248 ntlm_cred->password = HeapAlloc(GetProcessHeap(), 0,
249 ntlm_cred->pwlen);
250 if(!ntlm_cred->password)
251 {
253 break;
254 }
255
257 ntlm_cred->password, ntlm_cred->pwlen, NULL, NULL);
258 }
259 }
260
261 phCredential->dwUpper = fCredentialUse;
262 phCredential->dwLower = (ULONG_PTR)ntlm_cred;
263 TRACE("ACH phCredential->dwUpper: 0x%08lx, dwLower: 0x%08lx\n",
264 phCredential->dwUpper, phCredential->dwLower);
265 ret = SEC_E_OK;
266 break;
267 }
268 case SECPKG_CRED_BOTH:
269 FIXME("AcquireCredentialsHandle: SECPKG_CRED_BOTH stub\n");
271 phCredential = NULL;
272 break;
273 default:
274 phCredential = NULL;
276 }
277
278 if (auth_data && auth_data->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
279 {
283 }
284 return ret;
285}
286
287/***********************************************************************
288 * AcquireCredentialsHandleA
289 */
291 SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
292 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
293 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
294{
296 int user_sizeW, domain_sizeW, passwd_sizeW;
297
298 SEC_WCHAR *user = NULL, *domain = NULL, *passwd = NULL, *package = NULL;
299
300 PSEC_WINNT_AUTH_IDENTITY_W pAuthDataW = NULL;
302
303 TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
304 debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
305 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
306
307 if(pszPackage != NULL)
308 {
309 int package_sizeW = MultiByteToWideChar(CP_ACP, 0, pszPackage, -1,
310 NULL, 0);
311
312 package = HeapAlloc(GetProcessHeap(), 0, package_sizeW *
313 sizeof(SEC_WCHAR));
314 MultiByteToWideChar(CP_ACP, 0, pszPackage, -1, package, package_sizeW);
315 }
316
317
318 if(pAuthData != NULL)
319 {
320 identity = pAuthData;
321
323 {
324 pAuthDataW = HeapAlloc(GetProcessHeap(), 0,
326
327 if(identity->UserLength != 0)
328 {
329 user_sizeW = MultiByteToWideChar(CP_ACP, 0,
330 (LPCSTR)identity->User, identity->UserLength, NULL, 0);
331 user = HeapAlloc(GetProcessHeap(), 0, user_sizeW *
332 sizeof(SEC_WCHAR));
334 identity->UserLength, user, user_sizeW);
335 }
336 else
337 {
338 user_sizeW = 0;
339 }
340
341 if(identity->DomainLength != 0)
342 {
343 domain_sizeW = MultiByteToWideChar(CP_ACP, 0,
344 (LPCSTR)identity->Domain, identity->DomainLength, NULL, 0);
345 domain = HeapAlloc(GetProcessHeap(), 0, domain_sizeW
346 * sizeof(SEC_WCHAR));
348 identity->DomainLength, domain, domain_sizeW);
349 }
350 else
351 {
352 domain_sizeW = 0;
353 }
354
355 if(identity->PasswordLength != 0)
356 {
357 passwd_sizeW = MultiByteToWideChar(CP_ACP, 0,
358 (LPCSTR)identity->Password, identity->PasswordLength,
359 NULL, 0);
360 passwd = HeapAlloc(GetProcessHeap(), 0, passwd_sizeW
361 * sizeof(SEC_WCHAR));
363 identity->PasswordLength, passwd, passwd_sizeW);
364 }
365 else
366 {
367 passwd_sizeW = 0;
368 }
369
370 pAuthDataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
371 pAuthDataW->User = user;
372 pAuthDataW->UserLength = user_sizeW;
373 pAuthDataW->Domain = domain;
374 pAuthDataW->DomainLength = domain_sizeW;
375 pAuthDataW->Password = passwd;
376 pAuthDataW->PasswordLength = passwd_sizeW;
377 }
378 else
379 {
381 }
382 }
383
384 ret = ntlm_AcquireCredentialsHandleW(NULL, package, fCredentialUse,
385 pLogonID, pAuthDataW, pGetKeyFn, pGetKeyArgument, phCredential,
386 ptsExpiry);
387
388 HeapFree(GetProcessHeap(), 0, package);
391 HeapFree(GetProcessHeap(), 0, passwd);
392 if(pAuthDataW != (PSEC_WINNT_AUTH_IDENTITY_W)identity)
393 HeapFree(GetProcessHeap(), 0, pAuthDataW);
394
395 return ret;
396}
397
398/*************************************************************************
399 * ntlm_GetTokenBufferIndex
400 * Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
401 * Returns index if found or -1 if not found.
402 */
404{
405 UINT i;
406
407 TRACE("%p\n", pMessage);
408
409 for( i = 0; i < pMessage->cBuffers; ++i )
410 {
411 if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
412 return i;
413 }
414
415 return -1;
416}
417
418/*************************************************************************
419 * ntlm_GetDataBufferIndex
420 * Calculates the index of the first secbuffer with BufferType == SECBUFFER_DATA
421 * Returns index if found or -1 if not found.
422 */
424{
425 UINT i;
426
427 TRACE("%p\n", pMessage);
428
429 for( i = 0; i < pMessage->cBuffers; ++i )
430 {
431 if(pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
432 return i;
433 }
434
435 return -1;
436}
437
438static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
439{
440 LPCWSTR p;
441 LPCWSTR pszHost;
442 LPWSTR pszHostOnly;
443 BOOL ret;
444
445 if (!pszTargetName)
446 return FALSE;
447
448 /* try to get the start of the hostname from service principal name (SPN) */
449 pszHost = strchrW(pszTargetName, '/');
450 if (pszHost)
451 {
452 /* skip slash character */
453 pszHost++;
454
455 /* find end of host by detecting start of instance port or start of referrer */
456 p = strchrW(pszHost, ':');
457 if (!p)
458 p = strchrW(pszHost, '/');
459 if (!p)
460 p = pszHost + strlenW(pszHost);
461 }
462 else /* otherwise not an SPN, just a host */
463 {
464 pszHost = pszTargetName;
465 p = pszHost + strlenW(pszHost);
466 }
467
468 pszHostOnly = HeapAlloc(GetProcessHeap(), 0, (p - pszHost + 1) * sizeof(WCHAR));
469 if (!pszHostOnly)
470 return FALSE;
471
472 memcpy(pszHostOnly, pszHost, (p - pszHost) * sizeof(WCHAR));
473 pszHostOnly[p - pszHost] = '\0';
474
475 ret = CredReadW(pszHostOnly, CRED_TYPE_DOMAIN_PASSWORD, 0, cred);
476
477 HeapFree(GetProcessHeap(), 0, pszHostOnly);
478 return ret;
479}
480
481/***********************************************************************
482 * InitializeSecurityContextW
483 */
485 PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
486 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
487 PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
488 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
489{
491 PNtlmCredentials ntlm_cred;
492 PNegoHelper helper = NULL;
493 ULONG ctxt_attr = 0;
494 char* buffer, *want_flags = NULL;
495 PBYTE bin;
496 int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
497 int token_idx;
501
502 TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext,
503 debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
504 Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
505
506 /****************************************
507 * When communicating with the client, there can be the
508 * following reply packets:
509 * YR <base64 blob> should be sent to the server
510 * PW should be sent back to helper with
511 * base64 encoded password
512 * AF <base64 blob> client is done, blob should be
513 * sent to server with KK prefixed
514 * GF <string list> A string list of negotiated flags
515 * GK <base64 blob> base64 encoded session key
516 * BH <char reason> something broke
517 */
518 /* The squid cache size is 2010 chars, and that's what ntlm_auth uses */
519
520 if(TargetDataRep == SECURITY_NETWORK_DREP){
521 TRACE("Setting SECURITY_NETWORK_DREP\n");
522 }
523
524 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(char) * NTLM_MAX_BUF);
525 bin = HeapAlloc(GetProcessHeap(), 0, sizeof(BYTE) * NTLM_MAX_BUF);
526
527 if((phContext == NULL) && (pInput == NULL))
528 {
529 static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1";
530 static CHAR credentials_argv[] = "--use-cached-creds";
531 SEC_CHAR *client_argv[5];
532 int pwlen = 0;
533
534 TRACE("First time in ISC()\n");
535
536 if(!phCredential)
537 {
539 goto isc_end;
540 }
541
542 /* As the server side of sspi never calls this, make sure that
543 * the handler is a client handler.
544 */
545 ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
546 if(ntlm_cred->mode != NTLM_CLIENT)
547 {
548 TRACE("Cred mode = %d\n", ntlm_cred->mode);
550 goto isc_end;
551 }
552
553 client_argv[0] = ntlm_auth;
554 client_argv[1] = helper_protocol;
555 if (!ntlm_cred->username_arg && !ntlm_cred->domain_arg)
556 {
559 PCREDENTIALW cred;
560
561 if (ntlm_GetCachedCredential(pszTargetName, &cred))
562 {
563 LPWSTR p;
564 p = strchrW(cred->UserName, '\\');
565 if (p)
566 {
567 domain = ntlm_GetDomainArg(cred->UserName, p - cred->UserName);
568 p++;
569 }
570 else
571 {
573 p = cred->UserName;
574 }
575
577
578 if(cred->CredentialBlobSize != 0)
579 {
582 cred->CredentialBlobSize / sizeof(WCHAR), NULL, 0,
583 NULL, NULL);
584
585 password = HeapAlloc(GetProcessHeap(), 0, pwlen);
586
588 (LPWSTR)cred->CredentialBlob,
589 cred->CredentialBlobSize / sizeof(WCHAR),
590 password, pwlen, NULL, NULL);
591 }
592
593 CredFree(cred);
594
595 client_argv[2] = username;
596 client_argv[3] = domain;
597 client_argv[4] = NULL;
598 }
599 else
600 {
602 if (status != NERR_Success || ui == NULL || ntlm_cred->no_cached_credentials)
603 {
605 goto isc_end;
606 }
607 username = ntlm_GetUsernameArg(ui->wkui1_username, -1);
609
610 TRACE("using cached credentials\n");
611
612 client_argv[2] = username;
613 client_argv[3] = credentials_argv;
614 client_argv[4] = NULL;
615 }
616 }
617 else
618 {
619 client_argv[2] = ntlm_cred->username_arg;
620 client_argv[3] = ntlm_cred->domain_arg;
621 client_argv[4] = NULL;
622 }
623
624 if((ret = fork_helper(&helper, ntlm_auth, client_argv)) != SEC_E_OK)
625 goto isc_end;
626
627 helper->mode = NTLM_CLIENT;
628 helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
629 if (!helper->session_key)
630 {
631 cleanup_helper(helper);
633 goto isc_end;
634 }
635
636 /* Generate the dummy session key = MD4(MD4(password))*/
637 if(password || ntlm_cred->password)
638 {
639 SEC_WCHAR *unicode_password;
640 int passwd_lenW;
641
642 TRACE("Converting password to unicode.\n");
643 passwd_lenW = MultiByteToWideChar(CP_ACP, 0,
644 password ? password : ntlm_cred->password,
645 password ? pwlen : ntlm_cred->pwlen,
646 NULL, 0);
647 unicode_password = HeapAlloc(GetProcessHeap(), 0,
648 passwd_lenW * sizeof(SEC_WCHAR));
650 password ? pwlen : ntlm_cred->pwlen, unicode_password, passwd_lenW);
651
652 SECUR32_CreateNTLM1SessionKey((PBYTE)unicode_password,
653 passwd_lenW * sizeof(SEC_WCHAR), helper->session_key);
654
655 HeapFree(GetProcessHeap(), 0, unicode_password);
656 }
657 else
658 memset(helper->session_key, 0, 16);
659
660 /* Allocate space for a maximal string of
661 * "SF NTLMSSP_FEATURE_SIGN NTLMSSP_FEATURE_SEAL
662 * NTLMSSP_FEATURE_SESSION_KEY"
663 */
664 want_flags = HeapAlloc(GetProcessHeap(), 0, 73);
665 if(want_flags == NULL)
666 {
667 cleanup_helper(helper);
669 goto isc_end;
670 }
671 lstrcpyA(want_flags, "SF");
672 if(fContextReq & ISC_REQ_CONFIDENTIALITY)
673 {
674 if(strstr(want_flags, "NTLMSSP_FEATURE_SEAL") == NULL)
675 lstrcatA(want_flags, " NTLMSSP_FEATURE_SEAL");
676 }
677 if(fContextReq & ISC_REQ_CONNECTION)
678 ctxt_attr |= ISC_RET_CONNECTION;
679 if(fContextReq & ISC_REQ_EXTENDED_ERROR)
680 ctxt_attr |= ISC_RET_EXTENDED_ERROR;
681 if(fContextReq & ISC_REQ_INTEGRITY)
682 {
683 if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
684 lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
685 }
686 if(fContextReq & ISC_REQ_MUTUAL_AUTH)
687 ctxt_attr |= ISC_RET_MUTUAL_AUTH;
688 if(fContextReq & ISC_REQ_REPLAY_DETECT)
689 {
690 if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
691 lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
692 }
693 if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
694 {
695 if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
696 lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
697 }
698 if(fContextReq & ISC_REQ_STREAM)
699 FIXME("ISC_REQ_STREAM\n");
700 if(fContextReq & ISC_REQ_USE_DCE_STYLE)
701 ctxt_attr |= ISC_RET_USED_DCE_STYLE;
702 if(fContextReq & ISC_REQ_DELEGATE)
703 ctxt_attr |= ISC_RET_DELEGATE;
704
705 /* If no password is given, try to use cached credentials. Fall back to an empty
706 * password if this failed. */
707 if(!password && !ntlm_cred->password)
708 {
709 lstrcpynA(buffer, "OK", max_len-1);
710 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
711 {
712 cleanup_helper(helper);
713 goto isc_end;
714 }
715 /* If the helper replied with "PW", using cached credentials failed */
716 if(!strncmp(buffer, "PW", 2))
717 {
718 TRACE("Using cached credentials failed.\n");
719 lstrcpynA(buffer, "PW AA==", max_len-1);
720 }
721 else /* Just do a noop on the next run */
722 lstrcpynA(buffer, "OK", max_len-1);
723 }
724 else
725 {
726 lstrcpynA(buffer, "PW ", max_len-1);
727 if((ret = encodeBase64(password ? (unsigned char *)password : (unsigned char *)ntlm_cred->password,
728 password ? pwlen : ntlm_cred->pwlen, buffer+3,
729 max_len-3, &buffer_len)) != SEC_E_OK)
730 {
731 cleanup_helper(helper);
732 goto isc_end;
733 }
734
735 }
736
737 TRACE("Sending to helper: %s\n", debugstr_a(buffer));
738 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
739 {
740 cleanup_helper(helper);
741 goto isc_end;
742 }
743
744 TRACE("Helper returned %s\n", debugstr_a(buffer));
745
746 if(lstrlenA(want_flags) > 2)
747 {
748 TRACE("Want flags are %s\n", debugstr_a(want_flags));
749 lstrcpynA(buffer, want_flags, max_len-1);
750 if((ret = run_helper(helper, buffer, max_len, &buffer_len))
751 != SEC_E_OK)
752 {
753 cleanup_helper(helper);
754 goto isc_end;
755 }
756 if(!strncmp(buffer, "BH", 2))
757 ERR("Helper doesn't understand new command set. Expect more things to fail.\n");
758 }
759
760 lstrcpynA(buffer, "YR", max_len-1);
761
762 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
763 {
764 cleanup_helper(helper);
765 goto isc_end;
766 }
767
768 TRACE("%s\n", buffer);
769
770 if(strncmp(buffer, "YR ", 3) != 0)
771 {
772 /* Something borked */
773 TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
775 cleanup_helper(helper);
776 goto isc_end;
777 }
778 if((ret = decodeBase64(buffer+3, buffer_len-3, bin,
779 max_len-1, &bin_len)) != SEC_E_OK)
780 {
781 cleanup_helper(helper);
782 goto isc_end;
783 }
784
785 /* put the decoded client blob into the out buffer */
786
787 phNewContext->dwUpper = ctxt_attr;
788 phNewContext->dwLower = (ULONG_PTR)helper;
789
791 }
792 else
793 {
794 int input_token_idx;
795
796 /* handle second call here */
797 /* encode server data to base64 */
798 if (!pInput || ((input_token_idx = ntlm_GetTokenBufferIndex(pInput)) == -1))
799 {
801 goto isc_end;
802 }
803
804 if(!phContext)
805 {
807 goto isc_end;
808 }
809
810 /* As the server side of sspi never calls this, make sure that
811 * the handler is a client handler.
812 */
813 helper = (PNegoHelper)phContext->dwLower;
814 if(helper->mode != NTLM_CLIENT)
815 {
816 TRACE("Helper mode = %d\n", helper->mode);
818 goto isc_end;
819 }
820
821 if (!pInput->pBuffers[input_token_idx].pvBuffer)
822 {
824 goto isc_end;
825 }
826
827 if(pInput->pBuffers[input_token_idx].cbBuffer > max_len)
828 {
829 TRACE("pInput->pBuffers[%d].cbBuffer is: %d\n",
830 input_token_idx,
831 pInput->pBuffers[input_token_idx].cbBuffer);
833 goto isc_end;
834 }
835 else
836 bin_len = pInput->pBuffers[input_token_idx].cbBuffer;
837
838 memcpy(bin, pInput->pBuffers[input_token_idx].pvBuffer, bin_len);
839
840 lstrcpynA(buffer, "TT ", max_len-1);
841
842 if((ret = encodeBase64(bin, bin_len, buffer+3,
843 max_len-3, &buffer_len)) != SEC_E_OK)
844 goto isc_end;
845
846 TRACE("Server sent: %s\n", debugstr_a(buffer));
847
848 /* send TT base64 blob to ntlm_auth */
849 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
850 goto isc_end;
851
852 TRACE("Helper replied: %s\n", debugstr_a(buffer));
853
854 if( (strncmp(buffer, "KK ", 3) != 0) &&
855 (strncmp(buffer, "AF ", 3) !=0))
856 {
857 TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
859 goto isc_end;
860 }
861
862 /* decode the blob and send it to server */
863 if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
864 &bin_len)) != SEC_E_OK)
865 {
866 goto isc_end;
867 }
868
869 phNewContext->dwUpper = ctxt_attr;
870 phNewContext->dwLower = (ULONG_PTR)helper;
871
872 ret = SEC_E_OK;
873 }
874
875 /* put the decoded client blob into the out buffer */
876
877 if (!pOutput || ((token_idx = ntlm_GetTokenBufferIndex(pOutput)) == -1))
878 {
879 TRACE("no SECBUFFER_TOKEN buffer could be found\n");
881 if ((phContext == NULL) && (pInput == NULL))
882 {
883 cleanup_helper(helper);
884 phNewContext->dwUpper = 0;
885 phNewContext->dwLower = 0;
886 }
887 goto isc_end;
888 }
889
890 if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
891 {
892 pOutput->pBuffers[token_idx].pvBuffer = HeapAlloc(GetProcessHeap(), 0, bin_len);
893 pOutput->pBuffers[token_idx].cbBuffer = bin_len;
894 }
895 else if (pOutput->pBuffers[token_idx].cbBuffer < bin_len)
896 {
897 TRACE("out buffer is NULL or has not enough space\n");
899 if ((phContext == NULL) && (pInput == NULL))
900 {
901 cleanup_helper(helper);
902 phNewContext->dwUpper = 0;
903 phNewContext->dwLower = 0;
904 }
905 goto isc_end;
906 }
907
908 if (!pOutput->pBuffers[token_idx].pvBuffer)
909 {
910 TRACE("out buffer is NULL\n");
912 if ((phContext == NULL) && (pInput == NULL))
913 {
914 cleanup_helper(helper);
915 phNewContext->dwUpper = 0;
916 phNewContext->dwLower = 0;
917 }
918 goto isc_end;
919 }
920
921 pOutput->pBuffers[token_idx].cbBuffer = bin_len;
922 memcpy(pOutput->pBuffers[token_idx].pvBuffer, bin, bin_len);
923
924 if(ret == SEC_E_OK)
925 {
926 TRACE("Getting negotiated flags\n");
927 lstrcpynA(buffer, "GF", max_len - 1);
928 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
929 goto isc_end;
930
931 if(buffer_len < 3)
932 {
933 TRACE("No flags negotiated.\n");
934 helper->neg_flags = 0l;
935 }
936 else
937 {
938 TRACE("Negotiated %s\n", debugstr_a(buffer));
939 sscanf(buffer + 3, "%lx", &(helper->neg_flags));
940 TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
941 }
942
943 TRACE("Getting session key\n");
944 lstrcpynA(buffer, "GK", max_len - 1);
945 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
946 goto isc_end;
947
948 if(strncmp(buffer, "BH", 2) == 0)
949 TRACE("No key negotiated.\n");
950 else if(strncmp(buffer, "GK ", 3) == 0)
951 {
952 if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
953 &bin_len)) != SEC_E_OK)
954 {
955 TRACE("Failed to decode session key\n");
956 }
957 TRACE("Session key is %s\n", debugstr_a(buffer+3));
958 HeapFree(GetProcessHeap(), 0, helper->session_key);
959 helper->session_key = HeapAlloc(GetProcessHeap(), 0, bin_len);
960 if(!helper->session_key)
961 {
963 goto isc_end;
964 }
965 memcpy(helper->session_key, bin, bin_len);
966 }
967
968 helper->crypt.ntlm.a4i = SECUR32_arc4Alloc();
969 SECUR32_arc4Init(helper->crypt.ntlm.a4i, helper->session_key, 16);
970 helper->crypt.ntlm.seq_num = 0l;
972 helper->crypt.ntlm2.send_a4i = SECUR32_arc4Alloc();
973 helper->crypt.ntlm2.recv_a4i = SECUR32_arc4Alloc();
974 SECUR32_arc4Init(helper->crypt.ntlm2.send_a4i,
975 helper->crypt.ntlm2.send_seal_key, 16);
976 SECUR32_arc4Init(helper->crypt.ntlm2.recv_a4i,
977 helper->crypt.ntlm2.recv_seal_key, 16);
978 helper->crypt.ntlm2.send_seq_no = 0l;
979 helper->crypt.ntlm2.recv_seq_no = 0l;
980 }
981
982isc_end:
986 HeapFree(GetProcessHeap(), 0, want_flags);
989 return ret;
990}
991
992/***********************************************************************
993 * InitializeSecurityContextA
994 */
996 PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
997 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
998 PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext,
999 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
1000{
1003
1004 TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
1005 debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
1006 Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
1007
1008 if(pszTargetName != NULL)
1009 {
1010 int target_size = MultiByteToWideChar(CP_ACP, 0, pszTargetName,
1011 strlen(pszTargetName)+1, NULL, 0);
1012 target = HeapAlloc(GetProcessHeap(), 0, target_size *
1013 sizeof(SEC_WCHAR));
1014 MultiByteToWideChar(CP_ACP, 0, pszTargetName, strlen(pszTargetName)+1,
1015 target, target_size);
1016 }
1017
1018 ret = ntlm_InitializeSecurityContextW(phCredential, phContext, target,
1019 fContextReq, Reserved1, TargetDataRep, pInput, Reserved2,
1020 phNewContext, pOutput, pfContextAttr, ptsExpiry);
1021
1023 return ret;
1024}
1025
1026/***********************************************************************
1027 * AcceptSecurityContext
1028 */
1030 PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
1031 ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
1032 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
1033{
1035 char *buffer, *want_flags = NULL;
1036 PBYTE bin;
1037 int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
1038 ULONG ctxt_attr = 0;
1039 PNegoHelper helper;
1040 PNtlmCredentials ntlm_cred;
1041
1042 TRACE("%p %p %p %d %d %p %p %p %p\n", phCredential, phContext, pInput,
1043 fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
1044 ptsExpiry);
1045
1046 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(char) * NTLM_MAX_BUF);
1047 bin = HeapAlloc(GetProcessHeap(),0, sizeof(BYTE) * NTLM_MAX_BUF);
1048
1049 if(TargetDataRep == SECURITY_NETWORK_DREP){
1050 TRACE("Using SECURITY_NETWORK_DREP\n");
1051 }
1052
1053 if(phContext == NULL)
1054 {
1055 static CHAR server_helper_protocol[] = "--helper-protocol=squid-2.5-ntlmssp";
1056 SEC_CHAR *server_argv[] = { ntlm_auth,
1057 server_helper_protocol,
1058 NULL };
1059
1060 if (!phCredential)
1061 {
1063 goto asc_end;
1064 }
1065
1066 ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
1067
1068 if(ntlm_cred->mode != NTLM_SERVER)
1069 {
1071 goto asc_end;
1072 }
1073
1074 /* This is the first call to AcceptSecurityHandle */
1075 if(pInput == NULL)
1076 {
1078 goto asc_end;
1079 }
1080
1081 if(pInput->cBuffers < 1)
1082 {
1084 goto asc_end;
1085 }
1086
1087 if(pInput->pBuffers[0].cbBuffer > max_len)
1088 {
1090 goto asc_end;
1091 }
1092 else
1093 bin_len = pInput->pBuffers[0].cbBuffer;
1094
1095 if( (ret = fork_helper(&helper, ntlm_auth, server_argv)) !=
1096 SEC_E_OK)
1097 {
1099 goto asc_end;
1100 }
1101 helper->mode = NTLM_SERVER;
1102
1103 /* Handle all the flags */
1104 want_flags = HeapAlloc(GetProcessHeap(), 0, 73);
1105 if(want_flags == NULL)
1106 {
1107 TRACE("Failed to allocate memory for the want_flags!\n");
1109 cleanup_helper(helper);
1110 goto asc_end;
1111 }
1112 lstrcpyA(want_flags, "SF");
1113 if(fContextReq & ASC_REQ_ALLOCATE_MEMORY)
1114 {
1115 FIXME("ASC_REQ_ALLOCATE_MEMORY stub\n");
1116 }
1117 if(fContextReq & ASC_REQ_CONFIDENTIALITY)
1118 {
1119 lstrcatA(want_flags, " NTLMSSP_FEATURE_SEAL");
1120 }
1121 if(fContextReq & ASC_REQ_CONNECTION)
1122 {
1123 /* This is default, so we'll enable it */
1124 lstrcatA(want_flags, " NTLMSSP_FEATURE_SESSION_KEY");
1125 ctxt_attr |= ASC_RET_CONNECTION;
1126 }
1127 if(fContextReq & ASC_REQ_EXTENDED_ERROR)
1128 {
1129 FIXME("ASC_REQ_EXTENDED_ERROR stub\n");
1130 }
1131 if(fContextReq & ASC_REQ_INTEGRITY)
1132 {
1133 lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
1134 }
1135 if(fContextReq & ASC_REQ_MUTUAL_AUTH)
1136 {
1137 FIXME("ASC_REQ_MUTUAL_AUTH stub\n");
1138 }
1139 if(fContextReq & ASC_REQ_REPLAY_DETECT)
1140 {
1141 FIXME("ASC_REQ_REPLAY_DETECT stub\n");
1142 }
1143 if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
1144 {
1145 FIXME("ASC_REQ_SEQUENCE_DETECT stub\n");
1146 }
1147 if(fContextReq & ISC_REQ_STREAM)
1148 {
1149 FIXME("ASC_REQ_STREAM stub\n");
1150 }
1151 /* Done with the flags */
1152
1153 if(lstrlenA(want_flags) > 3)
1154 {
1155 TRACE("Server set want_flags: %s\n", debugstr_a(want_flags));
1156 lstrcpynA(buffer, want_flags, max_len - 1);
1157 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
1158 SEC_E_OK)
1159 {
1160 cleanup_helper(helper);
1161 goto asc_end;
1162 }
1163 if(!strncmp(buffer, "BH", 2))
1164 TRACE("Helper doesn't understand new command set\n");
1165 }
1166
1167 /* This is the YR request from the client, encode to base64 */
1168
1169 memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
1170
1171 lstrcpynA(buffer, "YR ", max_len-1);
1172
1173 if((ret = encodeBase64(bin, bin_len, buffer+3, max_len-3,
1174 &buffer_len)) != SEC_E_OK)
1175 {
1176 cleanup_helper(helper);
1177 goto asc_end;
1178 }
1179
1180 TRACE("Client sent: %s\n", debugstr_a(buffer));
1181
1182 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
1183 SEC_E_OK)
1184 {
1185 cleanup_helper(helper);
1186 goto asc_end;
1187 }
1188
1189 TRACE("Reply from ntlm_auth: %s\n", debugstr_a(buffer));
1190 /* The expected answer is TT <base64 blob> */
1191
1192 if(strncmp(buffer, "TT ", 3) != 0)
1193 {
1195 cleanup_helper(helper);
1196 goto asc_end;
1197 }
1198
1199 if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
1200 &bin_len)) != SEC_E_OK)
1201 {
1202 cleanup_helper(helper);
1203 goto asc_end;
1204 }
1205
1206 /* send this to the client */
1207 if(pOutput == NULL)
1208 {
1210 cleanup_helper(helper);
1211 goto asc_end;
1212 }
1213
1214 if(pOutput->cBuffers < 1)
1215 {
1217 cleanup_helper(helper);
1218 goto asc_end;
1219 }
1220
1221 pOutput->pBuffers[0].cbBuffer = bin_len;
1222 pOutput->pBuffers[0].BufferType = SECBUFFER_DATA;
1223 memcpy(pOutput->pBuffers[0].pvBuffer, bin, bin_len);
1225
1226 }
1227 else
1228 {
1229 /* we expect a KK request from client */
1230 if(pInput == NULL)
1231 {
1233 goto asc_end;
1234 }
1235
1236 if(pInput->cBuffers < 1)
1237 {
1239 goto asc_end;
1240 }
1241
1242 helper = (PNegoHelper)phContext->dwLower;
1243
1244 if(helper->mode != NTLM_SERVER)
1245 {
1247 goto asc_end;
1248 }
1249
1250 if(pInput->pBuffers[0].cbBuffer > max_len)
1251 {
1253 goto asc_end;
1254 }
1255 else
1256 bin_len = pInput->pBuffers[0].cbBuffer;
1257
1258 memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
1259
1260 lstrcpynA(buffer, "KK ", max_len-1);
1261
1262 if((ret = encodeBase64(bin, bin_len, buffer+3, max_len-3,
1263 &buffer_len)) != SEC_E_OK)
1264 {
1265 goto asc_end;
1266 }
1267
1268 TRACE("Client sent: %s\n", debugstr_a(buffer));
1269
1270 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
1271 SEC_E_OK)
1272 {
1273 goto asc_end;
1274 }
1275
1276 TRACE("Reply from ntlm_auth: %s\n", debugstr_a(buffer));
1277
1278 /* At this point, we get a NA if the user didn't authenticate, but a BH
1279 * if ntlm_auth could not connect to winbindd. Apart from running Wine
1280 * as root, there is no way to fix this for now, so just handle this as
1281 * a failed login. */
1282 if(strncmp(buffer, "AF ", 3) != 0)
1283 {
1284 if(strncmp(buffer, "NA ", 3) == 0)
1285 {
1287 goto asc_end;
1288 }
1289 else
1290 {
1291 size_t ntlm_pipe_err_v3_len = strlen("BH NT_STATUS_ACCESS_DENIED");
1292 size_t ntlm_pipe_err_v4_len = strlen("BH NT_STATUS_UNSUCCESSFUL");
1293
1294 if( (buffer_len >= ntlm_pipe_err_v3_len &&
1295 strncmp(buffer, "BH NT_STATUS_ACCESS_DENIED", ntlm_pipe_err_v3_len) == 0) ||
1296 (buffer_len >= ntlm_pipe_err_v4_len &&
1297 strncmp(buffer, "BH NT_STATUS_UNSUCCESSFUL", ntlm_pipe_err_v4_len) == 0) )
1298 {
1299 TRACE("Connection to winbindd failed\n");
1301 }
1302 else
1304
1305 goto asc_end;
1306 }
1307 }
1308 pOutput->pBuffers[0].cbBuffer = 0;
1309
1310 TRACE("Getting negotiated flags\n");
1311 lstrcpynA(buffer, "GF", max_len - 1);
1312 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
1313 goto asc_end;
1314
1315 if(buffer_len < 3)
1316 {
1317 TRACE("No flags negotiated, or helper does not support GF command\n");
1318 }
1319 else
1320 {
1321 TRACE("Negotiated %s\n", debugstr_a(buffer));
1322 sscanf(buffer + 3, "%lx", &(helper->neg_flags));
1323 TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
1324 }
1325
1326 TRACE("Getting session key\n");
1327 lstrcpynA(buffer, "GK", max_len - 1);
1328 if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
1329 goto asc_end;
1330
1331 if(buffer_len < 3)
1332 TRACE("Helper does not support GK command\n");
1333 else
1334 {
1335 if(strncmp(buffer, "BH ", 3) == 0)
1336 {
1337 TRACE("Helper sent %s\n", debugstr_a(buffer+3));
1338 HeapFree(GetProcessHeap(), 0, helper->session_key);
1339 helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
1340 if (!helper->session_key)
1341 {
1343 goto asc_end;
1344 }
1345 /*FIXME: Generate the dummy session key = MD4(MD4(password))*/
1346 memset(helper->session_key, 0 , 16);
1347 }
1348 else if(strncmp(buffer, "GK ", 3) == 0)
1349 {
1350 if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
1351 &bin_len)) != SEC_E_OK)
1352 {
1353 TRACE("Failed to decode session key\n");
1354 }
1355 TRACE("Session key is %s\n", debugstr_a(buffer+3));
1356 HeapFree(GetProcessHeap(), 0, helper->session_key);
1357 helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
1358 if(!helper->session_key)
1359 {
1361 goto asc_end;
1362 }
1363 memcpy(helper->session_key, bin, 16);
1364 }
1365 }
1366 helper->crypt.ntlm.a4i = SECUR32_arc4Alloc();
1367 SECUR32_arc4Init(helper->crypt.ntlm.a4i, helper->session_key, 16);
1368 helper->crypt.ntlm.seq_num = 0l;
1369 }
1370
1371 phNewContext->dwUpper = ctxt_attr;
1372 phNewContext->dwLower = (ULONG_PTR)helper;
1373
1374asc_end:
1375 HeapFree(GetProcessHeap(), 0, want_flags);
1378 return ret;
1379}
1380
1381/***********************************************************************
1382 * CompleteAuthToken
1383 */
1385 PSecBufferDesc pToken)
1386{
1387 /* We never need to call CompleteAuthToken anyway */
1388 TRACE("%p %p\n", phContext, pToken);
1389 if (!phContext)
1390 return SEC_E_INVALID_HANDLE;
1391
1392 return SEC_E_OK;
1393}
1394
1395/***********************************************************************
1396 * DeleteSecurityContext
1397 */
1399{
1400 PNegoHelper helper;
1401
1402 TRACE("%p\n", phContext);
1403 if (!phContext)
1404 return SEC_E_INVALID_HANDLE;
1405
1406 helper = (PNegoHelper)phContext->dwLower;
1407
1408 phContext->dwUpper = 0;
1409 phContext->dwLower = 0;
1410
1411 SECUR32_arc4Cleanup(helper->crypt.ntlm.a4i);
1412 SECUR32_arc4Cleanup(helper->crypt.ntlm2.send_a4i);
1413 SECUR32_arc4Cleanup(helper->crypt.ntlm2.recv_a4i);
1414 HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.send_sign_key);
1415 HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.send_seal_key);
1416 HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.recv_sign_key);
1417 HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.recv_seal_key);
1418
1419 cleanup_helper(helper);
1420
1421 return SEC_E_OK;
1422}
1423
1424/***********************************************************************
1425 * QueryContextAttributesW
1426 */
1428 ULONG ulAttribute, void *pBuffer)
1429{
1430 TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer);
1431 if (!phContext)
1432 return SEC_E_INVALID_HANDLE;
1433
1434 switch(ulAttribute)
1435 {
1436#define _x(x) case (x) : FIXME(#x" stub\n"); break
1440 case SECPKG_ATTR_FLAGS:
1441 {
1443 PNegoHelper helper = (PNegoHelper)phContext->dwLower;
1444
1445 spcf->Flags = 0;
1446 if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
1447 spcf->Flags |= ISC_RET_INTEGRITY;
1448 if(helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
1450 return SEC_E_OK;
1451 }
1460 case SECPKG_ATTR_SIZES:
1461 {
1463 spcs->cbMaxToken = NTLM_MAX_BUF;
1464 spcs->cbMaxSignature = 16;
1465 spcs->cbBlockSize = 0;
1466 spcs->cbSecurityTrailer = 16;
1467 return SEC_E_OK;
1468 }
1471#undef _x
1472 default:
1473 TRACE("Unknown value %d passed for ulAttribute\n", ulAttribute);
1474 }
1475
1477}
1478
1479/***********************************************************************
1480 * QueryContextAttributesA
1481 */
1483 ULONG ulAttribute, void *pBuffer)
1484{
1485 return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
1486}
1487
1488/***********************************************************************
1489 * ImpersonateSecurityContext
1490 */
1492{
1494
1495 TRACE("%p\n", phContext);
1496 if (phContext)
1497 {
1499 }
1500 else
1501 {
1503 }
1504 return ret;
1505}
1506
1507/***********************************************************************
1508 * RevertSecurityContext
1509 */
1511{
1513
1514 TRACE("%p\n", phContext);
1515 if (phContext)
1516 {
1518 }
1519 else
1520 {
1522 }
1523 return ret;
1524}
1525
1526/***********************************************************************
1527 * ntlm_CreateSignature
1528 * As both MakeSignature and VerifySignature need this, but different keys
1529 * are needed for NTLM2, the logic goes into a helper function.
1530 * To ensure maximal reusability, we can specify the direction as NTLM_SEND for
1531 * signing/encrypting and NTLM_RECV for verifying/decrypting. When encrypting,
1532 * the signature is encrypted after the message was encrypted, so
1533 * CreateSignature shouldn't do it. In this case, encrypt_sig can be set to
1534 * false.
1535 */
1537 int token_idx, SignDirection direction, BOOL encrypt_sig)
1538{
1539 ULONG sign_version = 1;
1540 UINT i;
1541 PBYTE sig;
1542 TRACE("%p, %p, %d, %d, %d\n", helper, pMessage, token_idx, direction,
1543 encrypt_sig);
1544
1545 sig = pMessage->pBuffers[token_idx].pvBuffer;
1546
1547 if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 &&
1549 {
1550 BYTE digest[16];
1551 BYTE seq_no[4];
1552 HMAC_MD5_CTX hmac_md5_ctx;
1553
1554 TRACE("Signing NTLM2 style\n");
1555
1556 if(direction == NTLM_SEND)
1557 {
1558 seq_no[0] = (helper->crypt.ntlm2.send_seq_no >> 0) & 0xff;
1559 seq_no[1] = (helper->crypt.ntlm2.send_seq_no >> 8) & 0xff;
1560 seq_no[2] = (helper->crypt.ntlm2.send_seq_no >> 16) & 0xff;
1561 seq_no[3] = (helper->crypt.ntlm2.send_seq_no >> 24) & 0xff;
1562
1563 ++(helper->crypt.ntlm2.send_seq_no);
1564
1565 HMACMD5Init(&hmac_md5_ctx, helper->crypt.ntlm2.send_sign_key, 16);
1566 }
1567 else
1568 {
1569 seq_no[0] = (helper->crypt.ntlm2.recv_seq_no >> 0) & 0xff;
1570 seq_no[1] = (helper->crypt.ntlm2.recv_seq_no >> 8) & 0xff;
1571 seq_no[2] = (helper->crypt.ntlm2.recv_seq_no >> 16) & 0xff;
1572 seq_no[3] = (helper->crypt.ntlm2.recv_seq_no >> 24) & 0xff;
1573
1574 ++(helper->crypt.ntlm2.recv_seq_no);
1575
1576 HMACMD5Init(&hmac_md5_ctx, helper->crypt.ntlm2.recv_sign_key, 16);
1577 }
1578
1579 HMACMD5Update(&hmac_md5_ctx, seq_no, 4);
1580 for( i = 0; i < pMessage->cBuffers; ++i )
1581 {
1582 if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
1583 HMACMD5Update(&hmac_md5_ctx, pMessage->pBuffers[i].pvBuffer,
1584 pMessage->pBuffers[i].cbBuffer);
1585 }
1586
1587 HMACMD5Final(&hmac_md5_ctx, digest);
1588
1589 if(encrypt_sig && helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
1590 {
1591 if(direction == NTLM_SEND)
1592 SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i, digest, 8);
1593 else
1594 SECUR32_arc4Process(helper->crypt.ntlm2.recv_a4i, digest, 8);
1595 }
1596
1597 /* The NTLM2 signature is the sign version */
1598 sig[ 0] = (sign_version >> 0) & 0xff;
1599 sig[ 1] = (sign_version >> 8) & 0xff;
1600 sig[ 2] = (sign_version >> 16) & 0xff;
1601 sig[ 3] = (sign_version >> 24) & 0xff;
1602 /* The first 8 bytes of the digest */
1603 memcpy(sig+4, digest, 8);
1604 /* And the sequence number */
1605 memcpy(sig+12, seq_no, 4);
1606
1607 pMessage->pBuffers[token_idx].cbBuffer = 16;
1608
1609 return SEC_E_OK;
1610 }
1611 if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
1612 {
1613 ULONG crc = 0U;
1614 TRACE("Signing NTLM1 style\n");
1615
1616 for(i=0; i < pMessage->cBuffers; ++i)
1617 {
1618 if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
1619 {
1620 crc = ComputeCrc32(pMessage->pBuffers[i].pvBuffer,
1621 pMessage->pBuffers[i].cbBuffer, crc);
1622 }
1623 }
1624
1625 sig[ 0] = (sign_version >> 0) & 0xff;
1626 sig[ 1] = (sign_version >> 8) & 0xff;
1627 sig[ 2] = (sign_version >> 16) & 0xff;
1628 sig[ 3] = (sign_version >> 24) & 0xff;
1629 memset(sig+4, 0, 4);
1630 sig[ 8] = (crc >> 0) & 0xff;
1631 sig[ 9] = (crc >> 8) & 0xff;
1632 sig[10] = (crc >> 16) & 0xff;
1633 sig[11] = (crc >> 24) & 0xff;
1634 sig[12] = (helper->crypt.ntlm.seq_num >> 0) & 0xff;
1635 sig[13] = (helper->crypt.ntlm.seq_num >> 8) & 0xff;
1636 sig[14] = (helper->crypt.ntlm.seq_num >> 16) & 0xff;
1637 sig[15] = (helper->crypt.ntlm.seq_num >> 24) & 0xff;
1638
1639 ++(helper->crypt.ntlm.seq_num);
1640
1641 if(encrypt_sig)
1642 SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
1643 return SEC_E_OK;
1644 }
1645
1646 if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
1647 {
1648 TRACE("Creating a dummy signature.\n");
1649 /* A dummy signature is 0x01 followed by 15 bytes of 0x00 */
1650 memset(pMessage->pBuffers[token_idx].pvBuffer, 0, 16);
1651 memset(pMessage->pBuffers[token_idx].pvBuffer, 0x01, 1);
1652 pMessage->pBuffers[token_idx].cbBuffer = 16;
1653 return SEC_E_OK;
1654 }
1655
1657}
1658
1659/***********************************************************************
1660 * MakeSignature
1661 */
1663 ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
1664{
1665 PNegoHelper helper;
1666 int token_idx;
1667
1668 TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
1669 if (!phContext)
1670 return SEC_E_INVALID_HANDLE;
1671
1672 if(fQOP)
1673 FIXME("Ignoring fQOP 0x%08x\n", fQOP);
1674
1675 if(MessageSeqNo)
1676 FIXME("Ignoring MessageSeqNo\n");
1677
1678 if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
1679 return SEC_E_INVALID_TOKEN;
1680
1681 /* If we didn't find a SECBUFFER_TOKEN type buffer */
1682 if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
1683 return SEC_E_INVALID_TOKEN;
1684
1685 if(pMessage->pBuffers[token_idx].cbBuffer < 16)
1687
1688 helper = (PNegoHelper)phContext->dwLower;
1689 TRACE("Negotiated flags are: 0x%08x\n", helper->neg_flags);
1690
1691 return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, TRUE);
1692}
1693
1694/***********************************************************************
1695 * VerifySignature
1696 */
1698 PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
1699{
1700 PNegoHelper helper;
1701 UINT i;
1702 int token_idx;
1704 SecBufferDesc local_desc;
1705 PSecBuffer local_buff;
1706 BYTE local_sig[16];
1707
1708 TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
1709 if(!phContext)
1710 return SEC_E_INVALID_HANDLE;
1711
1712 if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
1713 return SEC_E_INVALID_TOKEN;
1714
1715 if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
1716 return SEC_E_INVALID_TOKEN;
1717
1718 if(pMessage->pBuffers[token_idx].cbBuffer < 16)
1720
1721 if(MessageSeqNo)
1722 FIXME("Ignoring MessageSeqNo\n");
1723
1724 helper = (PNegoHelper)phContext->dwLower;
1725 TRACE("Negotiated flags: 0x%08x\n", helper->neg_flags);
1726
1727 local_buff = HeapAlloc(GetProcessHeap(), 0, pMessage->cBuffers * sizeof(SecBuffer));
1728
1729 local_desc.ulVersion = SECBUFFER_VERSION;
1730 local_desc.cBuffers = pMessage->cBuffers;
1731 local_desc.pBuffers = local_buff;
1732
1733 for(i=0; i < pMessage->cBuffers; ++i)
1734 {
1735 if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
1736 {
1737 local_buff[i].BufferType = SECBUFFER_TOKEN;
1738 local_buff[i].cbBuffer = 16;
1739 local_buff[i].pvBuffer = local_sig;
1740 }
1741 else
1742 {
1743 local_buff[i].BufferType = pMessage->pBuffers[i].BufferType;
1744 local_buff[i].cbBuffer = pMessage->pBuffers[i].cbBuffer;
1745 local_buff[i].pvBuffer = pMessage->pBuffers[i].pvBuffer;
1746 }
1747 }
1748
1749 if((ret = ntlm_CreateSignature(helper, &local_desc, token_idx, NTLM_RECV, TRUE)) != SEC_E_OK)
1750 return ret;
1751
1752 if(memcmp(((PBYTE)local_buff[token_idx].pvBuffer) + 8,
1753 ((PBYTE)pMessage->pBuffers[token_idx].pvBuffer) + 8, 8))
1755 else
1756 ret = SEC_E_OK;
1757
1758 HeapFree(GetProcessHeap(), 0, local_buff);
1759
1760 return ret;
1761
1762}
1763
1764/***********************************************************************
1765 * FreeCredentialsHandle
1766 */
1768{
1770
1771 if(phCredential){
1772 PNtlmCredentials ntlm_cred = (PNtlmCredentials) phCredential->dwLower;
1773 phCredential->dwUpper = 0;
1774 phCredential->dwLower = 0;
1775 if (ntlm_cred->password)
1776 memset(ntlm_cred->password, 0, ntlm_cred->pwlen);
1777 HeapFree(GetProcessHeap(), 0, ntlm_cred->password);
1778 HeapFree(GetProcessHeap(), 0, ntlm_cred->username_arg);
1779 HeapFree(GetProcessHeap(), 0, ntlm_cred->domain_arg);
1780 HeapFree(GetProcessHeap(), 0, ntlm_cred);
1781 ret = SEC_E_OK;
1782 }
1783 else
1784 ret = SEC_E_OK;
1785
1786 return ret;
1787}
1788
1789/***********************************************************************
1790 * EncryptMessage
1791 */
1793 ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
1794{
1795 PNegoHelper helper;
1796 int token_idx, data_idx;
1797
1798 TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
1799
1800 if(!phContext)
1801 return SEC_E_INVALID_HANDLE;
1802
1803 if(fQOP)
1804 FIXME("Ignoring fQOP\n");
1805
1806 if(MessageSeqNo)
1807 FIXME("Ignoring MessageSeqNo\n");
1808
1809 if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
1810 return SEC_E_INVALID_TOKEN;
1811
1812 if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
1813 return SEC_E_INVALID_TOKEN;
1814
1815 if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1 )
1816 return SEC_E_INVALID_TOKEN;
1817
1818 if(pMessage->pBuffers[token_idx].cbBuffer < 16)
1820
1821 helper = (PNegoHelper) phContext->dwLower;
1822
1823 if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 &&
1825 {
1826 ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
1827 SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
1828 pMessage->pBuffers[data_idx].pvBuffer,
1829 pMessage->pBuffers[data_idx].cbBuffer);
1830
1832 SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
1833 ((BYTE *)pMessage->pBuffers[token_idx].pvBuffer)+4, 8);
1834 }
1835 else
1836 {
1837 PBYTE sig;
1838 ULONG save_flags;
1839
1840 /* EncryptMessage always produces real signatures, so make sure
1841 * NTLMSSP_NEGOTIATE_SIGN is set*/
1842 save_flags = helper->neg_flags;
1844 ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
1845 helper->neg_flags = save_flags;
1846
1847 sig = pMessage->pBuffers[token_idx].pvBuffer;
1848
1849 SECUR32_arc4Process(helper->crypt.ntlm.a4i,
1850 pMessage->pBuffers[data_idx].pvBuffer,
1851 pMessage->pBuffers[data_idx].cbBuffer);
1852 SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
1853
1854 if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
1855 memset(sig+4, 0, 4);
1856 }
1857 return SEC_E_OK;
1858}
1859
1860/***********************************************************************
1861 * DecryptMessage
1862 */
1864 PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
1865{
1867 ULONG ntlmssp_flags_save;
1868 PNegoHelper helper;
1869 int token_idx, data_idx;
1870 TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
1871
1872 if(!phContext)
1873 return SEC_E_INVALID_HANDLE;
1874
1875 if(MessageSeqNo)
1876 FIXME("Ignoring MessageSeqNo\n");
1877
1878 if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
1879 return SEC_E_INVALID_TOKEN;
1880
1881 if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
1882 return SEC_E_INVALID_TOKEN;
1883
1884 if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1)
1885 return SEC_E_INVALID_TOKEN;
1886
1887 if(pMessage->pBuffers[token_idx].cbBuffer < 16)
1889
1890 helper = (PNegoHelper) phContext->dwLower;
1891
1893 {
1894 SECUR32_arc4Process(helper->crypt.ntlm2.recv_a4i,
1895 pMessage->pBuffers[data_idx].pvBuffer,
1896 pMessage->pBuffers[data_idx].cbBuffer);
1897 }
1898 else
1899 {
1900 SECUR32_arc4Process(helper->crypt.ntlm.a4i,
1901 pMessage->pBuffers[data_idx].pvBuffer,
1902 pMessage->pBuffers[data_idx].cbBuffer);
1903 }
1904
1905 /* Make sure we use a session key for the signature check, EncryptMessage
1906 * always does that, even in the dummy case */
1907 ntlmssp_flags_save = helper->neg_flags;
1908
1910 ret = ntlm_VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
1911
1912 helper->neg_flags = ntlmssp_flags_save;
1913
1914 return ret;
1915}
1916
1918 1,
1919 NULL, /* EnumerateSecurityPackagesA */
1920 ntlm_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */
1921 ntlm_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */
1922 ntlm_FreeCredentialsHandle, /* FreeCredentialsHandle */
1923 NULL, /* Reserved2 */
1924 ntlm_InitializeSecurityContextA, /* InitializeSecurityContextA */
1925 ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
1926 ntlm_CompleteAuthToken, /* CompleteAuthToken */
1927 ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
1928 NULL, /* ApplyControlToken */
1929 ntlm_QueryContextAttributesA, /* QueryContextAttributesA */
1930 ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
1931 ntlm_RevertSecurityContext, /* RevertSecurityContext */
1932 ntlm_MakeSignature, /* MakeSignature */
1933 ntlm_VerifySignature, /* VerifySignature */
1934 FreeContextBuffer, /* FreeContextBuffer */
1935 NULL, /* QuerySecurityPackageInfoA */
1936 NULL, /* Reserved3 */
1937 NULL, /* Reserved4 */
1938 NULL, /* ExportSecurityContext */
1939 NULL, /* ImportSecurityContextA */
1940 NULL, /* AddCredentialsA */
1941 NULL, /* Reserved8 */
1942 NULL, /* QuerySecurityContextToken */
1943 ntlm_EncryptMessage, /* EncryptMessage */
1944 ntlm_DecryptMessage, /* DecryptMessage */
1945 NULL, /* SetContextAttributesA */
1946};
1947
1949 1,
1950 NULL, /* EnumerateSecurityPackagesW */
1951 ntlm_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */
1952 ntlm_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */
1953 ntlm_FreeCredentialsHandle, /* FreeCredentialsHandle */
1954 NULL, /* Reserved2 */
1955 ntlm_InitializeSecurityContextW, /* InitializeSecurityContextW */
1956 ntlm_AcceptSecurityContext, /* AcceptSecurityContext */
1957 ntlm_CompleteAuthToken, /* CompleteAuthToken */
1958 ntlm_DeleteSecurityContext, /* DeleteSecurityContext */
1959 NULL, /* ApplyControlToken */
1960 ntlm_QueryContextAttributesW, /* QueryContextAttributesW */
1961 ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
1962 ntlm_RevertSecurityContext, /* RevertSecurityContext */
1963 ntlm_MakeSignature, /* MakeSignature */
1964 ntlm_VerifySignature, /* VerifySignature */
1965 FreeContextBuffer, /* FreeContextBuffer */
1966 NULL, /* QuerySecurityPackageInfoW */
1967 NULL, /* Reserved3 */
1968 NULL, /* Reserved4 */
1969 NULL, /* ExportSecurityContext */
1970 NULL, /* ImportSecurityContextW */
1971 NULL, /* AddCredentialsW */
1972 NULL, /* Reserved8 */
1973 NULL, /* QuerySecurityContextToken */
1974 ntlm_EncryptMessage, /* EncryptMessage */
1975 ntlm_DecryptMessage, /* DecryptMessage */
1976 NULL, /* SetContextAttributesW */
1977};
1978
1979#define NTLM_COMMENT \
1980 { 'N', 'T', 'L', 'M', ' ', \
1981 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', \
1982 'P', 'a', 'c', 'k', 'a', 'g', 'e', 0}
1983
1986
1987#define NTLM_NAME {'N', 'T', 'L', 'M', 0}
1988
1989static char ntlm_name_A[] = NTLM_NAME;
1991
1992/* According to Windows, NTLM has the following capabilities. */
1993#define CAPS ( \
1994 SECPKG_FLAG_INTEGRITY | \
1995 SECPKG_FLAG_PRIVACY | \
1996 SECPKG_FLAG_TOKEN_ONLY | \
1997 SECPKG_FLAG_CONNECTION | \
1998 SECPKG_FLAG_MULTI_REQUIRED | \
1999 SECPKG_FLAG_IMPERSONATION | \
2000 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
2001 SECPKG_FLAG_NEGOTIABLE | \
2002 SECPKG_FLAG_LOGON | \
2003 SECPKG_FLAG_RESTRICTED_TOKENS )
2004
2005static const SecPkgInfoW infoW = {
2006 CAPS,
2007 1,
2012};
2013
2014static const SecPkgInfoA infoA = {
2015 CAPS,
2016 1,
2021};
2022
2025
2027{
2028 PNegoHelper helper;
2029 static CHAR version[] = "--version";
2030
2031 SEC_CHAR *args[] = {
2032 ntlm_auth,
2033 version,
2034 NULL };
2035
2036 if(fork_helper(&helper, ntlm_auth, args) != SEC_E_OK)
2037 helper = NULL;
2038 else
2039 check_version(helper);
2040
2041 if( helper &&
2042 ((helper->major > MIN_NTLM_AUTH_MAJOR_VERSION) ||
2043 (helper->major == MIN_NTLM_AUTH_MAJOR_VERSION &&
2045 (helper->major == MIN_NTLM_AUTH_MAJOR_VERSION &&
2047 helper->micro >= MIN_NTLM_AUTH_MICRO_VERSION)) )
2048 {
2051 }
2052 else
2053 {
2054 ERR_(winediag)("%s was not found or is outdated. "
2055 "Make sure that ntlm_auth >= %d.%d.%d is in your path. "
2056 "Usually, you can find it in the winbind package of your distribution.\n",
2057 ntlm_auth,
2061
2062 }
2063 cleanup_helper(helper);
2064}
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
SECURITY_STATUS decodeBase64(char *in_buf, int in_len, PBYTE out_buf, int max_len, int *out_len)
Definition: base64_codec.c:113
SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char *out_buf, int max_len, int *out_len)
Definition: base64_codec.c:29
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define U(x)
Definition: wordpad.c:45
@ Reserved2
Definition: bcd.h:202
@ Reserved1
Definition: bcd.h:201
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
r l[0]
Definition: byte_order.h:168
#define _x(oid)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential)
Definition: cred.c:1450
VOID WINAPI CredFree(PVOID Buffer)
Definition: cred.c:1395
#define CP_UNIXCP
Definition: compat.h:79
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define lstrcpynA
Definition: compat.h:751
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
static const WCHAR version[]
Definition: asmname.c:66
NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
Definition: apibuf.c:43
NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level, PBYTE *bufptr)
Definition: wksta.c:279
#define SEC_ENTRY
Definition: stubs.c:6
SECURITY_STATUS fork_helper(PNegoHelper *new_helper, const char *prog, char *const argv[])
Definition: dispatcher.c:76
SECURITY_STATUS run_helper(PNegoHelper helper, char *buffer, unsigned int max_buflen, int *buflen)
Definition: dispatcher.c:331
void cleanup_helper(PNegoHelper helper)
Definition: dispatcher.c:377
static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc pMessage, int token_idx, SignDirection direction, BOOL encrypt_sig)
Definition: ntlm.c:1536
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: ntlm.c:1427
#define NTLM_COMMENT
Definition: ntlm.c:1979
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
Definition: ntlm.c:70
SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: ntlm.c:484
static CHAR ntlm_comment_A[]
Definition: ntlm.c:1984
static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1510
SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: ntlm.c:1029
static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse, PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: ntlm.c:290
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: ntlm.c:1482
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
Definition: ntlm.c:49
#define NTLM_MAX_BUF
Definition: ntlm.c:35
SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: ntlm.c:1697
static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
Definition: ntlm.c:438
static CHAR ntlm_auth[]
Definition: ntlm.c:44
static const SecurityFunctionTableW ntlmTableW
Definition: ntlm.c:1948
static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
Definition: ntlm.c:403
SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
Definition: ntlm.c:1767
#define MIN_NTLM_AUTH_MICRO_VERSION
Definition: ntlm.c:39
static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1491
SecPkgInfoW * ntlm_package_infoW
Definition: ntlm.c:2024
static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
Definition: ntlm.c:1384
SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: ntlm.c:127
static char ntlm_name_A[]
Definition: ntlm.c:1989
void SECUR32_initNTLMSP(void)
Definition: ntlm.c:2026
static int ntlm_GetDataBufferIndex(PSecBufferDesc pMessage)
Definition: ntlm.c:423
#define NTLM_NAME
Definition: ntlm.c:1987
static const SecurityFunctionTableA ntlmTableA
Definition: ntlm.c:1917
static char * ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
Definition: ntlm.c:106
static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
Definition: ntlm.c:995
static WCHAR ntlm_name_W[]
Definition: ntlm.c:1990
SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: ntlm.c:1662
#define MIN_NTLM_AUTH_MINOR_VERSION
Definition: ntlm.c:37
static char * ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
Definition: ntlm.c:88
static WCHAR ntlm_comment_W[]
Definition: ntlm.c:1985
SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: ntlm.c:1863
SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: ntlm.c:1792
SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1398
#define MIN_NTLM_AUTH_MAJOR_VERSION
Definition: ntlm.c:36
SecPkgInfoA * ntlm_package_infoA
Definition: ntlm.c:2023
void SECUR32_arc4Cleanup(arc4_info *a4i)
Definition: util.c:246
void SECUR32_arc4Init(arc4_info *a4i, const BYTE *key, unsigned int keyLen)
Definition: util.c:199
ULONG ComputeCrc32(const BYTE *pData, INT iLen, ULONG initial_crc)
Definition: util.c:109
void SECUR32_arc4Process(arc4_info *a4i, BYTE *inoutString, unsigned int length)
Definition: util.c:224
arc4_info * SECUR32_arc4Alloc(void)
Definition: util.c:189
#define ULONG_PTR
Definition: config.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint buffer
Definition: glext.h:5915
GLfloat GLfloat p
Definition: glext.h:8902
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void HMACMD5Final(HMAC_MD5_CTX *ctx, unsigned char *digest)
Definition: hmac_md5.c:63
void HMACMD5Update(HMAC_MD5_CTX *ctx, const unsigned char *data, unsigned int data_len)
Definition: hmac_md5.c:58
void HMACMD5Init(HMAC_MD5_CTX *ctx, const unsigned char *key, unsigned int key_len)
Definition: hmac_md5.c:24
#define WC_NO_BEST_FIT_CHARS
Definition: unicode.h:46
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
static const SecPkgInfoW infoW
Definition: kerberos.c:293
static const SecPkgInfoA infoA
Definition: kerberos.c:302
#define CAPS
Definition: kerberos.c:274
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
#define NERR_Success
Definition: lmerr.h:5
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static struct _PeImage bin
static WCHAR password[]
Definition: url.c:33
static WCHAR username[]
Definition: url.c:32
DWORD NET_API_STATUS
Definition: ms-dtyp.idl:91
unsigned int UINT
Definition: ndis.h:50
static BOOL check_version(LPCWSTR gre_path, const char *version_string)
Definition: nsembed.c:521
#define NTLMSSP_NEGOTIATE_NTLM2
Definition: ntlm.h:91
#define NTLMSSP_NEGOTIATE_SEAL
Definition: ntlm.h:81
SECURITY_STATUS SECUR32_CreateNTLM2SubKeys(PNegoHelper helper) DECLSPEC_HIDDEN
Definition: util.c:156
#define NTLMSSP_NEGOTIATE_SIGN
Definition: ntlm.h:80
#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE
Definition: ntlm.h:94
@ NTLM_RECV
Definition: ntlm.h:70
@ NTLM_SEND
Definition: ntlm.h:69
enum _sign_direction SignDirection
struct _NtlmCredentials * PNtlmCredentials
@ NTLM_SERVER
Definition: ntlm.h:11
@ NTLM_CLIENT
Definition: ntlm.h:12
struct _NegoHelper * PNegoHelper
SECURITY_STATUS SECUR32_CreateNTLM1SessionKey(PBYTE password, int len, PBYTE session_key) DECLSPEC_HIDDEN
Definition: util.c:122
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN
Definition: ntlm.h:88
PVOID *typedef PSecBuffer
Definition: ntsecpkg.h:440
UINT ui
Definition: oleauto.h:49
BYTE * PBYTE
Definition: pedump.c:66
#define ISC_RET_DELEGATE
Definition: sspi.h:385
#define SECPKG_ATTR_ACCESS_TOKEN
Definition: sspi.h:539
struct _SecPkgContext_Flags * PSecPkgContext_Flags
#define ISC_REQ_CONFIDENTIALITY
Definition: sspi.h:366
LONG SECURITY_STATUS
Definition: sspi.h:34
#define ISC_RET_EXTENDED_ERROR
Definition: sspi.h:399
#define ASC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:432
#define ISC_REQ_STREAM
Definition: sspi.h:377
#define SECPKG_ATTR_SESSION_KEY
Definition: sspi.h:530
#define ISC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:370
#define ASC_REQ_CONNECTION
Definition: sspi.h:435
#define SECPKG_CRED_BOTH
Definition: sspi.h:292
#define ASC_REQ_CONFIDENTIALITY
Definition: sspi.h:430
#define SECPKG_ATTR_AUTHORITY
Definition: sspi.h:527
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:291
#define ISC_REQ_EXTENDED_ERROR
Definition: sspi.h:376
#define SECPKG_ATTR_KEY_INFO
Definition: sspi.h:526
#define SECBUFFER_TOKEN
Definition: sspi.h:161
#define ASC_RET_CONNECTION
Definition: sspi.h:458
#define SECURITY_NETWORK_DREP
Definition: sspi.h:474
#define SECPKG_ATTR_PACKAGE_INFO
Definition: sspi.h:531
#define ISC_REQ_SEQUENCE_DETECT
Definition: sspi.h:365
CHAR SEC_CHAR
Definition: sspi.h:30
#define SECPKG_ATTR_NEGOTIATION_INFO
Definition: sspi.h:533
#define ISC_RET_USED_DCE_STYLE
Definition: sspi.h:394
#define ISC_REQ_REPLAY_DETECT
Definition: sspi.h:364
struct _SecPkgContext_Sizes * PSecPkgContext_Sizes
#define ASC_REQ_REPLAY_DETECT
Definition: sspi.h:428
#define ISC_REQ_INTEGRITY
Definition: sspi.h:378
#define ISC_REQ_DELEGATE
Definition: sspi.h:362
void(SEC_ENTRY * SEC_GET_KEY_FN)(void *Arg, void *Principal, ULONG KeyVer, void **Key, SECURITY_STATUS *Status)
Definition: sspi.h:189
#define ISC_RET_CONFIDENTIALITY
Definition: sspi.h:389
#define SECPKG_ATTR_TARGET_INFORMATION
Definition: sspi.h:538
#define ASC_REQ_EXTENDED_ERROR
Definition: sspi.h:438
#define SECBUFFER_DATA
Definition: sspi.h:160
#define SECPKG_ATTR_PASSWORD_EXPIRY
Definition: sspi.h:529
#define SECPKG_ATTR_LIFESPAN
Definition: sspi.h:523
#define SECPKG_CRED_INBOUND
Definition: sspi.h:290
#define SECPKG_ATTR_SIZES
Definition: sspi.h:521
#define ISC_RET_INTEGRITY
Definition: sspi.h:401
#define ISC_REQ_MUTUAL_AUTH
Definition: sspi.h:363
#define ASC_REQ_INTEGRITY
Definition: sspi.h:440
#define SECPKG_ATTR_STREAM_SIZES
Definition: sspi.h:525
#define SECPKG_ATTR_FLAGS
Definition: sspi.h:535
#define SECBUFFER_VERSION
Definition: sspi.h:187
#define SECPKG_ATTR_NAMES
Definition: sspi.h:522
WCHAR SEC_WCHAR
Definition: sspi.h:29
#define ISC_RET_MUTUAL_AUTH
Definition: sspi.h:386
#define SECPKG_ATTR_DCE_INFO
Definition: sspi.h:524
#define ASC_REQ_MUTUAL_AUTH
Definition: sspi.h:427
#define ISC_REQ_CONNECTION
Definition: sspi.h:373
#define ISC_RET_CONNECTION
Definition: sspi.h:396
#define SECPKG_ATTR_NATIVE_NAMES
Definition: sspi.h:534
#define ISC_REQ_USE_DCE_STYLE
Definition: sspi.h:371
PVOID pBuffer
#define strchrW(s, c)
Definition: unicode.h:34
#define strlenW(s)
Definition: unicode.h:28
struct _SEC_WINNT_AUTH_IDENTITY_W * PSEC_WINNT_AUTH_IDENTITY_W
#define SEC_WINNT_AUTH_IDENTITY_UNICODE
Definition: rpcdce.h:310
#define SEC_WINNT_AUTH_IDENTITY_ANSI
Definition: rpcdce.h:309
#define RPC_C_AUTHN_WINNT
Definition: rpcdce.h:158
SecureProvider * SECUR32_addProvider(const SecurityFunctionTableA *fnTableA, const SecurityFunctionTableW *fnTableW, PCWSTR moduleName) DECLSPEC_HIDDEN
Definition: secur32_wine.c:314
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd, const SecPkgInfoA *infoA, const SecPkgInfoW *infoW) DECLSPEC_HIDDEN
Definition: secur32_wine.c:362
#define ERR_(ch,...)
Definition: debug.h:156
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
LPBYTE CredentialBlob
Definition: wincred.h:90
LPWSTR UserName
Definition: wincred.h:95
DWORD CredentialBlobSize
Definition: wincred.h:89
int minor
Definition: ntlm.h:31
BYTE * session_key
Definition: ntlm.h:36
ULONG neg_flags
Definition: ntlm.h:37
struct _NegoHelper::@549 crypt
int major
Definition: ntlm.h:30
int micro
Definition: ntlm.h:32
HelperMode mode
Definition: ntlm.h:27
char * domain_arg
Definition: ntlm.h:62
HelperMode mode
Definition: ntlm.h:58
char * username_arg
Definition: ntlm.h:61
char * password
Definition: ntlm.h:63
int no_cached_credentials
Definition: ntlm.h:65
unsigned short * Domain
Definition: rpcdce.h:225
unsigned short * User
Definition: rpcdce.h:223
unsigned short * Password
Definition: rpcdce.h:227
ULONG cBuffers
Definition: sspi.h:182
ULONG ulVersion
Definition: sspi.h:181
ULONG_PTR dwLower
Definition: sspi.h:53
ULONG_PTR dwUpper
Definition: sspi.h:54
ULONG cbBlockSize
Definition: sspi.h:563
ULONG cbSecurityTrailer
Definition: sspi.h:564
ULONG cbMaxSignature
Definition: sspi.h:562
ULONG cbMaxToken
Definition: sspi.h:561
Definition: match.c:390
Definition: cookie.c:42
Definition: ps.c:97
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
int ret
#define CRED_TYPE_DOMAIN_PASSWORD
Definition: wincred.h:205
#define SEC_E_OK
Definition: winerror.h:2356
#define SEC_E_INVALID_HANDLE
Definition: winerror.h:2910
#define SEC_E_LOGON_DENIED
Definition: winerror.h:2921
#define SEC_E_INTERNAL_ERROR
Definition: winerror.h:2913
#define SEC_E_UNKNOWN_CREDENTIALS
Definition: winerror.h:2922
#define SEC_E_UNSUPPORTED_FUNCTION
Definition: winerror.h:2911
#define SEC_E_BUFFER_TOO_SMALL
Definition: winerror.h:2937
#define SEC_E_MESSAGE_ALTERED
Definition: winerror.h:2924
#define SEC_E_INVALID_TOKEN
Definition: winerror.h:2917
#define SEC_E_NO_CREDENTIALS
Definition: winerror.h:2923
#define SEC_E_INSUFFICIENT_MEMORY
Definition: winerror.h:2909
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:2927
#define SEC_E_INCOMPLETE_MESSAGE
Definition: winerror.h:2934
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193