Sec.h
/*
SPDX-License-Identifier: MIT
Copyright © 1991-2022 Amebis
Copyright © 2016 GÉANT
*/
#pragma once
#include "Common.h"
#include <Security.h>
#include <string>
#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL)
template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<char[]> szBuffer(new char[ulSize]);
if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]);
if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
#endif
namespace winstd
{
class sec_credentials : public handle<PCredHandle, NULL>
{
WINSTD_NONCOPYABLE(sec_credentials)
public:
sec_credentials()
{
m_expires.QuadPart = -1;
}
sec_credentials(_In_opt_ handle_type h, _In_ const TimeStamp expires) :
m_expires(expires),
handle(h)
{
}
sec_credentials(_Inout_ sec_credentials &&h) noexcept :
m_expires(std::move(h.m_expires)),
handle<PCredHandle, NULL>(std::move(h))
{
}
virtual ~sec_credentials()
{
if (m_h != invalid)
free_internal();
}
sec_credentials& operator=(_Inout_ sec_credentials &&h) noexcept
{
if (this != std::addressof(h)) {
*(handle<handle_type, NULL>*)this = std::move(h);
m_expires = std::move(h.m_expires);
}
return *this;
}
SECURITY_STATUS acquire(
_In_opt_ LPTSTR pszPrincipal,
_In_ LPTSTR pszPackage,
_In_ unsigned long fCredentialUse,
_In_opt_ void *pvLogonId,
_In_opt_ void *pAuthData,
_In_opt_ SEC_GET_KEY_FN pGetKeyFn = NULL,
_In_opt_ void *pvGetKeyArgument = NULL)
{
handle_type h = new CredHandle;
TimeStamp exp;
SECURITY_STATUS res = AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, h, &exp);
if (SUCCEEDED(res)) {
attach(h);
m_expires = exp;
} else
delete h;
return res;
}
protected:
void free_internal() noexcept override
{
FreeCredentialsHandle(m_h);
delete m_h;
}
public:
TimeStamp m_expires;
};
class sec_context : public handle<PCtxtHandle, NULL>
{
public:
sec_context() :
m_attrib(0),
handle<PCtxtHandle, NULL>()
{
m_expires.QuadPart = -1;
}
sec_context(_Inout_ sec_context &&h) noexcept :
m_attrib (std::move(h.m_attrib )),
m_expires(std::move(h.m_expires)),
handle<PCtxtHandle, NULL>(std::move(h))
{
}
virtual ~sec_context()
{
if (m_h != invalid)
free_internal();
}
sec_context& operator=(_Inout_ sec_context &&h) noexcept
{
if (this != std::addressof(h)) {
*(handle<handle_type, NULL>*)this = std::move(h);
m_attrib = std::move(h.m_attrib);
m_expires = std::move(h.m_expires);
}
return *this;
}
SECURITY_STATUS initialize(
_In_opt_ PCredHandle phCredential,
_In_opt_z_ LPCTSTR pszTargetName,
_In_ ULONG fContextReq,
_In_ ULONG TargetDataRep,
_In_opt_ PSecBufferDesc pInput,
_Inout_opt_ PSecBufferDesc pOutput)
{
handle_type h = new CtxtHandle;
h->dwUpper = 0;
h->dwLower = 0;
ULONG attr;
TimeStamp exp;
SECURITY_STATUS res = InitializeSecurityContext(phCredential, NULL, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, h, pOutput, &attr, &exp);
if (SUCCEEDED(res)) {
attach(h);
m_attrib = attr;
m_expires = exp;
} else
delete h;
return res;
}
SECURITY_STATUS process(
_In_opt_ PCredHandle phCredential,
_In_opt_z_ LPCTSTR pszTargetName,
_In_ ULONG fContextReq,
_In_ ULONG TargetDataRep,
_In_opt_ PSecBufferDesc pInput,
_Inout_opt_ PSecBufferDesc pOutput)
{
return InitializeSecurityContext(phCredential, m_h, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, NULL, pOutput, &m_attrib, &m_expires);
}
protected:
void free_internal() noexcept override
{
DeleteSecurityContext(m_h);
delete m_h;
}
public:
ULONG m_attrib;
TimeStamp m_expires;
};
class sec_buffer_desc : public SecBufferDesc
{
public:
sec_buffer_desc(_Inout_count_(count) PSecBuffer buf, ULONG count, _In_ ULONG version = SECBUFFER_VERSION)
{
ulVersion = version;
cBuffers = count;
pBuffers = buf;
}
virtual ~sec_buffer_desc()
{
for (ULONG i = 0; i < cBuffers; i++) {
if (pBuffers[i].pvBuffer)
FreeContextBuffer(pBuffers[i].pvBuffer);
}
}
};
class sec_runtime_error : public num_runtime_error<SECURITY_STATUS>
{
public:
sec_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<SECURITY_STATUS>(num, msg)
{
}
sec_runtime_error(_In_ error_type num, _In_opt_z_ const char *msg = nullptr) : num_runtime_error<SECURITY_STATUS>(num, msg)
{
}
sec_runtime_error(const sec_runtime_error &other) : num_runtime_error<SECURITY_STATUS>(other)
{
}
};
}
winstd::handle
Base abstract template class to support generic object handle keeping.
Definition: Common.h:604
winstd::handle< PCredHandle, NULL >::handle_type
PCredHandle handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:609
winstd::handle< PCredHandle, NULL >::m_h
handle_type m_h
Object handle.
Definition: Common.h:855
winstd::handle< PCredHandle, NULL >::attach
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:818
winstd::num_runtime_error
Numerical runtime error.
Definition: Common.h:1003
winstd::num_runtime_error< SECURITY_STATUS >::error_type
SECURITY_STATUS error_type
Error number type.
Definition: Common.h:1005
winstd::sec_buffer_desc
SecBufferDesc wrapper class.
Definition: Sec.h:326
winstd::sec_buffer_desc::~sec_buffer_desc
virtual ~sec_buffer_desc()
Frees the security buffer descriptor.
Definition: Sec.h:343
winstd::sec_buffer_desc::sec_buffer_desc
sec_buffer_desc(PSecBuffer buf, ULONG count, ULONG version=SECBUFFER_VERSION)
Initializes security buffer descriptor.
Definition: Sec.h:331
winstd::sec_context
PCtxtHandle wrapper class.
Definition: Sec.h:203
winstd::sec_context::sec_context
sec_context(sec_context &&h) noexcept
Move constructor.
Definition: Sec.h:220
winstd::sec_context::process
SECURITY_STATUS process(PCredHandle phCredential, LPCTSTR pszTargetName, ULONG fContextReq, ULONG TargetDataRep, PSecBufferDesc pInput, PSecBufferDesc pOutput)
Continue security context.
Definition: Sec.h:294
winstd::sec_context::~sec_context
virtual ~sec_context()
Frees the security context.
Definition: Sec.h:232
winstd::sec_context::sec_context
sec_context()
Initializes a new class instance with the object handle set to NULL.
Definition: Sec.h:208
winstd::sec_context::initialize
SECURITY_STATUS initialize(PCredHandle phCredential, LPCTSTR pszTargetName, ULONG fContextReq, ULONG TargetDataRep, PSecBufferDesc pInput, PSecBufferDesc pOutput)
Initializes security context.
Definition: Sec.h:262
winstd::sec_context::m_attrib
ULONG m_attrib
Context attributes.
Definition: Sec.h:318
winstd::sec_context::m_expires
TimeStamp m_expires
Context expiration time.
Definition: Sec.h:319
winstd::sec_context::operator=
sec_context & operator=(sec_context &&h) noexcept
Move assignment.
Definition: Sec.h:243
winstd::sec_context::free_internal
void free_internal() noexcept override
Frees the security context.
Definition: Sec.h:311
winstd::sec_credentials
PCredHandle wrapper class.
Definition: Sec.h:94
winstd::sec_credentials::sec_credentials
sec_credentials()
Initializes a new class instance with the object handle set to NULL.
Definition: Sec.h:101
winstd::sec_credentials::free_internal
void free_internal() noexcept override
Frees the security credentials.
Definition: Sec.h:189
winstd::sec_credentials::m_expires
TimeStamp m_expires
Credentials expiration time.
Definition: Sec.h:196
winstd::sec_credentials::sec_credentials
sec_credentials(sec_credentials &&h) noexcept
Move constructor.
Definition: Sec.h:123
winstd::sec_credentials::~sec_credentials
virtual ~sec_credentials()
Frees the security credentials.
Definition: Sec.h:134
winstd::sec_credentials::sec_credentials
sec_credentials(handle_type h, const TimeStamp expires)
Initializes a new class with an already available object handle.
Definition: Sec.h:112
winstd::sec_credentials::acquire
SECURITY_STATUS acquire(LPTSTR pszPrincipal, LPTSTR pszPackage, unsigned long fCredentialUse, void *pvLogonId, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn=NULL, void *pvGetKeyArgument=NULL)
Acquires the security credentials.
Definition: Sec.h:163
winstd::sec_credentials::operator=
sec_credentials & operator=(sec_credentials &&h) noexcept
Move assignment.
Definition: Sec.h:145
winstd::sec_runtime_error
Security runtime error.
Definition: Sec.h:363
winstd::sec_runtime_error::sec_runtime_error
sec_runtime_error(error_type num, const char *msg=nullptr)
Constructs an exception.
Definition: Sec.h:381
winstd::sec_runtime_error::sec_runtime_error
sec_runtime_error(const sec_runtime_error &other)
Copies an exception.
Definition: Sec.h:390
winstd::sec_runtime_error::sec_runtime_error
sec_runtime_error(error_type num, const std::string &msg)
Constructs an exception.
Definition: Sec.h:371
WINSTD_NONCOPYABLE
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:53
WINSTD_STACK_BUFFER_BYTES
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:80
winstd::handle< PCredHandle, NULL >::invalid
static const PCredHandle invalid
Invalid handle value.
Definition: Common.h:614