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