FreeRDP/winpr/libwinpr/sspi/sspi_winpr.c

2227 lines
62 KiB
C
Raw Normal View History

/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Security Support Provider Interface (SSPI)
*
* Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
2017-05-11 19:51:45 +03:00
* Copyright 2017 Dorian Ducournau <dorian.ducournau@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.
*/
2022-02-16 12:08:00 +03:00
#include <winpr/config.h>
2022-03-25 16:10:35 +03:00
#include <winpr/assert.h>
#include <winpr/windows.h>
#include <winpr/crt.h>
#include <winpr/sspi.h>
OpenSSL thread safety freerdp/winpr had the following issues: * The non reentrant SSL_library_init() was called concurrently (crash) * Missing code/api to set the eventually required OpenSSL static and dynamic locking callbacks * Missing code/api to free the application-global or thread-local OpenSSL data and tables This commit creates two new winpr functions: BOOL winpr_InitializeSSL(DWORD flags): Use the flag WINPR_SSL_INIT_ALREADY_INITIALIZED if you want to tell winpr that your application has already initialized OpenSSL. If required use the flag WINPR_SSL_INIT_ENABLE_LOCKING to tell winpr that it should set the OpenSSL static and dynamic locking callbacks. Otherwise just call it with the flag WINPR_SSL_INIT_DEFAULT. The recommended way is that your application calls this function once before any threads are created. However, in order to support lazy OpenSSL library initialization winpr_InitializeSSL() can also safely be called multiple times and concurrently because it uses the new InitOnceExecuteOnce() function to guarantee that the initialization is only performed successfully once during the life time of the calling process. BOOL winpr_CleanupSSL(DWORD flags): If you create a thread that uses SSL you should call this function before the thread returns using the flag WINPR_SSL_CLEANUP_THREAD in order to clean up the thread-local OpenSSL data and tables. Call the function with the flag WINPR_SSL_CLEANUP_GLOBAL before terminating your application. Note: This commit only replaced the current occurences of the SSL_load_error_strings(); SSL_library_init(); pairs in the freerdp source with winpr_InitializeSSL(). None of the server or client applications has been changed according to the recommended usage described above (TBDL).
2014-07-28 23:55:57 +04:00
#include <winpr/ssl.h>
#include <winpr/print.h>
#include "sspi.h"
#include "sspi_winpr.h"
2015-07-07 18:17:29 +03:00
#include "../log.h"
#define TAG WINPR_TAG("sspi")
/* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */
#include "NTLM/ntlm.h"
2021-06-17 12:25:58 +03:00
#include "NTLM/ntlm_export.h"
#include "CredSSP/credssp.h"
#include "Kerberos/kerberos.h"
#include "Negotiate/negotiate.h"
#include "Schannel/schannel.h"
2019-11-06 17:24:51 +03:00
static const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, &KERBEROS_SecPkgInfoA,
&NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA,
&SCHANNEL_SecPkgInfoA };
2019-11-06 17:24:51 +03:00
static const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, &KERBEROS_SecPkgInfoW,
&NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW,
&SCHANNEL_SecPkgInfoW };
static SecurityFunctionTableA winpr_SecurityFunctionTableA;
static SecurityFunctionTableW winpr_SecurityFunctionTableW;
typedef struct
{
const SEC_CHAR* Name;
const SecurityFunctionTableA* SecurityFunctionTable;
} SecurityFunctionTableA_NAME;
typedef struct
{
const SEC_WCHAR* Name;
const SecurityFunctionTableW* SecurityFunctionTable;
} SecurityFunctionTableW_NAME;
2019-11-06 17:24:51 +03:00
static const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = {
{ "NTLM", &NTLM_SecurityFunctionTableA },
{ "Kerberos", &KERBEROS_SecurityFunctionTableA },
{ "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA },
{ "Schannel", &SCHANNEL_SecurityFunctionTableA }
};
static WCHAR BUFFER_NAME_LIST_W[5][32] = { 0 };
2019-11-06 17:24:51 +03:00
static const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = {
{ BUFFER_NAME_LIST_W[0], &NTLM_SecurityFunctionTableW },
{ BUFFER_NAME_LIST_W[1], &KERBEROS_SecurityFunctionTableW },
{ BUFFER_NAME_LIST_W[2], &NEGOTIATE_SecurityFunctionTableW },
{ BUFFER_NAME_LIST_W[3], &CREDSSP_SecurityFunctionTableW },
{ BUFFER_NAME_LIST_W[4], &SCHANNEL_SecurityFunctionTableW }
};
2019-11-06 17:24:51 +03:00
#define SecHandle_LOWER_MAX 0xFFFFFFFF
#define SecHandle_UPPER_MAX 0xFFFFFFFE
typedef struct
{
void* contextBuffer;
UINT32 allocatorIndex;
} CONTEXT_BUFFER_ALLOC_ENTRY;
typedef struct
{
UINT32 cEntries;
UINT32 cMaxEntries;
CONTEXT_BUFFER_ALLOC_ENTRY* entries;
} CONTEXT_BUFFER_ALLOC_TABLE;
static CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable = { 0 };
static int sspi_ContextBufferAllocTableNew(void)
{
size_t size = 0;
ContextBufferAllocTable.entries = NULL;
ContextBufferAllocTable.cEntries = 0;
ContextBufferAllocTable.cMaxEntries = 4;
size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
2019-11-06 17:24:51 +03:00
ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)calloc(1, size);
2014-06-07 01:20:34 +04:00
if (!ContextBufferAllocTable.entries)
return -1;
return 1;
}
static int sspi_ContextBufferAllocTableGrow(void)
{
size_t size = 0;
CONTEXT_BUFFER_ALLOC_ENTRY* entries = NULL;
ContextBufferAllocTable.cEntries = 0;
ContextBufferAllocTable.cMaxEntries *= 2;
size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
2014-06-07 01:20:34 +04:00
if (!size)
2014-06-07 01:20:34 +04:00
return -1;
2019-11-06 17:24:51 +03:00
entries = (CONTEXT_BUFFER_ALLOC_ENTRY*)realloc(ContextBufferAllocTable.entries, size);
2014-06-07 01:20:34 +04:00
if (!entries)
{
free(ContextBufferAllocTable.entries);
return -1;
}
ContextBufferAllocTable.entries = entries;
2019-11-06 17:24:51 +03:00
ZeroMemory((void*)&ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
2017-05-11 19:51:45 +03:00
size / 2);
2014-06-07 01:20:34 +04:00
return 1;
}
static void sspi_ContextBufferAllocTableFree(void)
{
2017-12-12 12:47:17 +03:00
if (ContextBufferAllocTable.cEntries != 0)
2019-11-06 17:24:51 +03:00
WLog_ERR(TAG, "ContextBufferAllocTable.entries == %" PRIu32,
ContextBufferAllocTable.cEntries);
2017-12-12 12:47:17 +03:00
ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0;
free(ContextBufferAllocTable.entries);
ContextBufferAllocTable.entries = NULL;
}
static void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
{
void* contextBuffer = NULL;
for (UINT32 index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
{
2014-06-07 01:20:34 +04:00
if (!ContextBufferAllocTable.entries[index].contextBuffer)
{
2014-06-07 01:20:34 +04:00
contextBuffer = calloc(1, size);
2015-07-07 18:17:29 +03:00
2014-06-07 01:20:34 +04:00
if (!contextBuffer)
return NULL;
ContextBufferAllocTable.cEntries++;
ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
return ContextBufferAllocTable.entries[index].contextBuffer;
}
}
/* no available entry was found, the table needs to be grown */
2014-06-07 01:20:34 +04:00
if (sspi_ContextBufferAllocTableGrow() < 0)
return NULL;
/* the next call to sspi_ContextBufferAlloc() should now succeed */
return sspi_ContextBufferAlloc(allocatorIndex, size);
}
SSPI_CREDENTIALS* sspi_CredentialsNew(void)
{
SSPI_CREDENTIALS* credentials = NULL;
2019-11-06 17:24:51 +03:00
credentials = (SSPI_CREDENTIALS*)calloc(1, sizeof(SSPI_CREDENTIALS));
return credentials;
}
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
{
2017-05-11 19:51:45 +03:00
size_t userLength = 0;
size_t domainLength = 0;
size_t passwordLength = 0;
if (!credentials)
return;
if (credentials->ntlmSettings.samFile)
free(credentials->ntlmSettings.samFile);
userLength = credentials->identity.UserLength;
domainLength = credentials->identity.DomainLength;
passwordLength = credentials->identity.PasswordLength;
if (passwordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET) /* [pth] */
passwordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
if (credentials->identity.Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
{
userLength *= 2;
domainLength *= 2;
passwordLength *= 2;
}
2020-05-15 12:16:50 +03:00
if (credentials->identity.User)
memset(credentials->identity.User, 0, userLength);
if (credentials->identity.Domain)
memset(credentials->identity.Domain, 0, domainLength);
if (credentials->identity.Password)
memset(credentials->identity.Password, 0, passwordLength);
2014-06-10 16:40:04 +04:00
free(credentials->identity.User);
free(credentials->identity.Domain);
free(credentials->identity.Password);
free(credentials);
}
void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
{
if (!SecBuffer)
return NULL;
2014-06-07 01:20:34 +04:00
SecBuffer->pvBuffer = calloc(1, size);
2017-05-11 19:51:45 +03:00
if (!SecBuffer->pvBuffer)
return NULL;
SecBuffer->cbBuffer = size;
return SecBuffer->pvBuffer;
}
void sspi_SecBufferFree(PSecBuffer SecBuffer)
{
2015-05-11 10:07:39 +03:00
if (!SecBuffer)
return;
if (SecBuffer->pvBuffer)
memset(SecBuffer->pvBuffer, 0, SecBuffer->cbBuffer);
free(SecBuffer->pvBuffer);
SecBuffer->pvBuffer = NULL;
SecBuffer->cbBuffer = 0;
}
SecHandle* sspi_SecureHandleAlloc(void)
{
2019-11-06 17:24:51 +03:00
SecHandle* handle = (SecHandle*)calloc(1, sizeof(SecHandle));
2014-06-07 01:20:34 +04:00
if (!handle)
return NULL;
2014-06-08 02:28:02 +04:00
SecInvalidateHandle(handle);
return handle;
}
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
{
void* pointer = NULL;
2014-06-08 02:28:02 +04:00
if (!handle || !SecIsValidHandle(handle) || !handle->dwLower)
return NULL;
2019-11-06 17:24:51 +03:00
pointer = (void*)~((size_t)handle->dwLower);
return pointer;
}
2017-07-18 14:23:22 +03:00
void sspi_SecureHandleInvalidate(SecHandle* handle)
{
if (!handle)
return;
handle->dwLower = 0;
handle->dwUpper = 0;
}
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
{
if (!handle)
return;
2019-11-06 17:24:51 +03:00
handle->dwLower = (ULONG_PTR)(~((size_t)pointer));
}
void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
{
void* pointer = NULL;
2014-06-08 02:28:02 +04:00
if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper)
return NULL;
2019-11-06 17:24:51 +03:00
pointer = (void*)~((size_t)handle->dwUpper);
return pointer;
}
void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
{
if (!handle)
return;
2019-11-06 17:24:51 +03:00
handle->dwUpper = (ULONG_PTR)(~((size_t)pointer));
}
void sspi_SecureHandleFree(SecHandle* handle)
{
free(handle);
}
2022-03-25 16:10:35 +03:00
int sspi_SetAuthIdentityW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user, const WCHAR* domain,
const WCHAR* password)
{
return sspi_SetAuthIdentityWithLengthW(identity, user, user ? _wcslen(user) : 0, domain,
domain ? _wcslen(domain) : 0, password,
password ? _wcslen(password) : 0);
}
static BOOL copy(WCHAR** dst, ULONG* dstLen, const WCHAR* what, size_t len)
2022-03-25 16:10:35 +03:00
{
WINPR_ASSERT(dst);
WINPR_ASSERT(dstLen);
*dst = NULL;
*dstLen = 0;
2022-03-25 16:10:35 +03:00
*dst = calloc(sizeof(WCHAR), len + 1);
if (!*dst)
return FALSE;
memcpy(*dst, what, len * sizeof(WCHAR));
*dstLen = len;
return TRUE;
}
int sspi_SetAuthIdentityWithLengthW(SEC_WINNT_AUTH_IDENTITY* identity, const WCHAR* user,
size_t userLen, const WCHAR* domain, size_t domainLen,
const WCHAR* password, size_t passwordLen)
{
WINPR_ASSERT(identity);
sspi_FreeAuthIdentity(identity);
identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
if (!copy(&identity->User, &identity->UserLength, user, userLen))
return -1;
if (!copy(&identity->Domain, &identity->DomainLength, domain, domainLen))
return -1;
if (!copy(&identity->Password, &identity->PasswordLength, password, passwordLen))
return -1;
2022-03-25 16:10:35 +03:00
return 1;
}
static void zfree(WCHAR* str, size_t len)
{
if (str)
memset(str, 0, len * sizeof(WCHAR));
free(str);
}
2022-03-25 16:10:35 +03:00
int sspi_SetAuthIdentityA(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain,
const char* password)
{
int rc = 0;
size_t unicodeUserLenW = 0;
size_t unicodeDomainLenW = 0;
size_t unicodePasswordLenW = 0;
LPWSTR unicodeUser = ConvertUtf8ToWCharAlloc(user, &unicodeUserLenW);
LPWSTR unicodeDomain = ConvertUtf8ToWCharAlloc(domain, &unicodeDomainLenW);
LPWSTR unicodePassword = ConvertUtf8ToWCharAlloc(password, &unicodePasswordLenW);
rc = sspi_SetAuthIdentityWithLengthW(identity, unicodeUser, unicodeUserLenW, unicodeDomain,
unicodeDomainLenW, unicodePassword, unicodePasswordLenW);
zfree(unicodeUser, unicodeUserLenW);
zfree(unicodeDomain, unicodeDomainLenW);
zfree(unicodePassword, unicodePasswordLenW);
return rc;
}
UINT32 sspi_GetAuthIdentityVersion(const void* identity)
{
UINT32 version = 0;
if (!identity)
return 0;
version = *((const UINT32*)identity);
if ((version == SEC_WINNT_AUTH_IDENTITY_VERSION) ||
(version == SEC_WINNT_AUTH_IDENTITY_VERSION_2))
{
return version;
}
return 0; // SEC_WINNT_AUTH_IDENTITY (no version)
}
UINT32 sspi_GetAuthIdentityFlags(const void* identity)
{
UINT32 version = 0;
UINT32 flags = 0;
if (!identity)
return 0;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
flags = ((const SEC_WINNT_AUTH_IDENTITY_EX*)identity)->Flags;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
flags = ((const SEC_WINNT_AUTH_IDENTITY_EX2*)identity)->Flags;
}
else // SEC_WINNT_AUTH_IDENTITY
{
flags = ((const SEC_WINNT_AUTH_IDENTITY*)identity)->Flags;
}
return flags;
}
BOOL sspi_GetAuthIdentityUserDomainW(const void* identity, const WCHAR** pUser, UINT32* pUserLength,
const WCHAR** pDomain, UINT32* pDomainLength)
{
UINT32 version = 0;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
*pUser = (const WCHAR*)id->User;
*pUserLength = id->UserLength;
*pDomain = (const WCHAR*)id->Domain;
*pDomainLength = id->DomainLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
UINT32 UserOffset = id->UserOffset;
UINT32 DomainOffset = id->DomainOffset;
*pUser = (const WCHAR*)&((const uint8_t*)identity)[UserOffset];
*pUserLength = id->UserLength / 2;
*pDomain = (const WCHAR*)&((const uint8_t*)identity)[DomainOffset];
*pDomainLength = id->DomainLength / 2;
}
else // SEC_WINNT_AUTH_IDENTITY
{
const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
*pUser = (const WCHAR*)id->User;
*pUserLength = id->UserLength;
*pDomain = (const WCHAR*)id->Domain;
*pDomainLength = id->DomainLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityUserDomainA(const void* identity, const char** pUser, UINT32* pUserLength,
const char** pDomain, UINT32* pDomainLength)
{
UINT32 version = 0;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
*pUser = (const char*)id->User;
*pUserLength = id->UserLength;
*pDomain = (const char*)id->Domain;
*pDomainLength = id->DomainLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
const SEC_WINNT_AUTH_IDENTITY_EX2* id = (const SEC_WINNT_AUTH_IDENTITY_EX2*)identity;
UINT32 UserOffset = id->UserOffset;
UINT32 DomainOffset = id->DomainOffset;
*pUser = (const char*)&((const uint8_t*)identity)[UserOffset];
*pUserLength = id->UserLength;
*pDomain = (const char*)&((const uint8_t*)identity)[DomainOffset];
*pDomainLength = id->DomainLength;
}
else // SEC_WINNT_AUTH_IDENTITY
{
const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
*pUser = (const char*)id->User;
*pUserLength = id->UserLength;
*pDomain = (const char*)id->Domain;
*pDomainLength = id->DomainLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityPasswordW(const void* identity, const WCHAR** pPassword,
UINT32* pPasswordLength)
{
UINT32 version = 0;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXW* id = (const SEC_WINNT_AUTH_IDENTITY_EXW*)identity;
*pPassword = (const WCHAR*)id->Password;
*pPasswordLength = id->PasswordLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
return FALSE; // TODO: packed credentials
}
else // SEC_WINNT_AUTH_IDENTITY
{
const SEC_WINNT_AUTH_IDENTITY_W* id = (const SEC_WINNT_AUTH_IDENTITY_W*)identity;
*pPassword = (const WCHAR*)id->Password;
*pPasswordLength = id->PasswordLength;
}
return TRUE;
}
BOOL sspi_GetAuthIdentityPasswordA(const void* identity, const char** pPassword,
UINT32* pPasswordLength)
{
UINT32 version = 0;
if (!identity)
return FALSE;
version = sspi_GetAuthIdentityVersion(identity);
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXA* id = (const SEC_WINNT_AUTH_IDENTITY_EXA*)identity;
*pPassword = (const char*)id->Password;
*pPasswordLength = id->PasswordLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
return FALSE; // TODO: packed credentials
}
else // SEC_WINNT_AUTH_IDENTITY
{
const SEC_WINNT_AUTH_IDENTITY_A* id = (const SEC_WINNT_AUTH_IDENTITY_A*)identity;
*pPassword = (const char*)id->Password;
*pPasswordLength = id->PasswordLength;
}
return TRUE;
}
BOOL sspi_CopyAuthIdentityFieldsA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pUser,
char** pDomain, char** pPassword)
{
BOOL success = FALSE;
2022-11-28 15:32:40 +03:00
const char* UserA = NULL;
const char* DomainA = NULL;
const char* PasswordA = NULL;
const WCHAR* UserW = NULL;
const WCHAR* DomainW = NULL;
const WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
if (!identity || !pUser || !pDomain || !pPassword)
return FALSE;
*pUser = *pDomain = *pPassword = NULL;
UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
goto cleanup;
if (UserA && UserLength)
{
*pUser = _strdup(UserA);
if (!(*pUser))
goto cleanup;
}
if (DomainA && DomainLength)
{
*pDomain = _strdup(DomainA);
if (!(*pDomain))
goto cleanup;
}
if (PasswordA && PasswordLength)
{
*pPassword = _strdup(PasswordA);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
else
{
if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
goto cleanup;
if (UserW && (UserLength > 0))
{
*pUser = ConvertWCharNToUtf8Alloc(UserW, UserLength, NULL);
if (!(*pUser))
goto cleanup;
}
if (DomainW && (DomainLength > 0))
{
*pDomain = ConvertWCharNToUtf8Alloc(DomainW, DomainLength, NULL);
if (!(*pDomain))
goto cleanup;
}
if (PasswordW && (PasswordLength > 0))
{
*pPassword = ConvertWCharNToUtf8Alloc(PasswordW, PasswordLength, NULL);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
cleanup:
return success;
}
BOOL sspi_CopyAuthIdentityFieldsW(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, WCHAR** pUser,
WCHAR** pDomain, WCHAR** pPassword)
{
BOOL success = FALSE;
const char* UserA = NULL;
const char* DomainA = NULL;
const char* PasswordA = NULL;
2022-11-28 15:32:40 +03:00
const WCHAR* UserW = NULL;
const WCHAR* DomainW = NULL;
const WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
if (!identity || !pUser || !pDomain || !pPassword)
return FALSE;
*pUser = *pDomain = *pPassword = NULL;
UINT32 identityFlags = sspi_GetAuthIdentityFlags(identity);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (!sspi_GetAuthIdentityUserDomainA(identity, &UserA, &UserLength, &DomainA,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordA(identity, &PasswordA, &PasswordLength))
goto cleanup;
if (UserA && (UserLength > 0))
{
WCHAR* ptr = ConvertUtf8NToWCharAlloc(UserA, UserLength, NULL);
*pUser = ptr;
if (!ptr)
goto cleanup;
}
if (DomainA && (DomainLength > 0))
{
WCHAR* ptr = ConvertUtf8NToWCharAlloc(DomainA, DomainLength, NULL);
*pDomain = ptr;
if (!ptr)
goto cleanup;
}
if (PasswordA && (PasswordLength > 0))
{
WCHAR* ptr = ConvertUtf8NToWCharAlloc(PasswordA, PasswordLength, NULL);
*pPassword = ptr;
if (!ptr)
goto cleanup;
}
success = TRUE;
}
else
{
if (!sspi_GetAuthIdentityUserDomainW(identity, &UserW, &UserLength, &DomainW,
&DomainLength))
goto cleanup;
if (!sspi_GetAuthIdentityPasswordW(identity, &PasswordW, &PasswordLength))
goto cleanup;
if (UserW && UserLength)
{
*pUser = _wcsdup(UserW);
if (!(*pUser))
goto cleanup;
}
if (DomainW && DomainLength)
{
*pDomain = _wcsdup(DomainW);
if (!(*pDomain))
goto cleanup;
}
if (PasswordW && PasswordLength)
{
*pPassword = _wcsdup(PasswordW);
if (!(*pPassword))
goto cleanup;
}
success = TRUE;
}
cleanup:
return success;
}
BOOL sspi_CopyAuthPackageListA(const SEC_WINNT_AUTH_IDENTITY_INFO* identity, char** pPackageList)
{
UINT32 version = 0;
UINT32 identityFlags = 0;
char* PackageList = NULL;
const char* PackageListA = NULL;
const WCHAR* PackageListW = NULL;
UINT32 PackageListLength = 0;
UINT32 PackageListOffset = 0;
const void* pAuthData = (const void*)identity;
if (!pAuthData)
return FALSE;
version = sspi_GetAuthIdentityVersion(pAuthData);
identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXA* ad = (const SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData;
PackageListA = (const char*)ad->PackageList;
PackageListLength = ad->PackageListLength;
}
if (PackageListA && PackageListLength)
{
PackageList = _strdup(PackageListA);
}
}
else
{
if (version == SEC_WINNT_AUTH_IDENTITY_VERSION)
{
const SEC_WINNT_AUTH_IDENTITY_EXW* ad = (const SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData;
PackageListW = (const WCHAR*)ad->PackageList;
PackageListLength = ad->PackageListLength;
}
else if (version == SEC_WINNT_AUTH_IDENTITY_VERSION_2)
{
const SEC_WINNT_AUTH_IDENTITY_EX2* ad = (const SEC_WINNT_AUTH_IDENTITY_EX2*)pAuthData;
PackageListOffset = ad->PackageListOffset;
PackageListW = (const WCHAR*)&((const uint8_t*)pAuthData)[PackageListOffset];
PackageListLength = ad->PackageListLength / 2;
}
if (PackageListW && (PackageListLength > 0))
PackageList = ConvertWCharNToUtf8Alloc(PackageListW, PackageListLength, NULL);
}
if (PackageList)
{
*pPackageList = PackageList;
return TRUE;
}
return FALSE;
}
int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity,
const SEC_WINNT_AUTH_IDENTITY_INFO* srcIdentity)
{
int status = 0;
UINT32 identityFlags = 0;
2022-11-28 15:32:40 +03:00
const char* UserA = NULL;
const char* DomainA = NULL;
const char* PasswordA = NULL;
const WCHAR* UserW = NULL;
const WCHAR* DomainW = NULL;
const WCHAR* PasswordW = NULL;
UINT32 UserLength = 0;
UINT32 DomainLength = 0;
UINT32 PasswordLength = 0;
2014-06-07 01:20:34 +04:00
2022-03-25 15:06:36 +03:00
sspi_FreeAuthIdentity(identity);
identityFlags = sspi_GetAuthIdentityFlags(srcIdentity);
identity->Flags = identityFlags;
if (identityFlags & SEC_WINNT_AUTH_IDENTITY_ANSI)
{
if (!sspi_GetAuthIdentityUserDomainA(srcIdentity, &UserA, &UserLength, &DomainA,
&DomainLength))
{
return -1;
}
if (!sspi_GetAuthIdentityPasswordA(srcIdentity, &PasswordA, &PasswordLength))
{
return -1;
}
status = sspi_SetAuthIdentity(identity, UserA, DomainA, PasswordA);
2014-06-07 01:20:34 +04:00
if (status <= 0)
return -1;
identity->Flags &= ~SEC_WINNT_AUTH_IDENTITY_ANSI;
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
2014-06-07 01:20:34 +04:00
return 1;
}
identity->Flags |= SEC_WINNT_AUTH_IDENTITY_UNICODE;
2022-03-25 15:06:36 +03:00
if (!sspi_GetAuthIdentityUserDomainW(srcIdentity, &UserW, &UserLength, &DomainW, &DomainLength))
{
return -1;
}
if (!sspi_GetAuthIdentityPasswordW(srcIdentity, &PasswordW, &PasswordLength))
{
return -1;
}
2017-05-11 19:51:45 +03:00
/* login/password authentication */
identity->UserLength = UserLength;
if (identity->UserLength > 0)
{
2019-11-06 17:24:51 +03:00
identity->User = (UINT16*)calloc((identity->UserLength + 1), sizeof(WCHAR));
2014-06-07 01:20:34 +04:00
if (!identity->User)
return -1;
CopyMemory(identity->User, UserW, identity->UserLength * sizeof(WCHAR));
identity->User[identity->UserLength] = 0;
}
identity->DomainLength = DomainLength;
if (identity->DomainLength > 0)
{
2019-11-06 17:24:51 +03:00
identity->Domain = (UINT16*)calloc((identity->DomainLength + 1), sizeof(WCHAR));
2014-06-07 01:20:34 +04:00
if (!identity->Domain)
return -1;
CopyMemory(identity->Domain, DomainW, identity->DomainLength * sizeof(WCHAR));
identity->Domain[identity->DomainLength] = 0;
}
identity->PasswordLength = PasswordLength;
if (identity->PasswordLength > SSPI_CREDENTIALS_HASH_LENGTH_OFFSET)
identity->PasswordLength -= SSPI_CREDENTIALS_HASH_LENGTH_OFFSET;
if (PasswordW)
{
2019-11-06 17:24:51 +03:00
identity->Password = (UINT16*)calloc((identity->PasswordLength + 1), sizeof(WCHAR));
2014-06-07 01:20:34 +04:00
if (!identity->Password)
return -1;
CopyMemory(identity->Password, PasswordW, identity->PasswordLength * sizeof(WCHAR));
identity->Password[identity->PasswordLength] = 0;
}
identity->PasswordLength = PasswordLength;
2017-05-11 19:51:45 +03:00
/* End of login/password authentication */
2014-06-07 01:20:34 +04:00
return 1;
}
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
{
PSecBuffer pSecBuffer = NULL;
for (UINT32 index = 0; index < pMessage->cBuffers; index++)
{
if (pMessage->pBuffers[index].BufferType == BufferType)
{
pSecBuffer = &pMessage->pBuffers[index];
break;
}
}
return pSecBuffer;
}
static BOOL WINPR_init(void)
{
for (size_t x = 0; x < ARRAYSIZE(SecurityFunctionTableA_NAME_LIST); x++)
{
const SecurityFunctionTableA_NAME* const cur = &SecurityFunctionTableA_NAME_LIST[x];
InitializeConstWCharFromUtf8(cur->Name, BUFFER_NAME_LIST_W[x],
ARRAYSIZE(BUFFER_NAME_LIST_W[x]));
}
return TRUE;
}
static BOOL CALLBACK sspi_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
{
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
sspi_ContextBufferAllocTableNew();
if (!SCHANNEL_init())
return FALSE;
if (!KERBEROS_init())
return FALSE;
if (!NTLM_init())
return FALSE;
if (!CREDSSP_init())
return FALSE;
if (!NEGOTIATE_init())
return FALSE;
return WINPR_init();
}
void sspi_GlobalInit(void)
{
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
DWORD flags = 0;
InitOnceExecuteOnce(&once, sspi_init, &flags, NULL);
}
void sspi_GlobalFinish(void)
{
sspi_ContextBufferAllocTableFree();
}
2021-08-02 13:13:34 +03:00
static const SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
{
size_t cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
for (size_t index = 0; index < cPackages; index++)
{
if (strcmp(Name, SecurityFunctionTableA_NAME_LIST[index].Name) == 0)
{
2021-08-02 13:13:34 +03:00
return (const SecurityFunctionTableA*)SecurityFunctionTableA_NAME_LIST[index]
2019-11-06 17:24:51 +03:00
.SecurityFunctionTable;
}
}
return NULL;
}
2021-08-02 13:13:34 +03:00
static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
{
size_t cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
for (size_t index = 0; index < cPackages; index++)
{
if (_wcscmp(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0)
{
2021-08-02 13:13:34 +03:00
return (const SecurityFunctionTableW*)SecurityFunctionTableW_NAME_LIST[index]
2019-11-06 17:24:51 +03:00
.SecurityFunctionTable;
}
}
return NULL;
}
2021-08-26 12:23:32 +03:00
static const SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
{
SEC_WCHAR* NameW = NULL;
const SecurityFunctionTableW* table = NULL;
if (!Name)
return NULL;
NameW = ConvertUtf8ToWCharAlloc(Name, NULL);
2014-06-07 01:20:34 +04:00
if (!NameW)
2014-06-07 01:20:34 +04:00
return NULL;
table = sspi_GetSecurityFunctionTableWByNameW(NameW);
free(NameW);
return table;
}
static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
static void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
static void sspi_ContextBufferFree(void* contextBuffer)
{
UINT32 allocatorIndex = 0;
for (size_t index = 0; index < ContextBufferAllocTable.cMaxEntries; index++)
{
if (contextBuffer == ContextBufferAllocTable.entries[index].contextBuffer)
{
contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
ContextBufferAllocTable.cEntries--;
ContextBufferAllocTable.entries[index].allocatorIndex = 0;
ContextBufferAllocTable.entries[index].contextBuffer = NULL;
switch (allocatorIndex)
{
case EnumerateSecurityPackagesIndex:
FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
break;
case QuerySecurityPackageInfoIndex:
FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
break;
}
}
}
}
/**
* Standard SSPI API
*/
/* Package Management */
static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
2019-11-06 17:24:51 +03:00
PSecPkgInfoW* ppPackageInfo)
{
size_t size = 0;
UINT32 cPackages = 0;
SecPkgInfoW* pPackageInfo = NULL;
cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
size = sizeof(SecPkgInfoW) * cPackages;
2019-11-06 17:24:51 +03:00
pPackageInfo = (SecPkgInfoW*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
2014-06-07 01:20:34 +04:00
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
for (size_t index = 0; index < cPackages; index++)
{
pPackageInfo[index].fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
pPackageInfo[index].wVersion = SecPkgInfoW_LIST[index]->wVersion;
pPackageInfo[index].wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
pPackageInfo[index].cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
pPackageInfo[index].Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
pPackageInfo[index].Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
}
*(pcPackages) = cPackages;
*(ppPackageInfo) = pPackageInfo;
return SEC_E_OK;
}
static SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
2019-11-06 17:24:51 +03:00
PSecPkgInfoA* ppPackageInfo)
{
size_t size = 0;
UINT32 cPackages = 0;
SecPkgInfoA* pPackageInfo = NULL;
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
size = sizeof(SecPkgInfoA) * cPackages;
2019-11-06 17:24:51 +03:00
pPackageInfo = (SecPkgInfoA*)sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
2014-06-07 01:20:34 +04:00
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
for (size_t index = 0; index < cPackages; index++)
{
pPackageInfo[index].fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
pPackageInfo[index].wVersion = SecPkgInfoA_LIST[index]->wVersion;
pPackageInfo[index].wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
2017-05-11 19:51:45 +03:00
if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
{
sspi_ContextBufferFree(pPackageInfo);
return SEC_E_INSUFFICIENT_MEMORY;
}
}
*(pcPackages) = cPackages;
*(ppPackageInfo) = pPackageInfo;
return SEC_E_OK;
}
static void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
{
UINT32 cPackages = 0;
2019-11-06 17:24:51 +03:00
SecPkgInfoA* pPackageInfo = (SecPkgInfoA*)contextBuffer;
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
if (!pPackageInfo)
return;
for (size_t index = 0; index < cPackages; index++)
{
2015-05-11 10:07:39 +03:00
free(pPackageInfo[index].Name);
free(pPackageInfo[index].Comment);
}
free(pPackageInfo);
}
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
{
return &winpr_SecurityFunctionTableW;
}
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
{
return &winpr_SecurityFunctionTableA;
}
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
2019-11-06 17:24:51 +03:00
PSecPkgInfoW* ppPackageInfo)
{
size_t size = 0;
SecPkgInfoW* pPackageInfo = NULL;
size_t cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
for (size_t index = 0; index < cPackages; index++)
{
if (_wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
{
size = sizeof(SecPkgInfoW);
2019-11-06 17:24:51 +03:00
pPackageInfo =
(SecPkgInfoW*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
2014-06-07 01:20:34 +04:00
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
pPackageInfo->fCapabilities = SecPkgInfoW_LIST[index]->fCapabilities;
pPackageInfo->wVersion = SecPkgInfoW_LIST[index]->wVersion;
pPackageInfo->wRPCID = SecPkgInfoW_LIST[index]->wRPCID;
pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
*(ppPackageInfo) = pPackageInfo;
return SEC_E_OK;
}
}
*(ppPackageInfo) = NULL;
return SEC_E_SECPKG_NOT_FOUND;
}
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
2019-11-06 17:24:51 +03:00
PSecPkgInfoA* ppPackageInfo)
{
size_t size = 0;
SecPkgInfoA* pPackageInfo = NULL;
size_t cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
for (size_t index = 0; index < cPackages; index++)
{
if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
{
size = sizeof(SecPkgInfoA);
2019-11-06 17:24:51 +03:00
pPackageInfo =
(SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
2014-06-07 01:20:34 +04:00
if (!pPackageInfo)
return SEC_E_INSUFFICIENT_MEMORY;
pPackageInfo->fCapabilities = SecPkgInfoA_LIST[index]->fCapabilities;
pPackageInfo->wVersion = SecPkgInfoA_LIST[index]->wVersion;
pPackageInfo->wRPCID = SecPkgInfoA_LIST[index]->wRPCID;
pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
2017-05-11 19:51:45 +03:00
if (!pPackageInfo->Name || !pPackageInfo->Comment)
{
sspi_ContextBufferFree(pPackageInfo);
return SEC_E_INSUFFICIENT_MEMORY;
}
*(ppPackageInfo) = pPackageInfo;
return SEC_E_OK;
}
}
*(ppPackageInfo) = NULL;
return SEC_E_SECPKG_NOT_FOUND;
}
void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
{
2019-11-06 17:24:51 +03:00
SecPkgInfo* pPackageInfo = (SecPkgInfo*)contextBuffer;
2015-05-11 10:07:39 +03:00
if (!pPackageInfo)
return;
2015-05-11 10:07:39 +03:00
free(pPackageInfo->Name);
free(pPackageInfo->Comment);
free(pPackageInfo);
}
/* Credential Management */
2019-11-06 17:24:51 +03:00
static SECURITY_STATUS SEC_ENTRY winpr_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;
2021-08-02 13:13:34 +03:00
const SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->AcquireCredentialsHandleW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
2019-11-06 17:24:51 +03:00
status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
ptsExpiry);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
2019-11-06 17:24:51 +03:00
static SECURITY_STATUS SEC_ENTRY winpr_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;
2021-08-02 13:13:34 +03:00
const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->AcquireCredentialsHandleA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
2019-11-06 17:24:51 +03:00
status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID,
pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential,
ptsExpiry);
2015-07-07 18:17:29 +03:00
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
2019-11-06 17:24:51 +03:00
PSecBuffer pPackedContext,
HANDLE* pToken)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->ExportSecurityContext)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->FreeCredentialsHandle)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->FreeCredentialsHandle(phCredential);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
2019-11-06 17:24:51 +03:00
PSecBuffer pPackedContext,
HANDLE pToken, PCtxtHandle phContext)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->ImportSecurityContextW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
2019-11-06 17:24:51 +03:00
PSecBuffer pPackedContext,
HANDLE pToken, PCtxtHandle phContext)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->ImportSecurityContextA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer)
{
SEC_WCHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameW(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->QueryCredentialsAttributesW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->QueryCredentialsAttributesA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesW(PCredHandle phCredential,
2022-09-29 18:42:43 +03:00
ULONG ulAttribute, void* pBuffer,
ULONG cbBuffer)
{
SEC_WCHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
Name = (SEC_WCHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameW(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->SetCredentialsAttributesW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->SetCredentialsAttributesW(phCredential, ulAttribute, pBuffer, cbBuffer);
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "SetCredentialsAttributesW status %s [0x%08" PRIX32 "]",
GetSecurityStatusString(status), status);
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_SetCredentialsAttributesA(PCredHandle phCredential,
2022-09-29 18:42:43 +03:00
ULONG ulAttribute, void* pBuffer,
ULONG cbBuffer)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->SetCredentialsAttributesA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->SetCredentialsAttributesA(phCredential, ulAttribute, pBuffer, cbBuffer);
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "SetCredentialsAttributesA status %s [0x%08" PRIX32 "]",
GetSecurityStatusString(status), status);
}
return status;
}
/* Context Management */
2019-11-06 17:24:51 +03:00
static SECURITY_STATUS SEC_ENTRY
winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->AcceptSecurityContext)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
2019-11-06 17:24:51 +03:00
status =
table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep,
phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
2015-07-07 18:17:29 +03:00
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pInput)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->ApplyControlToken)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->ApplyControlToken(phContext, pInput);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "ApplyControlToken status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pToken)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->CompleteAuthToken)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->CompleteAuthToken(phContext, pToken);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
{
const char* Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
const SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->DeleteSecurityContext)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
const UINT32 status = table->DeleteSecurityContext(phContext);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
{
if (!pvContextBuffer)
return SEC_E_INVALID_HANDLE;
sspi_ContextBufferFree(pvContextBuffer);
return SEC_E_OK;
}
static SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->ImpersonateSecurityContext)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->ImpersonateSecurityContext(phContext);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
2019-11-06 17:24:51 +03:00
static SECURITY_STATUS SEC_ENTRY winpr_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)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->InitializeSecurityContextW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
2019-11-06 17:24:51 +03:00
status = table->InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2,
phNewContext, pOutput, pfContextAttr, ptsExpiry);
2015-07-07 18:17:29 +03:00
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
2019-11-06 17:24:51 +03:00
static SECURITY_STATUS SEC_ENTRY winpr_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)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->InitializeSecurityContextA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
2019-11-06 17:24:51 +03:00
status = table->InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq,
Reserved1, TargetDataRep, pInput, Reserved2,
phNewContext, pOutput, pfContextAttr, ptsExpiry);
2015-07-07 18:17:29 +03:00
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->QueryContextAttributesW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->QueryContextAttributesA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
HANDLE* phToken)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
2014-06-10 22:38:17 +04:00
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->QuerySecurityContextToken)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
2014-06-10 22:38:17 +04:00
return SEC_E_UNSUPPORTED_FUNCTION;
}
2014-06-10 22:38:17 +04:00
status = table->QuerySecurityContextToken(phContext, phToken);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
2014-06-10 22:38:17 +04:00
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer,
ULONG cbBuffer)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
2014-06-10 22:38:17 +04:00
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->SetContextAttributesW)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
2014-06-10 22:38:17 +04:00
return SEC_E_UNSUPPORTED_FUNCTION;
}
2014-06-10 22:38:17 +04:00
status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
2014-06-10 22:38:17 +04:00
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
ULONG ulAttribute, void* pBuffer,
ULONG cbBuffer)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
2014-06-10 22:38:17 +04:00
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->SetContextAttributesA)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
2014-06-10 22:38:17 +04:00
return SEC_E_UNSUPPORTED_FUNCTION;
}
2014-06-10 22:38:17 +04:00
status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
2014-06-10 22:38:17 +04:00
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
{
SEC_CHAR* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableW* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (SEC_CHAR*)sspi_SecureHandleGetUpperPointer(phContext);
2014-06-10 22:38:17 +04:00
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableWByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
if (!table->RevertSecurityContext)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
2014-06-10 22:38:17 +04:00
return SEC_E_UNSUPPORTED_FUNCTION;
}
2014-06-10 22:38:17 +04:00
status = table->RevertSecurityContext(phContext);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
2014-06-10 22:38:17 +04:00
return status;
}
/* Message Support */
static SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pMessage, ULONG MessageSeqNo,
PULONG pfQOP)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->DecryptMessage)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "DecryptMessage status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->EncryptMessage)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
2015-07-07 18:17:29 +03:00
if (status != SEC_E_OK)
{
2019-11-06 17:24:51 +03:00
WLog_ERR(TAG, "EncryptMessage status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->MakeSignature)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "MakeSignature status %s [0x%08" PRIX32 "]", GetSecurityStatusString(status),
status);
2015-07-07 18:17:29 +03:00
}
return status;
}
static SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext,
2019-11-06 17:24:51 +03:00
PSecBufferDesc pMessage, ULONG MessageSeqNo,
PULONG pfQOP)
{
char* Name = NULL;
SECURITY_STATUS status = 0;
const SecurityFunctionTableA* table = NULL;
2019-11-06 17:24:51 +03:00
Name = (char*)sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
return SEC_E_SECPKG_NOT_FOUND;
table = sspi_GetSecurityFunctionTableAByNameA(Name);
if (!table)
return SEC_E_SECPKG_NOT_FOUND;
2014-06-07 01:20:34 +04:00
if (!table->VerifySignature)
{
WLog_WARN(TAG, "Security module does not provide an implementation");
return SEC_E_UNSUPPORTED_FUNCTION;
}
status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
if (IsSecurityStatusError(status))
2015-07-07 18:17:29 +03:00
{
2019-11-06 17:24:51 +03:00
WLog_WARN(TAG, "VerifySignature status %s [0x%08" PRIX32 "]",
2017-05-11 19:51:45 +03:00
GetSecurityStatusString(status), status);
2015-07-07 18:17:29 +03:00
}
return status;
}
2019-11-06 17:24:51 +03:00
static SecurityFunctionTableA winpr_SecurityFunctionTableA = {
3, /* dwVersion */
2019-11-06 17:24:51 +03:00
winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */
winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
2019-11-06 17:24:51 +03:00
winpr_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */
winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
winpr_InitializeSecurityContextA, /* InitializeSecurityContext */
winpr_AcceptSecurityContext, /* AcceptSecurityContext */
winpr_CompleteAuthToken, /* CompleteAuthToken */
winpr_DeleteSecurityContext, /* DeleteSecurityContext */
winpr_ApplyControlToken, /* ApplyControlToken */
winpr_QueryContextAttributesA, /* QueryContextAttributes */
winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
winpr_RevertSecurityContext, /* RevertSecurityContext */
winpr_MakeSignature, /* MakeSignature */
winpr_VerifySignature, /* VerifySignature */
winpr_FreeContextBuffer, /* FreeContextBuffer */
winpr_QuerySecurityPackageInfoA, /* QuerySecurityPackageInfo */
NULL, /* Reserved3 */
NULL, /* Reserved4 */
winpr_ExportSecurityContext, /* ExportSecurityContext */
winpr_ImportSecurityContextA, /* ImportSecurityContext */
NULL, /* AddCredentials */
NULL, /* Reserved8 */
winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
winpr_EncryptMessage, /* EncryptMessage */
winpr_DecryptMessage, /* DecryptMessage */
winpr_SetContextAttributesA, /* SetContextAttributes */
winpr_SetCredentialsAttributesA, /* SetCredentialsAttributes */
};
2019-11-06 17:24:51 +03:00
static SecurityFunctionTableW winpr_SecurityFunctionTableW = {
3, /* dwVersion */
2019-11-06 17:24:51 +03:00
winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */
winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
2019-11-06 17:24:51 +03:00
winpr_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */
winpr_FreeCredentialsHandle, /* FreeCredentialsHandle */
NULL, /* Reserved2 */
winpr_InitializeSecurityContextW, /* InitializeSecurityContext */
winpr_AcceptSecurityContext, /* AcceptSecurityContext */
winpr_CompleteAuthToken, /* CompleteAuthToken */
winpr_DeleteSecurityContext, /* DeleteSecurityContext */
winpr_ApplyControlToken, /* ApplyControlToken */
winpr_QueryContextAttributesW, /* QueryContextAttributes */
winpr_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
winpr_RevertSecurityContext, /* RevertSecurityContext */
winpr_MakeSignature, /* MakeSignature */
winpr_VerifySignature, /* VerifySignature */
winpr_FreeContextBuffer, /* FreeContextBuffer */
winpr_QuerySecurityPackageInfoW, /* QuerySecurityPackageInfo */
NULL, /* Reserved3 */
NULL, /* Reserved4 */
winpr_ExportSecurityContext, /* ExportSecurityContext */
winpr_ImportSecurityContextW, /* ImportSecurityContext */
NULL, /* AddCredentials */
NULL, /* Reserved8 */
winpr_QuerySecurityContextToken, /* QuerySecurityContextToken */
winpr_EncryptMessage, /* EncryptMessage */
winpr_DecryptMessage, /* DecryptMessage */
winpr_SetContextAttributesW, /* SetContextAttributes */
winpr_SetCredentialsAttributesW, /* SetCredentialsAttributes */
};