FreeRDP
Loading...
Searching...
No Matches
sspi.c
1
20#include <winpr/platform.h>
21#include <winpr/config.h>
22
23WINPR_PRAGMA_DIAG_PUSH
24WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO
25WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO
26
27#define _NO_KSECDD_IMPORT_ 1 // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
28
29WINPR_PRAGMA_DIAG_POP
30
31#include <winpr/sspi.h>
32
33#include <winpr/crt.h>
34#include <winpr/synch.h>
35#include <winpr/wlog.h>
36#include <winpr/library.h>
37#include <winpr/environment.h>
38
39#include "sspi.h"
40
41WINPR_PRAGMA_DIAG_PUSH
42WINPR_PRAGMA_DIAG_IGNORED_MISSING_PROTOTYPES
43
44static wLog* g_Log = NULL;
45
46static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
47#if defined(WITH_NATIVE_SSPI)
48static HMODULE g_SspiModule = NULL;
49static SecurityFunctionTableW windows_SecurityFunctionTableW = { 0 };
50static SecurityFunctionTableA windows_SecurityFunctionTableA = { 0 };
51#endif
52
53static SecurityFunctionTableW* g_SspiW = NULL;
54static SecurityFunctionTableA* g_SspiA = NULL;
55
56#if defined(WITH_NATIVE_SSPI)
57static BOOL ShouldUseNativeSspi(void);
58static BOOL InitializeSspiModule_Native(void);
59#endif
60
61#if defined(WITH_NATIVE_SSPI)
62BOOL ShouldUseNativeSspi(void)
63{
64 BOOL status = FALSE;
65#ifdef _WIN32
66 LPCSTR sspi = "WINPR_NATIVE_SSPI";
67 DWORD nSize;
68 char* env = NULL;
69 nSize = GetEnvironmentVariableA(sspi, NULL, 0);
70
71 if (!nSize)
72 return TRUE;
73
74 env = (LPSTR)malloc(nSize);
75
76 if (!env)
77 return TRUE;
78
79 if (GetEnvironmentVariableA(sspi, env, nSize) != nSize - 1)
80 {
81 free(env);
82 return TRUE;
83 }
84
85 if (strcmp(env, "0") == 0)
86 status = FALSE;
87 else
88 status = TRUE;
89
90 free(env);
91#endif
92 return status;
93}
94#endif
95
96#if defined(WITH_NATIVE_SSPI)
97BOOL InitializeSspiModule_Native(void)
98{
99 SecurityFunctionTableW* pSspiW = NULL;
100 SecurityFunctionTableA* pSspiA = NULL;
101 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW;
102 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA;
103 g_SspiModule = LoadLibraryA("secur32.dll");
104
105 if (!g_SspiModule)
106 g_SspiModule = LoadLibraryA("sspicli.dll");
107
108 if (!g_SspiModule)
109 return FALSE;
110
111 pInitSecurityInterfaceW =
112 GetProcAddressAs(g_SspiModule, "InitSecurityInterfaceW", INIT_SECURITY_INTERFACE_W);
113 pInitSecurityInterfaceA =
114 GetProcAddressAs(g_SspiModule, "InitSecurityInterfaceA", INIT_SECURITY_INTERFACE_A);
115
116 if (pInitSecurityInterfaceW)
117 {
118 pSspiW = pInitSecurityInterfaceW();
119
120 if (pSspiW)
121 {
122 g_SspiW = &windows_SecurityFunctionTableW;
123 CopyMemory(g_SspiW, pSspiW,
124 FIELD_OFFSET(SecurityFunctionTableW, SetContextAttributesW));
125
126 g_SspiW->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
127
128 g_SspiW->SetContextAttributesW = GetProcAddressAs(g_SspiModule, "SetContextAttributesW",
129 SET_CONTEXT_ATTRIBUTES_FN_W);
130
131 g_SspiW->SetCredentialsAttributesW = GetProcAddressAs(
132 g_SspiModule, "SetCredentialsAttributesW", SET_CREDENTIALS_ATTRIBUTES_FN_W);
133 }
134 }
135
136 if (pInitSecurityInterfaceA)
137 {
138 pSspiA = pInitSecurityInterfaceA();
139
140 if (pSspiA)
141 {
142 g_SspiA = &windows_SecurityFunctionTableA;
143 CopyMemory(g_SspiA, pSspiA,
144 FIELD_OFFSET(SecurityFunctionTableA, SetContextAttributesA));
145
146 g_SspiA->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
147
148 g_SspiA->SetContextAttributesA = GetProcAddressAs(g_SspiModule, "SetContextAttributesA",
149 SET_CONTEXT_ATTRIBUTES_FN_W);
150
151 g_SspiA->SetCredentialsAttributesA = GetProcAddressAs(
152 g_SspiModule, "SetCredentialsAttributesA", SET_CREDENTIALS_ATTRIBUTES_FN_W);
153 }
154 }
155
156 return TRUE;
157}
158#endif
159
160static BOOL CALLBACK InitializeSspiModuleInt(WINPR_ATTR_UNUSED PINIT_ONCE once,
161 WINPR_ATTR_UNUSED PVOID param,
162 WINPR_ATTR_UNUSED PVOID* context)
163{
164 BOOL status = FALSE;
165#if defined(WITH_NATIVE_SSPI)
166 DWORD flags = 0;
167
168 if (param)
169 flags = *(DWORD*)param;
170
171#endif
172 sspi_GlobalInit();
173 g_Log = WLog_Get("com.winpr.sspi");
174#if defined(WITH_NATIVE_SSPI)
175
176 if (flags && (flags & SSPI_INTERFACE_NATIVE))
177 {
178 status = InitializeSspiModule_Native();
179 }
180 else if (flags && (flags & SSPI_INTERFACE_WINPR))
181 {
182 g_SspiW = winpr_InitSecurityInterfaceW();
183 g_SspiA = winpr_InitSecurityInterfaceA();
184 status = TRUE;
185 }
186
187 if (!status && ShouldUseNativeSspi())
188 {
189 status = InitializeSspiModule_Native();
190 }
191
192#endif
193
194 if (!status)
195 {
196 g_SspiW = winpr_InitSecurityInterfaceW();
197 g_SspiA = winpr_InitSecurityInterfaceA();
198 }
199
200 return TRUE;
201}
202
203const char* GetSecurityStatusString(SECURITY_STATUS status)
204{
205 switch (status)
206 {
207 case SEC_E_OK:
208 return "SEC_E_OK";
209
210 case SEC_E_INSUFFICIENT_MEMORY:
211 return "SEC_E_INSUFFICIENT_MEMORY";
212
213 case SEC_E_INVALID_HANDLE:
214 return "SEC_E_INVALID_HANDLE";
215
216 case SEC_E_UNSUPPORTED_FUNCTION:
217 return "SEC_E_UNSUPPORTED_FUNCTION";
218
219 case SEC_E_TARGET_UNKNOWN:
220 return "SEC_E_TARGET_UNKNOWN";
221
222 case SEC_E_INTERNAL_ERROR:
223 return "SEC_E_INTERNAL_ERROR";
224
225 case SEC_E_SECPKG_NOT_FOUND:
226 return "SEC_E_SECPKG_NOT_FOUND";
227
228 case SEC_E_NOT_OWNER:
229 return "SEC_E_NOT_OWNER";
230
231 case SEC_E_CANNOT_INSTALL:
232 return "SEC_E_CANNOT_INSTALL";
233
234 case SEC_E_INVALID_TOKEN:
235 return "SEC_E_INVALID_TOKEN";
236
237 case SEC_E_CANNOT_PACK:
238 return "SEC_E_CANNOT_PACK";
239
240 case SEC_E_QOP_NOT_SUPPORTED:
241 return "SEC_E_QOP_NOT_SUPPORTED";
242
243 case SEC_E_NO_IMPERSONATION:
244 return "SEC_E_NO_IMPERSONATION";
245
246 case SEC_E_LOGON_DENIED:
247 return "SEC_E_LOGON_DENIED";
248
249 case SEC_E_UNKNOWN_CREDENTIALS:
250 return "SEC_E_UNKNOWN_CREDENTIALS";
251
252 case SEC_E_NO_CREDENTIALS:
253 return "SEC_E_NO_CREDENTIALS";
254
255 case SEC_E_MESSAGE_ALTERED:
256 return "SEC_E_MESSAGE_ALTERED";
257
258 case SEC_E_OUT_OF_SEQUENCE:
259 return "SEC_E_OUT_OF_SEQUENCE";
260
261 case SEC_E_NO_AUTHENTICATING_AUTHORITY:
262 return "SEC_E_NO_AUTHENTICATING_AUTHORITY";
263
264 case SEC_E_BAD_PKGID:
265 return "SEC_E_BAD_PKGID";
266
267 case SEC_E_CONTEXT_EXPIRED:
268 return "SEC_E_CONTEXT_EXPIRED";
269
270 case SEC_E_INCOMPLETE_MESSAGE:
271 return "SEC_E_INCOMPLETE_MESSAGE";
272
273 case SEC_E_INCOMPLETE_CREDENTIALS:
274 return "SEC_E_INCOMPLETE_CREDENTIALS";
275
276 case SEC_E_BUFFER_TOO_SMALL:
277 return "SEC_E_BUFFER_TOO_SMALL";
278
279 case SEC_E_WRONG_PRINCIPAL:
280 return "SEC_E_WRONG_PRINCIPAL";
281
282 case SEC_E_TIME_SKEW:
283 return "SEC_E_TIME_SKEW";
284
285 case SEC_E_UNTRUSTED_ROOT:
286 return "SEC_E_UNTRUSTED_ROOT";
287
288 case SEC_E_ILLEGAL_MESSAGE:
289 return "SEC_E_ILLEGAL_MESSAGE";
290
291 case SEC_E_CERT_UNKNOWN:
292 return "SEC_E_CERT_UNKNOWN";
293
294 case SEC_E_CERT_EXPIRED:
295 return "SEC_E_CERT_EXPIRED";
296
297 case SEC_E_ENCRYPT_FAILURE:
298 return "SEC_E_ENCRYPT_FAILURE";
299
300 case SEC_E_DECRYPT_FAILURE:
301 return "SEC_E_DECRYPT_FAILURE";
302
303 case SEC_E_ALGORITHM_MISMATCH:
304 return "SEC_E_ALGORITHM_MISMATCH";
305
306 case SEC_E_SECURITY_QOS_FAILED:
307 return "SEC_E_SECURITY_QOS_FAILED";
308
309 case SEC_E_UNFINISHED_CONTEXT_DELETED:
310 return "SEC_E_UNFINISHED_CONTEXT_DELETED";
311
312 case SEC_E_NO_TGT_REPLY:
313 return "SEC_E_NO_TGT_REPLY";
314
315 case SEC_E_NO_IP_ADDRESSES:
316 return "SEC_E_NO_IP_ADDRESSES";
317
318 case SEC_E_WRONG_CREDENTIAL_HANDLE:
319 return "SEC_E_WRONG_CREDENTIAL_HANDLE";
320
321 case SEC_E_CRYPTO_SYSTEM_INVALID:
322 return "SEC_E_CRYPTO_SYSTEM_INVALID";
323
324 case SEC_E_MAX_REFERRALS_EXCEEDED:
325 return "SEC_E_MAX_REFERRALS_EXCEEDED";
326
327 case SEC_E_MUST_BE_KDC:
328 return "SEC_E_MUST_BE_KDC";
329
330 case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
331 return "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
332
333 case SEC_E_TOO_MANY_PRINCIPALS:
334 return "SEC_E_TOO_MANY_PRINCIPALS";
335
336 case SEC_E_NO_PA_DATA:
337 return "SEC_E_NO_PA_DATA";
338
339 case SEC_E_PKINIT_NAME_MISMATCH:
340 return "SEC_E_PKINIT_NAME_MISMATCH";
341
342 case SEC_E_SMARTCARD_LOGON_REQUIRED:
343 return "SEC_E_SMARTCARD_LOGON_REQUIRED";
344
345 case SEC_E_SHUTDOWN_IN_PROGRESS:
346 return "SEC_E_SHUTDOWN_IN_PROGRESS";
347
348 case SEC_E_KDC_INVALID_REQUEST:
349 return "SEC_E_KDC_INVALID_REQUEST";
350
351 case SEC_E_KDC_UNABLE_TO_REFER:
352 return "SEC_E_KDC_UNABLE_TO_REFER";
353
354 case SEC_E_KDC_UNKNOWN_ETYPE:
355 return "SEC_E_KDC_UNKNOWN_ETYPE";
356
357 case SEC_E_UNSUPPORTED_PREAUTH:
358 return "SEC_E_UNSUPPORTED_PREAUTH";
359
360 case SEC_E_DELEGATION_REQUIRED:
361 return "SEC_E_DELEGATION_REQUIRED";
362
363 case SEC_E_BAD_BINDINGS:
364 return "SEC_E_BAD_BINDINGS";
365
366 case SEC_E_MULTIPLE_ACCOUNTS:
367 return "SEC_E_MULTIPLE_ACCOUNTS";
368
369 case SEC_E_NO_KERB_KEY:
370 return "SEC_E_NO_KERB_KEY";
371
372 case SEC_E_CERT_WRONG_USAGE:
373 return "SEC_E_CERT_WRONG_USAGE";
374
375 case SEC_E_DOWNGRADE_DETECTED:
376 return "SEC_E_DOWNGRADE_DETECTED";
377
378 case SEC_E_SMARTCARD_CERT_REVOKED:
379 return "SEC_E_SMARTCARD_CERT_REVOKED";
380
381 case SEC_E_ISSUING_CA_UNTRUSTED:
382 return "SEC_E_ISSUING_CA_UNTRUSTED";
383
384 case SEC_E_REVOCATION_OFFLINE_C:
385 return "SEC_E_REVOCATION_OFFLINE_C";
386
387 case SEC_E_PKINIT_CLIENT_FAILURE:
388 return "SEC_E_PKINIT_CLIENT_FAILURE";
389
390 case SEC_E_SMARTCARD_CERT_EXPIRED:
391 return "SEC_E_SMARTCARD_CERT_EXPIRED";
392
393 case SEC_E_NO_S4U_PROT_SUPPORT:
394 return "SEC_E_NO_S4U_PROT_SUPPORT";
395
396 case SEC_E_CROSSREALM_DELEGATION_FAILURE:
397 return "SEC_E_CROSSREALM_DELEGATION_FAILURE";
398
399 case SEC_E_REVOCATION_OFFLINE_KDC:
400 return "SEC_E_REVOCATION_OFFLINE_KDC";
401
402 case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
403 return "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
404
405 case SEC_E_KDC_CERT_EXPIRED:
406 return "SEC_E_KDC_CERT_EXPIRED";
407
408 case SEC_E_KDC_CERT_REVOKED:
409 return "SEC_E_KDC_CERT_REVOKED";
410
411 case SEC_E_INVALID_PARAMETER:
412 return "SEC_E_INVALID_PARAMETER";
413
414 case SEC_E_DELEGATION_POLICY:
415 return "SEC_E_DELEGATION_POLICY";
416
417 case SEC_E_POLICY_NLTM_ONLY:
418 return "SEC_E_POLICY_NLTM_ONLY";
419
420 case SEC_E_NO_CONTEXT:
421 return "SEC_E_NO_CONTEXT";
422
423 case SEC_E_PKU2U_CERT_FAILURE:
424 return "SEC_E_PKU2U_CERT_FAILURE";
425
426 case SEC_E_MUTUAL_AUTH_FAILED:
427 return "SEC_E_MUTUAL_AUTH_FAILED";
428
429 case SEC_I_CONTINUE_NEEDED:
430 return "SEC_I_CONTINUE_NEEDED";
431
432 case SEC_I_COMPLETE_NEEDED:
433 return "SEC_I_COMPLETE_NEEDED";
434
435 case SEC_I_COMPLETE_AND_CONTINUE:
436 return "SEC_I_COMPLETE_AND_CONTINUE";
437
438 case SEC_I_LOCAL_LOGON:
439 return "SEC_I_LOCAL_LOGON";
440
441 case SEC_I_CONTEXT_EXPIRED:
442 return "SEC_I_CONTEXT_EXPIRED";
443
444 case SEC_I_INCOMPLETE_CREDENTIALS:
445 return "SEC_I_INCOMPLETE_CREDENTIALS";
446
447 case SEC_I_RENEGOTIATE:
448 return "SEC_I_RENEGOTIATE";
449
450 case SEC_I_NO_LSA_CONTEXT:
451 return "SEC_I_NO_LSA_CONTEXT";
452
453 case SEC_I_SIGNATURE_NEEDED:
454 return "SEC_I_SIGNATURE_NEEDED";
455
456 case SEC_I_NO_RENEGOTIATION:
457 return "SEC_I_NO_RENEGOTIATION";
458 default:
459 break;
460 }
461
462 return NtStatus2Tag(status);
463}
464
465BOOL IsSecurityStatusError(SECURITY_STATUS status)
466{
467 BOOL error = TRUE;
468
469 switch (status)
470 {
471 case SEC_E_OK:
472 case SEC_I_CONTINUE_NEEDED:
473 case SEC_I_COMPLETE_NEEDED:
474 case SEC_I_COMPLETE_AND_CONTINUE:
475 case SEC_I_LOCAL_LOGON:
476 case SEC_I_CONTEXT_EXPIRED:
477 case SEC_I_INCOMPLETE_CREDENTIALS:
478 case SEC_I_RENEGOTIATE:
479 case SEC_I_NO_LSA_CONTEXT:
480 case SEC_I_SIGNATURE_NEEDED:
481 case SEC_I_NO_RENEGOTIATION:
482 error = FALSE;
483 break;
484 default:
485 break;
486 }
487
488 return error;
489}
490
491SecurityFunctionTableW* SEC_ENTRY InitSecurityInterfaceExW(DWORD flags)
492{
493 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
494 WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExW");
495 return g_SspiW;
496}
497
498SecurityFunctionTableA* SEC_ENTRY InitSecurityInterfaceExA(DWORD flags)
499{
500 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
501 WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExA");
502 return g_SspiA;
503}
504
509/* Package Management */
510
511SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(ULONG* pcPackages,
512 PSecPkgInfoW* ppPackageInfo)
513{
514 SECURITY_STATUS status = 0;
515 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
516
517 if (!(g_SspiW && g_SspiW->EnumerateSecurityPackagesW))
518 {
519 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
520
521 return SEC_E_UNSUPPORTED_FUNCTION;
522 }
523
524 status = g_SspiW->EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
525 WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesW: %s (0x%08" PRIX32 ")",
526 GetSecurityStatusString(status), status);
527 return status;
528}
529
530SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(ULONG* pcPackages,
531 PSecPkgInfoA* ppPackageInfo)
532{
533 SECURITY_STATUS status = 0;
534 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
535
536 if (!(g_SspiA && g_SspiA->EnumerateSecurityPackagesA))
537 {
538 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
539
540 return SEC_E_UNSUPPORTED_FUNCTION;
541 }
542
543 status = g_SspiA->EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
544 WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesA: %s (0x%08" PRIX32 ")",
545 GetSecurityStatusString(status), status);
546 return status;
547}
548
549SecurityFunctionTableW* SEC_ENTRY sspi_InitSecurityInterfaceW(void)
550{
551 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
552 WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceW");
553 return g_SspiW;
554}
555
556SecurityFunctionTableA* SEC_ENTRY sspi_InitSecurityInterfaceA(void)
557{
558 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
559 WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceA");
560 return g_SspiA;
561}
562
563SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
564 PSecPkgInfoW* ppPackageInfo)
565{
566 SECURITY_STATUS status = 0;
567 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
568
569 if (!(g_SspiW && g_SspiW->QuerySecurityPackageInfoW))
570 {
571 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
572
573 return SEC_E_UNSUPPORTED_FUNCTION;
574 }
575
576 status = g_SspiW->QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
577 WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoW: %s (0x%08" PRIX32 ")",
578 GetSecurityStatusString(status), status);
579 return status;
580}
581
582SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
583 PSecPkgInfoA* ppPackageInfo)
584{
585 SECURITY_STATUS status = 0;
586 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
587
588 if (!(g_SspiA && g_SspiA->QuerySecurityPackageInfoA))
589 {
590 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
591
592 return SEC_E_UNSUPPORTED_FUNCTION;
593 }
594
595 status = g_SspiA->QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
596 WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoA: %s (0x%08" PRIX32 ")",
597 GetSecurityStatusString(status), status);
598 return status;
599}
600
601/* Credential Management */
602
603SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(
604 SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
605 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
606 PTimeStamp ptsExpiry)
607{
608 SECURITY_STATUS status = 0;
609 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
610
611 if (!(g_SspiW && g_SspiW->AcquireCredentialsHandleW))
612 {
613 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
614
615 return SEC_E_UNSUPPORTED_FUNCTION;
616 }
617
618 status = g_SspiW->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
619 pAuthData, pGetKeyFn, pvGetKeyArgument,
620 phCredential, ptsExpiry);
621 WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleW: %s (0x%08" PRIX32 ")",
622 GetSecurityStatusString(status), status);
623 return status;
624}
625
626SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(
627 SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
628 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
629 PTimeStamp ptsExpiry)
630{
631 SECURITY_STATUS status = 0;
632 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
633
634 if (!(g_SspiA && g_SspiA->AcquireCredentialsHandleA))
635 {
636 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
637
638 return SEC_E_UNSUPPORTED_FUNCTION;
639 }
640
641 status = g_SspiA->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
642 pAuthData, pGetKeyFn, pvGetKeyArgument,
643 phCredential, ptsExpiry);
644 WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleA: %s (0x%08" PRIX32 ")",
645 GetSecurityStatusString(status), status);
646 return status;
647}
648
649SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
650 PSecBuffer pPackedContext, HANDLE* pToken)
651{
652 SECURITY_STATUS status = 0;
653 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
654
655 if (!(g_SspiW && g_SspiW->ExportSecurityContext))
656 {
657 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
658
659 return SEC_E_UNSUPPORTED_FUNCTION;
660 }
661
662 status = g_SspiW->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
663 WLog_Print(g_Log, WLOG_DEBUG, "ExportSecurityContext: %s (0x%08" PRIX32 ")",
664 GetSecurityStatusString(status), status);
665 return status;
666}
667
668SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(PCredHandle phCredential)
669{
670 SECURITY_STATUS status = 0;
671 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
672
673 if (!(g_SspiW && g_SspiW->FreeCredentialsHandle))
674 {
675 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
676
677 return SEC_E_UNSUPPORTED_FUNCTION;
678 }
679
680 status = g_SspiW->FreeCredentialsHandle(phCredential);
681 WLog_Print(g_Log, WLOG_DEBUG, "FreeCredentialsHandle: %s (0x%08" PRIX32 ")",
682 GetSecurityStatusString(status), status);
683 return status;
684}
685
686SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(SEC_WCHAR* pszPackage,
687 PSecBuffer pPackedContext, HANDLE pToken,
688 PCtxtHandle phContext)
689{
690 SECURITY_STATUS status = 0;
691 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
692
693 if (!(g_SspiW && g_SspiW->ImportSecurityContextW))
694 {
695 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
696
697 return SEC_E_UNSUPPORTED_FUNCTION;
698 }
699
700 status = g_SspiW->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
701 WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextW: %s (0x%08" PRIX32 ")",
702 GetSecurityStatusString(status), status);
703 return status;
704}
705
706SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(SEC_CHAR* pszPackage,
707 PSecBuffer pPackedContext, HANDLE pToken,
708 PCtxtHandle phContext)
709{
710 SECURITY_STATUS status = 0;
711 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
712
713 if (!(g_SspiA && g_SspiA->ImportSecurityContextA))
714 {
715 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
716
717 return SEC_E_UNSUPPORTED_FUNCTION;
718 }
719
720 status = g_SspiA->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
721 WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextA: %s (0x%08" PRIX32 ")",
722 GetSecurityStatusString(status), status);
723 return status;
724}
725
726SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(PCredHandle phCredential,
727 ULONG ulAttribute, void* pBuffer)
728{
729 SECURITY_STATUS status = 0;
730 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
731
732 if (!(g_SspiW && g_SspiW->QueryCredentialsAttributesW))
733 {
734 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
735
736 return SEC_E_UNSUPPORTED_FUNCTION;
737 }
738
739 status = g_SspiW->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
740 WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesW: %s (0x%08" PRIX32 ")",
741 GetSecurityStatusString(status), status);
742 return status;
743}
744
745SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(PCredHandle phCredential,
746 ULONG ulAttribute, void* pBuffer)
747{
748 SECURITY_STATUS status = 0;
749 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
750
751 if (!(g_SspiA && g_SspiA->QueryCredentialsAttributesA))
752 {
753 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
754
755 return SEC_E_UNSUPPORTED_FUNCTION;
756 }
757
758 status = g_SspiA->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
759 WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesA: %s (0x%08" PRIX32 ")",
760 GetSecurityStatusString(status), status);
761 return status;
762}
763
764/* Context Management */
765
766SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(PCredHandle phCredential,
767 PCtxtHandle phContext, PSecBufferDesc pInput,
768 ULONG fContextReq, ULONG TargetDataRep,
769 PCtxtHandle phNewContext,
770 PSecBufferDesc pOutput, PULONG pfContextAttr,
771 PTimeStamp ptsTimeStamp)
772{
773 SECURITY_STATUS status = 0;
774 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
775
776 if (!(g_SspiW && g_SspiW->AcceptSecurityContext))
777 {
778 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
779
780 return SEC_E_UNSUPPORTED_FUNCTION;
781 }
782
783 status =
784 g_SspiW->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
785 phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
786 WLog_Print(g_Log, WLOG_DEBUG, "AcceptSecurityContext: %s (0x%08" PRIX32 ")",
787 GetSecurityStatusString(status), status);
788 return status;
789}
790
791SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput)
792{
793 SECURITY_STATUS status = 0;
794 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
795
796 if (!(g_SspiW && g_SspiW->ApplyControlToken))
797 {
798 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
799
800 return SEC_E_UNSUPPORTED_FUNCTION;
801 }
802
803 status = g_SspiW->ApplyControlToken(phContext, pInput);
804 WLog_Print(g_Log, WLOG_DEBUG, "ApplyControlToken: %s (0x%08" PRIX32 ")",
805 GetSecurityStatusString(status), status);
806 return status;
807}
808
809SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
810{
811 SECURITY_STATUS status = 0;
812 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
813
814 if (!(g_SspiW && g_SspiW->CompleteAuthToken))
815 {
816 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
817
818 return SEC_E_UNSUPPORTED_FUNCTION;
819 }
820
821 status = g_SspiW->CompleteAuthToken(phContext, pToken);
822 WLog_Print(g_Log, WLOG_DEBUG, "CompleteAuthToken: %s (0x%08" PRIX32 ")",
823 GetSecurityStatusString(status), status);
824 return status;
825}
826
827SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(PCtxtHandle phContext)
828{
829 SECURITY_STATUS status = 0;
830 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
831
832 if (!(g_SspiW && g_SspiW->DeleteSecurityContext))
833 {
834 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
835
836 return SEC_E_UNSUPPORTED_FUNCTION;
837 }
838
839 status = g_SspiW->DeleteSecurityContext(phContext);
840 WLog_Print(g_Log, WLOG_DEBUG, "DeleteSecurityContext: %s (0x%08" PRIX32 ")",
841 GetSecurityStatusString(status), status);
842 return status;
843}
844
845SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void* pvContextBuffer)
846{
847 SECURITY_STATUS status = 0;
848 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
849
850 if (!(g_SspiW && g_SspiW->FreeContextBuffer))
851 {
852 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
853
854 return SEC_E_UNSUPPORTED_FUNCTION;
855 }
856
857 status = g_SspiW->FreeContextBuffer(pvContextBuffer);
858 WLog_Print(g_Log, WLOG_DEBUG, "FreeContextBuffer: %s (0x%08" PRIX32 ")",
859 GetSecurityStatusString(status), status);
860 return status;
861}
862
863SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(PCtxtHandle phContext)
864{
865 SECURITY_STATUS status = 0;
866 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
867
868 if (!(g_SspiW && g_SspiW->ImpersonateSecurityContext))
869 {
870 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
871
872 return SEC_E_UNSUPPORTED_FUNCTION;
873 }
874
875 status = g_SspiW->ImpersonateSecurityContext(phContext);
876 WLog_Print(g_Log, WLOG_DEBUG, "ImpersonateSecurityContext: %s (0x%08" PRIX32 ")",
877 GetSecurityStatusString(status), status);
878 return status;
879}
880
881SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(
882 PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
883 ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
884 PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
885{
886 SECURITY_STATUS status = 0;
887 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
888
889 if (!(g_SspiW && g_SspiW->InitializeSecurityContextW))
890 {
891 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
892
893 return SEC_E_UNSUPPORTED_FUNCTION;
894 }
895
896 status = g_SspiW->InitializeSecurityContextW(
897 phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
898 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
899 WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextW: %s (0x%08" PRIX32 ")",
900 GetSecurityStatusString(status), status);
901 return status;
902}
903
904SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(
905 PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
906 ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
907 PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
908{
909 SECURITY_STATUS status = 0;
910 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
911
912 if (!(g_SspiA && g_SspiA->InitializeSecurityContextA))
913 {
914 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
915
916 return SEC_E_UNSUPPORTED_FUNCTION;
917 }
918
919 status = g_SspiA->InitializeSecurityContextA(
920 phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
921 Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
922 WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextA: %s (0x%08" PRIX32 ")",
923 GetSecurityStatusString(status), status);
924 return status;
925}
926
927SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
928 void* pBuffer)
929{
930 SECURITY_STATUS status = 0;
931 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
932
933 if (!(g_SspiW && g_SspiW->QueryContextAttributesW))
934 {
935 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
936
937 return SEC_E_UNSUPPORTED_FUNCTION;
938 }
939
940 status = g_SspiW->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
941 WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesW: %s (0x%08" PRIX32 ")",
942 GetSecurityStatusString(status), status);
943 return status;
944}
945
946SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
947 void* pBuffer)
948{
949 SECURITY_STATUS status = 0;
950 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
951
952 if (!(g_SspiA && g_SspiA->QueryContextAttributesA))
953 {
954 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
955
956 return SEC_E_UNSUPPORTED_FUNCTION;
957 }
958
959 status = g_SspiA->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
960 WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesA: %s (0x%08" PRIX32 ")",
961 GetSecurityStatusString(status), status);
962 return status;
963}
964
965SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken)
966{
967 SECURITY_STATUS status = 0;
968 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
969
970 if (!(g_SspiW && g_SspiW->QuerySecurityContextToken))
971 {
972 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
973
974 return SEC_E_UNSUPPORTED_FUNCTION;
975 }
976
977 status = g_SspiW->QuerySecurityContextToken(phContext, phToken);
978 WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityContextToken: %s (0x%08" PRIX32 ")",
979 GetSecurityStatusString(status), status);
980 return status;
981}
982
983SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
984 void* pBuffer, ULONG cbBuffer)
985{
986 SECURITY_STATUS status = 0;
987 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
988
989 if (!(g_SspiW && g_SspiW->SetContextAttributesW))
990 {
991 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
992
993 return SEC_E_UNSUPPORTED_FUNCTION;
994 }
995
996 status = g_SspiW->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
997 WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesW: %s (0x%08" PRIX32 ")",
998 GetSecurityStatusString(status), status);
999 return status;
1000}
1001
1002SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
1003 void* pBuffer, ULONG cbBuffer)
1004{
1005 SECURITY_STATUS status = 0;
1006 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1007
1008 if (!(g_SspiA && g_SspiA->SetContextAttributesA))
1009 {
1010 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1011
1012 return SEC_E_UNSUPPORTED_FUNCTION;
1013 }
1014
1015 status = g_SspiA->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
1016 WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesA: %s (0x%08" PRIX32 ")",
1017 GetSecurityStatusString(status), status);
1018 return status;
1019}
1020
1021SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(PCtxtHandle phContext)
1022{
1023 SECURITY_STATUS status = 0;
1024 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1025
1026 if (!(g_SspiW && g_SspiW->RevertSecurityContext))
1027 {
1028 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1029
1030 return SEC_E_UNSUPPORTED_FUNCTION;
1031 }
1032
1033 status = g_SspiW->RevertSecurityContext(phContext);
1034 WLog_Print(g_Log, WLOG_DEBUG, "RevertSecurityContext: %s (0x%08" PRIX32 ")",
1035 GetSecurityStatusString(status), status);
1036 return status;
1037}
1038
1039/* Message Support */
1040
1041SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
1042 ULONG MessageSeqNo, PULONG pfQOP)
1043{
1044 SECURITY_STATUS status = 0;
1045 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1046
1047 if (!(g_SspiW && g_SspiW->DecryptMessage))
1048 {
1049 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1050
1051 return SEC_E_UNSUPPORTED_FUNCTION;
1052 }
1053
1054 status = g_SspiW->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
1055 WLog_Print(g_Log, WLOG_DEBUG, "DecryptMessage: %s (0x%08" PRIX32 ")",
1056 GetSecurityStatusString(status), status);
1057 return status;
1058}
1059
1060SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
1061 PSecBufferDesc pMessage, ULONG MessageSeqNo)
1062{
1063 SECURITY_STATUS status = 0;
1064 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1065
1066 if (!(g_SspiW && g_SspiW->EncryptMessage))
1067 {
1068 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1069
1070 return SEC_E_UNSUPPORTED_FUNCTION;
1071 }
1072
1073 status = g_SspiW->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
1074 WLog_Print(g_Log, WLOG_DEBUG, "EncryptMessage: %s (0x%08" PRIX32 ")",
1075 GetSecurityStatusString(status), status);
1076 return status;
1077}
1078
1079SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
1080 PSecBufferDesc pMessage, ULONG MessageSeqNo)
1081{
1082 SECURITY_STATUS status = 0;
1083 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1084
1085 if (!(g_SspiW && g_SspiW->MakeSignature))
1086 {
1087 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1088
1089 return SEC_E_UNSUPPORTED_FUNCTION;
1090 }
1091
1092 status = g_SspiW->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
1093 WLog_Print(g_Log, WLOG_DEBUG, "MakeSignature: %s (0x%08" PRIX32 ")",
1094 GetSecurityStatusString(status), status);
1095 return status;
1096}
1097
1098SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage,
1099 ULONG MessageSeqNo, PULONG pfQOP)
1100{
1101 SECURITY_STATUS status = 0;
1102 InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
1103
1104 if (!(g_SspiW && g_SspiW->VerifySignature))
1105 {
1106 WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
1107
1108 return SEC_E_UNSUPPORTED_FUNCTION;
1109 }
1110
1111 status = g_SspiW->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
1112 WLog_Print(g_Log, WLOG_DEBUG, "VerifySignature: %s (0x%08" PRIX32 ")",
1113 GetSecurityStatusString(status), status);
1114 return status;
1115}
1116
1117WINPR_PRAGMA_DIAG_POP
1118
1119static void zfree(WCHAR* str, size_t len, BOOL isWCHAR)
1120{
1121 if (str)
1122 memset(str, 0, len * (isWCHAR ? sizeof(WCHAR) : sizeof(char)));
1123 free(str);
1124}
1125
1126void sspi_FreeAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity)
1127{
1128 if (!identity)
1129 return;
1130
1131 const BOOL wc = (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) != 0;
1132 zfree(identity->User, identity->UserLength, wc);
1133 zfree(identity->Domain, identity->DomainLength, wc);
1134
1135 /* identity->PasswordLength does have a dual use. In Pass The Hash (PTH) mode the maximum
1136 * password length (512) is added to the real length to mark this as a hash. when we free up
1137 * this field without removing these additional bytes we would corrupt the stack.
1138 */
1139 size_t len = identity->PasswordLength;
1140 if (len > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
1141 len -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
1142 zfree(identity->Password, len, wc);
1143
1144 const SEC_WINNT_AUTH_IDENTITY empty = { 0 };
1145 *identity = empty;
1146}