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