cdcdec99bc
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).
1443 lines
37 KiB
C
1443 lines
37 KiB
C
/**
|
|
* 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.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <winpr/windows.h>
|
|
|
|
#include <winpr/crt.h>
|
|
#include <winpr/sspi.h>
|
|
#include <winpr/ssl.h>
|
|
#include <winpr/print.h>
|
|
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/err.h>
|
|
|
|
#include "sspi.h"
|
|
|
|
#include "sspi_winpr.h"
|
|
|
|
/* Authentication Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731/ */
|
|
|
|
extern const SecPkgInfoA NTLM_SecPkgInfoA;
|
|
extern const SecPkgInfoW NTLM_SecPkgInfoW;
|
|
extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
|
|
extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
|
|
|
|
extern const SecPkgInfoA NEGOTIATE_SecPkgInfoA;
|
|
extern const SecPkgInfoW NEGOTIATE_SecPkgInfoW;
|
|
extern const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA;
|
|
extern const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW;
|
|
|
|
extern const SecPkgInfoA CREDSSP_SecPkgInfoA;
|
|
extern const SecPkgInfoW CREDSSP_SecPkgInfoW;
|
|
extern const SecurityFunctionTableA CREDSSP_SecurityFunctionTableA;
|
|
extern const SecurityFunctionTableW CREDSSP_SecurityFunctionTableW;
|
|
|
|
extern const SecPkgInfoA SCHANNEL_SecPkgInfoA;
|
|
extern const SecPkgInfoW SCHANNEL_SecPkgInfoW;
|
|
extern const SecurityFunctionTableA SCHANNEL_SecurityFunctionTableA;
|
|
extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW;
|
|
|
|
const SecPkgInfoA* SecPkgInfoA_LIST[] =
|
|
{
|
|
&NTLM_SecPkgInfoA,
|
|
&NEGOTIATE_SecPkgInfoA,
|
|
&CREDSSP_SecPkgInfoA,
|
|
&SCHANNEL_SecPkgInfoA
|
|
};
|
|
|
|
const SecPkgInfoW* SecPkgInfoW_LIST[] =
|
|
{
|
|
&NTLM_SecPkgInfoW,
|
|
&NEGOTIATE_SecPkgInfoW,
|
|
&CREDSSP_SecPkgInfoW,
|
|
&SCHANNEL_SecPkgInfoW
|
|
};
|
|
|
|
SecurityFunctionTableA winpr_SecurityFunctionTableA;
|
|
SecurityFunctionTableW winpr_SecurityFunctionTableW;
|
|
|
|
struct _SecurityFunctionTableA_NAME
|
|
{
|
|
SEC_CHAR* Name;
|
|
const SecurityFunctionTableA* SecurityFunctionTable;
|
|
};
|
|
typedef struct _SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME;
|
|
|
|
struct _SecurityFunctionTableW_NAME
|
|
{
|
|
SEC_WCHAR* Name;
|
|
const SecurityFunctionTableW* SecurityFunctionTable;
|
|
};
|
|
typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME;
|
|
|
|
const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] =
|
|
{
|
|
{ "NTLM", &NTLM_SecurityFunctionTableA },
|
|
{ "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
|
|
{ "CREDSSP", &CREDSSP_SecurityFunctionTableA },
|
|
{ "Schannel", &SCHANNEL_SecurityFunctionTableA }
|
|
};
|
|
|
|
WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' };
|
|
WCHAR NEGOTIATE_NAME_W[] = { 'N','e','g','o','t','i','a','t','e','\0' };
|
|
WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' };
|
|
WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' };
|
|
|
|
const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] =
|
|
{
|
|
{ NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
|
|
{ NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW },
|
|
{ CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW },
|
|
{ SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW }
|
|
};
|
|
|
|
#define SecHandle_LOWER_MAX 0xFFFFFFFF
|
|
#define SecHandle_UPPER_MAX 0xFFFFFFFE
|
|
|
|
struct _CONTEXT_BUFFER_ALLOC_ENTRY
|
|
{
|
|
void* contextBuffer;
|
|
UINT32 allocatorIndex;
|
|
};
|
|
typedef struct _CONTEXT_BUFFER_ALLOC_ENTRY CONTEXT_BUFFER_ALLOC_ENTRY;
|
|
|
|
struct _CONTEXT_BUFFER_ALLOC_TABLE
|
|
{
|
|
UINT32 cEntries;
|
|
UINT32 cMaxEntries;
|
|
CONTEXT_BUFFER_ALLOC_ENTRY* entries;
|
|
};
|
|
typedef struct _CONTEXT_BUFFER_ALLOC_TABLE CONTEXT_BUFFER_ALLOC_TABLE;
|
|
|
|
CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable;
|
|
|
|
int sspi_ContextBufferAllocTableNew()
|
|
{
|
|
size_t size;
|
|
|
|
ContextBufferAllocTable.entries = NULL;
|
|
ContextBufferAllocTable.cEntries = 0;
|
|
ContextBufferAllocTable.cMaxEntries = 4;
|
|
|
|
size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
|
|
|
|
ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*) calloc(1, size);
|
|
|
|
if (!ContextBufferAllocTable.entries)
|
|
return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int sspi_ContextBufferAllocTableGrow()
|
|
{
|
|
size_t size;
|
|
CONTEXT_BUFFER_ALLOC_ENTRY* entries;
|
|
ContextBufferAllocTable.cEntries = 0;
|
|
ContextBufferAllocTable.cMaxEntries *= 2;
|
|
|
|
size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
|
|
|
|
if (!size)
|
|
return -1;
|
|
|
|
entries = (CONTEXT_BUFFER_ALLOC_ENTRY*) realloc(ContextBufferAllocTable.entries, size);
|
|
|
|
if (!entries)
|
|
{
|
|
free(ContextBufferAllocTable.entries);
|
|
return -1;
|
|
}
|
|
|
|
ContextBufferAllocTable.entries = entries;
|
|
|
|
ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void sspi_ContextBufferAllocTableFree()
|
|
{
|
|
ContextBufferAllocTable.cEntries = ContextBufferAllocTable.cMaxEntries = 0;
|
|
free(ContextBufferAllocTable.entries);
|
|
}
|
|
|
|
void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
|
|
{
|
|
int index;
|
|
void* contextBuffer;
|
|
|
|
for (index = 0; index < (int) ContextBufferAllocTable.cMaxEntries; index++)
|
|
{
|
|
if (!ContextBufferAllocTable.entries[index].contextBuffer)
|
|
{
|
|
contextBuffer = calloc(1, size);
|
|
|
|
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 */
|
|
|
|
if (sspi_ContextBufferAllocTableGrow() < 0)
|
|
return NULL;
|
|
|
|
/* the next call to sspi_ContextBufferAlloc() should now succeed */
|
|
|
|
return sspi_ContextBufferAlloc(allocatorIndex, size);
|
|
}
|
|
|
|
SSPI_CREDENTIALS* sspi_CredentialsNew()
|
|
{
|
|
SSPI_CREDENTIALS* credentials;
|
|
|
|
credentials = (SSPI_CREDENTIALS*) calloc(1, sizeof(SSPI_CREDENTIALS));
|
|
|
|
return credentials;
|
|
}
|
|
|
|
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
|
|
{
|
|
if (!credentials)
|
|
return;
|
|
|
|
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;
|
|
|
|
SecBuffer->cbBuffer = size;
|
|
SecBuffer->pvBuffer = calloc(1, size);
|
|
|
|
return SecBuffer->pvBuffer;
|
|
}
|
|
|
|
void sspi_SecBufferFree(PSecBuffer SecBuffer)
|
|
{
|
|
free(SecBuffer->pvBuffer);
|
|
SecBuffer->pvBuffer = NULL;
|
|
SecBuffer->cbBuffer = 0;
|
|
}
|
|
|
|
SecHandle* sspi_SecureHandleAlloc()
|
|
{
|
|
SecHandle* handle = (SecHandle*) calloc(1, sizeof(SecHandle));
|
|
|
|
if (!handle)
|
|
return NULL;
|
|
|
|
SecInvalidateHandle(handle);
|
|
|
|
return handle;
|
|
}
|
|
|
|
void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
|
|
{
|
|
void* pointer;
|
|
|
|
if (!handle || !SecIsValidHandle(handle) || !handle->dwLower)
|
|
return NULL;
|
|
|
|
pointer = (void*) ~((size_t) handle->dwLower);
|
|
|
|
return pointer;
|
|
}
|
|
|
|
void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
|
|
{
|
|
if (!handle)
|
|
return;
|
|
|
|
handle->dwLower = (ULONG_PTR) (~((size_t) pointer));
|
|
}
|
|
|
|
void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
|
|
{
|
|
void* pointer;
|
|
|
|
if (!handle || !SecIsValidHandle(handle) || !handle->dwUpper)
|
|
return NULL;
|
|
|
|
pointer = (void*) ~((size_t) handle->dwUpper);
|
|
|
|
return pointer;
|
|
}
|
|
|
|
void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
|
|
{
|
|
if (!handle)
|
|
return;
|
|
|
|
handle->dwUpper = (ULONG_PTR) (~((size_t) pointer));
|
|
}
|
|
|
|
void sspi_SecureHandleFree(SecHandle* handle)
|
|
{
|
|
if (!handle)
|
|
return;
|
|
|
|
free(handle);
|
|
}
|
|
|
|
int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password)
|
|
{
|
|
int status;
|
|
|
|
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
|
|
|
if (identity->User)
|
|
free(identity->User);
|
|
|
|
identity->User = (UINT16*) NULL;
|
|
identity->UserLength = 0;
|
|
|
|
if (user)
|
|
{
|
|
status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) &(identity->User), 0);
|
|
|
|
if (status <= 0)
|
|
return -1;
|
|
|
|
identity->UserLength = (ULONG) (status - 1);
|
|
}
|
|
|
|
if (identity->Domain)
|
|
free(identity->Domain);
|
|
|
|
identity->Domain = (UINT16*) NULL;
|
|
identity->DomainLength = 0;
|
|
|
|
if (domain)
|
|
{
|
|
status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) &(identity->Domain), 0);
|
|
|
|
if (status <= 0)
|
|
return -1;
|
|
|
|
identity->DomainLength = (ULONG) (status - 1);
|
|
}
|
|
|
|
if (identity->Password)
|
|
free(identity->Password);
|
|
|
|
identity->Password = NULL;
|
|
identity->PasswordLength = 0;
|
|
|
|
if (password)
|
|
{
|
|
status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) &(identity->Password), 0);
|
|
|
|
if (status <= 0)
|
|
return -1;
|
|
|
|
identity->PasswordLength = (ULONG) (status - 1);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDENTITY* srcIdentity)
|
|
{
|
|
int status;
|
|
|
|
if (identity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
|
|
{
|
|
status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User,
|
|
(char*) srcIdentity->Domain, (char*) srcIdentity->Password);
|
|
|
|
if (status <= 0)
|
|
return -1;
|
|
|
|
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
|
|
|
return 1;
|
|
}
|
|
|
|
identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
|
|
|
identity->User = identity->Domain = identity->Password = NULL;
|
|
|
|
identity->UserLength = srcIdentity->UserLength;
|
|
|
|
if (identity->UserLength > 0)
|
|
{
|
|
identity->User = (UINT16*) malloc((identity->UserLength + 1) * sizeof(WCHAR));
|
|
|
|
if (!identity->User)
|
|
return -1;
|
|
|
|
CopyMemory(identity->User, srcIdentity->User, identity->UserLength * sizeof(WCHAR));
|
|
identity->User[identity->UserLength] = 0;
|
|
}
|
|
|
|
identity->DomainLength = srcIdentity->DomainLength;
|
|
|
|
if (identity->DomainLength > 0)
|
|
{
|
|
identity->Domain = (UINT16*) malloc((identity->DomainLength + 1) * sizeof(WCHAR));
|
|
|
|
if (!identity->Domain)
|
|
return -1;
|
|
|
|
CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength * sizeof(WCHAR));
|
|
identity->Domain[identity->DomainLength] = 0;
|
|
}
|
|
|
|
identity->PasswordLength = srcIdentity->PasswordLength;
|
|
|
|
if (identity->PasswordLength > 256)
|
|
identity->PasswordLength /= SSPI_CREDENTIALS_HASH_LENGTH_FACTOR;
|
|
|
|
if (identity->PasswordLength > 0)
|
|
{
|
|
identity->Password = (UINT16*) malloc((identity->PasswordLength + 1) * sizeof(WCHAR));
|
|
|
|
if (!identity->Password)
|
|
return -1;
|
|
|
|
CopyMemory(identity->Password, srcIdentity->Password, identity->PasswordLength * sizeof(WCHAR));
|
|
identity->Password[identity->PasswordLength] = 0;
|
|
}
|
|
|
|
identity->PasswordLength = srcIdentity->PasswordLength;
|
|
|
|
return 1;
|
|
}
|
|
|
|
PSecBuffer sspi_FindSecBuffer(PSecBufferDesc pMessage, ULONG BufferType)
|
|
{
|
|
ULONG index;
|
|
PSecBuffer pSecBuffer = NULL;
|
|
|
|
for (index = 0; index < pMessage->cBuffers; index++)
|
|
{
|
|
if (pMessage->pBuffers[index].BufferType == BufferType)
|
|
{
|
|
pSecBuffer = &pMessage->pBuffers[index];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return pSecBuffer;
|
|
}
|
|
|
|
static BOOL sspi_initialized = FALSE;
|
|
|
|
void sspi_GlobalInit()
|
|
{
|
|
if (!sspi_initialized)
|
|
{
|
|
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
|
|
|
sspi_ContextBufferAllocTableNew();
|
|
sspi_initialized = TRUE;
|
|
}
|
|
}
|
|
|
|
void sspi_GlobalFinish()
|
|
{
|
|
if (sspi_initialized)
|
|
{
|
|
sspi_ContextBufferAllocTableFree();
|
|
}
|
|
|
|
sspi_initialized = FALSE;
|
|
}
|
|
|
|
SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Name)
|
|
{
|
|
int index;
|
|
UINT32 cPackages;
|
|
|
|
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
|
|
|
|
for (index = 0; index < (int) cPackages; index++)
|
|
{
|
|
if (strcmp(Name, SecurityFunctionTableA_NAME_LIST[index].Name) == 0)
|
|
{
|
|
return (SecurityFunctionTableA*) SecurityFunctionTableA_NAME_LIST[index].SecurityFunctionTable;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameW(const SEC_WCHAR* Name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* Name)
|
|
{
|
|
int index;
|
|
UINT32 cPackages;
|
|
|
|
cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
|
|
|
|
for (index = 0; index < (int) cPackages; index++)
|
|
{
|
|
if (lstrcmpW(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0)
|
|
{
|
|
return (SecurityFunctionTableW*) SecurityFunctionTableW_NAME_LIST[index].SecurityFunctionTable;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Name)
|
|
{
|
|
int status;
|
|
SEC_WCHAR* NameW = NULL;
|
|
SecurityFunctionTableW* table;
|
|
|
|
status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0);
|
|
|
|
if (status <= 0)
|
|
return NULL;
|
|
|
|
table = sspi_GetSecurityFunctionTableWByNameW(NameW);
|
|
free(NameW);
|
|
|
|
return table;
|
|
}
|
|
|
|
void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer);
|
|
void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer);
|
|
|
|
void sspi_ContextBufferFree(void* contextBuffer)
|
|
{
|
|
int index;
|
|
UINT32 allocatorIndex;
|
|
|
|
for (index = 0; index < (int) 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 */
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo)
|
|
{
|
|
int index;
|
|
size_t size;
|
|
UINT32 cPackages;
|
|
SecPkgInfoW* pPackageInfo;
|
|
|
|
cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
|
|
size = sizeof(SecPkgInfoW) * cPackages;
|
|
|
|
pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
|
|
|
|
if (!pPackageInfo)
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
for (index = 0; index < (int) 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;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo)
|
|
{
|
|
int index;
|
|
size_t size;
|
|
UINT32 cPackages;
|
|
SecPkgInfoA* pPackageInfo;
|
|
|
|
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
|
|
size = sizeof(SecPkgInfoA) * cPackages;
|
|
|
|
pPackageInfo = (SecPkgInfoA*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
|
|
|
|
if (!pPackageInfo)
|
|
return SEC_E_INSUFFICIENT_MEMORY;
|
|
|
|
for (index = 0; index < (int) 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);
|
|
}
|
|
|
|
*(pcPackages) = cPackages;
|
|
*(ppPackageInfo) = pPackageInfo;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
|
|
{
|
|
int index;
|
|
UINT32 cPackages;
|
|
SecPkgInfoA* pPackageInfo = (SecPkgInfoA*) contextBuffer;
|
|
|
|
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
|
|
|
|
for (index = 0; index < (int) cPackages; index++)
|
|
{
|
|
if (pPackageInfo[index].Name)
|
|
free(pPackageInfo[index].Name);
|
|
|
|
if (pPackageInfo[index].Comment)
|
|
free(pPackageInfo[index].Comment);
|
|
}
|
|
|
|
free(pPackageInfo);
|
|
}
|
|
|
|
SecurityFunctionTableW* SEC_ENTRY winpr_InitSecurityInterfaceW(void)
|
|
{
|
|
return &winpr_SecurityFunctionTableW;
|
|
}
|
|
|
|
SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
|
|
{
|
|
return &winpr_SecurityFunctionTableA;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo)
|
|
{
|
|
int index;
|
|
size_t size;
|
|
UINT32 cPackages;
|
|
SecPkgInfoW* pPackageInfo;
|
|
|
|
cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
|
|
|
|
for (index = 0; index < (int) cPackages; index++)
|
|
{
|
|
if (lstrcmpW(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0)
|
|
{
|
|
size = sizeof(SecPkgInfoW);
|
|
pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
|
|
|
|
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;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo)
|
|
{
|
|
int index;
|
|
size_t size;
|
|
UINT32 cPackages;
|
|
SecPkgInfoA* pPackageInfo;
|
|
|
|
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
|
|
|
|
for (index = 0; index < (int) cPackages; index++)
|
|
{
|
|
if (strcmp(pszPackageName, SecPkgInfoA_LIST[index]->Name) == 0)
|
|
{
|
|
size = sizeof(SecPkgInfoA);
|
|
pPackageInfo = (SecPkgInfoA*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
|
|
|
|
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);
|
|
|
|
*(ppPackageInfo) = pPackageInfo;
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
}
|
|
|
|
*(ppPackageInfo) = NULL;
|
|
|
|
return SEC_E_SECPKG_NOT_FOUND;
|
|
}
|
|
|
|
void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
|
|
{
|
|
SecPkgInfo* pPackageInfo = (SecPkgInfo*) contextBuffer;
|
|
|
|
if (pPackageInfo->Name)
|
|
free(pPackageInfo->Name);
|
|
|
|
if (pPackageInfo->Comment)
|
|
free(pPackageInfo->Comment);
|
|
|
|
free(pPackageInfo);
|
|
}
|
|
|
|
/* Credential Management */
|
|
|
|
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;
|
|
SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
|
|
|
|
if (!table)
|
|
return SEC_E_SECPKG_NOT_FOUND;
|
|
|
|
if (!table->AcquireCredentialsHandleW)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse,
|
|
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
|
|
|
|
return status;
|
|
}
|
|
|
|
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;
|
|
SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
|
|
|
|
if (!table)
|
|
return SEC_E_SECPKG_NOT_FOUND;
|
|
|
|
if (!table->AcquireCredentialsHandleA)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse,
|
|
pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->FreeCredentialsHandle)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->FreeCredentialsHandle(phCredential);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
|
|
{
|
|
char* Name = NULL;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
|
|
{
|
|
SEC_WCHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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->QueryCredentialsAttributesW)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->QueryCredentialsAttributesA)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
/* Context Management */
|
|
|
|
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;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->AcceptSecurityContext)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq,
|
|
TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput)
|
|
{
|
|
char* Name = NULL;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->ApplyControlToken(phContext, pInput);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBufferDesc pToken)
|
|
{
|
|
char* Name = NULL;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->CompleteAuthToken(phContext, pToken);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
|
|
{
|
|
char* Name = NULL;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->DeleteSecurityContext)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->DeleteSecurityContext(phContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
|
|
{
|
|
if (!pvContextBuffer)
|
|
return SEC_E_INVALID_HANDLE;
|
|
|
|
sspi_ContextBufferFree(pvContextBuffer);
|
|
|
|
return SEC_E_OK;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->ImpersonateSecurityContext(phContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
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;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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;
|
|
|
|
if (!table->InitializeSecurityContextW)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->InitializeSecurityContextW(phCredential, phContext,
|
|
pszTargetName, fContextReq, Reserved1, TargetDataRep,
|
|
pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
|
|
|
|
return status;
|
|
}
|
|
|
|
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;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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;
|
|
|
|
if (!table->InitializeSecurityContextA)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->InitializeSecurityContextA(phCredential, phContext,
|
|
pszTargetName, fContextReq, Reserved1, TargetDataRep,
|
|
pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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->QueryContextAttributesW)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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;
|
|
|
|
if (!table->QueryContextAttributesA)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, HANDLE* phToken)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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->QuerySecurityContextToken)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->QuerySecurityContextToken(phContext, phToken);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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->SetContextAttributesW)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->SetContextAttributesA)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
|
|
{
|
|
SEC_CHAR* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableW* table;
|
|
|
|
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->RevertSecurityContext)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->RevertSecurityContext(phContext);
|
|
|
|
return status;
|
|
}
|
|
|
|
/* Message Support */
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->DecryptMessage)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->EncryptMessage)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->MakeSignature)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo);
|
|
|
|
return status;
|
|
}
|
|
|
|
SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
|
|
{
|
|
char* Name;
|
|
SECURITY_STATUS status;
|
|
SecurityFunctionTableA* table;
|
|
|
|
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->VerifySignature)
|
|
return SEC_E_UNSUPPORTED_FUNCTION;
|
|
|
|
status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP);
|
|
|
|
return status;
|
|
}
|
|
|
|
SecurityFunctionTableA winpr_SecurityFunctionTableA =
|
|
{
|
|
1, /* dwVersion */
|
|
winpr_EnumerateSecurityPackagesA, /* EnumerateSecurityPackages */
|
|
winpr_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */
|
|
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 */
|
|
};
|
|
|
|
SecurityFunctionTableW winpr_SecurityFunctionTableW =
|
|
{
|
|
1, /* dwVersion */
|
|
winpr_EnumerateSecurityPackagesW, /* EnumerateSecurityPackages */
|
|
winpr_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */
|
|
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 */
|
|
};
|