- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[reactos.git] / reactos / ntoskrnl / se / priv.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/priv.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, SepInitPrivileges)
19 #endif
20
21
22 /* GLOBALS *******************************************************************/
23
24 LUID SeCreateTokenPrivilege;
25 LUID SeAssignPrimaryTokenPrivilege;
26 LUID SeLockMemoryPrivilege;
27 LUID SeIncreaseQuotaPrivilege;
28 LUID SeUnsolicitedInputPrivilege;
29 LUID SeTcbPrivilege;
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;
50
51
52 /* FUNCTIONS ***************************************************************/
53
54 VOID
55 INIT_FUNCTION
56 NTAPI
57 SepInitPrivileges (VOID)
58 {
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;
111 }
112
113
114 BOOLEAN
115 NTAPI
116 SepPrivilegeCheck (PTOKEN Token,
117 PLUID_AND_ATTRIBUTES Privileges,
118 ULONG PrivilegeCount,
119 ULONG PrivilegeControl,
120 KPROCESSOR_MODE PreviousMode)
121 {
122 ULONG i;
123 ULONG j;
124 ULONG k;
125
126 DPRINT ("SepPrivilegeCheck() called\n");
127
128 PAGED_CODE();
129
130 if (PreviousMode == KernelMode)
131 {
132 return TRUE;
133 }
134
135 k = 0;
136 if (PrivilegeCount > 0)
137 {
138 for (i = 0; i < Token->PrivilegeCount; i++)
139 {
140 for (j = 0; j < PrivilegeCount; j++)
141 {
142 if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
143 Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
144 {
145 DPRINT ("Found privilege\n");
146 DPRINT ("Privilege attributes %lx\n",
147 Token->Privileges[i].Attributes);
148
149 if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
150 {
151 Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
152 k++;
153 }
154 }
155 }
156 }
157 }
158
159 if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
160 PrivilegeCount == k)
161 {
162 return TRUE;
163 }
164
165 if (k > 0 &&
166 !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
167 {
168 return TRUE;
169 }
170
171 return FALSE;
172 }
173
174
175 NTSTATUS
176 NTAPI
177 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
178 ULONG PrivilegeCount,
179 KPROCESSOR_MODE PreviousMode,
180 PLUID_AND_ATTRIBUTES AllocatedMem,
181 ULONG AllocatedLength,
182 POOL_TYPE PoolType,
183 ULONG d,
184 PLUID_AND_ATTRIBUTES* Dest,
185 PULONG Length)
186 {
187 PLUID_AND_ATTRIBUTES* NewMem;
188 ULONG SrcLength;
189
190 PAGED_CODE();
191
192 if (PrivilegeCount == 0)
193 {
194 *Dest = 0;
195 *Length = 0;
196 return STATUS_SUCCESS;
197 }
198
199 if (PreviousMode == KernelMode && d == 0)
200 {
201 *Dest = Src;
202 return STATUS_SUCCESS;
203 }
204
205 SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
206 *Length = SrcLength;
207 if (AllocatedMem == NULL)
208 {
209 NewMem = ExAllocatePool (PoolType,
210 SrcLength);
211 *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
212 if (NewMem == NULL)
213 {
214 return STATUS_UNSUCCESSFUL;
215 }
216 }
217 else
218 {
219 if (SrcLength > AllocatedLength)
220 {
221 return STATUS_UNSUCCESSFUL;
222 }
223 *Dest = AllocatedMem;
224 }
225 memmove (*Dest, Src, SrcLength);
226
227 return STATUS_SUCCESS;
228 }
229
230
231 VOID
232 NTAPI
233 SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
234 KPROCESSOR_MODE PreviousMode,
235 ULONG a)
236 {
237 PAGED_CODE();
238
239 ExFreePool (Privilege);
240 }
241
242
243 NTSTATUS STDCALL
244 NtPrivilegeCheck (IN HANDLE ClientToken,
245 IN PPRIVILEGE_SET RequiredPrivileges,
246 IN PBOOLEAN Result)
247 {
248 PLUID_AND_ATTRIBUTES Privilege;
249 PTOKEN Token;
250 ULONG PrivilegeCount;
251 ULONG PrivilegeControl;
252 ULONG Length;
253 KPROCESSOR_MODE PreviousMode;
254 NTSTATUS Status;
255
256 PAGED_CODE();
257
258 PreviousMode = KeGetPreviousMode();
259
260 Status = ObReferenceObjectByHandle (ClientToken,
261 TOKEN_QUERY,
262 SepTokenObjectType,
263 PreviousMode,
264 (PVOID*)&Token,
265 NULL);
266 if (!NT_SUCCESS(Status))
267 {
268 return Status;
269 }
270
271 if (Token->TokenType == TokenImpersonation &&
272 Token->ImpersonationLevel < SecurityAnonymous)
273 {
274 ObDereferenceObject (Token);
275 return STATUS_UNSUCCESSFUL;
276 }
277
278 PrivilegeCount = RequiredPrivileges->PrivilegeCount;
279 PrivilegeControl = RequiredPrivileges->Control;
280 Privilege = 0;
281 Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
282 PrivilegeCount,
283 UserMode,
284 NULL,
285 0,
286 PagedPool,
287 1,
288 &Privilege,
289 &Length);
290 if (!NT_SUCCESS(Status))
291 {
292 ObDereferenceObject (Token);
293 return STATUS_UNSUCCESSFUL;
294 }
295
296 *Result = SepPrivilegeCheck (Token,
297 Privilege,
298 PrivilegeCount,
299 PrivilegeControl,
300 UserMode);
301
302 memmove (RequiredPrivileges->Privilege,
303 Privilege,
304 Length);
305
306 SeReleaseLuidAndAttributesArray (Privilege,
307 UserMode,
308 1);
309
310 return STATUS_SUCCESS;
311 }
312
313
314 /*
315 * @implemented
316 */
317 BOOLEAN STDCALL
318 SePrivilegeCheck (PPRIVILEGE_SET Privileges,
319 PSECURITY_SUBJECT_CONTEXT SubjectContext,
320 KPROCESSOR_MODE PreviousMode)
321 {
322 PACCESS_TOKEN Token = NULL;
323
324 PAGED_CODE();
325
326 if (SubjectContext->ClientToken == NULL)
327 {
328 Token = SubjectContext->PrimaryToken;
329 }
330 else
331 {
332 Token = SubjectContext->ClientToken;
333 if (SubjectContext->ImpersonationLevel < 2)
334 {
335 return FALSE;
336 }
337 }
338
339 return SepPrivilegeCheck (Token,
340 Privileges->Privilege,
341 Privileges->PrivilegeCount,
342 Privileges->Control,
343 PreviousMode);
344 }
345
346
347 /*
348 * @implemented
349 */
350 BOOLEAN STDCALL
351 SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
352 IN KPROCESSOR_MODE PreviousMode)
353 {
354 SECURITY_SUBJECT_CONTEXT SubjectContext;
355 PRIVILEGE_SET Priv;
356 BOOLEAN Result;
357
358 PAGED_CODE();
359
360 SeCaptureSubjectContext (&SubjectContext);
361
362 Priv.PrivilegeCount = 1;
363 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
364 Priv.Privilege[0].Luid = PrivilegeValue;
365 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
366
367 Result = SePrivilegeCheck (&Priv,
368 &SubjectContext,
369 PreviousMode);
370
371 if (PreviousMode != KernelMode)
372 {
373 #if 0
374 SePrivilegedServiceAuditAlarm (0,
375 &SubjectContext,
376 &PrivilegeValue);
377 #endif
378 }
379
380 SeReleaseSubjectContext (&SubjectContext);
381
382 return Result;
383 }
384
385 /* EOF */