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