2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/priv.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: No programmer listed.
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitPrivileges)
21 /* GLOBALS *******************************************************************/
23 LUID SeCreateTokenPrivilege
;
24 LUID SeAssignPrimaryTokenPrivilege
;
25 LUID SeLockMemoryPrivilege
;
26 LUID SeIncreaseQuotaPrivilege
;
27 LUID SeUnsolicitedInputPrivilege
;
29 LUID SeSecurityPrivilege
;
30 LUID SeTakeOwnershipPrivilege
;
31 LUID SeLoadDriverPrivilege
;
32 LUID SeCreatePagefilePrivilege
;
33 LUID SeIncreaseBasePriorityPrivilege
;
34 LUID SeSystemProfilePrivilege
;
35 LUID SeSystemtimePrivilege
;
36 LUID SeProfileSingleProcessPrivilege
;
37 LUID SeCreatePermanentPrivilege
;
38 LUID SeBackupPrivilege
;
39 LUID SeRestorePrivilege
;
40 LUID SeShutdownPrivilege
;
41 LUID SeDebugPrivilege
;
42 LUID SeAuditPrivilege
;
43 LUID SeSystemEnvironmentPrivilege
;
44 LUID SeChangeNotifyPrivilege
;
45 LUID SeRemoteShutdownPrivilege
;
46 LUID SeUndockPrivilege
;
47 LUID SeSyncAgentPrivilege
;
48 LUID SeEnableDelegationPrivilege
;
51 /* FUNCTIONS ***************************************************************/
56 SepInitPrivileges (VOID
)
58 SeCreateTokenPrivilege
.LowPart
= SE_CREATE_TOKEN_PRIVILEGE
;
59 SeCreateTokenPrivilege
.HighPart
= 0;
60 SeAssignPrimaryTokenPrivilege
.LowPart
= SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
;
61 SeAssignPrimaryTokenPrivilege
.HighPart
= 0;
62 SeLockMemoryPrivilege
.LowPart
= SE_LOCK_MEMORY_PRIVILEGE
;
63 SeLockMemoryPrivilege
.HighPart
= 0;
64 SeIncreaseQuotaPrivilege
.LowPart
= SE_INCREASE_QUOTA_PRIVILEGE
;
65 SeIncreaseQuotaPrivilege
.HighPart
= 0;
66 SeUnsolicitedInputPrivilege
.LowPart
= SE_UNSOLICITED_INPUT_PRIVILEGE
;
67 SeUnsolicitedInputPrivilege
.HighPart
= 0;
68 SeTcbPrivilege
.LowPart
= SE_TCB_PRIVILEGE
;
69 SeTcbPrivilege
.HighPart
= 0;
70 SeSecurityPrivilege
.LowPart
= SE_SECURITY_PRIVILEGE
;
71 SeSecurityPrivilege
.HighPart
= 0;
72 SeTakeOwnershipPrivilege
.LowPart
= SE_TAKE_OWNERSHIP_PRIVILEGE
;
73 SeTakeOwnershipPrivilege
.HighPart
= 0;
74 SeLoadDriverPrivilege
.LowPart
= SE_LOAD_DRIVER_PRIVILEGE
;
75 SeLoadDriverPrivilege
.HighPart
= 0;
76 SeSystemProfilePrivilege
.LowPart
= SE_SYSTEM_PROFILE_PRIVILEGE
;
77 SeSystemProfilePrivilege
.HighPart
= 0;
78 SeSystemtimePrivilege
.LowPart
= SE_SYSTEMTIME_PRIVILEGE
;
79 SeSystemtimePrivilege
.HighPart
= 0;
80 SeProfileSingleProcessPrivilege
.LowPart
= SE_PROF_SINGLE_PROCESS_PRIVILEGE
;
81 SeProfileSingleProcessPrivilege
.HighPart
= 0;
82 SeIncreaseBasePriorityPrivilege
.LowPart
= SE_INC_BASE_PRIORITY_PRIVILEGE
;
83 SeIncreaseBasePriorityPrivilege
.HighPart
= 0;
84 SeCreatePagefilePrivilege
.LowPart
= SE_CREATE_PAGEFILE_PRIVILEGE
;
85 SeCreatePagefilePrivilege
.HighPart
= 0;
86 SeCreatePermanentPrivilege
.LowPart
= SE_CREATE_PERMANENT_PRIVILEGE
;
87 SeCreatePermanentPrivilege
.HighPart
= 0;
88 SeBackupPrivilege
.LowPart
= SE_BACKUP_PRIVILEGE
;
89 SeBackupPrivilege
.HighPart
= 0;
90 SeRestorePrivilege
.LowPart
= SE_RESTORE_PRIVILEGE
;
91 SeRestorePrivilege
.HighPart
= 0;
92 SeShutdownPrivilege
.LowPart
= SE_SHUTDOWN_PRIVILEGE
;
93 SeShutdownPrivilege
.HighPart
= 0;
94 SeDebugPrivilege
.LowPart
= SE_DEBUG_PRIVILEGE
;
95 SeDebugPrivilege
.HighPart
= 0;
96 SeAuditPrivilege
.LowPart
= SE_AUDIT_PRIVILEGE
;
97 SeAuditPrivilege
.HighPart
= 0;
98 SeSystemEnvironmentPrivilege
.LowPart
= SE_SYSTEM_ENVIRONMENT_PRIVILEGE
;
99 SeSystemEnvironmentPrivilege
.HighPart
= 0;
100 SeChangeNotifyPrivilege
.LowPart
= SE_CHANGE_NOTIFY_PRIVILEGE
;
101 SeChangeNotifyPrivilege
.HighPart
= 0;
102 SeRemoteShutdownPrivilege
.LowPart
= SE_REMOTE_SHUTDOWN_PRIVILEGE
;
103 SeRemoteShutdownPrivilege
.HighPart
= 0;
104 SeUndockPrivilege
.LowPart
= SE_UNDOCK_PRIVILEGE
;
105 SeUndockPrivilege
.HighPart
= 0;
106 SeSyncAgentPrivilege
.LowPart
= SE_SYNC_AGENT_PRIVILEGE
;
107 SeSyncAgentPrivilege
.HighPart
= 0;
108 SeEnableDelegationPrivilege
.LowPart
= SE_ENABLE_DELEGATION_PRIVILEGE
;
109 SeEnableDelegationPrivilege
.HighPart
= 0;
115 SepPrivilegeCheck (PTOKEN Token
,
116 PLUID_AND_ATTRIBUTES Privileges
,
117 ULONG PrivilegeCount
,
118 ULONG PrivilegeControl
,
119 KPROCESSOR_MODE PreviousMode
)
125 DPRINT ("SepPrivilegeCheck() called\n");
129 if (PreviousMode
== KernelMode
)
135 if (PrivilegeCount
> 0)
137 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
139 for (j
= 0; j
< PrivilegeCount
; j
++)
141 if (Token
->Privileges
[i
].Luid
.LowPart
== Privileges
[j
].Luid
.LowPart
&&
142 Token
->Privileges
[i
].Luid
.HighPart
== Privileges
[j
].Luid
.HighPart
)
144 DPRINT ("Found privilege\n");
145 DPRINT ("Privilege attributes %lx\n",
146 Token
->Privileges
[i
].Attributes
);
148 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
150 Privileges
[j
].Attributes
|= SE_PRIVILEGE_USED_FOR_ACCESS
;
158 if ((PrivilegeControl
& PRIVILEGE_SET_ALL_NECESSARY
) &&
165 !(PrivilegeControl
& PRIVILEGE_SET_ALL_NECESSARY
))
176 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src
,
177 ULONG PrivilegeCount
,
178 KPROCESSOR_MODE PreviousMode
,
179 PLUID_AND_ATTRIBUTES AllocatedMem
,
180 ULONG AllocatedLength
,
182 BOOLEAN CaptureIfKernel
,
183 PLUID_AND_ATTRIBUTES
* Dest
,
187 NTSTATUS Status
= STATUS_SUCCESS
;
191 if (PrivilegeCount
== 0)
195 return STATUS_SUCCESS
;
198 if (PreviousMode
== KernelMode
&& !CaptureIfKernel
)
201 return STATUS_SUCCESS
;
204 /* FIXME - check PrivilegeCount for a valid number so we don't
205 cause an integer overflow or exhaust system resources! */
207 BufferSize
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
208 *Length
= ROUND_UP(BufferSize
, 4); /* round up to a 4 byte alignment */
210 /* probe the buffer */
211 if (PreviousMode
!= KernelMode
)
221 Status
= _SEH_GetExceptionCode();
225 if (!NT_SUCCESS(Status
))
231 /* allocate enough memory or check if the provided buffer is
232 large enough to hold the array */
233 if (AllocatedMem
!= NULL
)
235 if (AllocatedLength
< BufferSize
)
237 return STATUS_BUFFER_TOO_SMALL
;
240 *Dest
= AllocatedMem
;
244 *Dest
= ExAllocatePool(PoolType
,
249 return STATUS_INSUFFICIENT_RESOURCES
;
253 /* copy the array to the buffer */
262 Status
= _SEH_GetExceptionCode();
266 if (!NT_SUCCESS(Status
) && AllocatedMem
== NULL
)
277 SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege
,
278 KPROCESSOR_MODE PreviousMode
,
279 BOOLEAN CaptureIfKernel
)
283 if (Privilege
!= NULL
&&
284 (PreviousMode
!= KernelMode
|| CaptureIfKernel
))
286 ExFreePool(Privilege
);
292 NtPrivilegeCheck (IN HANDLE ClientToken
,
293 IN PPRIVILEGE_SET RequiredPrivileges
,
296 PLUID_AND_ATTRIBUTES Privileges
;
298 ULONG PrivilegeCount
= 0;
299 ULONG PrivilegeControl
= 0;
302 KPROCESSOR_MODE PreviousMode
;
303 NTSTATUS Status
= STATUS_SUCCESS
;
307 PreviousMode
= KeGetPreviousMode();
309 /* probe the buffers */
310 if (PreviousMode
!= KernelMode
)
314 ProbeForWrite(RequiredPrivileges
,
315 FIELD_OFFSET(PRIVILEGE_SET
,
319 PrivilegeCount
= RequiredPrivileges
->PrivilegeCount
;
320 PrivilegeControl
= RequiredPrivileges
->Control
;
322 /* Check PrivilegeCount to avoid an integer overflow! */
323 if (FIELD_OFFSET(PRIVILEGE_SET
,
324 Privilege
[PrivilegeCount
]) /
325 sizeof(RequiredPrivileges
->Privilege
[0]) != PrivilegeCount
)
327 Status
= STATUS_INVALID_PARAMETER
;
331 /* probe all of the array */
332 ProbeForWrite(RequiredPrivileges
,
333 FIELD_OFFSET(PRIVILEGE_SET
,
334 Privilege
[PrivilegeCount
]),
337 ProbeForWriteBoolean(Result
);
341 Status
= _SEH_GetExceptionCode();
345 if (!NT_SUCCESS(Status
))
352 PrivilegeCount
= RequiredPrivileges
->PrivilegeCount
;
353 PrivilegeControl
= RequiredPrivileges
->Control
;
356 /* reference the token and make sure we're
357 not doing an anonymous impersonation */
358 Status
= ObReferenceObjectByHandle (ClientToken
,
364 if (!NT_SUCCESS(Status
))
369 if (Token
->TokenType
== TokenImpersonation
&&
370 Token
->ImpersonationLevel
< SecurityIdentification
)
372 ObDereferenceObject (Token
);
373 return STATUS_BAD_IMPERSONATION_LEVEL
;
376 /* capture the privileges */
377 Status
= SeCaptureLuidAndAttributesArray (RequiredPrivileges
->Privilege
,
386 if (!NT_SUCCESS(Status
))
388 ObDereferenceObject (Token
);
392 CheckResult
= SepPrivilegeCheck (Token
,
398 ObDereferenceObject (Token
);
400 /* return the array */
403 RtlCopyMemory(RequiredPrivileges
->Privilege
,
405 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
406 *Result
= CheckResult
;
407 Status
= STATUS_SUCCESS
;
411 Status
= _SEH_GetExceptionCode();
415 SeReleaseLuidAndAttributesArray (Privileges
,
427 SePrivilegeCheck (PPRIVILEGE_SET Privileges
,
428 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
429 KPROCESSOR_MODE PreviousMode
)
431 PACCESS_TOKEN Token
= NULL
;
435 if (SubjectContext
->ClientToken
== NULL
)
437 Token
= SubjectContext
->PrimaryToken
;
441 Token
= SubjectContext
->ClientToken
;
442 if (SubjectContext
->ImpersonationLevel
< 2)
448 return SepPrivilegeCheck (Token
,
449 Privileges
->Privilege
,
450 Privileges
->PrivilegeCount
,
460 SeSinglePrivilegeCheck (IN LUID PrivilegeValue
,
461 IN KPROCESSOR_MODE PreviousMode
)
463 SECURITY_SUBJECT_CONTEXT SubjectContext
;
469 SeCaptureSubjectContext (&SubjectContext
);
471 Priv
.PrivilegeCount
= 1;
472 Priv
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
473 Priv
.Privilege
[0].Luid
= PrivilegeValue
;
474 Priv
.Privilege
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
476 Result
= SePrivilegeCheck (&Priv
,
480 if (PreviousMode
!= KernelMode
)
483 SePrivilegedServiceAuditAlarm (0,
489 SeReleaseSubjectContext (&SubjectContext
);