Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2023-10-01 22:47:28 +02:00
parent 40003c4054
commit ca4e9d069f
3 changed files with 393 additions and 397 deletions

View File

@ -1,4 +1,4 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 1991-2023 Amebis Copyright © 1991-2023 Amebis
Copyright © 2016 GÉANT Copyright © 2016 GÉANT

View File

@ -1056,7 +1056,7 @@ namespace winstd
} }
/// ///
/// Returns the Windows error number /// Returns the error number
/// ///
error_type number() const error_type number() const
{ {

View File

@ -1,395 +1,391 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 1991-2023 Amebis Copyright © 1991-2023 Amebis
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// \defgroup WinStdSecurityAPI Security API /// \defgroup WinStdSecurityAPI Security API
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include <Security.h> #include <Security.h>
#include <string> #include <string>
/// \addtogroup WinStdSecurityAPI /// \addtogroup WinStdSecurityAPI
/// @{ /// @{
#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL) #if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL)
/// @copydoc GetUserNameExW() /// @copydoc GetUserNameExW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName) static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
ULONG ulSize = _countof(szStackBuffer); ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first. // Try with stack buffer first.
if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) { if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack. // Copy from stack.
sName.assign(szStackBuffer, ulSize); sName.assign(szStackBuffer, ulSize);
return TRUE; return TRUE;
} else { }
if (::GetLastError() == ERROR_MORE_DATA) { if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry. // Allocate buffer on heap and retry.
std::unique_ptr<char[]> szBuffer(new char[ulSize]); std::unique_ptr<char[]> szBuffer(new char[ulSize]);
if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) { if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize); sName.assign(szBuffer.get(), ulSize);
return TRUE; return TRUE;
} }
} }
} return FALSE;
}
return FALSE;
} ///
/// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::wstring string.
/// ///
/// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::wstring string. /// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx)
/// ///
/// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx) template<class _Traits, class _Ax>
/// static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName)
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.
{
assert(0); // TODO: Test this code. wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
ULONG ulSize = _countof(szStackBuffer);
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
ULONG ulSize = _countof(szStackBuffer); // Try with stack buffer first.
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
// Try with stack buffer first. // Copy from stack.
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) { sName.assign(szStackBuffer, ulSize);
// Copy from stack. return TRUE;
sName.assign(szStackBuffer, ulSize); }
return TRUE; if (::GetLastError() == ERROR_MORE_DATA) {
} else { // Allocate buffer on heap and retry.
if (::GetLastError() == ERROR_MORE_DATA) { std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]);
// Allocate buffer on heap and retry. if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]); sName.assign(szBuffer.get(), ulSize);
if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) { return TRUE;
sName.assign(szBuffer.get(), ulSize); }
return TRUE; }
} return FALSE;
} }
}
#endif
return FALSE;
} /// @}
#endif namespace winstd
{
/// @} /// \addtogroup WinStdSecurityAPI
/// @{
namespace winstd
{ ///
/// \addtogroup WinStdSecurityAPI /// PCredHandle wrapper class
/// @{ ///
class sec_credentials : public handle<PCredHandle, NULL>
/// {
/// PCredHandle wrapper class WINSTD_NONCOPYABLE(sec_credentials)
///
class sec_credentials : public handle<PCredHandle, NULL> public:
{ ///
WINSTD_NONCOPYABLE(sec_credentials) /// Initializes a new class instance with the object handle set to NULL.
///
public: sec_credentials()
/// {
/// Initializes a new class instance with the object handle set to NULL. m_expires.QuadPart = -1;
/// }
sec_credentials()
{ ///
m_expires.QuadPart = -1; /// Initializes a new class with an already available object handle.
} ///
/// \param[in] h Initial class handle value
/// /// \param[in] expires Credentials expiration
/// Initializes a new class with an already available object handle. ///
/// sec_credentials(_In_opt_ handle_type h, _In_ const TimeStamp expires) :
/// \param[in] h Initial class handle value m_expires(expires),
/// \param[in] expires Credentials expiration handle(h)
/// {
sec_credentials(_In_opt_ handle_type h, _In_ const TimeStamp expires) : }
m_expires(expires),
handle(h) ///
{ /// Move constructor
} ///
/// \param[inout] h A rvalue reference of another object
/// ///
/// Move constructor sec_credentials(_Inout_ sec_credentials &&h) noexcept :
/// m_expires(std::move(h.m_expires)),
/// \param[inout] h A rvalue reference of another object handle<PCredHandle, NULL>(std::move(h))
/// {
sec_credentials(_Inout_ sec_credentials &&h) noexcept : }
m_expires(std::move(h.m_expires)),
handle<PCredHandle, NULL>(std::move(h)) ///
{ /// Frees the security credentials.
} ///
/// \sa [FreeCredentialsHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375417.aspx)
/// ///
/// Frees the security credentials. virtual ~sec_credentials()
/// {
/// \sa [FreeCredentialsHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375417.aspx) if (m_h != invalid)
/// free_internal();
virtual ~sec_credentials() }
{
if (m_h != invalid) ///
free_internal(); /// Move assignment
} ///
/// \param[inout] h A rvalue reference of another object
/// ///
/// Move assignment sec_credentials& operator=(_Inout_ sec_credentials &&h) noexcept
/// {
/// \param[inout] h A rvalue reference of another object if (this != std::addressof(h)) {
/// *(handle<handle_type, NULL>*)this = std::move(h);
sec_credentials& operator=(_Inout_ sec_credentials &&h) noexcept m_expires = std::move(h.m_expires);
{ }
if (this != std::addressof(h)) { return *this;
*(handle<handle_type, NULL>*)this = std::move(h); }
m_expires = std::move(h.m_expires);
} ///
return *this; /// Acquires the security credentials.
} ///
/// \return
/// /// - \c SEC_E_OK when succeeds;
/// Acquires the security credentials. /// - Error code when fails.
/// ///
/// \return /// \sa [AcquireCredentialsHandle (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374712.aspx)
/// - \c SEC_E_OK when succeeds; ///
/// - Error code when fails. SECURITY_STATUS acquire(
/// _In_opt_ LPTSTR pszPrincipal,
/// \sa [AcquireCredentialsHandle (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374712.aspx) _In_ LPTSTR pszPackage,
/// _In_ unsigned long fCredentialUse,
SECURITY_STATUS acquire( _In_opt_ void *pvLogonId,
_In_opt_ LPTSTR pszPrincipal, _In_opt_ void *pAuthData,
_In_ LPTSTR pszPackage, _In_opt_ SEC_GET_KEY_FN pGetKeyFn = NULL,
_In_ unsigned long fCredentialUse, _In_opt_ void *pvGetKeyArgument = NULL)
_In_opt_ void *pvLogonId, {
_In_opt_ void *pAuthData, handle_type h = new CredHandle;
_In_opt_ SEC_GET_KEY_FN pGetKeyFn = NULL, TimeStamp exp;
_In_opt_ void *pvGetKeyArgument = NULL) SECURITY_STATUS res = AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, h, &exp);
{ if (SUCCEEDED(res)) {
handle_type h = new CredHandle; attach(h);
TimeStamp exp; m_expires = exp;
SECURITY_STATUS res = AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, h, &exp); } else
if (SUCCEEDED(res)) { delete h;
attach(h); return res;
m_expires = exp; }
} else
delete h; protected:
return res; ///
} /// Frees the security credentials.
///
protected: /// \sa [FreeCredentialsHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375417.aspx)
/// ///
/// Frees the security credentials. void free_internal() noexcept override
/// {
/// \sa [FreeCredentialsHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375417.aspx) FreeCredentialsHandle(m_h);
/// delete m_h;
void free_internal() noexcept override }
{
FreeCredentialsHandle(m_h); public:
delete m_h; TimeStamp m_expires; ///< Credentials expiration time
} };
public: ///
TimeStamp m_expires; ///< Credentials expiration time /// PCtxtHandle wrapper class
}; ///
class sec_context : public handle<PCtxtHandle, NULL>
/// {
/// PCtxtHandle wrapper class public:
/// ///
class sec_context : public handle<PCtxtHandle, NULL> /// Initializes a new class instance with the object handle set to NULL.
{ ///
public: sec_context() :
/// m_attrib(0),
/// Initializes a new class instance with the object handle set to NULL. handle<PCtxtHandle, NULL>()
/// {
sec_context() : m_expires.QuadPart = -1;
m_attrib(0), }
handle<PCtxtHandle, NULL>()
{ ///
m_expires.QuadPart = -1; /// Move constructor
} ///
/// \param[inout] h A rvalue reference of another object
/// ///
/// Move constructor sec_context(_Inout_ sec_context &&h) noexcept :
/// m_attrib (std::move(h.m_attrib )),
/// \param[inout] h A rvalue reference of another object m_expires(std::move(h.m_expires)),
/// handle<PCtxtHandle, NULL>(std::move(h))
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)) ///
{ /// Frees the security context.
} ///
/// \sa [DeleteSecurityContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375354.aspx)
/// ///
/// Frees the security context. virtual ~sec_context()
/// {
/// \sa [DeleteSecurityContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375354.aspx) if (m_h != invalid)
/// free_internal();
virtual ~sec_context() }
{
if (m_h != invalid) ///
free_internal(); /// Move assignment
} ///
/// \param[inout] h A rvalue reference of another object
/// ///
/// Move assignment sec_context& operator=(_Inout_ sec_context &&h) noexcept
/// {
/// \param[inout] h A rvalue reference of another object if (this != std::addressof(h)) {
/// *(handle<handle_type, NULL>*)this = std::move(h);
sec_context& operator=(_Inout_ sec_context &&h) noexcept m_attrib = std::move(h.m_attrib);
{ m_expires = std::move(h.m_expires);
if (this != std::addressof(h)) { }
*(handle<handle_type, NULL>*)this = std::move(h); return *this;
m_attrib = std::move(h.m_attrib); }
m_expires = std::move(h.m_expires);
} ///
return *this; /// Initializes security context.
} ///
/// \return
/// /// - \c SEC_E_OK when succeeds;
/// Initializes security context. /// - Error code when fails.
/// ///
/// \return /// \sa [InitializeSecurityContext (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375506.aspx)
/// - \c SEC_E_OK when succeeds; ///
/// - Error code when fails. SECURITY_STATUS initialize(
/// _In_opt_ PCredHandle phCredential,
/// \sa [InitializeSecurityContext (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375506.aspx) _In_opt_z_ LPCTSTR pszTargetName,
/// _In_ ULONG fContextReq,
SECURITY_STATUS initialize( _In_ ULONG TargetDataRep,
_In_opt_ PCredHandle phCredential, _In_opt_ PSecBufferDesc pInput,
_In_opt_z_ LPCTSTR pszTargetName, _Inout_opt_ PSecBufferDesc pOutput)
_In_ ULONG fContextReq, {
_In_ ULONG TargetDataRep, handle_type h = new CtxtHandle;
_In_opt_ PSecBufferDesc pInput, h->dwUpper = 0;
_Inout_opt_ PSecBufferDesc pOutput) h->dwLower = 0;
{ ULONG attr;
handle_type h = new CtxtHandle; TimeStamp exp;
h->dwUpper = 0; SECURITY_STATUS res = InitializeSecurityContext(phCredential, NULL, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, h, pOutput, &attr, &exp);
h->dwLower = 0; if (SUCCEEDED(res)) {
ULONG attr; attach(h);
TimeStamp exp; m_attrib = attr;
SECURITY_STATUS res = InitializeSecurityContext(phCredential, NULL, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, h, pOutput, &attr, &exp); m_expires = exp;
if (SUCCEEDED(res)) { } else
attach(h); delete h;
m_attrib = attr; return res;
m_expires = exp; }
} else
delete h; ///
return res; /// Continue security context.
} ///
/// \return
/// /// - \c SEC_E_OK when succeeds;
/// Continue security context. /// - Error code when fails.
/// ///
/// \return /// \sa [InitializeSecurityContext (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375506.aspx)
/// - \c SEC_E_OK when succeeds; ///
/// - Error code when fails. SECURITY_STATUS process(
/// _In_opt_ PCredHandle phCredential,
/// \sa [InitializeSecurityContext (General) function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375506.aspx) _In_opt_z_ LPCTSTR pszTargetName,
/// _In_ ULONG fContextReq,
SECURITY_STATUS process( _In_ ULONG TargetDataRep,
_In_opt_ PCredHandle phCredential, _In_opt_ PSecBufferDesc pInput,
_In_opt_z_ LPCTSTR pszTargetName, _Inout_opt_ PSecBufferDesc pOutput)
_In_ ULONG fContextReq, {
_In_ ULONG TargetDataRep, return InitializeSecurityContext(phCredential, m_h, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, NULL, pOutput, &m_attrib, &m_expires);
_In_opt_ PSecBufferDesc pInput, }
_Inout_opt_ PSecBufferDesc pOutput)
{ protected:
return InitializeSecurityContext(phCredential, m_h, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, NULL, pOutput, &m_attrib, &m_expires); ///
} /// Frees the security context.
///
protected: /// \sa [DeleteSecurityContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375354.aspx)
/// ///
/// Frees the security context. void free_internal() noexcept override
/// {
/// \sa [DeleteSecurityContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375354.aspx) DeleteSecurityContext(m_h);
/// delete m_h;
void free_internal() noexcept override }
{
DeleteSecurityContext(m_h); public:
delete m_h; ULONG m_attrib; ///< Context attributes
} TimeStamp m_expires; ///< Context expiration time
};
public:
ULONG m_attrib; ///< Context attributes ///
TimeStamp m_expires; ///< Context expiration time /// SecBufferDesc wrapper class
}; ///
class sec_buffer_desc : public SecBufferDesc
/// {
/// SecBufferDesc wrapper class public:
/// ///
class sec_buffer_desc : public SecBufferDesc /// Initializes security buffer descriptor.
{ ///
public: sec_buffer_desc(_Inout_count_(count) PSecBuffer buf, ULONG count, _In_ ULONG version = SECBUFFER_VERSION)
/// {
/// Initializes security buffer descriptor. ulVersion = version;
/// cBuffers = count;
sec_buffer_desc(_Inout_count_(count) PSecBuffer buf, ULONG count, _In_ ULONG version = SECBUFFER_VERSION) pBuffers = buf;
{ }
ulVersion = version;
cBuffers = count; ///
pBuffers = buf; /// Frees the security buffer descriptor.
} ///
/// \sa [FreeContextBuffer function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375416.aspx)
/// ///
/// Frees the security buffer descriptor. virtual ~sec_buffer_desc()
/// {
/// \sa [FreeContextBuffer function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375416.aspx) for (ULONG i = 0; i < cBuffers; i++) {
/// if (pBuffers[i].pvBuffer)
virtual ~sec_buffer_desc() FreeContextBuffer(pBuffers[i].pvBuffer);
{ }
for (ULONG i = 0; i < cBuffers; i++) { }
if (pBuffers[i].pvBuffer) };
FreeContextBuffer(pBuffers[i].pvBuffer);
} /// @}
}
}; /// \addtogroup WinStdExceptions
/// @{
/// @}
///
/// \addtogroup WinStdExceptions /// Security runtime error
/// @{ ///
/// \note Must be defined as derived class from num_runtime_error<> to allow correct type info for dynamic typecasting and prevent folding with other derivates of num_runtime_error<>.
/// ///
/// Security runtime error class sec_runtime_error : public num_runtime_error<SECURITY_STATUS>
/// {
/// \note Must be defined as derived class from num_runtime_error<> to allow correct type info for dynamic typecasting and prevent folding with other derivates of num_runtime_error<>. public:
/// ///
class sec_runtime_error : public num_runtime_error<SECURITY_STATUS> /// Constructs an exception
{ ///
public: /// \param[in] num Security provider error code
/// /// \param[in] msg Error message
/// Constructs an exception ///
/// sec_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<SECURITY_STATUS>(num, msg)
/// \param[in] num Security provider error code {
/// \param[in] msg Error message }
///
sec_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<SECURITY_STATUS>(num, msg) ///
{ /// Constructs an exception
} ///
/// \param[in] num Security provider error code
/// /// \param[in] msg Error message
/// Constructs an exception ///
/// sec_runtime_error(_In_ error_type num, _In_opt_z_ const char *msg = nullptr) : num_runtime_error<SECURITY_STATUS>(num, msg)
/// \param[in] num Security provider error code {
/// \param[in] msg Error message }
///
sec_runtime_error(_In_ error_type num, _In_opt_z_ const char *msg = nullptr) : num_runtime_error<SECURITY_STATUS>(num, msg) ///
{ /// Copies an exception
} ///
/// \param[in] other Exception to copy from
/// ///
/// Copies an exception sec_runtime_error(const sec_runtime_error &other) : num_runtime_error<SECURITY_STATUS>(other)
/// {
/// \param[in] other Exception to copy from }
/// };
sec_runtime_error(const sec_runtime_error &other) : num_runtime_error<SECURITY_STATUS>(other)
{ /// @}
} }
};
/// @}
}