KERNEL_VERSION_MAJOR: 0 -> 5
[reactos.git] / ntoskrnl / se / priv.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Security manager
6  * FILE:              kernel/se/priv.c
7  * PROGRAMER:         ?
8  * REVISION HISTORY:
9  *                 26/07/98: Added stubs for security functions
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/se.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20
21 /* GLOBALS *******************************************************************/
22
23 LUID SeCreateTokenPrivilege;
24 LUID SeAssignPrimaryTokenPrivilege;
25 LUID SeLockMemoryPrivilege;
26 LUID SeIncreaseQuotaPrivilege;
27 LUID SeUnsolicitedInputPrivilege;
28 LUID SeTcbPrivilege;
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
47
48 /* FUNCTIONS ***************************************************************/
49
50 VOID
51 SepInitPrivileges (VOID)
52 {
53   SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
54   SeCreateTokenPrivilege.HighPart = 0;
55   SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE;
56   SeAssignPrimaryTokenPrivilege.HighPart = 0;
57   SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE;
58   SeLockMemoryPrivilege.HighPart = 0;
59   SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE;
60   SeIncreaseQuotaPrivilege.HighPart = 0;
61   SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE;
62   SeUnsolicitedInputPrivilege.HighPart = 0;
63   SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE;
64   SeTcbPrivilege.HighPart = 0;
65   SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE;
66   SeSecurityPrivilege.HighPart = 0;
67   SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
68   SeTakeOwnershipPrivilege.HighPart = 0;
69   SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE;
70   SeLoadDriverPrivilege.HighPart = 0;
71   SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE;
72   SeSystemProfilePrivilege.HighPart = 0;
73   SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE;
74   SeSystemtimePrivilege.HighPart = 0;
75   SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE;
76   SeProfileSingleProcessPrivilege.HighPart = 0;
77   SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE;
78   SeIncreaseBasePriorityPrivilege.HighPart = 0;
79   SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE;
80   SeCreatePagefilePrivilege.HighPart = 0;
81   SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE;
82   SeCreatePermanentPrivilege.HighPart = 0;
83   SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE;
84   SeBackupPrivilege.HighPart = 0;
85   SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE;
86   SeRestorePrivilege.HighPart = 0;
87   SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE;
88   SeShutdownPrivilege.HighPart = 0;
89   SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE;
90   SeDebugPrivilege.HighPart = 0;
91   SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE;
92   SeAuditPrivilege.HighPart = 0;
93   SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
94   SeSystemEnvironmentPrivilege.HighPart = 0;
95   SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE;
96   SeChangeNotifyPrivilege.HighPart = 0;
97   SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE;
98   SeRemoteShutdownPrivilege.HighPart = 0;
99 }
100
101 #ifndef LIBCAPTIVE
102
103 BOOLEAN
104 SepPrivilegeCheck (PACCESS_TOKEN Token,
105                    PLUID_AND_ATTRIBUTES Privileges,
106                    ULONG PrivilegeCount,
107                    ULONG PrivilegeControl,
108                    KPROCESSOR_MODE PreviousMode)
109 {
110   ULONG i;
111   ULONG j;
112   ULONG k;
113
114   DPRINT ("SepPrivilegeCheck() called\n");
115
116   if (PreviousMode == KernelMode)
117     {
118       return TRUE;
119     }
120
121   k = 0;
122   if (PrivilegeCount > 0)
123     {
124       for (i = 0; i < Token->PrivilegeCount; i++)
125         {
126           for (j = 0; j < PrivilegeCount; j++)
127             {
128               if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
129                   Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
130                 {
131                   DPRINT ("Found privilege\n");
132                   DPRINT ("Privilege attributes %lx\n",
133                           Token->Privileges[i].Attributes);
134
135                   if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
136                     {
137                       Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
138                       k++;
139                     }
140                 }
141             }
142         }
143     }
144
145   if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
146       PrivilegeCount == k)
147     {
148       return TRUE;
149     }
150
151   if (k > 0 &&
152       !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
153     {
154       return TRUE;
155     }
156
157   return FALSE;
158 }
159
160
161 NTSTATUS
162 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
163                                  ULONG PrivilegeCount,
164                                  KPROCESSOR_MODE PreviousMode,
165                                  PLUID_AND_ATTRIBUTES AllocatedMem,
166                                  ULONG AllocatedLength,
167                                  POOL_TYPE PoolType,
168                                  ULONG d,
169                                  PLUID_AND_ATTRIBUTES* Dest,
170                                  PULONG Length)
171 {
172   PLUID_AND_ATTRIBUTES* NewMem;
173   ULONG SrcLength;
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   ExFreePool (Privilege);
220 }
221
222
223 NTSTATUS STDCALL
224 NtPrivilegeCheck (IN HANDLE ClientToken,
225                   IN PPRIVILEGE_SET RequiredPrivileges,
226                   IN PBOOLEAN Result)
227 {
228   PLUID_AND_ATTRIBUTES Privilege;
229   PACCESS_TOKEN Token;
230   ULONG PrivilegeCount;
231   ULONG PrivilegeControl;
232   ULONG Length;
233   NTSTATUS Status;
234
235   Status = ObReferenceObjectByHandle (ClientToken,
236                                       0,
237                                       SepTokenObjectType,
238                                       UserMode,
239                                       (PVOID*)&Token,
240                                       NULL);
241   if (!NT_SUCCESS(Status))
242     {
243       return Status;
244     }
245
246   if (Token->TokenType == TokenImpersonation &&
247       Token->ImpersonationLevel < SecurityAnonymous)
248     {
249       ObDereferenceObject (Token);
250       return STATUS_UNSUCCESSFUL;
251     }
252
253   PrivilegeCount = RequiredPrivileges->PrivilegeCount;
254   PrivilegeControl = RequiredPrivileges->Control;
255   Privilege = 0;
256   Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
257                                             PrivilegeCount,
258                                             1,
259                                             0,
260                                             0,
261                                             1,
262                                             1,
263                                             &Privilege,
264                                             &Length);
265   if (!NT_SUCCESS(Status))
266     {
267       ObDereferenceObject (Token);
268       return STATUS_UNSUCCESSFUL;
269     }
270
271   *Result = SepPrivilegeCheck (Token,
272                                Privilege,
273                                PrivilegeCount,
274                                PrivilegeControl,
275                                UserMode);
276
277   memmove (RequiredPrivileges->Privilege,
278            Privilege,
279            Length);
280
281   SeReleaseLuidAndAttributesArray (Privilege,
282                                    UserMode,
283                                    1);
284
285   return STATUS_SUCCESS;
286 }
287
288
289 /*
290  * @implemented
291  */
292 BOOLEAN STDCALL
293 SePrivilegeCheck (PPRIVILEGE_SET Privileges,
294                   PSECURITY_SUBJECT_CONTEXT SubjectContext,
295                   KPROCESSOR_MODE PreviousMode)
296 {
297   PACCESS_TOKEN Token = NULL;
298
299   if (SubjectContext->ClientToken == NULL)
300     {
301       Token = SubjectContext->PrimaryToken;
302     }
303   else
304     {
305       Token = SubjectContext->ClientToken;
306       if (SubjectContext->ImpersonationLevel < 2)
307         {
308           return FALSE;
309         }
310     }
311
312   return SepPrivilegeCheck (Token,
313                             Privileges->Privilege,
314                             Privileges->PrivilegeCount,
315                             Privileges->Control,
316                             PreviousMode);
317 }
318
319
320 /*
321  * @implemented
322  */
323 BOOLEAN STDCALL
324 SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
325                         IN KPROCESSOR_MODE PreviousMode)
326 {
327   SECURITY_SUBJECT_CONTEXT SubjectContext;
328   PRIVILEGE_SET Priv;
329   BOOLEAN Result;
330
331   SeCaptureSubjectContext (&SubjectContext);
332
333   Priv.PrivilegeCount = 1;
334   Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
335   Priv.Privilege[0].Luid = PrivilegeValue;
336   Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
337
338   Result = SePrivilegeCheck (&Priv,
339                              &SubjectContext,
340                              PreviousMode);
341
342   if (PreviousMode != KernelMode)
343     {
344 #if 0
345       SePrivilegedServiceAuditAlarm (0,
346                                      &SubjectContext,
347                                      &PrivilegeValue);
348 #endif
349     }
350
351   SeReleaseSubjectContext (&SubjectContext);
352
353   return Result;
354 }
355
356 #endif /* LIBCAPTIVE */
357
358 /* EOF */