summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/sspi/sspi.c
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/sspi/sspi.c')
-rw-r--r--winpr/libwinpr/sspi/sspi.c1129
1 files changed, 1129 insertions, 0 deletions
diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c
new file mode 100644
index 0000000..acecb5b
--- /dev/null
+++ b/winpr/libwinpr/sspi/sspi.c
@@ -0,0 +1,1129 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Security Support Provider Interface (SSPI)
+ *
+ * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/platform.h>
+#include <winpr/config.h>
+
+WINPR_PRAGMA_DIAG_PUSH
+WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO
+
+#define _NO_KSECDD_IMPORT_ 1
+
+WINPR_PRAGMA_DIAG_POP
+
+#include <winpr/sspi.h>
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <winpr/wlog.h>
+#include <winpr/library.h>
+#include <winpr/environment.h>
+
+#include "sspi.h"
+
+WINPR_PRAGMA_DIAG_PUSH
+WINPR_PRAGMA_DIAG_IGNORED_MISSING_PROTOTYPES
+
+static wLog* g_Log = NULL;
+
+static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
+#if defined(WITH_NATIVE_SSPI)
+static HMODULE g_SspiModule = NULL;
+static SecurityFunctionTableW windows_SecurityFunctionTableW = { 0 };
+static SecurityFunctionTableA windows_SecurityFunctionTableA = { 0 };
+#endif
+
+static SecurityFunctionTableW* g_SspiW = NULL;
+static SecurityFunctionTableA* g_SspiA = NULL;
+
+#if defined(WITH_NATIVE_SSPI)
+static BOOL ShouldUseNativeSspi(void);
+static BOOL InitializeSspiModule_Native(void);
+#endif
+
+#if defined(WITH_NATIVE_SSPI)
+BOOL ShouldUseNativeSspi(void)
+{
+ BOOL status = FALSE;
+#ifdef _WIN32
+ LPCSTR sspi = "WINPR_NATIVE_SSPI";
+ DWORD nSize;
+ char* env = NULL;
+ nSize = GetEnvironmentVariableA(sspi, NULL, 0);
+
+ if (!nSize)
+ return TRUE;
+
+ env = (LPSTR)malloc(nSize);
+
+ if (!env)
+ return TRUE;
+
+ if (GetEnvironmentVariableA(sspi, env, nSize) != nSize - 1)
+ {
+ free(env);
+ return TRUE;
+ }
+
+ if (strcmp(env, "0") == 0)
+ status = FALSE;
+ else
+ status = TRUE;
+
+ free(env);
+#endif
+ return status;
+}
+#endif
+
+#if defined(WITH_NATIVE_SSPI)
+BOOL InitializeSspiModule_Native(void)
+{
+ SecurityFunctionTableW* pSspiW = NULL;
+ SecurityFunctionTableA* pSspiA = NULL;
+ INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW;
+ INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA;
+ g_SspiModule = LoadLibraryA("secur32.dll");
+
+ if (!g_SspiModule)
+ g_SspiModule = LoadLibraryA("sspicli.dll");
+
+ if (!g_SspiModule)
+ return FALSE;
+
+ pInitSecurityInterfaceW =
+ (INIT_SECURITY_INTERFACE_W)GetProcAddress(g_SspiModule, "InitSecurityInterfaceW");
+ pInitSecurityInterfaceA =
+ (INIT_SECURITY_INTERFACE_A)GetProcAddress(g_SspiModule, "InitSecurityInterfaceA");
+
+ if (pInitSecurityInterfaceW)
+ {
+ pSspiW = pInitSecurityInterfaceW();
+
+ if (pSspiW)
+ {
+ g_SspiW = &windows_SecurityFunctionTableW;
+ CopyMemory(g_SspiW, pSspiW,
+ FIELD_OFFSET(SecurityFunctionTableW, SetContextAttributesW));
+
+ g_SspiW->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
+
+ g_SspiW->SetContextAttributesW =
+ (SET_CONTEXT_ATTRIBUTES_FN_W)GetProcAddress(g_SspiModule, "SetContextAttributesW");
+
+ g_SspiW->SetCredentialsAttributesW = (SET_CREDENTIALS_ATTRIBUTES_FN_W)GetProcAddress(
+ g_SspiModule, "SetCredentialsAttributesW");
+ }
+ }
+
+ if (pInitSecurityInterfaceA)
+ {
+ pSspiA = pInitSecurityInterfaceA();
+
+ if (pSspiA)
+ {
+ g_SspiA = &windows_SecurityFunctionTableA;
+ CopyMemory(g_SspiA, pSspiA,
+ FIELD_OFFSET(SecurityFunctionTableA, SetContextAttributesA));
+
+ g_SspiA->dwVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_3;
+
+ g_SspiA->SetContextAttributesA =
+ (SET_CONTEXT_ATTRIBUTES_FN_W)GetProcAddress(g_SspiModule, "SetContextAttributesA");
+
+ g_SspiA->SetCredentialsAttributesA = (SET_CREDENTIALS_ATTRIBUTES_FN_W)GetProcAddress(
+ g_SspiModule, "SetCredentialsAttributesA");
+ }
+ }
+
+ return TRUE;
+}
+#endif
+
+static BOOL CALLBACK InitializeSspiModuleInt(PINIT_ONCE once, PVOID param, PVOID* context)
+{
+ BOOL status = FALSE;
+#if defined(WITH_NATIVE_SSPI)
+ DWORD flags = 0;
+
+ if (param)
+ flags = *(DWORD*)param;
+
+#endif
+ sspi_GlobalInit();
+ g_Log = WLog_Get("com.winpr.sspi");
+#if defined(WITH_NATIVE_SSPI)
+
+ if (flags && (flags & SSPI_INTERFACE_NATIVE))
+ {
+ status = InitializeSspiModule_Native();
+ }
+ else if (flags && (flags & SSPI_INTERFACE_WINPR))
+ {
+ g_SspiW = winpr_InitSecurityInterfaceW();
+ g_SspiA = winpr_InitSecurityInterfaceA();
+ status = TRUE;
+ }
+
+ if (!status && ShouldUseNativeSspi())
+ {
+ status = InitializeSspiModule_Native();
+ }
+
+#endif
+
+ if (!status)
+ {
+ g_SspiW = winpr_InitSecurityInterfaceW();
+ g_SspiA = winpr_InitSecurityInterfaceA();
+ }
+
+ return TRUE;
+}
+
+const char* GetSecurityStatusString(SECURITY_STATUS status)
+{
+ switch (status)
+ {
+ case SEC_E_OK:
+ return "SEC_E_OK";
+
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return "SEC_E_INSUFFICIENT_MEMORY";
+
+ case SEC_E_INVALID_HANDLE:
+ return "SEC_E_INVALID_HANDLE";
+
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ return "SEC_E_UNSUPPORTED_FUNCTION";
+
+ case SEC_E_TARGET_UNKNOWN:
+ return "SEC_E_TARGET_UNKNOWN";
+
+ case SEC_E_INTERNAL_ERROR:
+ return "SEC_E_INTERNAL_ERROR";
+
+ case SEC_E_SECPKG_NOT_FOUND:
+ return "SEC_E_SECPKG_NOT_FOUND";
+
+ case SEC_E_NOT_OWNER:
+ return "SEC_E_NOT_OWNER";
+
+ case SEC_E_CANNOT_INSTALL:
+ return "SEC_E_CANNOT_INSTALL";
+
+ case SEC_E_INVALID_TOKEN:
+ return "SEC_E_INVALID_TOKEN";
+
+ case SEC_E_CANNOT_PACK:
+ return "SEC_E_CANNOT_PACK";
+
+ case SEC_E_QOP_NOT_SUPPORTED:
+ return "SEC_E_QOP_NOT_SUPPORTED";
+
+ case SEC_E_NO_IMPERSONATION:
+ return "SEC_E_NO_IMPERSONATION";
+
+ case SEC_E_LOGON_DENIED:
+ return "SEC_E_LOGON_DENIED";
+
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ return "SEC_E_UNKNOWN_CREDENTIALS";
+
+ case SEC_E_NO_CREDENTIALS:
+ return "SEC_E_NO_CREDENTIALS";
+
+ case SEC_E_MESSAGE_ALTERED:
+ return "SEC_E_MESSAGE_ALTERED";
+
+ case SEC_E_OUT_OF_SEQUENCE:
+ return "SEC_E_OUT_OF_SEQUENCE";
+
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ return "SEC_E_NO_AUTHENTICATING_AUTHORITY";
+
+ case SEC_E_BAD_PKGID:
+ return "SEC_E_BAD_PKGID";
+
+ case SEC_E_CONTEXT_EXPIRED:
+ return "SEC_E_CONTEXT_EXPIRED";
+
+ case SEC_E_INCOMPLETE_MESSAGE:
+ return "SEC_E_INCOMPLETE_MESSAGE";
+
+ case SEC_E_INCOMPLETE_CREDENTIALS:
+ return "SEC_E_INCOMPLETE_CREDENTIALS";
+
+ case SEC_E_BUFFER_TOO_SMALL:
+ return "SEC_E_BUFFER_TOO_SMALL";
+
+ case SEC_E_WRONG_PRINCIPAL:
+ return "SEC_E_WRONG_PRINCIPAL";
+
+ case SEC_E_TIME_SKEW:
+ return "SEC_E_TIME_SKEW";
+
+ case SEC_E_UNTRUSTED_ROOT:
+ return "SEC_E_UNTRUSTED_ROOT";
+
+ case SEC_E_ILLEGAL_MESSAGE:
+ return "SEC_E_ILLEGAL_MESSAGE";
+
+ case SEC_E_CERT_UNKNOWN:
+ return "SEC_E_CERT_UNKNOWN";
+
+ case SEC_E_CERT_EXPIRED:
+ return "SEC_E_CERT_EXPIRED";
+
+ case SEC_E_ENCRYPT_FAILURE:
+ return "SEC_E_ENCRYPT_FAILURE";
+
+ case SEC_E_DECRYPT_FAILURE:
+ return "SEC_E_DECRYPT_FAILURE";
+
+ case SEC_E_ALGORITHM_MISMATCH:
+ return "SEC_E_ALGORITHM_MISMATCH";
+
+ case SEC_E_SECURITY_QOS_FAILED:
+ return "SEC_E_SECURITY_QOS_FAILED";
+
+ case SEC_E_UNFINISHED_CONTEXT_DELETED:
+ return "SEC_E_UNFINISHED_CONTEXT_DELETED";
+
+ case SEC_E_NO_TGT_REPLY:
+ return "SEC_E_NO_TGT_REPLY";
+
+ case SEC_E_NO_IP_ADDRESSES:
+ return "SEC_E_NO_IP_ADDRESSES";
+
+ case SEC_E_WRONG_CREDENTIAL_HANDLE:
+ return "SEC_E_WRONG_CREDENTIAL_HANDLE";
+
+ case SEC_E_CRYPTO_SYSTEM_INVALID:
+ return "SEC_E_CRYPTO_SYSTEM_INVALID";
+
+ case SEC_E_MAX_REFERRALS_EXCEEDED:
+ return "SEC_E_MAX_REFERRALS_EXCEEDED";
+
+ case SEC_E_MUST_BE_KDC:
+ return "SEC_E_MUST_BE_KDC";
+
+ case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
+ return "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
+
+ case SEC_E_TOO_MANY_PRINCIPALS:
+ return "SEC_E_TOO_MANY_PRINCIPALS";
+
+ case SEC_E_NO_PA_DATA:
+ return "SEC_E_NO_PA_DATA";
+
+ case SEC_E_PKINIT_NAME_MISMATCH:
+ return "SEC_E_PKINIT_NAME_MISMATCH";
+
+ case SEC_E_SMARTCARD_LOGON_REQUIRED:
+ return "SEC_E_SMARTCARD_LOGON_REQUIRED";
+
+ case SEC_E_SHUTDOWN_IN_PROGRESS:
+ return "SEC_E_SHUTDOWN_IN_PROGRESS";
+
+ case SEC_E_KDC_INVALID_REQUEST:
+ return "SEC_E_KDC_INVALID_REQUEST";
+
+ case SEC_E_KDC_UNABLE_TO_REFER:
+ return "SEC_E_KDC_UNABLE_TO_REFER";
+
+ case SEC_E_KDC_UNKNOWN_ETYPE:
+ return "SEC_E_KDC_UNKNOWN_ETYPE";
+
+ case SEC_E_UNSUPPORTED_PREAUTH:
+ return "SEC_E_UNSUPPORTED_PREAUTH";
+
+ case SEC_E_DELEGATION_REQUIRED:
+ return "SEC_E_DELEGATION_REQUIRED";
+
+ case SEC_E_BAD_BINDINGS:
+ return "SEC_E_BAD_BINDINGS";
+
+ case SEC_E_MULTIPLE_ACCOUNTS:
+ return "SEC_E_MULTIPLE_ACCOUNTS";
+
+ case SEC_E_NO_KERB_KEY:
+ return "SEC_E_NO_KERB_KEY";
+
+ case SEC_E_CERT_WRONG_USAGE:
+ return "SEC_E_CERT_WRONG_USAGE";
+
+ case SEC_E_DOWNGRADE_DETECTED:
+ return "SEC_E_DOWNGRADE_DETECTED";
+
+ case SEC_E_SMARTCARD_CERT_REVOKED:
+ return "SEC_E_SMARTCARD_CERT_REVOKED";
+
+ case SEC_E_ISSUING_CA_UNTRUSTED:
+ return "SEC_E_ISSUING_CA_UNTRUSTED";
+
+ case SEC_E_REVOCATION_OFFLINE_C:
+ return "SEC_E_REVOCATION_OFFLINE_C";
+
+ case SEC_E_PKINIT_CLIENT_FAILURE:
+ return "SEC_E_PKINIT_CLIENT_FAILURE";
+
+ case SEC_E_SMARTCARD_CERT_EXPIRED:
+ return "SEC_E_SMARTCARD_CERT_EXPIRED";
+
+ case SEC_E_NO_S4U_PROT_SUPPORT:
+ return "SEC_E_NO_S4U_PROT_SUPPORT";
+
+ case SEC_E_CROSSREALM_DELEGATION_FAILURE:
+ return "SEC_E_CROSSREALM_DELEGATION_FAILURE";
+
+ case SEC_E_REVOCATION_OFFLINE_KDC:
+ return "SEC_E_REVOCATION_OFFLINE_KDC";
+
+ case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
+ return "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
+
+ case SEC_E_KDC_CERT_EXPIRED:
+ return "SEC_E_KDC_CERT_EXPIRED";
+
+ case SEC_E_KDC_CERT_REVOKED:
+ return "SEC_E_KDC_CERT_REVOKED";
+
+ case SEC_E_INVALID_PARAMETER:
+ return "SEC_E_INVALID_PARAMETER";
+
+ case SEC_E_DELEGATION_POLICY:
+ return "SEC_E_DELEGATION_POLICY";
+
+ case SEC_E_POLICY_NLTM_ONLY:
+ return "SEC_E_POLICY_NLTM_ONLY";
+
+ case SEC_E_NO_CONTEXT:
+ return "SEC_E_NO_CONTEXT";
+
+ case SEC_E_PKU2U_CERT_FAILURE:
+ return "SEC_E_PKU2U_CERT_FAILURE";
+
+ case SEC_E_MUTUAL_AUTH_FAILED:
+ return "SEC_E_MUTUAL_AUTH_FAILED";
+
+ case SEC_I_CONTINUE_NEEDED:
+ return "SEC_I_CONTINUE_NEEDED";
+
+ case SEC_I_COMPLETE_NEEDED:
+ return "SEC_I_COMPLETE_NEEDED";
+
+ case SEC_I_COMPLETE_AND_CONTINUE:
+ return "SEC_I_COMPLETE_AND_CONTINUE";
+
+ case SEC_I_LOCAL_LOGON:
+ return "SEC_I_LOCAL_LOGON";
+
+ case SEC_I_CONTEXT_EXPIRED:
+ return "SEC_I_CONTEXT_EXPIRED";
+
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ return "SEC_I_INCOMPLETE_CREDENTIALS";
+
+ case SEC_I_RENEGOTIATE:
+ return "SEC_I_RENEGOTIATE";
+
+ case SEC_I_NO_LSA_CONTEXT:
+ return "SEC_I_NO_LSA_CONTEXT";
+
+ case SEC_I_SIGNATURE_NEEDED:
+ return "SEC_I_SIGNATURE_NEEDED";
+
+ case SEC_I_NO_RENEGOTIATION:
+ return "SEC_I_NO_RENEGOTIATION";
+ }
+
+ return NtStatus2Tag((DWORD)status);
+}
+
+BOOL IsSecurityStatusError(SECURITY_STATUS status)
+{
+ BOOL error = TRUE;
+
+ switch (status)
+ {
+ case SEC_E_OK:
+ case SEC_I_CONTINUE_NEEDED:
+ case SEC_I_COMPLETE_NEEDED:
+ case SEC_I_COMPLETE_AND_CONTINUE:
+ case SEC_I_LOCAL_LOGON:
+ case SEC_I_CONTEXT_EXPIRED:
+ case SEC_I_INCOMPLETE_CREDENTIALS:
+ case SEC_I_RENEGOTIATE:
+ case SEC_I_NO_LSA_CONTEXT:
+ case SEC_I_SIGNATURE_NEEDED:
+ case SEC_I_NO_RENEGOTIATION:
+ error = FALSE;
+ break;
+ }
+
+ return error;
+}
+
+SecurityFunctionTableW* SEC_ENTRY InitSecurityInterfaceExW(DWORD flags)
+{
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExW");
+ return g_SspiW;
+}
+
+SecurityFunctionTableA* SEC_ENTRY InitSecurityInterfaceExA(DWORD flags)
+{
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, &flags, NULL);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceExA");
+ return g_SspiA;
+}
+
+/**
+ * Standard SSPI API
+ */
+
+/* Package Management */
+
+SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesW(ULONG* pcPackages,
+ PSecPkgInfoW* ppPackageInfo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->EnumerateSecurityPackagesW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->EnumerateSecurityPackagesW(pcPackages, ppPackageInfo);
+ WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_EnumerateSecurityPackagesA(ULONG* pcPackages,
+ PSecPkgInfoA* ppPackageInfo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->EnumerateSecurityPackagesA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->EnumerateSecurityPackagesA(pcPackages, ppPackageInfo);
+ WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SecurityFunctionTableW* SEC_ENTRY sspi_InitSecurityInterfaceW(void)
+{
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceW");
+ return g_SspiW;
+}
+
+SecurityFunctionTableA* SEC_ENTRY sspi_InitSecurityInterfaceA(void)
+{
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitSecurityInterfaceA");
+ return g_SspiA;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
+ PSecPkgInfoW* ppPackageInfo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->QuerySecurityPackageInfoW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo);
+ WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
+ PSecPkgInfoA* ppPackageInfo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->QuerySecurityPackageInfoA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo);
+ WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+/* Credential Management */
+
+SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleW(
+ SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
+ void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
+ PTimeStamp ptsExpiry)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->AcquireCredentialsHandleW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
+ pAuthData, pGetKeyFn, pvGetKeyArgument,
+ phCredential, ptsExpiry);
+ WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_AcquireCredentialsHandleA(
+ SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse, void* pvLogonID,
+ void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential,
+ PTimeStamp ptsExpiry)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->AcquireCredentialsHandleA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
+ pAuthData, pGetKeyFn, pvGetKeyArgument,
+ phCredential, ptsExpiry);
+ WLog_Print(g_Log, WLOG_DEBUG, "AcquireCredentialsHandleA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
+ PSecBuffer pPackedContext, HANDLE* pToken)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->ExportSecurityContext))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
+ WLog_Print(g_Log, WLOG_DEBUG, "ExportSecurityContext: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_FreeCredentialsHandle(PCredHandle phCredential)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->FreeCredentialsHandle))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->FreeCredentialsHandle(phCredential);
+ WLog_Print(g_Log, WLOG_DEBUG, "FreeCredentialsHandle: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextW(SEC_WCHAR* pszPackage,
+ PSecBuffer pPackedContext, HANDLE pToken,
+ PCtxtHandle phContext)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->ImportSecurityContextW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
+ WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_ImportSecurityContextA(SEC_CHAR* pszPackage,
+ PSecBuffer pPackedContext, HANDLE pToken,
+ PCtxtHandle phContext)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->ImportSecurityContextA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
+ WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesW(PCredHandle phCredential,
+ ULONG ulAttribute, void* pBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->QueryCredentialsAttributesW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QueryCredentialsAttributesA(PCredHandle phCredential,
+ ULONG ulAttribute, void* pBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->QueryCredentialsAttributesA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+/* Context Management */
+
+SECURITY_STATUS SEC_ENTRY sspi_AcceptSecurityContext(PCredHandle phCredential,
+ PCtxtHandle phContext, PSecBufferDesc pInput,
+ ULONG fContextReq, ULONG TargetDataRep,
+ PCtxtHandle phNewContext,
+ PSecBufferDesc pOutput, PULONG pfContextAttr,
+ PTimeStamp ptsTimeStamp)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->AcceptSecurityContext))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status =
+ g_SspiW->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
+ phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
+ WLog_Print(g_Log, WLOG_DEBUG, "AcceptSecurityContext: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->ApplyControlToken))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->ApplyControlToken(phContext, pInput);
+ WLog_Print(g_Log, WLOG_DEBUG, "ApplyControlToken: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->CompleteAuthToken))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->CompleteAuthToken(phContext, pToken);
+ WLog_Print(g_Log, WLOG_DEBUG, "CompleteAuthToken: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_DeleteSecurityContext(PCtxtHandle phContext)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->DeleteSecurityContext))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->DeleteSecurityContext(phContext);
+ WLog_Print(g_Log, WLOG_DEBUG, "DeleteSecurityContext: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_FreeContextBuffer(void* pvContextBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->FreeContextBuffer))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->FreeContextBuffer(pvContextBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "FreeContextBuffer: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_ImpersonateSecurityContext(PCtxtHandle phContext)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->ImpersonateSecurityContext))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->ImpersonateSecurityContext(phContext);
+ WLog_Print(g_Log, WLOG_DEBUG, "ImpersonateSecurityContext: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextW(
+ PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
+ ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
+ PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->InitializeSecurityContextW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->InitializeSecurityContextW(
+ phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
+ Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_InitializeSecurityContextA(
+ PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR* pszTargetName, ULONG fContextReq,
+ ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
+ PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->InitializeSecurityContextA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->InitializeSecurityContextA(
+ phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput,
+ Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+ WLog_Print(g_Log, WLOG_DEBUG, "InitializeSecurityContextA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+ void* pBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->QueryContextAttributesW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+ void* pBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->QueryContextAttributesA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->QuerySecurityContextToken))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->QuerySecurityContextToken(phContext, phToken);
+ WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityContextToken: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+ void* pBuffer, ULONG cbBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->SetContextAttributesW))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesW: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+ void* pBuffer, ULONG cbBuffer)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiA && g_SspiA->SetContextAttributesA))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiA->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
+ WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesA: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_RevertSecurityContext(PCtxtHandle phContext)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->RevertSecurityContext))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->RevertSecurityContext(phContext);
+ WLog_Print(g_Log, WLOG_DEBUG, "RevertSecurityContext: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+/* Message Support */
+
+SECURITY_STATUS SEC_ENTRY sspi_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
+ ULONG MessageSeqNo, PULONG pfQOP)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->DecryptMessage))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
+ WLog_Print(g_Log, WLOG_DEBUG, "DecryptMessage: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
+ PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->EncryptMessage))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
+ WLog_Print(g_Log, WLOG_DEBUG, "EncryptMessage: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
+ PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->MakeSignature))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
+ WLog_Print(g_Log, WLOG_DEBUG, "MakeSignature: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+SECURITY_STATUS SEC_ENTRY sspi_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage,
+ ULONG MessageSeqNo, PULONG pfQOP)
+{
+ SECURITY_STATUS status = 0;
+ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL);
+
+ if (!(g_SspiW && g_SspiW->VerifySignature))
+ {
+ WLog_Print(g_Log, WLOG_WARN, "Security module does not provide an implementation");
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+ }
+
+ status = g_SspiW->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
+ WLog_Print(g_Log, WLOG_DEBUG, "VerifySignature: %s (0x%08" PRIX32 ")",
+ GetSecurityStatusString(status), status);
+ return status;
+}
+
+WINPR_PRAGMA_DIAG_POP
+
+void sspi_FreeAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity)
+{
+ if (!identity)
+ return;
+ free(identity->User);
+ identity->UserLength = (UINT32)0;
+ identity->User = NULL;
+
+ free(identity->Domain);
+ identity->DomainLength = (UINT32)0;
+ identity->Domain = NULL;
+
+ if (identity->PasswordLength > 0)
+ memset(identity->Password, 0, identity->PasswordLength);
+ free(identity->Password);
+ identity->Password = NULL;
+ identity->PasswordLength = (UINT32)0;
+}