754723133078520a3ce40d649796aaad553bed27
[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
18 /* GLOBALS *******************************************************************/
19
20 LUID SeCreateTokenPrivilege;
21 LUID SeAssignPrimaryTokenPrivilege;
22 LUID SeLockMemoryPrivilege;
23 LUID SeIncreaseQuotaPrivilege;
24 LUID SeUnsolicitedInputPrivilege;
25 LUID SeTcbPrivilege;
26 LUID SeSecurityPrivilege;
27 LUID SeTakeOwnershipPrivilege;
28 LUID SeLoadDriverPrivilege;
29 LUID SeCreatePagefilePrivilege;
30 LUID SeIncreaseBasePriorityPrivilege;
31 LUID SeSystemProfilePrivilege;
32 LUID SeSystemtimePrivilege;
33 LUID SeProfileSingleProcessPrivilege;
34 LUID SeCreatePermanentPrivilege;
35 LUID SeBackupPrivilege;
36 LUID SeRestorePrivilege;
37 LUID SeShutdownPrivilege;
38 LUID SeDebugPrivilege;
39 LUID SeAuditPrivilege;
40 LUID SeSystemEnvironmentPrivilege;
41 LUID SeChangeNotifyPrivilege;
42 LUID SeRemoteShutdownPrivilege;
43 LUID SeUndockPrivilege;
44 LUID SeSyncAgentPrivilege;
45 LUID SeEnableDelegationPrivilege;
46
47
48 /* FUNCTIONS ***************************************************************/
49
50 VOID
51 INIT_FUNCTION
52 NTAPI
53 SepInitPrivileges (VOID)
54 {
55 SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
56 SeCreateTokenPrivilege.HighPart = 0;
57 SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE;
58 SeAssignPrimaryTokenPrivilege.HighPart = 0;
59 SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE;
60 SeLockMemoryPrivilege.HighPart = 0;
61 SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE;
62 SeIncreaseQuotaPrivilege.HighPart = 0;
63 SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE;
64 SeUnsolicitedInputPrivilege.HighPart = 0;
65 SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE;
66 SeTcbPrivilege.HighPart = 0;
67 SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE;
68 SeSecurityPrivilege.HighPart = 0;
69 SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
70 SeTakeOwnershipPrivilege.HighPart = 0;
71 SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE;
72 SeLoadDriverPrivilege.HighPart = 0;
73 SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE;
74 SeSystemProfilePrivilege.HighPart = 0;
75 SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE;
76 SeSystemtimePrivilege.HighPart = 0;
77 SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE;
78 SeProfileSingleProcessPrivilege.HighPart = 0;
79 SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE;
80 SeIncreaseBasePriorityPrivilege.HighPart = 0;
81 SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE;
82 SeCreatePagefilePrivilege.HighPart = 0;
83 SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE;
84 SeCreatePermanentPrivilege.HighPart = 0;
85 SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE;
86 SeBackupPrivilege.HighPart = 0;
87 SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE;
88 SeRestorePrivilege.HighPart = 0;
89 SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE;
90 SeShutdownPrivilege.HighPart = 0;
91 SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE;
92 SeDebugPrivilege.HighPart = 0;
93 SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE;
94 SeAuditPrivilege.HighPart = 0;
95 SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
96 SeSystemEnvironmentPrivilege.HighPart = 0;
97 SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE;
98 SeChangeNotifyPrivilege.HighPart = 0;
99 SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE;
100 SeRemoteShutdownPrivilege.HighPart = 0;
101 SeUndockPrivilege.LowPart = SE_UNDOCK_PRIVILEGE;
102 SeUndockPrivilege.HighPart = 0;
103 SeSyncAgentPrivilege.LowPart = SE_SYNC_AGENT_PRIVILEGE;
104 SeSyncAgentPrivilege.HighPart = 0;
105 SeEnableDelegationPrivilege.LowPart = SE_ENABLE_DELEGATION_PRIVILEGE;
106 SeEnableDelegationPrivilege.HighPart = 0;
107 }
108
109
110 BOOLEAN
111 NTAPI
112 SepPrivilegeCheck (PTOKEN Token,
113 PLUID_AND_ATTRIBUTES Privileges,
114 ULONG PrivilegeCount,
115 ULONG PrivilegeControl,
116 KPROCESSOR_MODE PreviousMode)
117 {
118 ULONG i;
119 ULONG j;
120 ULONG k;
121
122 DPRINT ("SepPrivilegeCheck() called\n");
123
124 PAGED_CODE();
125
126 if (PreviousMode == KernelMode)
127 {
128 return TRUE;
129 }
130
131 k = 0;
132 if (PrivilegeCount > 0)
133 {
134 for (i = 0; i < Token->PrivilegeCount; i++)
135 {
136 for (j = 0; j < PrivilegeCount; j++)
137 {
138 if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
139 Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
140 {
141 DPRINT ("Found privilege\n");
142 DPRINT ("Privilege attributes %lx\n",
143 Token->Privileges[i].Attributes);
144
145 if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
146 {
147 Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
148 k++;
149 }
150 }
151 }
152 }
153 }
154
155 if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
156 PrivilegeCount == k)
157 {
158 return TRUE;
159 }
160
161 if (k > 0 &&
162 !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
163 {
164 return TRUE;
165 }
166
167 return FALSE;
168 }
169
170
171 NTSTATUS
172 NTAPI
173 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
174 ULONG PrivilegeCount,
175 KPROCESSOR_MODE PreviousMode,
176 PLUID_AND_ATTRIBUTES AllocatedMem,
177 ULONG AllocatedLength,
178 POOL_TYPE PoolType,
179 ULONG d,
180 PLUID_AND_ATTRIBUTES* Dest,
181 PULONG Length)
182 {
183 PLUID_AND_ATTRIBUTES* NewMem;
184 ULONG SrcLength;
185
186 PAGED_CODE();
187
188 if (PrivilegeCount == 0)
189 {
190 *Dest = 0;
191 *Length = 0;
192 return STATUS_SUCCESS;
193 }
194
195 if (PreviousMode == KernelMode && d == 0)
196 {
197 *Dest = Src;
198 return STATUS_SUCCESS;
199 }
200
201 SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
202 *Length = SrcLength;
203 if (AllocatedMem == NULL)
204 {
205 NewMem = ExAllocatePool (PoolType,
206 SrcLength);
207 *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
208 if (NewMem == NULL)
209 {
210 return STATUS_UNSUCCESSFUL;
211 }
212 }
213 else
214 {
215 if (SrcLength > AllocatedLength)
216 {
217 return STATUS_UNSUCCESSFUL;
218 }
219 *Dest = AllocatedMem;
220 }
221 memmove (*Dest, Src, SrcLength);
222
223 return STATUS_SUCCESS;
224 }
225
226
227 VOID
228 NTAPI
229 SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
230 KPROCESSOR_MODE PreviousMode,
231 ULONG a)
232 {
233 PAGED_CODE();
234
235 ExFreePool (Privilege);
236 }
237
238
239 NTSTATUS STDCALL
240 NtPrivilegeCheck (IN HANDLE ClientToken,
241 IN PPRIVILEGE_SET RequiredPrivileges,
242 IN PBOOLEAN Result)
243 {
244 PLUID_AND_ATTRIBUTES Privilege;
245 PTOKEN Token;
246 ULONG PrivilegeCount;
247 ULONG PrivilegeControl;
248 ULONG Length;
249 NTSTATUS Status;
250
251 PAGED_CODE();
252
253 Status = ObReferenceObjectByHandle (ClientToken,
254 0,
255 SepTokenObjectType,
256 UserMode,
257 (PVOID*)&Token,
258 NULL);
259 if (!NT_SUCCESS(Status))
260 {
261 return Status;
262 }
263
264 if (Token->TokenType == TokenImpersonation &&
265 Token->ImpersonationLevel < SecurityAnonymous)
266 {
267 ObDereferenceObject (Token);
268 return STATUS_UNSUCCESSFUL;
269 }
270
271 PrivilegeCount = RequiredPrivileges->PrivilegeCount;
272 PrivilegeControl = RequiredPrivileges->Control;
273 Privilege = 0;
274 Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
275 PrivilegeCount,
276 UserMode,
277 NULL,
278 0,
279 PagedPool,
280 1,
281 &Privilege,
282 &Length);
283 if (!NT_SUCCESS(Status))
284 {
285 ObDereferenceObject (Token);
286 return STATUS_UNSUCCESSFUL;
287 }
288
289 *Result = SepPrivilegeCheck (Token,
290 Privilege,
291 PrivilegeCount,
292 PrivilegeControl,
293 UserMode);
294
295 memmove (RequiredPrivileges->Privilege,
296 Privilege,
297 Length);
298
299 SeReleaseLuidAndAttributesArray (Privilege,
300 UserMode,
301 1);
302
303 return STATUS_SUCCESS;
304 }
305
306
307 /*
308 * @implemented
309 */
310 BOOLEAN STDCALL
311 SePrivilegeCheck (PPRIVILEGE_SET Privileges,
312 PSECURITY_SUBJECT_CONTEXT SubjectContext,
313 KPROCESSOR_MODE PreviousMode)
314 {
315 PACCESS_TOKEN Token = NULL;
316
317 PAGED_CODE();
318
319 if (SubjectContext->ClientToken == NULL)
320 {
321 Token = SubjectContext->PrimaryToken;
322 }
323 else
324 {
325 Token = SubjectContext->ClientToken;
326 if (SubjectContext->ImpersonationLevel < 2)
327 {
328 return FALSE;
329 }
330 }
331
332 return SepPrivilegeCheck (Token,
333 Privileges->Privilege,
334 Privileges->PrivilegeCount,
335 Privileges->Control,
336 PreviousMode);
337 }
338
339
340 /*
341 * @implemented
342 */
343 BOOLEAN STDCALL
344 SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
345 IN KPROCESSOR_MODE PreviousMode)
346 {
347 SECURITY_SUBJECT_CONTEXT SubjectContext;
348 PRIVILEGE_SET Priv;
349 BOOLEAN Result;
350
351 PAGED_CODE();
352
353 SeCaptureSubjectContext (&SubjectContext);
354
355 Priv.PrivilegeCount = 1;
356 Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
357 Priv.Privilege[0].Luid = PrivilegeValue;
358 Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
359
360 Result = SePrivilegeCheck (&Priv,
361 &SubjectContext,
362 PreviousMode);
363
364 if (PreviousMode != KernelMode)
365 {
366 #if 0
367 SePrivilegedServiceAuditAlarm (0,
368 &SubjectContext,
369 &PrivilegeValue);
370 #endif
371 }
372
373 SeReleaseSubjectContext (&SubjectContext);
374
375 return Result;
376 }
377
378 /* EOF */