ReactOS  0.4.13-dev-92-gf251225
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 
44 static 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 
88 static 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 
106 static 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;
134  LPWSTR domain = NULL, user = NULL, password = NULL;
135  PSEC_WINNT_AUTH_IDENTITY_W auth_data = NULL;
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  {
143  case SECPKG_CRED_INBOUND:
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  {
280  HeapFree(GetProcessHeap(), 0, domain);
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,
325  sizeof(SEC_WINNT_AUTH_IDENTITY_W));
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));
362  MultiByteToWideChar(CP_ACP, 0, (LPCSTR)identity->Password,
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  {
380  pAuthDataW = (PSEC_WINNT_AUTH_IDENTITY_W)identity;
381  }
382  }
383 
384  ret = ntlm_AcquireCredentialsHandleW(NULL, package, fCredentialUse,
385  pLogonID, pAuthDataW, pGetKeyFn, pGetKeyArgument, phCredential,
386  ptsExpiry);
387 
388  HeapFree(GetProcessHeap(), 0, package);
390  HeapFree(GetProcessHeap(), 0, domain);
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 
438 static 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;
499  SEC_CHAR *domain = NULL;
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  {
572  domain = ntlm_GetDomainArg(NULL, 0);
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 
982 isc_end:
984  HeapFree(GetProcessHeap(), 0, domain);
986  HeapFree(GetProcessHeap(), 0, want_flags);
988  HeapFree(GetProcessHeap(), 0, bin);
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 {
1002  SEC_WCHAR *target = NULL;
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 
1374 asc_end:
1375  HeapFree(GetProcessHeap(), 0, want_flags);
1377  HeapFree(GetProcessHeap(), 0, bin);
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)
1449  spcf->Flags |= ISC_RET_CONFIDENTIALITY;
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)
1686  return SEC_E_BUFFER_TOO_SMALL;
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)
1719  return SEC_E_BUFFER_TOO_SMALL;
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)
1819  return SEC_E_BUFFER_TOO_SMALL;
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;
1843  helper->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
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)
1888  return SEC_E_BUFFER_TOO_SMALL;
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 
1909  helper->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
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 
1989 static 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 
2005 static const SecPkgInfoW infoW = {
2006  CAPS,
2007  1,
2009  NTLM_MAX_BUF,
2010  ntlm_name_W,
2012 };
2013 
2014 static const SecPkgInfoA infoA = {
2015  CAPS,
2016  1,
2018  NTLM_MAX_BUF,
2019  ntlm_name_A,
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 &&
2044  helper->minor > MIN_NTLM_AUTH_MINOR_VERSION) ||
2045  (helper->major == MIN_NTLM_AUTH_MAJOR_VERSION &&
2046  helper->minor == MIN_NTLM_AUTH_MINOR_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 }
#define ISC_REQ_SEQUENCE_DETECT
Definition: sspi.h:351
#define SEC_E_INTERNAL_ERROR
Definition: winerror.h:2913
DWORD CredentialBlobSize
Definition: wincred.h:89
#define SECPKG_ATTR_NATIVE_NAMES
Definition: sspi.h:520
LPBYTE CredentialBlob
Definition: wincred.h:90
#define ASC_REQ_REPLAY_DETECT
Definition: sspi.h:414
int major
Definition: ntlm.h:30
#define RPC_C_AUTHN_WINNT
Definition: rpcdce.h:158
#define ASC_RET_CONNECTION
Definition: sspi.h:444
#define SECPKG_ATTR_KEY_INFO
Definition: sspi.h:512
#define CAPS
Definition: ntlm.c:1993
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd, const SecPkgInfoA *infoA, const SecPkgInfoW *infoW) DECLSPEC_HIDDEN
Definition: secur32_wine.c:362
#define SECPKG_ATTR_DCE_INFO
Definition: sspi.h:510
unsigned short * Domain
Definition: rpcdce.h:225
#define TRUE
Definition: types.h:120
unsigned short * User
Definition: rpcdce.h:223
#define SECPKG_ATTR_PACKAGE_INFO
Definition: sspi.h:517
static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1491
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:277
arc4_info * SECUR32_arc4Alloc(void)
Definition: util.c:189
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
void SECUR32_initNTLMSP(void)
Definition: ntlm.c:2026
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define SECPKG_ATTR_PASSWORD_EXPIRY
Definition: sspi.h:515
#define WideCharToMultiByte
Definition: compat.h:101
struct _NegoHelper * PNegoHelper
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
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
SecPkgInfoW * ntlm_package_infoW
Definition: ntlm.c:2024
WCHAR SEC_WCHAR
Definition: sspi.h:29
#define ISC_REQ_EXTENDED_ERROR
Definition: sspi.h:362
SecPkgInfoA * ntlm_package_infoA
Definition: ntlm.c:2023
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
#define ISC_RET_CONFIDENTIALITY
Definition: sspi.h:375
unsigned short * Password
Definition: rpcdce.h:227
ULONG ulVersion
Definition: sspi.h:167
#define ISC_REQ_STREAM
Definition: sspi.h:363
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
HelperMode mode
Definition: ntlm.h:27
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define CP_ACP
Definition: compat.h:99
char * password
Definition: ntlm.h:63
char CHAR
Definition: xmlstorage.h:175
static BOOL check_version(LPCWSTR gre_path, const char *version_string)
Definition: nsembed.c:521
static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
Definition: ntlm.c:403
#define U(x)
Definition: wordpad.c:44
void HMACMD5Init(HMAC_MD5_CTX *ctx, const unsigned char *key, unsigned int key_len)
Definition: hmac_md5.c:24
UINT ui
Definition: oleauto.h:49
#define ERR_(ch,...)
Definition: debug.h:156
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
Definition: ntlm.c:70
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: ntlm.c:1427
SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char *out_buf, int max_len, int *out_len)
Definition: base64_codec.c:29
#define ASC_REQ_CONNECTION
Definition: sspi.h:421
#define SECBUFFER_DATA
Definition: sspi.h:146
GLuint buffer
Definition: glext.h:5915
#define ISC_REQ_DELEGATE
Definition: sspi.h:348
static WCHAR ntlm_comment_W[]
Definition: ntlm.c:1985
ULONG_PTR dwLower
Definition: sspi.h:53
#define SEC_E_MESSAGE_ALTERED
Definition: winerror.h:2924
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 PSecPkgInfoA *static SEC_CHAR SEC_GET_KEY_FN
Definition: ntlm.c:66
void cleanup_helper(PNegoHelper helper)
Definition: dispatcher.c:377
#define ASC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:418
ULONG cbBlockSize
Definition: sspi.h:549
WINE_DECLARE_DEBUG_CHANNEL(winediag)
ULONG ComputeCrc32(const BYTE *pData, INT iLen, ULONG initial_crc)
Definition: util.c:109
#define SEC_E_UNSUPPORTED_FUNCTION
Definition: winerror.h:2911
Definition: match.c:390
#define SECPKG_ATTR_ACCESS_TOKEN
Definition: sspi.h:525
SecureProvider * SECUR32_addProvider(const SecurityFunctionTableA *fnTableA, const SecurityFunctionTableW *fnTableW, PCWSTR moduleName) DECLSPEC_HIDDEN
Definition: secur32_wine.c:314
int32_t INT
Definition: typedefs.h:56
LPWSTR UserName
Definition: wincred.h:95
SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: ntlm.c:1662
static const SecPkgInfoA infoA
Definition: ntlm.c:2014
WINE_DEFAULT_DEBUG_CHANNEL(ntlm)
#define NERR_Success
Definition: lmerr.h:5
struct _SecPkgContext_Sizes * PSecPkgContext_Sizes
#define SEC_E_LOGON_DENIED
Definition: winerror.h:2921
ULONG cbMaxSignature
Definition: sspi.h:548
SECURITY_STATUS SECUR32_CreateNTLM2SubKeys(PNegoHelper helper) DECLSPEC_HIDDEN
Definition: util.c:156
static int ntlm_GetDataBufferIndex(PSecBufferDesc pMessage)
Definition: ntlm.c:423
#define save_flags(x)
Definition: utils.h:285
#define ISC_RET_CONNECTION
Definition: sspi.h:382
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
int minor
Definition: ntlm.h:31
#define SECPKG_ATTR_SIZES
Definition: sspi.h:507
unsigned char * LPBYTE
Definition: typedefs.h:52
#define SEC_E_INSUFFICIENT_MEMORY
Definition: winerror.h:2909
unsigned int BOOL
Definition: ntddk_ex.h:94
SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
Definition: ntlm.c:1482
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
static WCHAR ntlm_name_W[]
Definition: ntlm.c:1990
#define SECPKG_CRED_INBOUND
Definition: sspi.h:276
static char * ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
Definition: ntlm.c:88
static char * ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
Definition: ntlm.c:106
smooth NULL
Definition: ftsmooth.c:416
struct _NtlmCredentials * PNtlmCredentials
static const WCHAR version[]
Definition: asmname.c:64
PVOID pBuffer
#define SECPKG_ATTR_NEGOTIATION_INFO
Definition: sspi.h:519
static char ntlm_name_A[]
Definition: ntlm.c:1989
SECURITY_STATUS decodeBase64(char *in_buf, int in_len, PBYTE out_buf, int max_len, int *out_len)
Definition: base64_codec.c:113
#define SEC_I_CONTINUE_NEEDED
Definition: winerror.h:2927
#define NTLMSSP_NEGOTIATE_SEAL
Definition: ntlm.h:81
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
const char * LPCSTR
Definition: xmlstorage.h:183
static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
Definition: ntlm.c:438
Definition: bcd.h:202
#define MIN_NTLM_AUTH_MICRO_VERSION
Definition: ntlm.c:39
LONG SECURITY_STATUS
Definition: sspi.h:34
#define MIN_NTLM_AUTH_MAJOR_VERSION
Definition: ntlm.c:36
#define CRED_TYPE_DOMAIN_PASSWORD
Definition: wincred.h:205
#define ISC_REQ_INTEGRITY
Definition: sspi.h:364
#define SEC_ENTRY
Definition: stubs.c:6
static WCHAR username[]
Definition: url.c:32
r l[0]
Definition: byte_order.h:167
#define ASC_REQ_EXTENDED_ERROR
Definition: sspi.h:424
#define NTLM_COMMENT
Definition: ntlm.c:1979
DWORD NET_API_STATUS
Definition: ms-dtyp.idl:91
NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level, PBYTE *bufptr)
Definition: wksta.c:279
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
Definition: ntlm.c:49
#define SECPKG_ATTR_LIFESPAN
Definition: sspi.h:509
#define TRACE(s)
Definition: solgame.cpp:4
#define SECPKG_ATTR_AUTHORITY
Definition: sspi.h:513
#define GetProcessHeap()
Definition: compat.h:395
struct _NegoHelper::@516 crypt
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
VOID WINAPI CredFree(PVOID Buffer)
Definition: cred.c:1395
#define CP_UNIXCP
Definition: compat.h:69
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
PVOID *typedef PSecBuffer
Definition: ntsecpkg.h:400
#define ISC_RET_EXTENDED_ERROR
Definition: sspi.h:385
#define ASC_REQ_CONFIDENTIALITY
Definition: sspi.h:416
#define SEC_WINNT_AUTH_IDENTITY_UNICODE
Definition: rpcdce.h:310
SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: ntlm.c:1863
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN
Definition: ntlm.h:88
void SECUR32_arc4Process(arc4_info *a4i, BYTE *inoutString, unsigned int length)
Definition: util.c:224
ULONG neg_flags
Definition: ntlm.h:37
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
#define WC_NO_BEST_FIT_CHARS
Definition: unicode.h:46
#define SECPKG_ATTR_STREAM_SIZES
Definition: sspi.h:511
#define ISC_RET_MUTUAL_AUTH
Definition: sspi.h:372
void HMACMD5Final(HMAC_MD5_CTX *ctx, unsigned char *digest)
Definition: hmac_md5.c:63
#define SEC_E_INVALID_HANDLE
Definition: winerror.h:2910
int ret
SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
Definition: ntlm.c:1792
static CHAR ntlm_comment_A[]
Definition: ntlm.c:1984
#define ISC_REQ_ALLOCATE_MEMORY
Definition: sspi.h:356
static const WCHAR L[]
Definition: oid.c:1250
#define MIN_NTLM_AUTH_MINOR_VERSION
Definition: ntlm.c:37
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
ULONG cbSecurityTrailer
Definition: sspi.h:550
struct _SecPkgContext_Flags * PSecPkgContext_Flags
#define SECBUFFER_TOKEN
Definition: sspi.h:147
#define SEC_E_INVALID_TOKEN
Definition: winerror.h:2917
SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1398
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
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
#define ASC_REQ_INTEGRITY
Definition: sspi.h:426
unsigned char BYTE
Definition: mem.h:68
#define ISC_REQ_USE_DCE_STYLE
Definition: sspi.h:357
#define ISC_RET_DELEGATE
Definition: sspi.h:371
#define SECURITY_NETWORK_DREP
Definition: sspi.h:460
SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
Definition: ntlm.c:1697
struct _SEC_WINNT_AUTH_IDENTITY_W * PSEC_WINNT_AUTH_IDENTITY_W
#define SEC_E_OK
Definition: winerror.h:2356
#define debugstr_wn
Definition: kernel32.h:33
BYTE * session_key
Definition: ntlm.h:36
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
#define SEC_WINNT_AUTH_IDENTITY_ANSI
Definition: rpcdce.h:309
#define ISC_REQ_CONNECTION
Definition: sspi.h:359
#define ERR(fmt,...)
Definition: debug.h:109
int micro
Definition: ntlm.h:32
#define SECPKG_ATTR_NAMES
Definition: sspi.h:508
char * username_arg
Definition: ntlm.h:61
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
NET_API_STATUS WINAPI NetApiBufferFree(LPVOID Buffer)
Definition: apibuf.c:43
#define SECPKG_CRED_BOTH
Definition: sspi.h:278
static const SecPkgInfoW infoW
Definition: ntlm.c:2005
#define SECBUFFER_VERSION
Definition: sspi.h:173
BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential)
Definition: cred.c:1450
ULONG cbMaxToken
Definition: sspi.h:547
static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
Definition: ntlm.c:1384
#define SECPKG_ATTR_FLAGS
Definition: sspi.h:521
SECURITY_STATUS SECUR32_CreateNTLM1SessionKey(PBYTE password, int len, PBYTE session_key) DECLSPEC_HIDDEN
Definition: util.c:122
HelperMode mode
Definition: ntlm.h:58
#define ASC_REQ_MUTUAL_AUTH
Definition: sspi.h:413
void SECUR32_arc4Cleanup(arc4_info *a4i)
Definition: util.c:246
SECURITY_STATUS run_helper(PNegoHelper helper, char *buffer, unsigned int max_buflen, int *buflen)
Definition: dispatcher.c:331
unsigned int * PULONG
Definition: retypes.h:1
#define ISC_RET_USED_DCE_STYLE
Definition: sspi.h:380
#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE
Definition: ntlm.h:94
unsigned int UINT
Definition: ndis.h:50
#define NTLMSSP_NEGOTIATE_NTLM2
Definition: ntlm.h:91
static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext)
Definition: ntlm.c:1510
CHAR SEC_CHAR
Definition: sspi.h:30
Definition: bcd.h:201
#define lstrcpynA
Definition: compat.h:408
#define ISC_REQ_MUTUAL_AUTH
Definition: sspi.h:349
static const SecurityFunctionTableA ntlmTableA
Definition: ntlm.c:1917
ULONG_PTR dwUpper
Definition: sspi.h:54
#define SEC_E_BUFFER_TOO_SMALL
Definition: winerror.h:2937
#define MultiByteToWideChar
Definition: compat.h:100
static SECURITY_STATUS ntlm_CreateSignature(PNegoHelper helper, PSecBufferDesc pMessage, int token_idx, SignDirection direction, BOOL encrypt_sig)
Definition: ntlm.c:1536
static struct _PeImage bin
#define NTLM_MAX_BUF
Definition: ntlm.c:35
int no_cached_credentials
Definition: ntlm.h:65
#define SECPKG_ATTR_TARGET_INFORMATION
Definition: sspi.h:524
#define NTLMSSP_NEGOTIATE_SIGN
Definition: ntlm.h:80
enum _sign_direction SignDirection
void HMACMD5Update(HMAC_MD5_CTX *ctx, const unsigned char *data, unsigned int data_len)
Definition: hmac_md5.c:58
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
Definition: ntlm.h:69
static CHAR ntlm_auth[]
Definition: ntlm.c:44
#define ULONG_PTR
Definition: config.h:101
#define ISC_REQ_CONFIDENTIALITY
Definition: sspi.h:352
#define _x(x)
#define SEC_E_NO_CREDENTIALS
Definition: winerror.h:2923
#define SEC_E_UNKNOWN_CREDENTIALS
Definition: winerror.h:2922
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
#define ISC_REQ_REPLAY_DETECT
Definition: sspi.h:350
SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle phCredential)
Definition: ntlm.c:1767
void SECUR32_arc4Init(arc4_info *a4i, const BYTE *key, unsigned int keyLen)
Definition: util.c:199
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
ULONG cBuffers
Definition: sspi.h:168
#define memset(x, y, z)
Definition: compat.h:39
#define ISC_RET_INTEGRITY
Definition: sspi.h:387
static SERVICE_STATUS status
Definition: service.c:31
SECURITY_STATUS fork_helper(PNegoHelper *new_helper, const char *prog, char *const argv[])
Definition: dispatcher.c:76
#define SECPKG_ATTR_SESSION_KEY
Definition: sspi.h:516
#define NTLM_NAME
Definition: ntlm.c:1987
BYTE * PBYTE
Definition: pedump.c:66
static const SecurityFunctionTableW ntlmTableW
Definition: ntlm.c:1948
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define HeapFree(x, y, z)
Definition: compat.h:394
#define SEC_E_INCOMPLETE_MESSAGE
Definition: winerror.h:2934
char * domain_arg
Definition: ntlm.h:62
Definition: ntlm.h:70
Definition: ps.c:97