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) != 0)
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 if ((identityFlags & SEC_WINNT_AUTH_IDENTITY_UNICODE) != 0)
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) != 0)
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 if ((identityFlags & SEC_WINNT_AUTH_IDENTITY_UNICODE) != 0)
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) != 0)
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 if ((identityFlags & SEC_WINNT_AUTH_IDENTITY_UNICODE) != 0)
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) != 0)
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 if (!Name)
1031 return nullptr;
1032
1033 WCHAR* NameW = ConvertUtf8ToWCharAlloc(Name, nullptr);
1034
1035 if (!NameW)
1036 return nullptr;
1037
1038 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(NameW);
1039 free(NameW);
1040 return table;
1041}
1042
1043static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
1044static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
1045
1046void sspi_ContextBufferFree(void* contextBuffer)
1047{
1048 UINT32 allocatorIndex = 0;
1049
1050 for (size_t index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
1051 {
1052 if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer)
1053 {
1054 contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
1055 allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
1056 ContextBufferAllocTable.cEntries--;
1057 ContextBufferAllocTable.entries[index].allocatorIndex = 0;
1058 ContextBufferAllocTable.entries[index].contextBuffer = nullptr;
1059
1060 switch (allocatorIndex)
1061 {
1062 case EnumerateSecurityPackagesIndex:
1063 FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
1064 break;
1065
1066 case QuerySecurityPackageInfoIndex:
1067 FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
1068 break;
1069 default:
1070 break;
1071 }
1072 }
1073 }
1074}
1075
1080/* Package Management */
1081
1082static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
1083 PSecPkgInfoW* ppPackageInfo)
1084{
1085 const size_t cPackages = ARRAYSIZE(SecPkgInfoW_LIST);
1086 const size_t size = sizeof(SecPkgInfoW) * cPackages;
1087 SecPkgInfoW* pPackageInfo =
1088 (SecPkgInfoW*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1089
1090 WINPR_ASSERT(cPackages <= UINT32_MAX);
1091
1092 if (!pPackageInfo)
1093 return SEC_E_INSUFFICIENT_MEMORY;
1094
1095 for (size_t index = 0; index < cPackages; index++)
1096 {
1097 pPackageInfo[index].fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1098 pPackageInfo[index].wVersion = SecPkgInfoW_LIST[index]->wVersion;
1099 pPackageInfo[index].wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1100 pPackageInfo[index].cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1101 pPackageInfo[index].Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1102 pPackageInfo[index].Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1103 }
1104
1105 *(pcPackages) = (UINT32)cPackages;
1106 *(ppPackageInfo) = pPackageInfo;
1107 return SEC_E_OK;
1108}
1109
1110static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
1111 PSecPkgInfoA* ppPackageInfo)
1112{
1113 const size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1114 const size_t size = sizeof(SecPkgInfoA) * cPackages;
1115 SecPkgInfoA* pPackageInfo =
1116 (SecPkgInfoA*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
1117
1118 WINPR_ASSERT(cPackages <= UINT32_MAX);
1119
1120 if (!pPackageInfo)
1121 return SEC_E_INSUFFICIENT_MEMORY;
1122
1123 for (size_t index = 0; index < cPackages; index++)
1124 {
1125 pPackageInfo[index].fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1126 pPackageInfo[index].wVersion = SecPkgInfoA_LIST[index]->wVersion;
1127 pPackageInfo[index].wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1128 pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1129 pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1130 pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1131
1132 if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
1133 {
1134 sspi_ContextBufferFree(pPackageInfo);
1135 return SEC_E_INSUFFICIENT_MEMORY;
1136 }
1137 }
1138
1139 *(pcPackages) = (UINT32)cPackages;
1140 *(ppPackageInfo) = pPackageInfo;
1141 return SEC_E_OK;
1142}
1143
1144static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
1145{
1146 SecPkgInfoA* pPackageInfo = (SecPkgInfoA*)contextBuffer;
1147 size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1148
1149 if (!pPackageInfo)
1150 return;
1151
1152 for (size_t index = 0; index < cPackages; index++)
1153 {
1154 free(pPackageInfo[index].Name);
1155 free(pPackageInfo[index].Comment);
1156 }
1157
1158 free(pPackageInfo);
1159}
1160
1161static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
1162 PSecPkgInfoW* ppPackageInfo)
1163{
1164 size_t cPackages = ARRAYSIZE(SecPkgInfoW_LIST);
1165
1166 for (size_t index = 0; index < cPackages; index++)
1167 {
1168 if (_wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
1169 {
1170 size_t size = sizeof(SecPkgInfoW);
1171 SecPkgInfoW* pPackageInfo =
1172 (SecPkgInfoW*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1173
1174 if (!pPackageInfo)
1175 return SEC_E_INSUFFICIENT_MEMORY;
1176
1177 pPackageInfo->fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
1178 pPackageInfo->wVersion = SecPkgInfoW_LIST[index]->wVersion;
1179 pPackageInfo->wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
1180 pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
1181 pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
1182 pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
1183 *(ppPackageInfo) = pPackageInfo;
1184 return SEC_E_OK;
1185 }
1186 }
1187
1188 *(ppPackageInfo) = nullptr;
1189 return SEC_E_SECPKG_NOT_FOUND;
1190}
1191
1192static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
1193 PSecPkgInfoA* ppPackageInfo)
1194{
1195 size_t cPackages = ARRAYSIZE(SecPkgInfoA_LIST);
1196
1197 for (size_t index = 0; index < cPackages; index++)
1198 {
1199 if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
1200 {
1201 size_t size = sizeof(SecPkgInfoA);
1202 SecPkgInfoA* pPackageInfo =
1203 (SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
1204
1205 if (!pPackageInfo)
1206 return SEC_E_INSUFFICIENT_MEMORY;
1207
1208 pPackageInfo->fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
1209 pPackageInfo->wVersion = SecPkgInfoA_LIST[index]->wVersion;
1210 pPackageInfo->wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
1211 pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
1212 pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
1213 pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
1214
1215 if (!pPackageInfo->Name || !pPackageInfo->Comment)
1216 {
1217 sspi_ContextBufferFree(pPackageInfo);
1218 return SEC_E_INSUFFICIENT_MEMORY;
1219 }
1220
1221 *(ppPackageInfo) = pPackageInfo;
1222 return SEC_E_OK;
1223 }
1224 }
1225
1226 *(ppPackageInfo) = nullptr;
1227 return SEC_E_SECPKG_NOT_FOUND;
1228}
1229
1230void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
1231{
1232 SecPkgInfo* pPackageInfo = (SecPkgInfo*)contextBuffer;
1233
1234 if (!pPackageInfo)
1235 return;
1236
1237 free(pPackageInfo->Name);
1238 free(pPackageInfo->Comment);
1239 free(pPackageInfo);
1240}
1241
1242#define log_status(what, status) log_status_((what), (status), __FILE__, __func__, __LINE__)
1243static SECURITY_STATUS log_status_(const char* what, SECURITY_STATUS status, const char* file,
1244 const char* fkt, size_t line)
1245{
1246 if (IsSecurityStatusError(status))
1247 {
1248 const DWORD level = WLOG_WARN;
1249 static wLog* log = nullptr;
1250 if (!log)
1251 log = WLog_Get(TAG);
1252
1253 if (WLog_IsLevelActive(log, level))
1254 {
1255 WLog_PrintTextMessage(log, level, line, file, fkt, "%s status %s [0x%08" PRIx32 "]",
1256 what, GetSecurityStatusString(status),
1257 WINPR_CXX_COMPAT_CAST(uint32_t, status));
1258 }
1259 }
1260 return status;
1261}
1262
1263/* Credential Management */
1264
1265static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(
1266 SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1267 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1268 PTimeStamp ptsExpiry)
1269{
1270 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
1271
1272 if (!table)
1273 return SEC_E_SECPKG_NOT_FOUND;
1274
1275 if (!table->AcquireCredentialsHandleW)
1276 {
1277 WLog_WARN(TAG, "Security module does not provide an implementation");
1278 return SEC_E_UNSUPPORTED_FUNCTION;
1279 }
1280
1281 SECURITY_STATUS status = table->AcquireCredentialsHandleW(
1282 pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument,
1283 phCredential, ptsExpiry);
1284 return log_status("AcquireCredentialsHandleW", status);
1285}
1286
1287static SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(
1288 SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
1289 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
1290 PTimeStamp ptsExpiry)
1291{
1292 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
1293
1294 if (!table)
1295 return SEC_E_SECPKG_NOT_FOUND;
1296
1297 if (!table->AcquireCredentialsHandleA)
1298 {
1299 WLog_WARN(TAG, "Security module does not provide an implementation");
1300 return SEC_E_UNSUPPORTED_FUNCTION;
1301 }
1302
1303 SECURITY_STATUS status = table->AcquireCredentialsHandleA(
1304 pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument,
1305 phCredential, ptsExpiry);
1306 return log_status("AcquireCredentialsHandleA", status);
1307}
1308
1309static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
1310 PSecBuffer pPackedContext,
1311 HANDLE* pToken)
1312{
1313 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1314
1315 if (!Name)
1316 return SEC_E_SECPKG_NOT_FOUND;
1317
1318 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1319
1320 if (!table)
1321 return SEC_E_SECPKG_NOT_FOUND;
1322
1323 if (!table->ExportSecurityContext)
1324 {
1325 WLog_WARN(TAG, "Security module does not provide an implementation");
1326 return SEC_E_UNSUPPORTED_FUNCTION;
1327 }
1328
1329 SECURITY_STATUS status =
1330 table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
1331 return log_status("ExportSecurityContext", status);
1332}
1333
1334static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
1335{
1336 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1337
1338 if (!Name)
1339 return SEC_E_SECPKG_NOT_FOUND;
1340
1341 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1342
1343 if (!table)
1344 return SEC_E_SECPKG_NOT_FOUND;
1345
1346 if (!table->FreeCredentialsHandle)
1347 {
1348 WLog_WARN(TAG, "Security module does not provide an implementation");
1349 return SEC_E_UNSUPPORTED_FUNCTION;
1350 }
1351
1352 SECURITY_STATUS status = table->FreeCredentialsHandle(phCredential);
1353 return log_status("FreeCredentialsHandle", status);
1354}
1355
1356static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
1357 PSecBuffer pPackedContext,
1358 HANDLE pToken, PCtxtHandle phContext)
1359{
1360 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1361
1362 if (!Name)
1363 return SEC_E_SECPKG_NOT_FOUND;
1364
1365 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1366
1367 if (!table)
1368 return SEC_E_SECPKG_NOT_FOUND;
1369
1370 if (!table->ImportSecurityContextW)
1371 {
1372 WLog_WARN(TAG, "Security module does not provide an implementation");
1373 return SEC_E_UNSUPPORTED_FUNCTION;
1374 }
1375
1376 SECURITY_STATUS status =
1377 table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
1378 return log_status("ImportSecurityContextW", status);
1379}
1380
1381static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
1382 PSecBuffer pPackedContext,
1383 HANDLE pToken, PCtxtHandle phContext)
1384{
1385 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1386
1387 if (!Name)
1388 return SEC_E_SECPKG_NOT_FOUND;
1389
1390 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1391
1392 if (!table)
1393 return SEC_E_SECPKG_NOT_FOUND;
1394
1395 if (!table->ImportSecurityContextA)
1396 {
1397 WLog_WARN(TAG, "Security module does not provide an implementation");
1398 return SEC_E_UNSUPPORTED_FUNCTION;
1399 }
1400
1401 SECURITY_STATUS status =
1402 table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
1403 return log_status("ImportSecurityContextA", status);
1404}
1405
1406static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
1407 ULONG ulAttribute, void* pBuffer)
1408{
1409 const WCHAR* Name = (const WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1410
1411 if (!Name)
1412 return SEC_E_SECPKG_NOT_FOUND;
1413
1414 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(Name);
1415
1416 if (!table)
1417 return SEC_E_SECPKG_NOT_FOUND;
1418
1419 if (!table->QueryCredentialsAttributesW)
1420 {
1421 WLog_WARN(TAG, "Security module does not provide an implementation");
1422 return SEC_E_UNSUPPORTED_FUNCTION;
1423 }
1424
1425 SECURITY_STATUS status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
1426 return log_status("QueryCredentialsAttributesW", status);
1427}
1428
1429static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
1430 ULONG ulAttribute, void* pBuffer)
1431{
1432 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1433
1434 if (!Name)
1435 return SEC_E_SECPKG_NOT_FOUND;
1436
1437 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1438
1439 if (!table)
1440 return SEC_E_SECPKG_NOT_FOUND;
1441
1442 if (!table->QueryCredentialsAttributesA)
1443 {
1444 WLog_WARN(TAG, "Security module does not provide an implementation");
1445 return SEC_E_UNSUPPORTED_FUNCTION;
1446 }
1447
1448 SECURITY_STATUS status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
1449 return log_status("QueryCredentialsAttributesA", status);
1450}
1451
1452static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesW(PCredHandle phCredential,
1453 ULONG ulAttribute, void* pBuffer,
1454 ULONG cbBuffer)
1455{
1456 const WCHAR* Name = (const WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
1457
1458 if (!Name)
1459 return SEC_E_SECPKG_NOT_FOUND;
1460
1461 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(Name);
1462
1463 if (!table)
1464 return SEC_E_SECPKG_NOT_FOUND;
1465
1466 if (!table->SetCredentialsAttributesW)
1467 {
1468 WLog_WARN(TAG, "Security module does not provide an implementation");
1469 return SEC_E_UNSUPPORTED_FUNCTION;
1470 }
1471
1472 SECURITY_STATUS status =
1473 table->SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer);
1474 return log_status("SetCredentialsAttributesW", status);
1475}
1476
1477static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesA(PCredHandle phCredential,
1478 ULONG ulAttribute, void* pBuffer,
1479 ULONG cbBuffer)
1480{
1481 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1482
1483 if (!Name)
1484 return SEC_E_SECPKG_NOT_FOUND;
1485
1486 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1487
1488 if (!table)
1489 return SEC_E_SECPKG_NOT_FOUND;
1490
1491 if (!table->SetCredentialsAttributesA)
1492 {
1493 WLog_WARN(TAG, "Security module does not provide an implementation");
1494 return SEC_E_UNSUPPORTED_FUNCTION;
1495 }
1496
1497 SECURITY_STATUS status =
1498 table->SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer);
1499 return log_status("SetCredentialsAttributesA", status);
1500}
1501
1502/* Context Management */
1503
1504static SECURITY_STATUS SEC_ENTRY
1505winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
1506 ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
1507 PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
1508{
1509 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1510
1511 if (!Name)
1512 return SEC_E_SECPKG_NOT_FOUND;
1513
1514 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1515
1516 if (!table)
1517 return SEC_E_SECPKG_NOT_FOUND;
1518
1519 if (!table->AcceptSecurityContext)
1520 {
1521 WLog_WARN(TAG, "Security module does not provide an implementation");
1522 return SEC_E_UNSUPPORTED_FUNCTION;
1523 }
1524
1525 SECURITY_STATUS status =
1526 table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
1527 phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
1528 return log_status("AcceptSecurityContext", status);
1529}
1530
1531static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext,
1532 PSecBufferDesc pInput)
1533{
1534 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1535
1536 if (!Name)
1537 return SEC_E_SECPKG_NOT_FOUND;
1538
1539 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1540
1541 if (!table)
1542 return SEC_E_SECPKG_NOT_FOUND;
1543
1544 if (!table->ApplyControlToken)
1545 {
1546 WLog_WARN(TAG, "Security module does not provide an implementation");
1547 return SEC_E_UNSUPPORTED_FUNCTION;
1548 }
1549
1550 SECURITY_STATUS status = table->ApplyControlToken(phContext, pInput);
1551 return log_status("ApplyControlToken", status);
1552}
1553
1554static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext,
1555 PSecBufferDesc pToken)
1556{
1557 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1558
1559 if (!Name)
1560 return SEC_E_SECPKG_NOT_FOUND;
1561
1562 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1563
1564 if (!table)
1565 return SEC_E_SECPKG_NOT_FOUND;
1566
1567 if (!table->CompleteAuthToken)
1568 {
1569 WLog_WARN(TAG, "Security module does not provide an implementation");
1570 return SEC_E_UNSUPPORTED_FUNCTION;
1571 }
1572
1573 SECURITY_STATUS status = table->CompleteAuthToken(phContext, pToken);
1574 return log_status("CompleteAuthToken", status);
1575}
1576
1577static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
1578{
1579 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1580
1581 if (!Name)
1582 return SEC_E_SECPKG_NOT_FOUND;
1583
1584 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1585
1586 if (!table)
1587 return SEC_E_SECPKG_NOT_FOUND;
1588
1589 if (!table->DeleteSecurityContext)
1590 {
1591 WLog_WARN(TAG, "Security module does not provide an implementation");
1592 return SEC_E_UNSUPPORTED_FUNCTION;
1593 }
1594
1595 const SECURITY_STATUS status = table->DeleteSecurityContext(phContext);
1596 return log_status("DeleteSecurityContext", status);
1597}
1598
1599static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
1600{
1601 if (!pvContextBuffer)
1602 return SEC_E_INVALID_HANDLE;
1603
1604 sspi_ContextBufferFree(pvContextBuffer);
1605 return SEC_E_OK;
1606}
1607
1608static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
1609{
1610 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1611
1612 if (!Name)
1613 return SEC_E_SECPKG_NOT_FOUND;
1614
1615 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1616
1617 if (!table)
1618 return SEC_E_SECPKG_NOT_FOUND;
1619
1620 if (!table->ImpersonateSecurityContext)
1621 {
1622 WLog_WARN(TAG, "Security module does not provide an implementation");
1623 return SEC_E_UNSUPPORTED_FUNCTION;
1624 }
1625
1626 SECURITY_STATUS status = table->ImpersonateSecurityContext(phContext);
1627 return log_status("ImpersonateSecurityContext", status);
1628}
1629
1630static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(
1631 PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
1632 ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1633 PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1634{
1635 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1636
1637 if (!Name)
1638 return SEC_E_SECPKG_NOT_FOUND;
1639
1640 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1641
1642 if (!table)
1643 return SEC_E_SECPKG_NOT_FOUND;
1644
1645 if (!table->InitializeSecurityContextW)
1646 {
1647 WLog_WARN(TAG, "Security module does not provide an implementation");
1648 return SEC_E_UNSUPPORTED_FUNCTION;
1649 }
1650
1651 const SECURITY_STATUS status = table->InitializeSecurityContextW(
1652 phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
1653 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
1654 return log_status("InitializeSecurityContextW", status);
1655}
1656
1657static SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(
1658 PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
1659 ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
1660 PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
1661{
1662 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phCredential);
1663
1664 if (!Name)
1665 return SEC_E_SECPKG_NOT_FOUND;
1666
1667 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1668
1669 if (!table)
1670 return SEC_E_SECPKG_NOT_FOUND;
1671
1672 if (!table->InitializeSecurityContextA)
1673 {
1674 WLog_WARN(TAG, "Security module does not provide an implementation");
1675 return SEC_E_UNSUPPORTED_FUNCTION;
1676 }
1677
1678 SECURITY_STATUS status = table->InitializeSecurityContextA(
1679 phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
1680 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
1681
1682 return log_status("InitializeSecurityContextA", status);
1683}
1684
1685static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext,
1686 ULONG ulAttribute, void* pBuffer)
1687{
1688 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1689
1690 if (!Name)
1691 return SEC_E_SECPKG_NOT_FOUND;
1692
1693 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1694
1695 if (!table)
1696 return SEC_E_SECPKG_NOT_FOUND;
1697
1698 if (!table->QueryContextAttributesW)
1699 {
1700 WLog_WARN(TAG, "Security module does not provide an implementation");
1701 return SEC_E_UNSUPPORTED_FUNCTION;
1702 }
1703
1704 SECURITY_STATUS status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
1705 return log_status("QueryContextAttributesW", status);
1706}
1707
1708static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext,
1709 ULONG ulAttribute, void* pBuffer)
1710{
1711 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1712
1713 if (!Name)
1714 return SEC_E_SECPKG_NOT_FOUND;
1715
1716 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1717
1718 if (!table)
1719 return SEC_E_SECPKG_NOT_FOUND;
1720
1721 if (!table->QueryContextAttributesA)
1722 {
1723 WLog_WARN(TAG, "Security module does not provide an implementation");
1724 return SEC_E_UNSUPPORTED_FUNCTION;
1725 }
1726
1727 SECURITY_STATUS status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
1728 return log_status("QueryContextAttributesA", status);
1729}
1730
1731static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
1732 HANDLE* phToken)
1733{
1734 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1735
1736 if (!Name)
1737 return SEC_E_SECPKG_NOT_FOUND;
1738
1739 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1740
1741 if (!table)
1742 return SEC_E_SECPKG_NOT_FOUND;
1743
1744 if (!table->QuerySecurityContextToken)
1745 {
1746 WLog_WARN(TAG, "Security module does not provide an implementation");
1747 return SEC_E_UNSUPPORTED_FUNCTION;
1748 }
1749
1750 SECURITY_STATUS status = table->QuerySecurityContextToken(phContext, phToken);
1751 return log_status("QuerySecurityContextToken", status);
1752}
1753
1754static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext,
1755 ULONG ulAttribute, void* pBuffer,
1756 ULONG cbBuffer)
1757{
1758 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1759
1760 if (!Name)
1761 return SEC_E_SECPKG_NOT_FOUND;
1762
1763 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1764
1765 if (!table)
1766 return SEC_E_SECPKG_NOT_FOUND;
1767
1768 if (!table->SetContextAttributesW)
1769 {
1770 WLog_WARN(TAG, "Security module does not provide an implementation");
1771 return SEC_E_UNSUPPORTED_FUNCTION;
1772 }
1773
1774 SECURITY_STATUS status =
1775 table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
1776 return log_status("SetContextAttributesW", status);
1777}
1778
1779static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext,
1780 ULONG ulAttribute, void* pBuffer,
1781 ULONG cbBuffer)
1782{
1783 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1784
1785 if (!Name)
1786 return SEC_E_SECPKG_NOT_FOUND;
1787
1788 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1789
1790 if (!table)
1791 return SEC_E_SECPKG_NOT_FOUND;
1792
1793 if (!table->SetContextAttributesA)
1794 {
1795 WLog_WARN(TAG, "Security module does not provide an implementation");
1796 return SEC_E_UNSUPPORTED_FUNCTION;
1797 }
1798
1799 SECURITY_STATUS status =
1800 table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
1801 return log_status("SetContextAttributesA", status);
1802}
1803
1804static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
1805{
1806 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1807
1808 if (!Name)
1809 return SEC_E_SECPKG_NOT_FOUND;
1810
1811 const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameA(Name);
1812
1813 if (!table)
1814 return SEC_E_SECPKG_NOT_FOUND;
1815
1816 if (!table->RevertSecurityContext)
1817 {
1818 WLog_WARN(TAG, "Security module does not provide an implementation");
1819 return SEC_E_UNSUPPORTED_FUNCTION;
1820 }
1821
1822 SECURITY_STATUS status = table->RevertSecurityContext(phContext);
1823
1824 return log_status("RevertSecurityContext", status);
1825}
1826
1827/* Message Support */
1828
1829static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext,
1830 PSecBufferDesc pMessage, ULONG MessageSeqNo,
1831 PULONG pfQOP)
1832{
1833 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1834
1835 if (!Name)
1836 return SEC_E_SECPKG_NOT_FOUND;
1837
1838 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1839
1840 if (!table)
1841 return SEC_E_SECPKG_NOT_FOUND;
1842
1843 if (!table->DecryptMessage)
1844 {
1845 WLog_WARN(TAG, "Security module does not provide an implementation");
1846 return SEC_E_UNSUPPORTED_FUNCTION;
1847 }
1848
1849 const SECURITY_STATUS status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
1850
1851 return log_status("DecryptMessage", status);
1852}
1853
1854static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
1855 PSecBufferDesc pMessage, ULONG MessageSeqNo)
1856{
1857 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1858
1859 if (!Name)
1860 return SEC_E_SECPKG_NOT_FOUND;
1861
1862 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1863
1864 if (!table)
1865 return SEC_E_SECPKG_NOT_FOUND;
1866
1867 if (!table->EncryptMessage)
1868 {
1869 WLog_WARN(TAG, "Security module does not provide an implementation");
1870 return SEC_E_UNSUPPORTED_FUNCTION;
1871 }
1872
1873 const SECURITY_STATUS status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
1874 return log_status("EncryptMessage", status);
1875}
1876
1877static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
1878 PSecBufferDesc pMessage, ULONG MessageSeqNo)
1879{
1880 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1881
1882 if (!Name)
1883 return SEC_E_SECPKG_NOT_FOUND;
1884
1885 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1886
1887 if (!table)
1888 return SEC_E_SECPKG_NOT_FOUND;
1889
1890 if (!table->MakeSignature)
1891 {
1892 WLog_WARN(TAG, "Security module does not provide an implementation");
1893 return SEC_E_UNSUPPORTED_FUNCTION;
1894 }
1895
1896 const SECURITY_STATUS status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
1897 return log_status("MakeSignature", status);
1898}
1899
1900static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext,
1901 PSecBufferDesc pMessage, ULONG MessageSeqNo,
1902 PULONG pfQOP)
1903{
1904 const char* Name = (const char*)sspi_SecureHandleGetUpperPointer(phContext);
1905
1906 if (!Name)
1907 return SEC_E_SECPKG_NOT_FOUND;
1908
1909 const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
1910
1911 if (!table)
1912 return SEC_E_SECPKG_NOT_FOUND;
1913
1914 if (!table->VerifySignature)
1915 {
1916 WLog_WARN(TAG, "Security module does not provide an implementation");
1917 return SEC_E_UNSUPPORTED_FUNCTION;
1918 }
1919
1920 SECURITY_STATUS status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
1921
1922 return log_status("VerifySignature", status);
1923}
1924
1925static SecurityFunctionTableA winpr_SecurityFunctionTableA = {
1926 3, /* dwVersion */
1927 winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */
1928 winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
1929 winpr_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */
1930 winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
1931 nullptr, /* Reserved2 */
1932 winpr_InitializeSecurityContextA, /* InitializeSecurityContext */
1933 winpr_AcceptSecurityContext, /* AcceptSecurityContext */
1934 winpr_CompleteAuthToken, /* CompleteAuthToken */
1935 winpr_DeleteSecurityContext, /* DeleteSecurityContext */
1936 winpr_ApplyControlToken, /* ApplyControlToken */
1937 winpr_QueryContextAttributesA, /* QueryContextAttributes */
1938 winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
1939 winpr_RevertSecurityContext, /* RevertSecurityContext */
1940 winpr_MakeSignature, /* MakeSignature */
1941 winpr_VerifySignature, /* VerifySignature */
1942 winpr_FreeContextBuffer, /* FreeContextBuffer */
1943 winpr_QuerySecurityPackageInfoA, /* QuerySecurityPackageInfo */
1944 nullptr, /* Reserved3 */
1945 nullptr, /* Reserved4 */
1946 winpr_ExportSecurityContext, /* ExportSecurityContext */
1947 winpr_ImportSecurityContextA, /* ImportSecurityContext */
1948 nullptr, /* AddCredentials */
1949 nullptr, /* Reserved8 */
1950 winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
1951 winpr_EncryptMessage, /* EncryptMessage */
1952 winpr_DecryptMessage, /* DecryptMessage */
1953 winpr_SetContextAttributesA, /* SetContextAttributes */
1954 winpr_SetCredentialsAttributesA, /* SetCredentialsAttributes */
1955};
1956
1957static SecurityFunctionTableW winpr_SecurityFunctionTableW = {
1958 3, /* dwVersion */
1959 winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */
1960 winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
1961 winpr_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */
1962 winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
1963 nullptr, /* Reserved2 */
1964 winpr_InitializeSecurityContextW, /* InitializeSecurityContext */
1965 winpr_AcceptSecurityContext, /* AcceptSecurityContext */
1966 winpr_CompleteAuthToken, /* CompleteAuthToken */
1967 winpr_DeleteSecurityContext, /* DeleteSecurityContext */
1968 winpr_ApplyControlToken, /* ApplyControlToken */
1969 winpr_QueryContextAttributesW, /* QueryContextAttributes */
1970 winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
1971 winpr_RevertSecurityContext, /* RevertSecurityContext */
1972 winpr_MakeSignature, /* MakeSignature */
1973 winpr_VerifySignature, /* VerifySignature */
1974 winpr_FreeContextBuffer, /* FreeContextBuffer */
1975 winpr_QuerySecurityPackageInfoW, /* QuerySecurityPackageInfo */
1976 nullptr, /* Reserved3 */
1977 nullptr, /* Reserved4 */
1978 winpr_ExportSecurityContext, /* ExportSecurityContext */
1979 winpr_ImportSecurityContextW, /* ImportSecurityContext */
1980 nullptr, /* AddCredentials */
1981 nullptr, /* Reserved8 */
1982 winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
1983 winpr_EncryptMessage, /* EncryptMessage */
1984 winpr_DecryptMessage, /* DecryptMessage */
1985 winpr_SetContextAttributesW, /* SetContextAttributes */
1986 winpr_SetCredentialsAttributesW, /* SetCredentialsAttributes */
1987};
1988
1989SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
1990{
1991 return &winpr_SecurityFunctionTableW;
1992}
1993
1994SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
1995{
1996 return &winpr_SecurityFunctionTableA;
1997}