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