FreeRDP
sspi_winpr.c
1 
21 #include <winpr/config.h>
22 #include <winpr/assert.h>
23 #include <winpr/windows.h>
24 
25 #include <winpr/crt.h>
26 #include <winpr/sspi.h>
27 #include <winpr/ssl.h>
28 #include <winpr/print.h>
29 
30 #include "sspi.h"
31 
32 #include "sspi_winpr.h"
33 
34 #include "../log.h"
35 #define TAG WINPR_TAG("sspi")
36 
37 /* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */
38 
39 #include "NTLM/ntlm.h"
40 #include "NTLM/ntlm_export.h"
41 #include "CredSSP/credssp.h"
42 #include "Kerberos/kerberos.h"
43 #include "Negotiate/negotiate.h"
44 #include "Schannel/schannel.h"
45 
46 static const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, &KERBEROS_SecPkgInfoA,
47  &NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA,
48  &SCHANNEL_SecPkgInfoA };
49 
50 static const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, &KERBEROS_SecPkgInfoW,
51  &NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW,
52  &SCHANNEL_SecPkgInfoW };
53 
54 static SecurityFunctionTableA winpr_SecurityFunctionTableA;
55 static SecurityFunctionTableW winpr_SecurityFunctionTableW;
56 
57 typedef struct
58 {
59  const SEC_CHAR* Name;
60  const SecurityFunctionTableA* SecurityFunctionTable;
61 } SecurityFunctionTableA_NAME;
62 
63 typedef struct
64 {
65  const SEC_WCHAR* Name;
66  const SecurityFunctionTableW* SecurityFunctionTable;
67 } SecurityFunctionTableW_NAME;
68 
69 static const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = {
70  { "NTLM", &NTLM_SecurityFunctionTableA },
71  { "Kerberos", &KERBEROS_SecurityFunctionTableA },
72  { "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
73  { "CREDSSP", &CREDSSP_SecurityFunctionTableA },
74  { "Schannel", &SCHANNEL_SecurityFunctionTableA }
75 };
76 
77 static WCHAR BUFFER_NAME_LIST_W[5][32] = { 0 };
78 
79 static const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = {
80  { BUFFER_NAME_LIST_W[0], &NTLM_SecurityFunctionTableW },
81  { BUFFER_NAME_LIST_W[1], &KERBEROS_SecurityFunctionTableW },
82  { BUFFER_NAME_LIST_W[2], &NEGOTIATE_SecurityFunctionTableW },
83  { BUFFER_NAME_LIST_W[3], &CREDSSP_SecurityFunctionTableW },
84  { BUFFER_NAME_LIST_W[4], &SCHANNEL_SecurityFunctionTableW }
85 };
86 
87 #define SecHandle_LOWER_MAX 0xFFFFFFFF
88 #define SecHandle_UPPER_MAX 0xFFFFFFFE
89 
90 typedef struct
91 {
92  void* contextBuffer;
93  UINT32 allocatorIndex;
94 } CONTEXT_BUFFER_ALLOC_ENTRY;
95 
96 typedef struct
97 {
98  UINT32 cEntries;
99  UINT32 cMaxEntries;
100  CONTEXT_BUFFER_ALLOC_ENTRY* entries;
101 } CONTEXT_BUFFER_ALLOC_TABLE;
102 
103 static CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable = { 0 };
104 
105 static int sspi_ContextBufferAllocTableNew(void)
106 {
107  size_t size = 0;
108  ContextBufferAllocTable.entries = NULL;
109  ContextBufferAllocTable.cEntries = 0;
110  ContextBufferAllocTable.cMaxEntries = 4;
111  size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
112  ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)calloc(1, size);
113 
114  if (!ContextBufferAllocTable.entries)
115  return -1;
116 
117  return 1;
118 }
119 
120 static int sspi_ContextBufferAllocTableGrow(void)
121 {
122  size_t size = 0;
123  CONTEXT_BUFFER_ALLOC_ENTRY* entries = NULL;
124  ContextBufferAllocTable.cEntries = 0;
125  ContextBufferAllocTable.cMaxEntries *= 2;
126  size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
127 
128  if (!size)
129  return -1;
130 
131  entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)realloc(ContextBufferAllocTable.entries, size);
132 
133  if (!entries)
134  {
135  free(ContextBufferAllocTable.entries);
136  return -1;
137  }
138 
139  ContextBufferAllocTable.entries = entries;
140  ZeroMemory((void*)&ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
141  size / 2);
142  return 1;
143 }
144 
145 static void sspi_ContextBufferAllocTableFree(void)
146 {
147  if (ContextBufferAllocTable.cEntries != 0)
148  WLog_ERR(TAG, "ContextBufferAllocTable.entries == %" PRIu32,
149  ContextBufferAllocTable.cEntries);
150 
151  ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0;
152  free(ContextBufferAllocTable.entries);
153  ContextBufferAllocTable.entries = NULL;
154 }
155 
156 static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
157 {
158  void* contextBuffer = NULL;
159 
160  for (UINT32 index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
161  {
162  if (!ContextBufferAllocTable.entries[index].contextBuffer)
163  {
164  contextBuffer = calloc(1, size);
165 
166  if (!contextBuffer)
167  return NULL;
168 
169  ContextBufferAllocTable.cEntries++;
170  ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
171  ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
172  return ContextBufferAllocTable.entries[index].contextBuffer;
173  }
174  }
175 
176  /* no available entry was found, the table needs to be grown */
177 
178  if (sspi_ContextBufferAllocTableGrow() < 0)
179  return NULL;
180 
181  /* the next call to sspi_ContextBufferAlloc() should now succeed */
182  return sspi_ContextBufferAlloc(allocatorIndex, size);
183 }
184 
185 SSPI_CREDENTIALS* sspi_CredentialsNew(void)
186 {
187  SSPI_CREDENTIALS* credentials = NULL;
188  credentials = (SSPI_CREDENTIALS*)calloc(1, sizeof(SSPI_CREDENTIALS));
189  return credentials;
190 }
191 
192 void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
193 {
194  size_t userLength = 0;
195  size_t domainLength = 0;
196  size_t passwordLength = 0;
197 
198  if (!credentials)
199  return;
200 
201  if (credentials->ntlmSettings.samFile)
202  free(credentials->ntlmSettings.samFile);
203 
204  userLength = credentials->identity.UserLength;
205  domainLength = credentials->identity.DomainLength;
206  passwordLength = credentials->identity.PasswordLength;
207 
208  if (passwordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) /* [pth] */
209  passwordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
210 
211  if (credentials->identity.Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
212  {
213  userLength *= 2;
214  domainLength *= 2;
215  passwordLength *= 2;
216  }
217 
218  if (credentials->identity.User)
219  memset(credentials->identity.User, 0, userLength);
220  if (credentials->identity.Domain)
221  memset(credentials->identity.Domain, 0, domainLength);
222  if (credentials->identity.Password)
223  memset(credentials->identity.Password, 0, passwordLength);
224  free(credentials->identity.User);
225  free(credentials->identity.Domain);
226  free(credentials->identity.Password);
227  free(credentials);
228 }
229 
230 void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
231 {
232  if (!SecBuffer)
233  return NULL;
234 
235  SecBuffer->pvBuffer = calloc(1, size);
236 
237  if (!SecBuffer->pvBuffer)
238  return NULL;
239 
240  SecBuffer->cbBuffer = size;
241  return SecBuffer->pvBuffer;
242 }
243 
244 void sspi_SecBufferFree(PSecBuffer SecBuffer)
245 {
246  if (!SecBuffer)
247  return;
248 
249  if (SecBuffer->pvBuffer)
250  memset(SecBuffer->pvBuffer, 0, SecBuffer->cbBuffer);
251 
252  free(SecBuffer->pvBuffer);
253  SecBuffer->pvBuffer = NULL;
254  SecBuffer->cbBuffer = 0;
255 }
256 
257 SecHandle* sspi_SecureHandleAlloc(void)
258 {
259  SecHandle* handle = (SecHandle*)calloc(1, sizeof(SecHandle));
260 
261  if (!handle)
262  return NULL;
263 
264  SecInvalidateHandle(handle);
265  return handle;
266 }
267 
268 void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
269 {
270  void* pointer = NULL;
271 
272  if (!handle || !SecIsValidHandle(handle) || !handle->dwLower)
273  return NULL;
274 
275  pointer = (void*)~((size_t)handle->dwLower);
276  return pointer;
277 }
278 
279 void sspi_SecureHandleInvalidate(SecHandle* handle)
280 {
281  if (!handle)
282  return;
283 
284  handle->dwLower = 0;
285  handle->dwUpper = 0;
286 }
287 
288 void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
289 {
290  if (!handle)
291  return;
292 
293  handle->dwLower = (ULONG_PTR)(~((size_t)pointer));
294 }
295 
296 void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
297 {
298  void* pointer = NULL;
299 
300  if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper)
301  return NULL;
302 
303  pointer = (void*)~((size_t)handle->dwUpper);
304  return pointer;
305 }
306 
307 void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
308 {
309  if (!handle)
310  return;
311 
312  handle->dwUpper = (ULONG_PTR)(~((size_t)pointer));
313 }
314 
315 void sspi_SecureHandleFree(SecHandle* handle)
316 {
317  free(handle);
318 }
319 
320 int sspi_SetAuthIdentityW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user, const WCHAR* domain,
321  const WCHAR* password)
322 {
323  return sspi_SetAuthIdentityWithLengthW(identity, user, user ? _wcslen(user) : 0, domain,
324  domain ? _wcslen(domain) : 0, password,
325  password ? _wcslen(password) : 0);
326 }
327 
328 static BOOL copy(WCHAR** dst, ULONG* dstLen, const WCHAR* what, size_t len)
329 {
330  WINPR_ASSERT(dst);
331  WINPR_ASSERT(dstLen);
332 
333  *dst = NULL;
334  *dstLen = 0;
335 
336  if (len > UINT32_MAX)
337  return FALSE;
338 
339  /* Case what="" and len=0 should allocate an empty string */
340  if (!what && (len != 0))
341  return FALSE;
342  if (!what && (len == 0))
343  return TRUE;
344 
345  *dst = calloc(sizeof(WCHAR), len + 1);
346  if (!*dst)
347  return FALSE;
348 
349  memcpy(*dst, what, len * sizeof(WCHAR));
350  *dstLen = (UINT32)len;
351  return TRUE;
352 }
353 
354 int sspi_SetAuthIdentityWithLengthW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user,
355  size_t userLen, const WCHAR* domain, size_t domainLen,
356  const WCHAR* password, size_t passwordLen)
357 {
358  WINPR_ASSERT(identity);
359  sspi_FreeAuthIdentity(identity);
360  identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
361  identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
362 
363  if (!copy(&identity->User, &identity->UserLength, user, userLen))
364  return -1;
365 
366  if (!copy(&identity->Domain, &identity->DomainLength, domain, domainLen))
367  return -1;
368 
369  if (!copy(&identity->Password, &identity->PasswordLength, password, passwordLen))
370  return -1;
371 
372  return 1;
373 }
374 
375 static void zfree(WCHAR* str, size_t len)
376 {
377  if (str)
378  memset(str, 0, len * sizeof(WCHAR));
379  free(str);
380 }
381 
382 int sspi_SetAuthIdentityA(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain,
383  const char* password)
384 {
385  int rc = 0;
386  size_t unicodeUserLenW = 0;
387  size_t unicodeDomainLenW = 0;
388  size_t unicodePasswordLenW = 0;
389  LPWSTR unicodeUser = NULL;
390  LPWSTR unicodeDomain = NULL;
391  LPWSTR unicodePassword = NULL;
392 
393  if (user)
394  unicodeUser = ConvertUtf8ToWCharAlloc(user, &unicodeUserLenW);
395 
396  if (domain)
397  unicodeDomain = ConvertUtf8ToWCharAlloc(domain, &unicodeDomainLenW);
398 
399  if (password)
400  unicodePassword = ConvertUtf8ToWCharAlloc(password, &unicodePasswordLenW);
401 
402  rc = sspi_SetAuthIdentityWithLengthW(identity, unicodeUser, unicodeUserLenW, unicodeDomain,
403  unicodeDomainLenW, unicodePassword, unicodePasswordLenW);
404 
405  zfree(unicodeUser, unicodeUserLenW);
406  zfree(unicodeDomain, unicodeDomainLenW);
407  zfree(unicodePassword, unicodePasswordLenW);
408  return rc;
409 }
410 
411 UINT32 sspi_GetAuthIdentityVersion(const void* identity)
412 {
413  UINT32 version = 0;
414 
415  if (!identity)
416  return 0;
417 
418  version = *((const UINT32*)identity);
419 
420  if ((version == SEC_WINNT_AUTH_IDENTITY_VERSION) ||
421  (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2))
422  {
423  return version;
424  }
425 
426  return 0; // SEC_WINNT_AUTH_IDENTITY (no version)
427 }
428 
429 UINT32 sspi_GetAuthIdentityFlags(const void* identity)
430 {
431  UINT32 version = 0;
432  UINT32 flags = 0;
433 
434  if (!identity)
435  return 0;
436 
437  version = sspi_GetAuthIdentityVersion(identity);
438 
439  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
440  {
441  flags = ((const SEC_WINNT_AUTH_IDENTITY_EX*)identity)->Flags;
442  }
443  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
444  {
445  flags = ((const SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->Flags;
446  }
447  else // SEC_WINNT_AUTH_IDENTITY
448  {
449  flags = ((const SEC_WINNT_AUTH_IDENTITY*)identity)->Flags;
450  }
451 
452  return flags;
453 }
454 
455 BOOL sspi_GetAuthIdentityUserDomainW(const void* identity, const WCHAR** pUser, UINT32* pUserLength,
456  const WCHAR** pDomain, UINT32* pDomainLength)
457 {
458  UINT32 version = 0;
459 
460  if (!identity)
461  return FALSE;
462 
463  version = sspi_GetAuthIdentityVersion(identity);
464 
465  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
466  {
467  const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
468  *pUser = (const WCHAR*)id->User;
469  *pUserLength = id->UserLength;
470  *pDomain = (const WCHAR*)id->Domain;
471  *pDomainLength = id->DomainLength;
472  }
473  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
474  {
475  const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
476  UINT32 UserOffset = id->UserOffset;
477  UINT32 DomainOffset = id->DomainOffset;
478  *pUser = (const WCHAR*)&((const uint8_t*)identity)[UserOffset];
479  *pUserLength = id->UserLength / 2;
480  *pDomain = (const WCHAR*)&((const uint8_t*)identity)[DomainOffset];
481  *pDomainLength = id->DomainLength / 2;
482  }
483  else // SEC_WINNT_AUTH_IDENTITY
484  {
485  const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
486  *pUser = (const WCHAR*)id->User;
487  *pUserLength = id->UserLength;
488  *pDomain = (const WCHAR*)id->Domain;
489  *pDomainLength = id->DomainLength;
490  }
491 
492  return TRUE;
493 }
494 
495 BOOL sspi_GetAuthIdentityUserDomainA(const void* identity, const char** pUser, UINT32* pUserLength,
496  const char** pDomain, UINT32* pDomainLength)
497 {
498  UINT32 version = 0;
499 
500  if (!identity)
501  return FALSE;
502 
503  version = sspi_GetAuthIdentityVersion(identity);
504 
505  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
506  {
507  const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
508  *pUser = (const char*)id->User;
509  *pUserLength = id->UserLength;
510  *pDomain = (const char*)id->Domain;
511  *pDomainLength = id->DomainLength;
512  }
513  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
514  {
515  const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
516  UINT32 UserOffset = id->UserOffset;
517  UINT32 DomainOffset = id->DomainOffset;
518  *pUser = (const char*)&((const uint8_t*)identity)[UserOffset];
519  *pUserLength = id->UserLength;
520  *pDomain = (const char*)&((const uint8_t*)identity)[DomainOffset];
521  *pDomainLength = id->DomainLength;
522  }
523  else // SEC_WINNT_AUTH_IDENTITY
524  {
525  const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
526  *pUser = (const char*)id->User;
527  *pUserLength = id->UserLength;
528  *pDomain = (const char*)id->Domain;
529  *pDomainLength = id->DomainLength;
530  }
531 
532  return TRUE;
533 }
534 
535 BOOL sspi_GetAuthIdentityPasswordW(const void* identity, const WCHAR** pPassword,
536  UINT32* pPasswordLength)
537 {
538  UINT32 version = 0;
539 
540  if (!identity)
541  return FALSE;
542 
543  version = sspi_GetAuthIdentityVersion(identity);
544 
545  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
546  {
547  const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
548  *pPassword = (const WCHAR*)id->Password;
549  *pPasswordLength = id->PasswordLength;
550  }
551  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
552  {
553  return FALSE; // TODO: packed credentials
554  }
555  else // SEC_WINNT_AUTH_IDENTITY
556  {
557  const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
558  *pPassword = (const WCHAR*)id->Password;
559  *pPasswordLength = id->PasswordLength;
560  }
561 
562  return TRUE;
563 }
564 
565 BOOL sspi_GetAuthIdentityPasswordA(const void* identity, const char** pPassword,
566  UINT32* pPasswordLength)
567 {
568  UINT32 version = 0;
569 
570  if (!identity)
571  return FALSE;
572 
573  version = sspi_GetAuthIdentityVersion(identity);
574 
575  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
576  {
577  const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
578  *pPassword = (const char*)id->Password;
579  *pPasswordLength = id->PasswordLength;
580  }
581  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
582  {
583  return FALSE; // TODO: packed credentials
584  }
585  else // SEC_WINNT_AUTH_IDENTITY
586  {
587  const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
588  *pPassword = (const char*)id->Password;
589  *pPasswordLength = id->PasswordLength;
590  }
591 
592  return TRUE;
593 }
594 
595 BOOL sspi_CopyAuthIdentityFieldsA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pUser,
596  char** pDomain, char** pPassword)
597 {
598  BOOL success = FALSE;
599  const char* UserA = NULL;
600  const char* DomainA = NULL;
601  const char* PasswordA = NULL;
602  const WCHAR* UserW = NULL;
603  const WCHAR* DomainW = NULL;
604  const WCHAR* PasswordW = NULL;
605  UINT32 UserLength = 0;
606  UINT32 DomainLength = 0;
607  UINT32 PasswordLength = 0;
608 
609  if (!identity || !pUser || !pDomain || !pPassword)
610  return FALSE;
611 
612  *pUser = *pDomain = *pPassword = NULL;
613 
614  UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
615 
616  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
617  {
618  if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
619  &DomainLength))
620  goto cleanup;
621 
622  if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
623  goto cleanup;
624 
625  if (UserA && UserLength)
626  {
627  *pUser = _strdup(UserA);
628 
629  if (!(*pUser))
630  goto cleanup;
631  }
632 
633  if (DomainA && DomainLength)
634  {
635  *pDomain = _strdup(DomainA);
636 
637  if (!(*pDomain))
638  goto cleanup;
639  }
640 
641  if (PasswordA && PasswordLength)
642  {
643  *pPassword = _strdup(PasswordA);
644 
645  if (!(*pPassword))
646  goto cleanup;
647  }
648 
649  success = TRUE;
650  }
651  else
652  {
653  if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
654  &DomainLength))
655  goto cleanup;
656 
657  if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
658  goto cleanup;
659 
660  if (UserW && (UserLength > 0))
661  {
662  *pUser = ConvertWCharNToUtf8Alloc(UserW, UserLength, NULL);
663  if (!(*pUser))
664  goto cleanup;
665  }
666 
667  if (DomainW && (DomainLength > 0))
668  {
669  *pDomain = ConvertWCharNToUtf8Alloc(DomainW, DomainLength, NULL);
670  if (!(*pDomain))
671  goto cleanup;
672  }
673 
674  if (PasswordW && (PasswordLength > 0))
675  {
676  *pPassword = ConvertWCharNToUtf8Alloc(PasswordW, PasswordLength, NULL);
677  if (!(*pPassword))
678  goto cleanup;
679  }
680 
681  success = TRUE;
682  }
683 
684 cleanup:
685  return success;
686 }
687 
688 BOOL sspi_CopyAuthIdentityFieldsW(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, WCHAR** pUser,
689  WCHAR** pDomain, WCHAR** pPassword)
690 {
691  BOOL success = FALSE;
692  const char* UserA = NULL;
693  const char* DomainA = NULL;
694  const char* PasswordA = NULL;
695  const WCHAR* UserW = NULL;
696  const WCHAR* DomainW = NULL;
697  const WCHAR* PasswordW = NULL;
698  UINT32 UserLength = 0;
699  UINT32 DomainLength = 0;
700  UINT32 PasswordLength = 0;
701 
702  if (!identity || !pUser || !pDomain || !pPassword)
703  return FALSE;
704 
705  *pUser = *pDomain = *pPassword = NULL;
706 
707  UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
708 
709  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
710  {
711  if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
712  &DomainLength))
713  goto cleanup;
714 
715  if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
716  goto cleanup;
717 
718  if (UserA && (UserLength > 0))
719  {
720  WCHAR* ptr = ConvertUtf8NToWCharAlloc(UserA, UserLength, NULL);
721  *pUser = ptr;
722 
723  if (!ptr)
724  goto cleanup;
725  }
726 
727  if (DomainA && (DomainLength > 0))
728  {
729  WCHAR* ptr = ConvertUtf8NToWCharAlloc(DomainA, DomainLength, NULL);
730  *pDomain = ptr;
731  if (!ptr)
732  goto cleanup;
733  }
734 
735  if (PasswordA && (PasswordLength > 0))
736  {
737  WCHAR* ptr = ConvertUtf8NToWCharAlloc(PasswordA, PasswordLength, NULL);
738 
739  *pPassword = ptr;
740  if (!ptr)
741  goto cleanup;
742  }
743 
744  success = TRUE;
745  }
746  else
747  {
748  if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
749  &DomainLength))
750  goto cleanup;
751 
752  if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
753  goto cleanup;
754 
755  if (UserW && UserLength)
756  {
757  *pUser = _wcsdup(UserW);
758 
759  if (!(*pUser))
760  goto cleanup;
761  }
762 
763  if (DomainW && DomainLength)
764  {
765  *pDomain = _wcsdup(DomainW);
766 
767  if (!(*pDomain))
768  goto cleanup;
769  }
770 
771  if (PasswordW && PasswordLength)
772  {
773  *pPassword = _wcsdup(PasswordW);
774 
775  if (!(*pPassword))
776  goto cleanup;
777  }
778 
779  success = TRUE;
780  }
781 
782 cleanup:
783  return success;
784 }
785 
786 BOOL sspi_CopyAuthPackageListA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pPackageList)
787 {
788  UINT32 version = 0;
789  UINT32 identityFlags = 0;
790  char* PackageList = NULL;
791  const char* PackageListA = NULL;
792  const WCHAR* PackageListW = NULL;
793  UINT32 PackageListLength = 0;
794  UINT32 PackageListOffset = 0;
795  const void* pAuthData = (const void*)identity;
796 
797  if (!pAuthData)
798  return FALSE;
799 
800  version = sspi_GetAuthIdentityVersion(pAuthData);
801  identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
802 
803  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
804  {
805  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
806  {
807  const SEC_WINNT_AUTH_IDENTITY_EXA* ad = (const SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData;
808  PackageListA = (const char*)ad->PackageList;
809  PackageListLength = ad->PackageListLength;
810  }
811 
812  if (PackageListA && PackageListLength)
813  {
814  PackageList = _strdup(PackageListA);
815  }
816  }
817  else
818  {
819  if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
820  {
821  const SEC_WINNT_AUTH_IDENTITY_EXW* ad = (const SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData;
822  PackageListW = (const WCHAR*)ad->PackageList;
823  PackageListLength = ad->PackageListLength;
824  }
825  else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
826  {
827  const SEC_WINNT_AUTH_IDENTITY_EX2* ad = (const SEC_WINNT_AUTH_IDENTITY_EX2*)pAuthData;
828  PackageListOffset = ad->PackageListOffset;
829  PackageListW = (const WCHAR*)&((const uint8_t*)pAuthData)[PackageListOffset];
830  PackageListLength = ad->PackageListLength / 2;
831  }
832 
833  if (PackageListW && (PackageListLength > 0))
834  PackageList = ConvertWCharNToUtf8Alloc(PackageListW, PackageListLength, NULL);
835  }
836 
837  if (PackageList)
838  {
839  *pPackageList = PackageList;
840  return TRUE;
841  }
842 
843  return FALSE;
844 }
845 
846 int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
847  const SEC_WINNT_AUTH_IDENTITY_INFO* srcIdentity)
848 {
849  int status = 0;
850  UINT32 identityFlags = 0;
851  const char* UserA = NULL;
852  const char* DomainA = NULL;
853  const char* PasswordA = NULL;
854  const WCHAR* UserW = NULL;
855  const WCHAR* DomainW = NULL;
856  const WCHAR* PasswordW = NULL;
857  UINT32 UserLength = 0;
858  UINT32 DomainLength = 0;
859  UINT32 PasswordLength = 0;
860 
861  sspi_FreeAuthIdentity(identity);
862 
863  identityFlags = sspi_GetAuthIdentityFlags(srcIdentity);
864 
865  identity->Flags = identityFlags;
866 
867  if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
868  {
869  if (!sspi_GetAuthIdentityUserDomainA(srcIdentity, &UserA, &UserLength, &DomainA,
870  &DomainLength))
871  {
872  return -1;
873  }
874 
875  if (!sspi_GetAuthIdentityPasswordA(srcIdentity, &PasswordA, &PasswordLength))
876  {
877  return -1;
878  }
879 
880  status = sspi_SetAuthIdentity(identity, UserA, DomainA, PasswordA);
881 
882  if (status <= 0)
883  return -1;
884 
885  identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
886  identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
887  return 1;
888  }
889 
890  identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
891 
892  if (!sspi_GetAuthIdentityUserDomainW(srcIdentity, &UserW, &UserLength, &DomainW, &DomainLength))
893  {
894  return -1;
895  }
896 
897  if (!sspi_GetAuthIdentityPasswordW(srcIdentity, &PasswordW, &PasswordLength))
898  {
899  return -1;
900  }
901 
902  /* login/password authentication */
903  identity->UserLength = UserLength;
904 
905  if (identity->UserLength > 0)
906  {
907  identity->User = (UINT16*)calloc((identity->UserLength + 1), sizeof(WCHAR));
908 
909  if (!identity->User)
910  return -1;
911 
912  CopyMemory(identity->User, UserW, identity->UserLength * sizeof(WCHAR));
913  identity->User[identity->UserLength] = 0;
914  }
915 
916  identity->DomainLength = DomainLength;
917 
918  if (identity->DomainLength > 0)
919  {
920  identity->Domain = (UINT16*)calloc((identity->DomainLength + 1), sizeof(WCHAR));
921 
922  if (!identity->Domain)
923  return -1;
924 
925  CopyMemory(identity->Domain, DomainW, identity->DomainLength * sizeof(WCHAR));
926  identity->Domain[identity->DomainLength] = 0;
927  }
928 
929  identity->PasswordLength = PasswordLength;
930 
931  if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
932  identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
933 
934  if (PasswordW)
935  {
936  identity->Password = (UINT16*)calloc((identity->PasswordLength + 1), sizeof(WCHAR));
937 
938  if (!identity->Password)
939  return -1;
940 
941  CopyMemory(identity->Password, PasswordW, identity->PasswordLength * sizeof(WCHAR));
942  identity->Password[identity->PasswordLength] = 0;
943  }
944 
945  identity->PasswordLength = PasswordLength;
946  /* End of login/password authentication */
947  return 1;
948 }
949 
950 PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
951 {
952  PSecBuffer pSecBuffer = NULL;
953 
954  for (UINT32 index = 0; index < pMessage->cBuffers; index++)
955  {
956  if (pMessage->pBuffers[index].BufferType == BufferType)
957  {
958  pSecBuffer = &pMessage->pBuffers[index];
959  break;
960  }
961  }
962 
963  return pSecBuffer;
964 }
965 
966 static BOOL WINPR_init(void)
967 {
968 
969  for (size_t x = 0; x < ARRAYSIZE(SecurityFunctionTableA_NAME_LIST); x++)
970  {
971  const SecurityFunctionTableA_NAME* cur = &SecurityFunctionTableA_NAME_LIST[x];
972  InitializeConstWCharFromUtf8(cur->Name, BUFFER_NAME_LIST_W[x],
973  ARRAYSIZE(BUFFER_NAME_LIST_W[x]));
974  }
975  return TRUE;
976 }
977 
978 static BOOL CALLBACK sspi_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
979 {
980  winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
981  sspi_ContextBufferAllocTableNew();
982  if (!SCHANNEL_init())
983  return FALSE;
984  if (!KERBEROS_init())
985  return FALSE;
986  if (!NTLM_init())
987  return FALSE;
988  if (!CREDSSP_init())
989  return FALSE;
990  if (!NEGOTIATE_init())
991  return FALSE;
992  return WINPR_init();
993 }
994 
995 void sspi_GlobalInit(void)
996 {
997  static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
998  DWORD flags = 0;
999  InitOnceExecuteOnce(&once, sspi_init, &flags, NULL);
1000 }
1001 
1002 void sspi_GlobalFinish(void)
1003 {
1004  sspi_ContextBufferAllocTableFree();
1005 }
1006 
1007 static const SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
1008 {
1009  size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1010 
1011  for (size_t index = 0; index < cPackages; index++)
1012  {
1013  if (strcmp(Name, SecurityFunctionTableA_NAME_LIST[index].Name) == 0)
1014  {
1015  return SecurityFunctionTableA_NAME_LIST[index].SecurityFunctionTable;
1016  }
1017  }
1018 
1019  return NULL;
1020 }
1021 
1022 static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
1023 {
1024  size_t cPackages = ARRAYSIZE(SecPkgInfoW_LIST);
1025 
1026  for (size_t index = 0; index < cPackages; index++)
1027  {
1028  if (_wcscmp(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0)
1029  {
1030  return SecurityFunctionTableW_NAME_LIST[index].SecurityFunctionTable;
1031  }
1032  }
1033 
1034  return NULL;
1035 }
1036 
1037 static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
1038 {
1039  SEC_WCHAR* NameW = NULL;
1040  const SecurityFunctionTableW* table = NULL;
1041 
1042  if (!Name)
1043  return NULL;
1044 
1045  NameW = ConvertUtf8ToWCharAlloc(Name, NULL);
1046 
1047  if (!NameW)
1048  return NULL;
1049 
1050  table = sspi_GetSecurityFunctionTableWByNameW(NameW);
1051  free(NameW);
1052  return table;
1053 }
1054 
1055 static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
1056 static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
1057 
1058 static void sspi_ContextBufferFree(void* contextBuffer)
1059 {
1060  UINT32 allocatorIndex = 0;
1061 
1062  for (size_t index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
1063  {
1064  if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer)
1065  {
1066  contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
1067  allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
1068  ContextBufferAllocTable.cEntries--;
1069  ContextBufferAllocTable.entries[index].allocatorIndex = 0;
1070  ContextBufferAllocTable.entries[index].contextBuffer = NULL;
1071 
1072  switch (allocatorIndex)
1073  {
1074  case EnumerateSecurityPackagesIndex:
1075  FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
1076  break;
1077 
1078  case QuerySecurityPackageInfoIndex:
1079  FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
1080  break;
1081  default:
1082  break;
1083  }
1084  }
1085  }
1086 }
1087 
1092 /* Package Management */
1093 
1094 static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
1095  PSecPkgInfoW* ppPackageInfo)
1096 {
1097  const size_t cPackages = ARRAYSIZE(SecPkgInfoW_LIST);
1098  const size_t size = sizeof(SecPkgInfoW) * cPackages;
1099  SecPkgInfoW* pPackageInfo =
1100  (SecPkgInfoW*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1101 
1102  WINPR_ASSERT(cPackages <= UINT32_MAX);
1103 
1104  if (!pPackageInfo)
1105  return SEC_E_INSUFFICIENT_MEMORY;
1106 
1107  for (size_t index = 0; index < cPackages; index++)
1108  {
1109  pPackageInfo[index].fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1110  pPackageInfo[index].wVersion = SecPkgInfoW_LIST[index]->wVersion;
1111  pPackageInfo[index].wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1112  pPackageInfo[index].cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1113  pPackageInfo[index].Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1114  pPackageInfo[index].Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1115  }
1116 
1117  *(pcPackages) = (UINT32)cPackages;
1118  *(ppPackageInfo) = pPackageInfo;
1119  return SEC_E_OK;
1120 }
1121 
1122 static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
1123  PSecPkgInfoA* ppPackageInfo)
1124 {
1125  const size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1126  const size_t size = sizeof(SecPkgInfoA) * cPackages;
1127  SecPkgInfoA* pPackageInfo =
1128  (SecPkgInfoA*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1129 
1130  WINPR_ASSERT(cPackages <= UINT32_MAX);
1131 
1132  if (!pPackageInfo)
1133  return SEC_E_INSUFFICIENT_MEMORY;
1134 
1135  for (size_t index = 0; index < cPackages; index++)
1136  {
1137  pPackageInfo[index].fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1138  pPackageInfo[index].wVersion = SecPkgInfoA_LIST[index]->wVersion;
1139  pPackageInfo[index].wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1140  pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1141  pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1142  pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1143 
1144  if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
1145  {
1146  sspi_ContextBufferFree(pPackageInfo);
1147  return SEC_E_INSUFFICIENT_MEMORY;
1148  }
1149  }
1150 
1151  *(pcPackages) = (UINT32)cPackages;
1152  *(ppPackageInfo) = pPackageInfo;
1153  return SEC_E_OK;
1154 }
1155 
1156 static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
1157 {
1158  SecPkgInfoA* pPackageInfo = (SecPkgInfoA*)contextBuffer;
1159  size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1160 
1161  if (!pPackageInfo)
1162  return;
1163 
1164  for (size_t index = 0; index < cPackages; index++)
1165  {
1166  free(pPackageInfo[index].Name);
1167  free(pPackageInfo[index].Comment);
1168  }
1169 
1170  free(pPackageInfo);
1171 }
1172 
1173 SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
1174 {
1175  return &winpr_SecurityFunctionTableW;
1176 }
1177 
1178 SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
1179 {
1180  return &winpr_SecurityFunctionTableA;
1181 }
1182 
1183 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
1184  PSecPkgInfoW* ppPackageInfo)
1185 {
1186  size_t cPackages = ARRAYSIZE(SecPkgInfoW_LIST);
1187 
1188  for (size_t index = 0; index < cPackages; index++)
1189  {
1190  if (_wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
1191  {
1192  size_t size = sizeof(SecPkgInfoW);
1193  SecPkgInfoW* pPackageInfo =
1194  (SecPkgInfoW*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1195 
1196  if (!pPackageInfo)
1197  return SEC_E_INSUFFICIENT_MEMORY;
1198 
1199  pPackageInfo->fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1200  pPackageInfo->wVersion = SecPkgInfoW_LIST[index]->wVersion;
1201  pPackageInfo->wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1202  pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1203  pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1204  pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1205  *(ppPackageInfo) = pPackageInfo;
1206  return SEC_E_OK;
1207  }
1208  }
1209 
1210  *(ppPackageInfo) = NULL;
1211  return SEC_E_SECPKG_NOT_FOUND;
1212 }
1213 
1214 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
1215  PSecPkgInfoA* ppPackageInfo)
1216 {
1217  size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1218 
1219  for (size_t index = 0; index < cPackages; index++)
1220  {
1221  if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
1222  {
1223  size_t size = sizeof(SecPkgInfoA);
1224  SecPkgInfoA* pPackageInfo =
1225  (SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1226 
1227  if (!pPackageInfo)
1228  return SEC_E_INSUFFICIENT_MEMORY;
1229 
1230  pPackageInfo->fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1231  pPackageInfo->wVersion = SecPkgInfoA_LIST[index]->wVersion;
1232  pPackageInfo->wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1233  pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1234  pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1235  pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1236 
1237  if (!pPackageInfo->Name || !pPackageInfo->Comment)
1238  {
1239  sspi_ContextBufferFree(pPackageInfo);
1240  return SEC_E_INSUFFICIENT_MEMORY;
1241  }
1242 
1243  *(ppPackageInfo) = pPackageInfo;
1244  return SEC_E_OK;
1245  }
1246  }
1247 
1248  *(ppPackageInfo) = NULL;
1249  return SEC_E_SECPKG_NOT_FOUND;
1250 }
1251 
1252 void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
1253 {
1254  SecPkgInfo* pPackageInfo = (SecPkgInfo*)contextBuffer;
1255 
1256  if (!pPackageInfo)
1257  return;
1258 
1259  free(pPackageInfo->Name);
1260  free(pPackageInfo->Comment);
1261  free(pPackageInfo);
1262 }
1263 
1264 /* Credential Management */
1265 
1266 static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(
1267  SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1268  void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1269  PTimeStamp ptsExpiry)
1270 {
1271  SECURITY_STATUS status = 0;
1272  const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
1273 
1274  if (!table)
1275  return SEC_E_SECPKG_NOT_FOUND;
1276 
1277  if (!table->AcquireCredentialsHandleW)
1278  {
1279  WLog_WARN(TAG, "Security module does not provide an implementation");
1280  return SEC_E_UNSUPPORTED_FUNCTION;
1281  }
1282 
1283  status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
1284  pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
1285  ptsExpiry);
1286 
1287  if (IsSecurityStatusError(status))
1288  {
1289  WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08" PRIX32 "]",
1290  GetSecurityStatusString(status), status);
1291  }
1292 
1293  return status;
1294 }
1295 
1296 static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(
1297  SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1298  void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1299  PTimeStamp ptsExpiry)
1300 {
1301  SECURITY_STATUS status = 0;
1302  const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
1303 
1304  if (!table)
1305  return SEC_E_SECPKG_NOT_FOUND;
1306 
1307  if (!table->AcquireCredentialsHandleA)
1308  {
1309  WLog_WARN(TAG, "Security module does not provide an implementation");
1310  return SEC_E_UNSUPPORTED_FUNCTION;
1311  }
1312 
1313  status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
1314  pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
1315  ptsExpiry);
1316 
1317  if (IsSecurityStatusError(status))
1318  {
1319  WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08" PRIX32 "]",
1320  GetSecurityStatusString(status), status);
1321  }
1322 
1323  return status;
1324 }
1325 
1326 static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
1327  PSecBuffer pPackedContext,
1328  HANDLE* pToken)
1329 {
1330  SEC_CHAR* Name = NULL;
1331  SECURITY_STATUS status = 0;
1332  const SecurityFunctionTableW* table = NULL;
1333  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1334 
1335  if (!Name)
1336  return SEC_E_SECPKG_NOT_FOUND;
1337 
1338  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1339 
1340  if (!table)
1341  return SEC_E_SECPKG_NOT_FOUND;
1342 
1343  if (!table->ExportSecurityContext)
1344  {
1345  WLog_WARN(TAG, "Security module does not provide an implementation");
1346  return SEC_E_UNSUPPORTED_FUNCTION;
1347  }
1348 
1349  status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
1350 
1351  if (IsSecurityStatusError(status))
1352  {
1353  WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08" PRIX32 "]",
1354  GetSecurityStatusString(status), status);
1355  }
1356 
1357  return status;
1358 }
1359 
1360 static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
1361 {
1362  char* Name = NULL;
1363  SECURITY_STATUS status = 0;
1364  const SecurityFunctionTableA* table = NULL;
1365  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1366 
1367  if (!Name)
1368  return SEC_E_SECPKG_NOT_FOUND;
1369 
1370  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1371 
1372  if (!table)
1373  return SEC_E_SECPKG_NOT_FOUND;
1374 
1375  if (!table->FreeCredentialsHandle)
1376  {
1377  WLog_WARN(TAG, "Security module does not provide an implementation");
1378  return SEC_E_UNSUPPORTED_FUNCTION;
1379  }
1380 
1381  status = table->FreeCredentialsHandle(phCredential);
1382 
1383  if (IsSecurityStatusError(status))
1384  {
1385  WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
1386  GetSecurityStatusString(status), status);
1387  }
1388 
1389  return status;
1390 }
1391 
1392 static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
1393  PSecBuffer pPackedContext,
1394  HANDLE pToken, PCtxtHandle phContext)
1395 {
1396  SEC_CHAR* Name = NULL;
1397  SECURITY_STATUS status = 0;
1398  const SecurityFunctionTableW* table = NULL;
1399  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1400 
1401  if (!Name)
1402  return SEC_E_SECPKG_NOT_FOUND;
1403 
1404  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1405 
1406  if (!table)
1407  return SEC_E_SECPKG_NOT_FOUND;
1408 
1409  if (!table->ImportSecurityContextW)
1410  {
1411  WLog_WARN(TAG, "Security module does not provide an implementation");
1412  return SEC_E_UNSUPPORTED_FUNCTION;
1413  }
1414 
1415  status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
1416 
1417  if (IsSecurityStatusError(status))
1418  {
1419  WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08" PRIX32 "]",
1420  GetSecurityStatusString(status), status);
1421  }
1422 
1423  return status;
1424 }
1425 
1426 static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
1427  PSecBuffer pPackedContext,
1428  HANDLE pToken, PCtxtHandle phContext)
1429 {
1430  char* Name = NULL;
1431  SECURITY_STATUS status = 0;
1432  const SecurityFunctionTableA* table = NULL;
1433  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1434 
1435  if (!Name)
1436  return SEC_E_SECPKG_NOT_FOUND;
1437 
1438  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1439 
1440  if (!table)
1441  return SEC_E_SECPKG_NOT_FOUND;
1442 
1443  if (!table->ImportSecurityContextA)
1444  {
1445  WLog_WARN(TAG, "Security module does not provide an implementation");
1446  return SEC_E_UNSUPPORTED_FUNCTION;
1447  }
1448 
1449  status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
1450 
1451  if (IsSecurityStatusError(status))
1452  {
1453  WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08" PRIX32 "]",
1454  GetSecurityStatusString(status), status);
1455  }
1456 
1457  return status;
1458 }
1459 
1460 static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
1461  ULONG ulAttribute, void* pBuffer)
1462 {
1463  SEC_WCHAR* Name = NULL;
1464  SECURITY_STATUS status = 0;
1465  const SecurityFunctionTableW* table = NULL;
1466  Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1467 
1468  if (!Name)
1469  return SEC_E_SECPKG_NOT_FOUND;
1470 
1471  table = sspi_GetSecurityFunctionTableWByNameW(Name);
1472 
1473  if (!table)
1474  return SEC_E_SECPKG_NOT_FOUND;
1475 
1476  if (!table->QueryCredentialsAttributesW)
1477  {
1478  WLog_WARN(TAG, "Security module does not provide an implementation");
1479  return SEC_E_UNSUPPORTED_FUNCTION;
1480  }
1481 
1482  status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
1483 
1484  if (IsSecurityStatusError(status))
1485  {
1486  WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08" PRIX32 "]",
1487  GetSecurityStatusString(status), status);
1488  }
1489 
1490  return status;
1491 }
1492 
1493 static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
1494  ULONG ulAttribute, void* pBuffer)
1495 {
1496  char* Name = NULL;
1497  SECURITY_STATUS status = 0;
1498  const SecurityFunctionTableA* table = NULL;
1499  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1500 
1501  if (!Name)
1502  return SEC_E_SECPKG_NOT_FOUND;
1503 
1504  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1505 
1506  if (!table)
1507  return SEC_E_SECPKG_NOT_FOUND;
1508 
1509  if (!table->QueryCredentialsAttributesA)
1510  {
1511  WLog_WARN(TAG, "Security module does not provide an implementation");
1512  return SEC_E_UNSUPPORTED_FUNCTION;
1513  }
1514 
1515  status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
1516 
1517  if (IsSecurityStatusError(status))
1518  {
1519  WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08" PRIX32 "]",
1520  GetSecurityStatusString(status), status);
1521  }
1522 
1523  return status;
1524 }
1525 
1526 static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesW(PCredHandle phCredential,
1527  ULONG ulAttribute, void* pBuffer,
1528  ULONG cbBuffer)
1529 {
1530  SEC_WCHAR* Name = NULL;
1531  SECURITY_STATUS status = 0;
1532  const SecurityFunctionTableW* table = NULL;
1533  Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1534 
1535  if (!Name)
1536  return SEC_E_SECPKG_NOT_FOUND;
1537 
1538  table = sspi_GetSecurityFunctionTableWByNameW(Name);
1539 
1540  if (!table)
1541  return SEC_E_SECPKG_NOT_FOUND;
1542 
1543  if (!table->SetCredentialsAttributesW)
1544  {
1545  WLog_WARN(TAG, "Security module does not provide an implementation");
1546  return SEC_E_UNSUPPORTED_FUNCTION;
1547  }
1548 
1549  status = table->SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer);
1550 
1551  if (IsSecurityStatusError(status))
1552  {
1553  WLog_WARN(TAG, "SetCredentialsAttributesW status %s [0x%08" PRIX32 "]",
1554  GetSecurityStatusString(status), status);
1555  }
1556 
1557  return status;
1558 }
1559 
1560 static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesA(PCredHandle phCredential,
1561  ULONG ulAttribute, void* pBuffer,
1562  ULONG cbBuffer)
1563 {
1564  char* Name = NULL;
1565  SECURITY_STATUS status = 0;
1566  const SecurityFunctionTableA* table = NULL;
1567  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1568 
1569  if (!Name)
1570  return SEC_E_SECPKG_NOT_FOUND;
1571 
1572  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1573 
1574  if (!table)
1575  return SEC_E_SECPKG_NOT_FOUND;
1576 
1577  if (!table->SetCredentialsAttributesA)
1578  {
1579  WLog_WARN(TAG, "Security module does not provide an implementation");
1580  return SEC_E_UNSUPPORTED_FUNCTION;
1581  }
1582 
1583  status = table->SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer);
1584 
1585  if (IsSecurityStatusError(status))
1586  {
1587  WLog_WARN(TAG, "SetCredentialsAttributesA status %s [0x%08" PRIX32 "]",
1588  GetSecurityStatusString(status), status);
1589  }
1590 
1591  return status;
1592 }
1593 
1594 /* Context Management */
1595 
1596 static SECURITY_STATUS SEC_ENTRY
1597 winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
1598  ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
1599  PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
1600 {
1601  char* Name = NULL;
1602  SECURITY_STATUS status = 0;
1603  const SecurityFunctionTableA* table = NULL;
1604  Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
1605 
1606  if (!Name)
1607  return SEC_E_SECPKG_NOT_FOUND;
1608 
1609  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1610 
1611  if (!table)
1612  return SEC_E_SECPKG_NOT_FOUND;
1613 
1614  if (!table->AcceptSecurityContext)
1615  {
1616  WLog_WARN(TAG, "Security module does not provide an implementation");
1617  return SEC_E_UNSUPPORTED_FUNCTION;
1618  }
1619 
1620  status =
1621  table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
1622  phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
1623 
1624  if (IsSecurityStatusError(status))
1625  {
1626  WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
1627  GetSecurityStatusString(status), status);
1628  }
1629 
1630  return status;
1631 }
1632 
1633 static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext,
1634  PSecBufferDesc pInput)
1635 {
1636  char* Name = NULL;
1637  SECURITY_STATUS status = 0;
1638  const SecurityFunctionTableA* table = NULL;
1639  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1640 
1641  if (!Name)
1642  return SEC_E_SECPKG_NOT_FOUND;
1643 
1644  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1645 
1646  if (!table)
1647  return SEC_E_SECPKG_NOT_FOUND;
1648 
1649  if (!table->ApplyControlToken)
1650  {
1651  WLog_WARN(TAG, "Security module does not provide an implementation");
1652  return SEC_E_UNSUPPORTED_FUNCTION;
1653  }
1654 
1655  status = table->ApplyControlToken(phContext, pInput);
1656 
1657  if (IsSecurityStatusError(status))
1658  {
1659  WLog_WARN(TAG, "ApplyControlToken status %s [0x%08" PRIX32 "]",
1660  GetSecurityStatusString(status), status);
1661  }
1662 
1663  return status;
1664 }
1665 
1666 static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext,
1667  PSecBufferDesc pToken)
1668 {
1669  char* Name = NULL;
1670  SECURITY_STATUS status = 0;
1671  const SecurityFunctionTableA* table = NULL;
1672  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1673 
1674  if (!Name)
1675  return SEC_E_SECPKG_NOT_FOUND;
1676 
1677  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1678 
1679  if (!table)
1680  return SEC_E_SECPKG_NOT_FOUND;
1681 
1682  if (!table->CompleteAuthToken)
1683  {
1684  WLog_WARN(TAG, "Security module does not provide an implementation");
1685  return SEC_E_UNSUPPORTED_FUNCTION;
1686  }
1687 
1688  status = table->CompleteAuthToken(phContext, pToken);
1689 
1690  if (IsSecurityStatusError(status))
1691  {
1692  WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
1693  GetSecurityStatusString(status), status);
1694  }
1695 
1696  return status;
1697 }
1698 
1699 static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
1700 {
1701  const char* Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1702 
1703  if (!Name)
1704  return SEC_E_SECPKG_NOT_FOUND;
1705 
1706  const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1707 
1708  if (!table)
1709  return SEC_E_SECPKG_NOT_FOUND;
1710 
1711  if (!table->DeleteSecurityContext)
1712  {
1713  WLog_WARN(TAG, "Security module does not provide an implementation");
1714  return SEC_E_UNSUPPORTED_FUNCTION;
1715  }
1716 
1717  const SECURITY_STATUS status = table->DeleteSecurityContext(phContext);
1718 
1719  if (IsSecurityStatusError(status))
1720  {
1721  WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
1722  GetSecurityStatusString(status), status);
1723  }
1724 
1725  return status;
1726 }
1727 
1728 static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
1729 {
1730  if (!pvContextBuffer)
1731  return SEC_E_INVALID_HANDLE;
1732 
1733  sspi_ContextBufferFree(pvContextBuffer);
1734  return SEC_E_OK;
1735 }
1736 
1737 static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
1738 {
1739  SEC_CHAR* Name = NULL;
1740  SECURITY_STATUS status = 0;
1741  const SecurityFunctionTableW* table = NULL;
1742  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1743 
1744  if (!Name)
1745  return SEC_E_SECPKG_NOT_FOUND;
1746 
1747  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1748 
1749  if (!table)
1750  return SEC_E_SECPKG_NOT_FOUND;
1751 
1752  if (!table->ImpersonateSecurityContext)
1753  {
1754  WLog_WARN(TAG, "Security module does not provide an implementation");
1755  return SEC_E_UNSUPPORTED_FUNCTION;
1756  }
1757 
1758  status = table->ImpersonateSecurityContext(phContext);
1759 
1760  if (IsSecurityStatusError(status))
1761  {
1762  WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08" PRIX32 "]",
1763  GetSecurityStatusString(status), status);
1764  }
1765 
1766  return status;
1767 }
1768 
1769 static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(
1770  PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
1771  ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1772  PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1773 {
1774  SEC_CHAR* Name = NULL;
1775  SECURITY_STATUS status = 0;
1776  const SecurityFunctionTableW* table = NULL;
1777  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1778 
1779  if (!Name)
1780  return SEC_E_SECPKG_NOT_FOUND;
1781 
1782  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1783 
1784  if (!table)
1785  return SEC_E_SECPKG_NOT_FOUND;
1786 
1787  if (!table->InitializeSecurityContextW)
1788  {
1789  WLog_WARN(TAG, "Security module does not provide an implementation");
1790  return SEC_E_UNSUPPORTED_FUNCTION;
1791  }
1792 
1793  status = table->InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq,
1794  Reserved1, TargetDataRep, pInput, Reserved2,
1795  phNewContext, pOutput, pfContextAttr, ptsExpiry);
1796 
1797  if (IsSecurityStatusError(status))
1798  {
1799  WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08" PRIX32 "]",
1800  GetSecurityStatusString(status), status);
1801  }
1802 
1803  return status;
1804 }
1805 
1806 static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(
1807  PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
1808  ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1809  PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1810 {
1811  SEC_CHAR* Name = NULL;
1812  SECURITY_STATUS status = 0;
1813  const SecurityFunctionTableA* table = NULL;
1814  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1815 
1816  if (!Name)
1817  return SEC_E_SECPKG_NOT_FOUND;
1818 
1819  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1820 
1821  if (!table)
1822  return SEC_E_SECPKG_NOT_FOUND;
1823 
1824  if (!table->InitializeSecurityContextA)
1825  {
1826  WLog_WARN(TAG, "Security module does not provide an implementation");
1827  return SEC_E_UNSUPPORTED_FUNCTION;
1828  }
1829 
1830  status = table->InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq,
1831  Reserved1, TargetDataRep, pInput, Reserved2,
1832  phNewContext, pOutput, pfContextAttr, ptsExpiry);
1833 
1834  if (IsSecurityStatusError(status))
1835  {
1836  WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08" PRIX32 "]",
1837  GetSecurityStatusString(status), status);
1838  }
1839 
1840  return status;
1841 }
1842 
1843 static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext,
1844  ULONG ulAttribute, void* pBuffer)
1845 {
1846  SEC_CHAR* Name = NULL;
1847  SECURITY_STATUS status = 0;
1848  const SecurityFunctionTableW* table = NULL;
1849  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1850 
1851  if (!Name)
1852  return SEC_E_SECPKG_NOT_FOUND;
1853 
1854  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1855 
1856  if (!table)
1857  return SEC_E_SECPKG_NOT_FOUND;
1858 
1859  if (!table->QueryContextAttributesW)
1860  {
1861  WLog_WARN(TAG, "Security module does not provide an implementation");
1862  return SEC_E_UNSUPPORTED_FUNCTION;
1863  }
1864 
1865  status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
1866 
1867  if (IsSecurityStatusError(status))
1868  {
1869  WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08" PRIX32 "]",
1870  GetSecurityStatusString(status), status);
1871  }
1872 
1873  return status;
1874 }
1875 
1876 static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext,
1877  ULONG ulAttribute, void* pBuffer)
1878 {
1879  SEC_CHAR* Name = NULL;
1880  SECURITY_STATUS status = 0;
1881  const SecurityFunctionTableA* table = NULL;
1882  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1883 
1884  if (!Name)
1885  return SEC_E_SECPKG_NOT_FOUND;
1886 
1887  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1888 
1889  if (!table)
1890  return SEC_E_SECPKG_NOT_FOUND;
1891 
1892  if (!table->QueryContextAttributesA)
1893  {
1894  WLog_WARN(TAG, "Security module does not provide an implementation");
1895  return SEC_E_UNSUPPORTED_FUNCTION;
1896  }
1897 
1898  status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
1899 
1900  if (IsSecurityStatusError(status))
1901  {
1902  WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08" PRIX32 "]",
1903  GetSecurityStatusString(status), status);
1904  }
1905 
1906  return status;
1907 }
1908 
1909 static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
1910  HANDLE* phToken)
1911 {
1912  SEC_CHAR* Name = NULL;
1913  SECURITY_STATUS status = 0;
1914  const SecurityFunctionTableW* table = NULL;
1915  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1916 
1917  if (!Name)
1918  return SEC_E_SECPKG_NOT_FOUND;
1919 
1920  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1921 
1922  if (!table)
1923  return SEC_E_SECPKG_NOT_FOUND;
1924 
1925  if (!table->QuerySecurityContextToken)
1926  {
1927  WLog_WARN(TAG, "Security module does not provide an implementation");
1928  return SEC_E_UNSUPPORTED_FUNCTION;
1929  }
1930 
1931  status = table->QuerySecurityContextToken(phContext, phToken);
1932 
1933  if (IsSecurityStatusError(status))
1934  {
1935  WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08" PRIX32 "]",
1936  GetSecurityStatusString(status), status);
1937  }
1938 
1939  return status;
1940 }
1941 
1942 static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext,
1943  ULONG ulAttribute, void* pBuffer,
1944  ULONG cbBuffer)
1945 {
1946  SEC_CHAR* Name = NULL;
1947  SECURITY_STATUS status = 0;
1948  const SecurityFunctionTableW* table = NULL;
1949  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
1950 
1951  if (!Name)
1952  return SEC_E_SECPKG_NOT_FOUND;
1953 
1954  table = sspi_GetSecurityFunctionTableWByNameA(Name);
1955 
1956  if (!table)
1957  return SEC_E_SECPKG_NOT_FOUND;
1958 
1959  if (!table->SetContextAttributesW)
1960  {
1961  WLog_WARN(TAG, "Security module does not provide an implementation");
1962  return SEC_E_UNSUPPORTED_FUNCTION;
1963  }
1964 
1965  status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
1966 
1967  if (IsSecurityStatusError(status))
1968  {
1969  WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08" PRIX32 "]",
1970  GetSecurityStatusString(status), status);
1971  }
1972 
1973  return status;
1974 }
1975 
1976 static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext,
1977  ULONG ulAttribute, void* pBuffer,
1978  ULONG cbBuffer)
1979 {
1980  char* Name = NULL;
1981  SECURITY_STATUS status = 0;
1982  const SecurityFunctionTableA* table = NULL;
1983  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
1984 
1985  if (!Name)
1986  return SEC_E_SECPKG_NOT_FOUND;
1987 
1988  table = sspi_GetSecurityFunctionTableAByNameA(Name);
1989 
1990  if (!table)
1991  return SEC_E_SECPKG_NOT_FOUND;
1992 
1993  if (!table->SetContextAttributesA)
1994  {
1995  WLog_WARN(TAG, "Security module does not provide an implementation");
1996  return SEC_E_UNSUPPORTED_FUNCTION;
1997  }
1998 
1999  status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
2000 
2001  if (IsSecurityStatusError(status))
2002  {
2003  WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08" PRIX32 "]",
2004  GetSecurityStatusString(status), status);
2005  }
2006 
2007  return status;
2008 }
2009 
2010 static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
2011 {
2012  SEC_CHAR* Name = NULL;
2013  SECURITY_STATUS status = 0;
2014  const SecurityFunctionTableW* table = NULL;
2015  Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
2016 
2017  if (!Name)
2018  return SEC_E_SECPKG_NOT_FOUND;
2019 
2020  table = sspi_GetSecurityFunctionTableWByNameA(Name);
2021 
2022  if (!table)
2023  return SEC_E_SECPKG_NOT_FOUND;
2024 
2025  if (!table->RevertSecurityContext)
2026  {
2027  WLog_WARN(TAG, "Security module does not provide an implementation");
2028  return SEC_E_UNSUPPORTED_FUNCTION;
2029  }
2030 
2031  status = table->RevertSecurityContext(phContext);
2032 
2033  if (IsSecurityStatusError(status))
2034  {
2035  WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08" PRIX32 "]",
2036  GetSecurityStatusString(status), status);
2037  }
2038 
2039  return status;
2040 }
2041 
2042 /* Message Support */
2043 
2044 static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext,
2045  PSecBufferDesc pMessage, ULONG MessageSeqNo,
2046  PULONG pfQOP)
2047 {
2048  char* Name = NULL;
2049  SECURITY_STATUS status = 0;
2050  const SecurityFunctionTableA* table = NULL;
2051  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2052 
2053  if (!Name)
2054  return SEC_E_SECPKG_NOT_FOUND;
2055 
2056  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2057 
2058  if (!table)
2059  return SEC_E_SECPKG_NOT_FOUND;
2060 
2061  if (!table->DecryptMessage)
2062  {
2063  WLog_WARN(TAG, "Security module does not provide an implementation");
2064  return SEC_E_UNSUPPORTED_FUNCTION;
2065  }
2066 
2067  status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
2068 
2069  if (IsSecurityStatusError(status))
2070  {
2071  WLog_WARN(TAG, "DecryptMessage status %s [0x%08" PRIX32 "]",
2072  GetSecurityStatusString(status), status);
2073  }
2074 
2075  return status;
2076 }
2077 
2078 static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
2079  PSecBufferDesc pMessage, ULONG MessageSeqNo)
2080 {
2081  char* Name = NULL;
2082  SECURITY_STATUS status = 0;
2083  const SecurityFunctionTableA* table = NULL;
2084  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2085 
2086  if (!Name)
2087  return SEC_E_SECPKG_NOT_FOUND;
2088 
2089  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2090 
2091  if (!table)
2092  return SEC_E_SECPKG_NOT_FOUND;
2093 
2094  if (!table->EncryptMessage)
2095  {
2096  WLog_WARN(TAG, "Security module does not provide an implementation");
2097  return SEC_E_UNSUPPORTED_FUNCTION;
2098  }
2099 
2100  status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
2101 
2102  if (status != SEC_E_OK)
2103  {
2104  WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
2105  status);
2106  }
2107 
2108  return status;
2109 }
2110 
2111 static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
2112  PSecBufferDesc pMessage, ULONG MessageSeqNo)
2113 {
2114  char* Name = NULL;
2115  SECURITY_STATUS status = 0;
2116  const SecurityFunctionTableA* table = NULL;
2117  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2118 
2119  if (!Name)
2120  return SEC_E_SECPKG_NOT_FOUND;
2121 
2122  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2123 
2124  if (!table)
2125  return SEC_E_SECPKG_NOT_FOUND;
2126 
2127  if (!table->MakeSignature)
2128  {
2129  WLog_WARN(TAG, "Security module does not provide an implementation");
2130  return SEC_E_UNSUPPORTED_FUNCTION;
2131  }
2132 
2133  status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
2134 
2135  if (IsSecurityStatusError(status))
2136  {
2137  WLog_WARN(TAG, "MakeSignature status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
2138  status);
2139  }
2140 
2141  return status;
2142 }
2143 
2144 static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext,
2145  PSecBufferDesc pMessage, ULONG MessageSeqNo,
2146  PULONG pfQOP)
2147 {
2148  char* Name = NULL;
2149  SECURITY_STATUS status = 0;
2150  const SecurityFunctionTableA* table = NULL;
2151  Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2152 
2153  if (!Name)
2154  return SEC_E_SECPKG_NOT_FOUND;
2155 
2156  table = sspi_GetSecurityFunctionTableAByNameA(Name);
2157 
2158  if (!table)
2159  return SEC_E_SECPKG_NOT_FOUND;
2160 
2161  if (!table->VerifySignature)
2162  {
2163  WLog_WARN(TAG, "Security module does not provide an implementation");
2164  return SEC_E_UNSUPPORTED_FUNCTION;
2165  }
2166 
2167  status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
2168 
2169  if (IsSecurityStatusError(status))
2170  {
2171  WLog_WARN(TAG, "VerifySignature status %s [0x%08" PRIX32 "]",
2172  GetSecurityStatusString(status), status);
2173  }
2174 
2175  return status;
2176 }
2177 
2178 static SecurityFunctionTableA winpr_SecurityFunctionTableA = {
2179  3, /* dwVersion */
2180  winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */
2181  winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
2182  winpr_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */
2183  winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
2184  NULL, /* Reserved2 */
2185  winpr_InitializeSecurityContextA, /* InitializeSecurityContext */
2186  winpr_AcceptSecurityContext, /* AcceptSecurityContext */
2187  winpr_CompleteAuthToken, /* CompleteAuthToken */
2188  winpr_DeleteSecurityContext, /* DeleteSecurityContext */
2189  winpr_ApplyControlToken, /* ApplyControlToken */
2190  winpr_QueryContextAttributesA, /* QueryContextAttributes */
2191  winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
2192  winpr_RevertSecurityContext, /* RevertSecurityContext */
2193  winpr_MakeSignature, /* MakeSignature */
2194  winpr_VerifySignature, /* VerifySignature */
2195  winpr_FreeContextBuffer, /* FreeContextBuffer */
2196  winpr_QuerySecurityPackageInfoA, /* QuerySecurityPackageInfo */
2197  NULL, /* Reserved3 */
2198  NULL, /* Reserved4 */
2199  winpr_ExportSecurityContext, /* ExportSecurityContext */
2200  winpr_ImportSecurityContextA, /* ImportSecurityContext */
2201  NULL, /* AddCredentials */
2202  NULL, /* Reserved8 */
2203  winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
2204  winpr_EncryptMessage, /* EncryptMessage */
2205  winpr_DecryptMessage, /* DecryptMessage */
2206  winpr_SetContextAttributesA, /* SetContextAttributes */
2207  winpr_SetCredentialsAttributesA, /* SetCredentialsAttributes */
2208 };
2209 
2210 static SecurityFunctionTableW winpr_SecurityFunctionTableW = {
2211  3, /* dwVersion */
2212  winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */
2213  winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
2214  winpr_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */
2215  winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
2216  NULL, /* Reserved2 */
2217  winpr_InitializeSecurityContextW, /* InitializeSecurityContext */
2218  winpr_AcceptSecurityContext, /* AcceptSecurityContext */
2219  winpr_CompleteAuthToken, /* CompleteAuthToken */
2220  winpr_DeleteSecurityContext, /* DeleteSecurityContext */
2221  winpr_ApplyControlToken, /* ApplyControlToken */
2222  winpr_QueryContextAttributesW, /* QueryContextAttributes */
2223  winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
2224  winpr_RevertSecurityContext, /* RevertSecurityContext */
2225  winpr_MakeSignature, /* MakeSignature */
2226  winpr_VerifySignature, /* VerifySignature */
2227  winpr_FreeContextBuffer, /* FreeContextBuffer */
2228  winpr_QuerySecurityPackageInfoW, /* QuerySecurityPackageInfo */
2229  NULL, /* Reserved3 */
2230  NULL, /* Reserved4 */
2231  winpr_ExportSecurityContext, /* ExportSecurityContext */
2232  winpr_ImportSecurityContextW, /* ImportSecurityContext */
2233  NULL, /* AddCredentials */
2234  NULL, /* Reserved8 */
2235  winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
2236  winpr_EncryptMessage, /* EncryptMessage */
2237  winpr_DecryptMessage, /* DecryptMessage */
2238  winpr_SetContextAttributesW, /* SetContextAttributes */
2239  winpr_SetCredentialsAttributesW, /* SetCredentialsAttributes */
2240 };