@@ -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 ( szS tackB uffer) ;
// Try with s tack b uffer 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 credentia ls.
/// - Error code when fai ls.
///
///
/// \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 SecB ufferD esc
/// Initializes security b uffer d escriptor.
{
///
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 )
{
/// @}
}
}
} ;
/// @}
}