3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/priv.c
6 * PURPOSE: Security manager
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, SepInitPrivileges)
22 /* GLOBALS *******************************************************************/
24 LUID SeCreateTokenPrivilege
;
25 LUID SeAssignPrimaryTokenPrivilege
;
26 LUID SeLockMemoryPrivilege
;
27 LUID SeIncreaseQuotaPrivilege
;
28 LUID SeUnsolicitedInputPrivilege
;
30 LUID SeSecurityPrivilege
;
31 LUID SeTakeOwnershipPrivilege
;
32 LUID SeLoadDriverPrivilege
;
33 LUID SeCreatePagefilePrivilege
;
34 LUID SeIncreaseBasePriorityPrivilege
;
35 LUID SeSystemProfilePrivilege
;
36 LUID SeSystemtimePrivilege
;
37 LUID SeProfileSingleProcessPrivilege
;
38 LUID SeCreatePermanentPrivilege
;
39 LUID SeBackupPrivilege
;
40 LUID SeRestorePrivilege
;
41 LUID SeShutdownPrivilege
;
42 LUID SeDebugPrivilege
;
43 LUID SeAuditPrivilege
;
44 LUID SeSystemEnvironmentPrivilege
;
45 LUID SeChangeNotifyPrivilege
;
46 LUID SeRemoteShutdownPrivilege
;
47 LUID SeUndockPrivilege
;
48 LUID SeSyncAgentPrivilege
;
49 LUID SeEnableDelegationPrivilege
;
52 /* FUNCTIONS ***************************************************************/
57 SepInitPrivileges (VOID
)
59 SeCreateTokenPrivilege
.LowPart
= SE_CREATE_TOKEN_PRIVILEGE
;
60 SeCreateTokenPrivilege
.HighPart
= 0;
61 SeAssignPrimaryTokenPrivilege
.LowPart
= SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
;
62 SeAssignPrimaryTokenPrivilege
.HighPart
= 0;
63 SeLockMemoryPrivilege
.LowPart
= SE_LOCK_MEMORY_PRIVILEGE
;
64 SeLockMemoryPrivilege
.HighPart
= 0;
65 SeIncreaseQuotaPrivilege
.LowPart
= SE_INCREASE_QUOTA_PRIVILEGE
;
66 SeIncreaseQuotaPrivilege
.HighPart
= 0;
67 SeUnsolicitedInputPrivilege
.LowPart
= SE_UNSOLICITED_INPUT_PRIVILEGE
;
68 SeUnsolicitedInputPrivilege
.HighPart
= 0;
69 SeTcbPrivilege
.LowPart
= SE_TCB_PRIVILEGE
;
70 SeTcbPrivilege
.HighPart
= 0;
71 SeSecurityPrivilege
.LowPart
= SE_SECURITY_PRIVILEGE
;
72 SeSecurityPrivilege
.HighPart
= 0;
73 SeTakeOwnershipPrivilege
.LowPart
= SE_TAKE_OWNERSHIP_PRIVILEGE
;
74 SeTakeOwnershipPrivilege
.HighPart
= 0;
75 SeLoadDriverPrivilege
.LowPart
= SE_LOAD_DRIVER_PRIVILEGE
;
76 SeLoadDriverPrivilege
.HighPart
= 0;
77 SeSystemProfilePrivilege
.LowPart
= SE_SYSTEM_PROFILE_PRIVILEGE
;
78 SeSystemProfilePrivilege
.HighPart
= 0;
79 SeSystemtimePrivilege
.LowPart
= SE_SYSTEMTIME_PRIVILEGE
;
80 SeSystemtimePrivilege
.HighPart
= 0;
81 SeProfileSingleProcessPrivilege
.LowPart
= SE_PROF_SINGLE_PROCESS_PRIVILEGE
;
82 SeProfileSingleProcessPrivilege
.HighPart
= 0;
83 SeIncreaseBasePriorityPrivilege
.LowPart
= SE_INC_BASE_PRIORITY_PRIVILEGE
;
84 SeIncreaseBasePriorityPrivilege
.HighPart
= 0;
85 SeCreatePagefilePrivilege
.LowPart
= SE_CREATE_PAGEFILE_PRIVILEGE
;
86 SeCreatePagefilePrivilege
.HighPart
= 0;
87 SeCreatePermanentPrivilege
.LowPart
= SE_CREATE_PERMANENT_PRIVILEGE
;
88 SeCreatePermanentPrivilege
.HighPart
= 0;
89 SeBackupPrivilege
.LowPart
= SE_BACKUP_PRIVILEGE
;
90 SeBackupPrivilege
.HighPart
= 0;
91 SeRestorePrivilege
.LowPart
= SE_RESTORE_PRIVILEGE
;
92 SeRestorePrivilege
.HighPart
= 0;
93 SeShutdownPrivilege
.LowPart
= SE_SHUTDOWN_PRIVILEGE
;
94 SeShutdownPrivilege
.HighPart
= 0;
95 SeDebugPrivilege
.LowPart
= SE_DEBUG_PRIVILEGE
;
96 SeDebugPrivilege
.HighPart
= 0;
97 SeAuditPrivilege
.LowPart
= SE_AUDIT_PRIVILEGE
;
98 SeAuditPrivilege
.HighPart
= 0;
99 SeSystemEnvironmentPrivilege
.LowPart
= SE_SYSTEM_ENVIRONMENT_PRIVILEGE
;
100 SeSystemEnvironmentPrivilege
.HighPart
= 0;
101 SeChangeNotifyPrivilege
.LowPart
= SE_CHANGE_NOTIFY_PRIVILEGE
;
102 SeChangeNotifyPrivilege
.HighPart
= 0;
103 SeRemoteShutdownPrivilege
.LowPart
= SE_REMOTE_SHUTDOWN_PRIVILEGE
;
104 SeRemoteShutdownPrivilege
.HighPart
= 0;
105 SeUndockPrivilege
.LowPart
= SE_UNDOCK_PRIVILEGE
;
106 SeUndockPrivilege
.HighPart
= 0;
107 SeSyncAgentPrivilege
.LowPart
= SE_SYNC_AGENT_PRIVILEGE
;
108 SeSyncAgentPrivilege
.HighPart
= 0;
109 SeEnableDelegationPrivilege
.LowPart
= SE_ENABLE_DELEGATION_PRIVILEGE
;
110 SeEnableDelegationPrivilege
.HighPart
= 0;
116 SepPrivilegeCheck (PTOKEN Token
,
117 PLUID_AND_ATTRIBUTES Privileges
,
118 ULONG PrivilegeCount
,
119 ULONG PrivilegeControl
,
120 KPROCESSOR_MODE PreviousMode
)
126 DPRINT ("SepPrivilegeCheck() called\n");
130 if (PreviousMode
== KernelMode
)
136 if (PrivilegeCount
> 0)
138 for (i
= 0; i
< Token
->PrivilegeCount
; i
++)
140 for (j
= 0; j
< PrivilegeCount
; j
++)
142 if (Token
->Privileges
[i
].Luid
.LowPart
== Privileges
[j
].Luid
.LowPart
&&
143 Token
->Privileges
[i
].Luid
.HighPart
== Privileges
[j
].Luid
.HighPart
)
145 DPRINT ("Found privilege\n");
146 DPRINT ("Privilege attributes %lx\n",
147 Token
->Privileges
[i
].Attributes
);
149 if (Token
->Privileges
[i
].Attributes
& SE_PRIVILEGE_ENABLED
)
151 Privileges
[j
].Attributes
|= SE_PRIVILEGE_USED_FOR_ACCESS
;
159 if ((PrivilegeControl
& PRIVILEGE_SET_ALL_NECESSARY
) &&
166 !(PrivilegeControl
& PRIVILEGE_SET_ALL_NECESSARY
))
177 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src
,
178 ULONG PrivilegeCount
,
179 KPROCESSOR_MODE PreviousMode
,
180 PLUID_AND_ATTRIBUTES AllocatedMem
,
181 ULONG AllocatedLength
,
183 BOOLEAN CaptureIfKernel
,
184 PLUID_AND_ATTRIBUTES
* Dest
,
188 NTSTATUS Status
= STATUS_SUCCESS
;
192 if (PrivilegeCount
== 0)
196 return STATUS_SUCCESS
;
199 if (PreviousMode
== KernelMode
&& !CaptureIfKernel
)
202 return STATUS_SUCCESS
;
205 /* FIXME - check PrivilegeCount for a valid number so we don't
206 cause an integer overflow or exhaust system resources! */
208 BufferSize
= PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
);
209 *Length
= ROUND_UP(BufferSize
, 4); /* round up to a 4 byte alignment */
211 /* probe the buffer */
212 if (PreviousMode
!= KernelMode
)
222 Status
= _SEH_GetExceptionCode();
226 if (!NT_SUCCESS(Status
))
232 /* allocate enough memory or check if the provided buffer is
233 large enough to hold the array */
234 if (AllocatedMem
!= NULL
)
236 if (AllocatedLength
< BufferSize
)
238 return STATUS_BUFFER_TOO_SMALL
;
241 *Dest
= AllocatedMem
;
245 *Dest
= ExAllocatePool(PoolType
,
250 return STATUS_INSUFFICIENT_RESOURCES
;
254 /* copy the array to the buffer */
263 Status
= _SEH_GetExceptionCode();
267 if (!NT_SUCCESS(Status
) && AllocatedMem
== NULL
)
278 SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege
,
279 KPROCESSOR_MODE PreviousMode
,
280 BOOLEAN CaptureIfKernel
)
284 if (Privilege
!= NULL
&&
285 (PreviousMode
!= KernelMode
|| CaptureIfKernel
))
287 ExFreePool(Privilege
);
293 NtPrivilegeCheck (IN HANDLE ClientToken
,
294 IN PPRIVILEGE_SET RequiredPrivileges
,
297 PLUID_AND_ATTRIBUTES Privileges
;
299 ULONG PrivilegeCount
= 0;
300 ULONG PrivilegeControl
= 0;
303 KPROCESSOR_MODE PreviousMode
;
304 NTSTATUS Status
= STATUS_SUCCESS
;
308 PreviousMode
= KeGetPreviousMode();
310 /* probe the buffers */
311 if (PreviousMode
!= KernelMode
)
315 ProbeForWrite(RequiredPrivileges
,
316 sizeof(PRIVILEGE_SET
),
319 PrivilegeCount
= RequiredPrivileges
->PrivilegeCount
;
320 PrivilegeControl
= RequiredPrivileges
->Control
;
322 /* probe all of the array */
323 ProbeForWrite(RequiredPrivileges
,
324 sizeof(FIELD_OFFSET(PRIVILEGE_SET
,
325 Privilege
[PrivilegeCount
])),
328 ProbeForWriteBoolean(Result
);
332 Status
= _SEH_GetExceptionCode();
336 if (!NT_SUCCESS(Status
))
343 PrivilegeCount
= RequiredPrivileges
->PrivilegeCount
;
344 PrivilegeControl
= RequiredPrivileges
->Control
;
347 /* reference the token and make sure we're
348 not doing an anonymous impersonation */
349 Status
= ObReferenceObjectByHandle (ClientToken
,
355 if (!NT_SUCCESS(Status
))
360 if (Token
->TokenType
== TokenImpersonation
&&
361 Token
->ImpersonationLevel
< SecurityIdentification
)
363 ObDereferenceObject (Token
);
364 return STATUS_BAD_IMPERSONATION_LEVEL
;
367 /* capture the privileges */
368 Status
= SeCaptureLuidAndAttributesArray (RequiredPrivileges
->Privilege
,
377 if (!NT_SUCCESS(Status
))
379 ObDereferenceObject (Token
);
383 CheckResult
= SepPrivilegeCheck (Token
,
389 ObDereferenceObject (Token
);
391 /* return the array */
394 RtlCopyMemory(RequiredPrivileges
->Privilege
,
396 PrivilegeCount
* sizeof(LUID_AND_ATTRIBUTES
));
397 *Result
= CheckResult
;
398 Status
= STATUS_SUCCESS
;
402 Status
= _SEH_GetExceptionCode();
406 SeReleaseLuidAndAttributesArray (Privileges
,
418 SePrivilegeCheck (PPRIVILEGE_SET Privileges
,
419 PSECURITY_SUBJECT_CONTEXT SubjectContext
,
420 KPROCESSOR_MODE PreviousMode
)
422 PACCESS_TOKEN Token
= NULL
;
426 if (SubjectContext
->ClientToken
== NULL
)
428 Token
= SubjectContext
->PrimaryToken
;
432 Token
= SubjectContext
->ClientToken
;
433 if (SubjectContext
->ImpersonationLevel
< 2)
439 return SepPrivilegeCheck (Token
,
440 Privileges
->Privilege
,
441 Privileges
->PrivilegeCount
,
451 SeSinglePrivilegeCheck (IN LUID PrivilegeValue
,
452 IN KPROCESSOR_MODE PreviousMode
)
454 SECURITY_SUBJECT_CONTEXT SubjectContext
;
460 SeCaptureSubjectContext (&SubjectContext
);
462 Priv
.PrivilegeCount
= 1;
463 Priv
.Control
= PRIVILEGE_SET_ALL_NECESSARY
;
464 Priv
.Privilege
[0].Luid
= PrivilegeValue
;
465 Priv
.Privilege
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
467 Result
= SePrivilegeCheck (&Priv
,
471 if (PreviousMode
!= KernelMode
)
474 SePrivilegedServiceAuditAlarm (0,
480 SeReleaseSubjectContext (&SubjectContext
);