ReactOS 0.4.15-dev-6056-gb29b268
security.c File Reference
#include <win32k.h>
Include dependency graph for security.c:

Go to the source code of this file.

Functions

 DBG_DEFAULT_CHANNEL (UserSecurity)
 
HANDLE IntGetCurrentAccessToken (VOID)
 Opens an access token that represents the effective security context of the caller. The purpose of this function is to query the authenticated user that is associated with the security context.
 
PVOID IntAllocateSecurityBuffer (_In_ SIZE_T Length)
 Allocates a buffer within UM (user mode) address space area. Such buffer is reserved for security purposes, such as allocating a buffer for a DACL or a security descriptor.
 
VOID IntFreeSecurityBuffer (_In_ PVOID Buffer)
 Frees an allocated security buffer from UM memory that is been previously allocated by IntAllocateSecurityBuffer function.
 
NTSTATUS IntQueryUserSecurityIdentification (_Out_ PTOKEN_USER *User)
 Queries the authenticated user security identifier (SID) that is associated with the security context of the access token that is being opened.
 
NTSTATUS NTAPI IntAssignDesktopSecurityOnParse (_In_ PWINSTATION_OBJECT WinSta, _In_ PDESKTOP Desktop, _In_ PACCESS_STATE AccessState)
 Assigns a security descriptor to the desktop object during a desktop object parse procedure.
 
NTSTATUS NTAPI IntCreateServiceSecurity (_Out_ PSECURITY_DESCRIPTOR *ServiceSd)
 Creates a security descriptor for the service.
 

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserSecurity  )

◆ IntAllocateSecurityBuffer()

PVOID IntAllocateSecurityBuffer ( _In_ SIZE_T  Length)

Allocates a buffer within UM (user mode) address space area. Such buffer is reserved for security purposes, such as allocating a buffer for a DACL or a security descriptor.

Parameters
[in]LengthThe length of the buffer that has to be allocated, in bytes.
Returns
Returns a pointer to an allocated buffer whose contents are arbitrary. If the function fails, it means no pages are available to reserve for memory allocation for this buffer.

Definition at line 97 of file security.c.

99{
101 PVOID Buffer = NULL;
102
103 /* Allocate the buffer in UM memory space */
104 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
105 &Buffer,
106 0,
107 &Length,
110 if (!NT_SUCCESS(Status))
111 {
112 ERR("IntAllocateSecurityBuffer(): Failed to allocate the buffer (Status 0x%08lx)\n", Status);
113 return NULL;
114 }
115
116 return Buffer;
117}
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: debug.h:110
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MEM_COMMIT
Definition: nt_native.h:1313
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define ZwCurrentProcess()

Referenced by IntCreateServiceSecurity(), and IntQueryUserSecurityIdentification().

◆ IntAssignDesktopSecurityOnParse()

NTSTATUS NTAPI IntAssignDesktopSecurityOnParse ( _In_ PWINSTATION_OBJECT  WinSta,
_In_ PDESKTOP  Desktop,
_In_ PACCESS_STATE  AccessState 
)

Assigns a security descriptor to the desktop object during a desktop object parse procedure.

Parameters
[in]WinStaA pointer to a window station object, of which such object contains its own security descriptor that will be captured.
[in]DesktopA pointer to a desktop object that is created during a parse procedure.
[in]AccessStateA pointer to an access state structure that describes the progress state of an access in action.
Returns
Returns STATUS_SUCCESS if the function has successfully assigned new security descriptor to the desktop object. A NTSTATUS failure code is returned otherwise.

Definition at line 264 of file security.c.

268{
270 PSECURITY_DESCRIPTOR CapturedDescriptor;
272
273 /*
274 * Capture the security descriptor from
275 * the window station. The window station
276 * in question has a descriptor that is
277 * inheritable and contains desktop access
278 * rights as well.
279 */
281 &CapturedDescriptor,
283 if (!NT_SUCCESS(Status))
284 {
285 ERR("IntAssignDesktopSecurityOnParse(): Failed to capture the security descriptor from window station (Status 0x%08lx)\n", Status);
286 return Status;
287 }
288
289 /* Assign new security to the desktop */
291 CapturedDescriptor,
292 Desktop,
294 if (!NT_SUCCESS(Status))
295 {
296 ERR("IntAssignDesktopSecurityOnParse(): Failed to assign security information to the desktop object (Status 0x%08lx)\n", Status);
297 }
298
299 /* Release the descriptor that we have captured */
300 ObReleaseObjectSecurity(CapturedDescriptor, MemoryAllocated);
301 return Status;
302}
unsigned char BOOLEAN
NTSTATUS NTAPI ObGetObjectSecurity(IN PVOID Object, OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, OUT PBOOLEAN MemoryAllocated)
Definition: obsecure.c:611
VOID NTAPI ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN MemoryAllocated)
Definition: obsecure.c:709
NTSTATUS NTAPI ObAssignSecurity(IN PACCESS_STATE AccessState, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PVOID Object, IN POBJECT_TYPE Type)
Definition: obsecure.c:550
POBJECT_TYPE ExDesktopObjectType
Definition: win32k.c:22
_Out_ PSECURITY_DESCRIPTOR _Out_ PBOOLEAN MemoryAllocated
Definition: obfuncs.h:24
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417

Referenced by IntDesktopObjectParse().

◆ IntCreateServiceSecurity()

NTSTATUS NTAPI IntCreateServiceSecurity ( _Out_ PSECURITY_DESCRIPTOR ServiceSd)

Creates a security descriptor for the service.

Parameters
[out]ServiceSdA pointer to a newly allocated and created security descriptor for the service.
Returns
Returns STATUS_SUCCESS if the function has successfully queried created the security descriptor. STATUS_NO_MEMORY is returned if memory allocation for security buffers because of a lack of needed pages to reserve for such allocation. A failure NTSTATUS code is returned otherwise.

Definition at line 321 of file security.c.

323{
325 PACL ServiceDacl;
327 ULONG RelSDSize;
331
332 /* Initialize our local variables */
333 RelSDSize = 0;
334 TokenUser = NULL;
335 RelSD = NULL;
336 ServiceDacl = NULL;
337
338 /* Query the logged in user of the current security context (aka token) */
340 if (!TokenUser)
341 {
342 ERR("IntCreateServiceSecurity(): Failed to query the token user (Status 0x%08lx)\n", Status);
343 return Status;
344 }
345
346 /* Initialize the absolute security descriptor */
348 if (!NT_SUCCESS(Status))
349 {
350 ERR("IntCreateServiceSecurity(): Failed to initialize absolute SD (Status 0x%08lx)\n", Status);
351 goto Quit;
352 }
353
354 /*
355 * Build up the size of access control
356 * list (the DACL) necessary to initialize
357 * our ACL. The first two entry members
358 * of ACL field are the authenticated user
359 * that is associated with the security
360 * context of the token. Then here come
361 * the last two entries which are admins.
362 * Why the ACL contains two ACEs of the
363 * same SID is because of service access
364 * rights and ACE inheritance.
365 *
366 * A service is composed of a default
367 * desktop and window station upon
368 * booting the system. On Windows connection
369 * to such service is being made if no
370 * default window station and desktop handles
371 * were created before. The desktop and winsta
372 * objects grant access on a separate type basis.
373 * The user is granted full access to the window
374 * station first and then full access to the desktop.
375 * After that admins are granted specific rights
376 * separately, just like the user. Ultimately the
377 * ACEs that handle desktop rights management are
378 * inherited to the default desktop object so
379 * that there's no need to have a separate security
380 * descriptor for the desktop object alone.
381 */
382 DaclSize = sizeof(ACL) +
383 sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(TokenUser->User.Sid) +
384 sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(TokenUser->User.Sid) +
387
388 /* Allocate memory for service DACL */
389 ServiceDacl = IntAllocateSecurityBuffer(DaclSize);
390 if (!ServiceDacl)
391 {
392 ERR("IntCreateServiceSecurity(): Failed to allocate memory for service DACL!\n");
394 goto Quit;
395 }
396
397 /* Now create the DACL */
398 Status = RtlCreateAcl(ServiceDacl,
399 DaclSize,
401 if (!NT_SUCCESS(Status))
402 {
403 ERR("IntCreateServiceSecurity(): Failed to create service DACL (Status 0x%08lx)\n", Status);
404 goto Quit;
405 }
406
407 /*
408 * The authenticated user is the ultimate and absolute
409 * king in charge of the created (or opened, whatever that is)
410 * window station object.
411 */
412 Status = RtlAddAccessAllowedAceEx(ServiceDacl,
414 0,
416 TokenUser->User.Sid);
417 if (!NT_SUCCESS(Status))
418 {
419 ERR("IntCreateServiceSecurity(): Failed to set up window station ACE for authenticated user (Status 0x%08lx)\n", Status);
420 goto Quit;
421 }
422
423 /*
424 * The authenticated user also has the ultimate power
425 * over the desktop object as well. This ACE cannot
426 * be propagated but inherited. See the comment
427 * above regarding ACL size for further explanation.
428 */
429 Status = RtlAddAccessAllowedAceEx(ServiceDacl,
433 TokenUser->User.Sid);
434 if (!NT_SUCCESS(Status))
435 {
436 ERR("IntCreateServiceSecurity(): Failed to set up desktop ACE for authenticated user (Status 0x%08lx)\n", Status);
437 goto Quit;
438 }
439
440 /*
441 * Administrators can only enumerate window
442 * stations within a desktop.
443 */
444 Status = RtlAddAccessAllowedAceEx(ServiceDacl,
446 0,
449 if (!NT_SUCCESS(Status))
450 {
451 ERR("IntCreateServiceSecurity(): Failed to set up window station ACE for admins (Status 0x%08lx)\n", Status);
452 goto Quit;
453 }
454
455 /*
456 * Administrators have some share of power over
457 * the desktop object. They can enumerate desktops,
458 * write and read upon the object itself.
459 */
460 Status = RtlAddAccessAllowedAceEx(ServiceDacl,
465 if (!NT_SUCCESS(Status))
466 {
467 ERR("IntCreateServiceSecurity(): Failed to set up desktop ACE for admins (Status 0x%08lx)\n", Status);
468 goto Quit;
469 }
470
471 /* Set the DACL to absolute SD */
473 TRUE,
474 ServiceDacl,
475 FALSE);
476 if (!NT_SUCCESS(Status))
477 {
478 ERR("IntCreateServiceSecurity(): Failed to set up service DACL to absolute SD (Status 0x%08lx)\n", Status);
479 goto Quit;
480 }
481
482 /* This descriptor is ownerless */
484 NULL,
485 FALSE);
486 if (!NT_SUCCESS(Status))
487 {
488 ERR("IntCreateServiceSecurity(): Failed to make the absolute SD as ownerless (Status 0x%08lx)\n", Status);
489 goto Quit;
490 }
491
492 /* This descriptor has no primary group */
494 NULL,
495 FALSE);
496 if (!NT_SUCCESS(Status))
497 {
498 ERR("IntCreateServiceSecurity(): Failed to make the absolute SD as having no primary group (Status 0x%08lx)\n", Status);
499 goto Quit;
500 }
501
502 /*
503 * Determine how much size is needed to allocate
504 * memory space for our relative security descriptor.
505 */
507 NULL,
508 &RelSDSize);
510 {
511 ERR("IntCreateServiceSecurity(): Unexpected status code, must be STATUS_BUFFER_TOO_SMALL (Status 0x%08lx)\n", Status);
512 goto Quit;
513 }
514
515 /* Allocate memory for this */
516 RelSD = IntAllocateSecurityBuffer(RelSDSize);
517 if (!RelSD)
518 {
519 ERR("IntCreateServiceSecurity(): Failed to allocate memory pool for relative SD!\n");
521 goto Quit;
522 }
523
524 /* Convert the absolute SD into a relative one now */
526 RelSD,
527 &RelSDSize);
528 if (!NT_SUCCESS(Status))
529 {
530 ERR("IntCreateServiceSecurity(): Failed to convert absolute SD to a relative one (Status 0x%08lx)\n", Status);
531 goto Quit;
532 }
533
534 /* All good, give the SD to the caller */
535 *ServiceSd = RelSD;
536
537Quit:
538 if (ServiceDacl)
539 {
540 IntFreeSecurityBuffer(ServiceDacl);
541 }
542
543 if (TokenUser)
544 {
546 }
547
548 if (!NT_SUCCESS(Status))
549 {
550 if (RelSD)
551 {
553 }
554 }
555
556 return Status;
557}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAceEx(PACL, DWORD, DWORD, DWORD, PSID)
NTSYSAPI NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR, PSID, BOOLEAN)
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:20
struct _ACL ACL
struct _ACCESS_ALLOWED_ACE ACCESS_ALLOWED_ACE
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG DaclSize
Definition: rtlfuncs.h:1594
NTSYSAPI NTSTATUS NTAPI RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group, IN BOOLEAN GroupDefaulted)
Definition: sd.c:410
NTSYSAPI NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN PULONG BufferLength)
Definition: sd.c:626
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
PSE_EXPORTS SeExports
Definition: semgr.c:21
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
PSID SeAliasAdminsSid
Definition: setypes.h:1225
uint32_t ULONG
Definition: typedefs.h:59
NTSTATUS IntQueryUserSecurityIdentification(_Out_ PTOKEN_USER *User)
Queries the authenticated user security identifier (SID) that is associated with the security context...
Definition: security.c:169
PVOID IntAllocateSecurityBuffer(_In_ SIZE_T Length)
Allocates a buffer within UM (user mode) address space area. Such buffer is reserved for security pur...
Definition: security.c:97
VOID IntFreeSecurityBuffer(_In_ PVOID Buffer)
Frees an allocated security buffer from UM memory that is been previously allocated by IntAllocateSec...
Definition: security.c:133
#define WINSTA_ACCESS_ALL
Definition: security.h:57
#define DESKTOP_ENUMERATE
Definition: winuser.h:218
#define DESKTOP_WRITEOBJECTS
Definition: winuser.h:224
#define WINSTA_ENUMERATE
Definition: winuser.h:412
#define DESKTOP_READOBJECTS
Definition: winuser.h:222
#define INHERIT_ONLY_ACE
Definition: setypes.h:749
#define OBJECT_INHERIT_ACE
Definition: setypes.h:746
@ TokenUser
Definition: setypes.h:962
#define NO_PROPAGATE_INHERIT_ACE
Definition: setypes.h:748
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
#define ACL_REVISION
Definition: setypes.h:39

Referenced by IntResolveDesktop().

◆ IntFreeSecurityBuffer()

VOID IntFreeSecurityBuffer ( _In_ PVOID  Buffer)

Frees an allocated security buffer from UM memory that is been previously allocated by IntAllocateSecurityBuffer function.

Parameters
[in]BufferA pointer to a buffer whose contents are arbitrary, to be freed from UM memory space.
Returns
Nothing.

Definition at line 133 of file security.c.

135{
136 SIZE_T Size = 0;
137
138 ZwFreeVirtualMemory(ZwCurrentProcess(),
139 &Buffer,
140 &Size,
142}
#define MEM_RELEASE
Definition: nt_native.h:1316
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by IntCreateServiceSecurity(), IntQueryUserSecurityIdentification(), and IntResolveDesktop().

◆ IntGetCurrentAccessToken()

HANDLE IntGetCurrentAccessToken ( VOID  )

Opens an access token that represents the effective security context of the caller. The purpose of this function is to query the authenticated user that is associated with the security context.

Returns
Returns a handle to an opened access token that represents the security context of the authenticated user, otherwise NULL.

Definition at line 27 of file security.c.

28{
31
32 /*
33 * Try acquiring the security context by opening
34 * the current thread (or so called impersonation)
35 * token. Such token represents the effective caller.
36 * Otherwise if the current thread does not have a
37 * token (hence no impersonation occurs) then open
38 * the token of main calling process instead.
39 */
42 FALSE,
44 if (!NT_SUCCESS(Status))
45 {
46 /*
47 * We might likely fail to open the thread
48 * token if the process isn't impersonating
49 * a client. In scenarios where the server
50 * isn't impersonating, open the main process
51 * token.
52 */
54 {
55 TRACE("IntGetCurrentAccessToken(): The thread doesn't have a token, trying to open the process one...\n");
59 if (!NT_SUCCESS(Status))
60 {
61 /* We failed opening process token as well, bail out... */
62 ERR("IntGetCurrentAccessToken(): Failed to capture security context, couldn't open the process token (Status 0x%08lx)\n", Status);
63 return NULL;
64 }
65
66 /* Return the opened token handle */
67 return TokenHandle;
68 }
69
70 /* There's a thread token but we couldn't open it so bail out */
71 ERR("IntGetCurrentAccessToken(): Failed to capture security context, couldn't open the thread token (Status 0x%08lx)\n", Status);
72 return NULL;
73 }
74
75 /* Return the opened token handle */
76 return TokenHandle;
77}
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:718
NTSYSAPI NTSTATUS NTAPI ZwOpenThreadToken(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _Out_ PHANDLE TokenHandle)
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
#define TRACE(s)
Definition: solgame.cpp:4
#define TOKEN_QUERY
Definition: setypes.h:924
#define ZwCurrentThread()
NTSYSAPI NTSTATUS NTAPI ZwOpenProcessToken(_In_ HANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE TokenHandle)

Referenced by IntQueryUserSecurityIdentification().

◆ IntQueryUserSecurityIdentification()

NTSTATUS IntQueryUserSecurityIdentification ( _Out_ PTOKEN_USER User)

Queries the authenticated user security identifier (SID) that is associated with the security context of the access token that is being opened.

Parameters
[out]UserA pointer to the token user that contains the security identifier of the authenticated user.
Returns
Returns STATUS_SUCCESS if the function has successfully queried the token user. STATUS_UNSUCCESSFUL is returned if the effective token of the caller couldn't be opened. STATUS_NO_MEMORY is returned if memory allocation for token user buffer has failed because of lack of necessary pages reserved for such allocation. A failure NTSTATUS code is returned otherwise.
Remarks
!!!WARNING!!! – THE CALLER WHO QUERIES THE TOKEN USER IS RESPONSIBLE TO FREE THE ALLOCATED TOKEN USER BUFFER THAT IS BEING GIVEN.

Definition at line 169 of file security.c.

171{
173 PTOKEN_USER UserToken;
176
177 /* Initialize the parameter */
178 *User = NULL;
179
180 /* Open the current token of the caller */
182 if (!Token)
183 {
184 ERR("IntQueryUserSecurityIdentification(): Couldn't capture the token!\n");
185 return STATUS_UNSUCCESSFUL;
186 }
187
188 /*
189 * Since we do not know what the length
190 * of the buffer size should be exactly to
191 * hold the user data, let the function
192 * tell us the size.
193 */
194 Status = ZwQueryInformationToken(Token,
195 TokenUser,
196 NULL,
197 0,
198 &BufferLength);
200 {
201 /*
202 * Allocate some memory for the buffer
203 * based on the size that the function
204 * gave us.
205 */
207 if (!UserToken)
208 {
209 /* Bail out if we failed */
210 ERR("IntQueryUserSecurityIdentification(): Couldn't allocate memory for the token user!\n");
211 ZwClose(Token);
212 return STATUS_NO_MEMORY;
213 }
214 }
215
216 /* Query the user now as we have plenty of space to hold it */
217 Status = ZwQueryInformationToken(Token,
218 TokenUser,
219 UserToken,
221 &BufferLength);
222 if (!NT_SUCCESS(Status))
223 {
224 /* We failed, bail out */
225 ERR("IntQueryUserSecurityIdentification(): Failed to query token user (Status 0x%08lx)\n", Status);
226 IntFreeSecurityBuffer(UserToken);
227 ZwClose(Token);
228 return Status;
229 }
230
231 /* All good, give the buffer to the caller and close the captured token */
232 *User = UserToken;
233 ZwClose(Token);
234
235 return STATUS_SUCCESS;
236}
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
HANDLE IntGetCurrentAccessToken(VOID)
Opens an access token that represents the effective security context of the caller....
Definition: security.c:27

Referenced by IntCreateServiceSecurity().