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