WinStd
Additional templates and function helpers for Microsoft Windows using Standard C++ classes
Sec.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
7#pragma once
8
9#include "Common.h"
10#include <Security.h>
11#include <string>
12
18
19#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL)
20
22template<class _Traits, class _Ax>
23static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName)
24{
25 assert(0); // TODO: Test this code.
26
27 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
28 ULONG ulSize = _countof(szStackBuffer);
29
30 // Try with stack buffer first.
31 if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
32 // Copy from stack.
33 sName.assign(szStackBuffer, ulSize);
34 return TRUE;
35 } else {
36 if (::GetLastError() == ERROR_MORE_DATA) {
37 // Allocate buffer on heap and retry.
38 std::unique_ptr<char[]> szBuffer(new char[ulSize]);
39 if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
40 sName.assign(szBuffer.get(), ulSize);
41 return TRUE;
42 }
43 }
44 }
45
46 return FALSE;
47}
48
54template<class _Traits, class _Ax>
55static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName)
56{
57 assert(0); // TODO: Test this code.
58
59 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
60 ULONG ulSize = _countof(szStackBuffer);
61
62 // Try with stack buffer first.
63 if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
64 // Copy from stack.
65 sName.assign(szStackBuffer, ulSize);
66 return TRUE;
67 } else {
68 if (::GetLastError() == ERROR_MORE_DATA) {
69 // Allocate buffer on heap and retry.
70 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]);
71 if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
72 sName.assign(szBuffer.get(), ulSize);
73 return TRUE;
74 }
75 }
76 }
77
78 return FALSE;
79}
80
81#endif
82
84
85namespace winstd
86{
89
93 class sec_credentials : public handle<PCredHandle, NULL>
94 {
96
97 public:
102 {
103 m_expires.QuadPart = -1;
104 }
105
112 sec_credentials(_In_opt_ handle_type h, _In_ const TimeStamp expires) :
113 m_expires(expires),
114 handle(h)
115 {
116 }
117
123 sec_credentials(_Inout_ sec_credentials &&h) noexcept :
124 m_expires(std::move(h.m_expires)),
125 handle<PCredHandle, NULL>(std::move(h))
126 {
127 }
128
135 {
136 if (m_h != invalid)
138 }
139
146 {
147 if (this != std::addressof(h)) {
148 *(handle<handle_type, NULL>*)this = std::move(h);
149 m_expires = std::move(h.m_expires);
150 }
151 return *this;
152 }
153
163 SECURITY_STATUS acquire(
164 _In_opt_ LPTSTR pszPrincipal,
165 _In_ LPTSTR pszPackage,
166 _In_ unsigned long fCredentialUse,
167 _In_opt_ void *pvLogonId,
168 _In_opt_ void *pAuthData,
169 _In_opt_ SEC_GET_KEY_FN pGetKeyFn = NULL,
170 _In_opt_ void *pvGetKeyArgument = NULL)
171 {
172 handle_type h = new CredHandle;
173 TimeStamp exp;
174 SECURITY_STATUS res = AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, pvLogonId, pAuthData, pGetKeyFn, pvGetKeyArgument, h, &exp);
175 if (SUCCEEDED(res)) {
176 attach(h);
177 m_expires = exp;
178 } else
179 delete h;
180 return res;
181 }
182
183 protected:
189 void free_internal() noexcept override
190 {
191 FreeCredentialsHandle(m_h);
192 delete m_h;
193 }
194
195 public:
196 TimeStamp m_expires;
197 };
198
202 class sec_context : public handle<PCtxtHandle, NULL>
203 {
204 public:
209 m_attrib(0),
210 handle<PCtxtHandle, NULL>()
211 {
212 m_expires.QuadPart = -1;
213 }
214
220 sec_context(_Inout_ sec_context &&h) noexcept :
221 m_attrib (std::move(h.m_attrib )),
222 m_expires(std::move(h.m_expires)),
223 handle<PCtxtHandle, NULL>(std::move(h))
224 {
225 }
226
232 virtual ~sec_context()
233 {
234 if (m_h != invalid)
236 }
237
243 sec_context& operator=(_Inout_ sec_context &&h) noexcept
244 {
245 if (this != std::addressof(h)) {
246 *(handle<handle_type, NULL>*)this = std::move(h);
247 m_attrib = std::move(h.m_attrib);
248 m_expires = std::move(h.m_expires);
249 }
250 return *this;
251 }
252
262 SECURITY_STATUS initialize(
263 _In_opt_ PCredHandle phCredential,
264 _In_opt_z_ LPCTSTR pszTargetName,
265 _In_ ULONG fContextReq,
266 _In_ ULONG TargetDataRep,
267 _In_opt_ PSecBufferDesc pInput,
268 _Inout_opt_ PSecBufferDesc pOutput)
269 {
270 handle_type h = new CtxtHandle;
271 h->dwUpper = 0;
272 h->dwLower = 0;
273 ULONG attr;
274 TimeStamp exp;
275 SECURITY_STATUS res = InitializeSecurityContext(phCredential, NULL, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, h, pOutput, &attr, &exp);
276 if (SUCCEEDED(res)) {
277 attach(h);
278 m_attrib = attr;
279 m_expires = exp;
280 } else
281 delete h;
282 return res;
283 }
284
294 SECURITY_STATUS process(
295 _In_opt_ PCredHandle phCredential,
296 _In_opt_z_ LPCTSTR pszTargetName,
297 _In_ ULONG fContextReq,
298 _In_ ULONG TargetDataRep,
299 _In_opt_ PSecBufferDesc pInput,
300 _Inout_opt_ PSecBufferDesc pOutput)
301 {
302 return InitializeSecurityContext(phCredential, m_h, const_cast<LPTSTR>(pszTargetName), fContextReq, 0, TargetDataRep, pInput, 0, NULL, pOutput, &m_attrib, &m_expires);
303 }
304
305 protected:
311 void free_internal() noexcept override
312 {
313 DeleteSecurityContext(m_h);
314 delete m_h;
315 }
316
317 public:
318 ULONG m_attrib;
319 TimeStamp m_expires;
320 };
321
325 class sec_buffer_desc : public SecBufferDesc
326 {
327 public:
331 sec_buffer_desc(_Inout_count_(count) PSecBuffer buf, ULONG count, _In_ ULONG version = SECBUFFER_VERSION)
332 {
333 ulVersion = version;
334 cBuffers = count;
335 pBuffers = buf;
336 }
337
344 {
345 for (ULONG i = 0; i < cBuffers; i++) {
346 if (pBuffers[i].pvBuffer)
347 FreeContextBuffer(pBuffers[i].pvBuffer);
348 }
349 }
350 };
351
353
356
362 class sec_runtime_error : public num_runtime_error<SECURITY_STATUS>
363 {
364 public:
371 sec_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<SECURITY_STATUS>(num, msg)
372 {
373 }
374
381 sec_runtime_error(_In_ error_type num, _In_opt_z_ const char *msg = nullptr) : num_runtime_error<SECURITY_STATUS>(num, msg)
382 {
383 }
384
390 sec_runtime_error(const sec_runtime_error &other) : num_runtime_error<SECURITY_STATUS>(other)
391 {
392 }
393 };
394
396}
Base abstract template class to support generic object handle keeping.
Definition: Common.h:604
PCredHandle handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:609
handle_type m_h
Object handle.
Definition: Common.h:855
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:818
Numerical runtime error.
Definition: Common.h:1003
SECURITY_STATUS error_type
Error number type.
Definition: Common.h:1005
SecBufferDesc wrapper class.
Definition: Sec.h:326
virtual ~sec_buffer_desc()
Frees the security buffer descriptor.
Definition: Sec.h:343
sec_buffer_desc(PSecBuffer buf, ULONG count, ULONG version=SECBUFFER_VERSION)
Initializes security buffer descriptor.
Definition: Sec.h:331
PCtxtHandle wrapper class.
Definition: Sec.h:203
sec_context(sec_context &&h) noexcept
Move constructor.
Definition: Sec.h:220
SECURITY_STATUS process(PCredHandle phCredential, LPCTSTR pszTargetName, ULONG fContextReq, ULONG TargetDataRep, PSecBufferDesc pInput, PSecBufferDesc pOutput)
Continue security context.
Definition: Sec.h:294
virtual ~sec_context()
Frees the security context.
Definition: Sec.h:232
sec_context()
Initializes a new class instance with the object handle set to NULL.
Definition: Sec.h:208
SECURITY_STATUS initialize(PCredHandle phCredential, LPCTSTR pszTargetName, ULONG fContextReq, ULONG TargetDataRep, PSecBufferDesc pInput, PSecBufferDesc pOutput)
Initializes security context.
Definition: Sec.h:262
ULONG m_attrib
Context attributes.
Definition: Sec.h:318
TimeStamp m_expires
Context expiration time.
Definition: Sec.h:319
sec_context & operator=(sec_context &&h) noexcept
Move assignment.
Definition: Sec.h:243
void free_internal() noexcept override
Frees the security context.
Definition: Sec.h:311
PCredHandle wrapper class.
Definition: Sec.h:94
sec_credentials()
Initializes a new class instance with the object handle set to NULL.
Definition: Sec.h:101
void free_internal() noexcept override
Frees the security credentials.
Definition: Sec.h:189
TimeStamp m_expires
Credentials expiration time.
Definition: Sec.h:196
sec_credentials(sec_credentials &&h) noexcept
Move constructor.
Definition: Sec.h:123
virtual ~sec_credentials()
Frees the security credentials.
Definition: Sec.h:134
sec_credentials(handle_type h, const TimeStamp expires)
Initializes a new class with an already available object handle.
Definition: Sec.h:112
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
sec_credentials & operator=(sec_credentials &&h) noexcept
Move assignment.
Definition: Sec.h:145
Security runtime error.
Definition: Sec.h:363
sec_runtime_error(error_type num, const char *msg=nullptr)
Constructs an exception.
Definition: Sec.h:381
sec_runtime_error(const sec_runtime_error &other)
Copies an exception.
Definition: Sec.h:390
sec_runtime_error(error_type num, const std::string &msg)
Constructs an exception.
Definition: Sec.h:371
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:53
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:80
static const PCredHandle invalid
Invalid handle value.
Definition: Common.h:614