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