update for HEAD-2003091401
[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
102 BOOLEAN
103 SepPrivilegeCheck (PACCESS_TOKEN Token,
104                    PLUID_AND_ATTRIBUTES Privileges,
105                    ULONG PrivilegeCount,
106                    ULONG PrivilegeControl,
107                    KPROCESSOR_MODE PreviousMode)
108 {
109   ULONG i;
110   ULONG j;
111   ULONG k;
112
113   DPRINT ("SepPrivilegeCheck() called\n");
114
115   if (PreviousMode == KernelMode)
116     {
117       return TRUE;
118     }
119
120   k = 0;
121   if (PrivilegeCount > 0)
122     {
123       for (i = 0; i < Token->PrivilegeCount; i++)
124         {
125           for (j = 0; j < PrivilegeCount; j++)
126             {
127               if (Token->Privileges[i].Luid.LowPart == Privileges[j].Luid.LowPart &&
128                   Token->Privileges[i].Luid.HighPart == Privileges[j].Luid.HighPart)
129                 {
130                   DPRINT ("Found privilege\n");
131                   DPRINT ("Privilege attributes %lx\n",
132                           Token->Privileges[i].Attributes);
133
134                   if (Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
135                     {
136                       Privileges[j].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
137                       k++;
138                     }
139                 }
140             }
141         }
142     }
143
144   if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) &&
145       PrivilegeCount == k)
146     {
147       return TRUE;
148     }
149
150   if (k > 0 &&
151       !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY))
152     {
153       return TRUE;
154     }
155
156   return FALSE;
157 }
158
159
160 NTSTATUS
161 SeCaptureLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Src,
162                                  ULONG PrivilegeCount,
163                                  KPROCESSOR_MODE PreviousMode,
164                                  PLUID_AND_ATTRIBUTES AllocatedMem,
165                                  ULONG AllocatedLength,
166                                  POOL_TYPE PoolType,
167                                  ULONG d,
168                                  PLUID_AND_ATTRIBUTES* Dest,
169                                  PULONG Length)
170 {
171   PLUID_AND_ATTRIBUTES* NewMem;
172   ULONG SrcLength;
173
174   if (PrivilegeCount == 0)
175     {
176       *Dest = 0;
177       *Length = 0;
178       return STATUS_SUCCESS;
179     }
180
181   if (PreviousMode == KernelMode && d == 0)
182     {
183       *Dest = Src;
184       return STATUS_SUCCESS;
185     }
186
187   SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc;
188   *Length = SrcLength;
189   if (AllocatedMem == NULL)
190     {
191       NewMem = ExAllocatePool (PoolType,
192                                SrcLength);
193       *Dest = (PLUID_AND_ATTRIBUTES)NewMem;
194       if (NewMem == NULL)
195         {
196           return STATUS_UNSUCCESSFUL;
197         }
198     }
199   else
200     {
201       if (SrcLength > AllocatedLength)
202         {
203           return STATUS_UNSUCCESSFUL;
204         }
205       *Dest = AllocatedMem;
206     }
207   memmove (*Dest, Src, SrcLength);
208
209   return STATUS_SUCCESS;
210 }
211
212
213 VOID
214 SeReleaseLuidAndAttributesArray (PLUID_AND_ATTRIBUTES Privilege,
215                                  KPROCESSOR_MODE PreviousMode,
216                                  ULONG a)
217 {
218   ExFreePool (Privilege);
219 }
220
221
222 NTSTATUS STDCALL
223 NtPrivilegeCheck (IN HANDLE ClientToken,
224                   IN PPRIVILEGE_SET RequiredPrivileges,
225                   IN PBOOLEAN Result)
226 {
227   PLUID_AND_ATTRIBUTES Privilege;
228   PACCESS_TOKEN Token;
229   ULONG PrivilegeCount;
230   ULONG PrivilegeControl;
231   ULONG Length;
232   NTSTATUS Status;
233
234   Status = ObReferenceObjectByHandle (ClientToken,
235                                       0,
236                                       SepTokenObjectType,
237                                       UserMode,
238                                       (PVOID*)&Token,
239                                       NULL);
240   if (!NT_SUCCESS(Status))
241     {
242       return Status;
243     }
244
245   if (Token->TokenType == TokenImpersonation &&
246       Token->ImpersonationLevel < SecurityAnonymous)
247     {
248       ObDereferenceObject (Token);
249       return STATUS_UNSUCCESSFUL;
250     }
251
252   PrivilegeCount = RequiredPrivileges->PrivilegeCount;
253   PrivilegeControl = RequiredPrivileges->Control;
254   Privilege = 0;
255   Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege,
256                                             PrivilegeCount,
257                                             1,
258                                             0,
259                                             0,
260                                             1,
261                                             1,
262                                             &Privilege,
263                                             &Length);
264   if (!NT_SUCCESS(Status))
265     {
266       ObDereferenceObject (Token);
267       return STATUS_UNSUCCESSFUL;
268     }
269
270   *Result = SepPrivilegeCheck (Token,
271                                Privilege,
272                                PrivilegeCount,
273                                PrivilegeControl,
274                                UserMode);
275
276   memmove (RequiredPrivileges->Privilege,
277            Privilege,
278            Length);
279
280   SeReleaseLuidAndAttributesArray (Privilege,
281                                    UserMode,
282                                    1);
283
284   return STATUS_SUCCESS;
285 }
286
287
288 /*
289  * @implemented
290  */
291 BOOLEAN STDCALL
292 SePrivilegeCheck (PPRIVILEGE_SET Privileges,
293                   PSECURITY_SUBJECT_CONTEXT SubjectContext,
294                   KPROCESSOR_MODE PreviousMode)
295 {
296   PACCESS_TOKEN Token = NULL;
297
298   if (SubjectContext->ClientToken == NULL)
299     {
300       Token = SubjectContext->PrimaryToken;
301     }
302   else
303     {
304       Token = SubjectContext->ClientToken;
305       if (SubjectContext->ImpersonationLevel < 2)
306         {
307           return FALSE;
308         }
309     }
310
311   return SepPrivilegeCheck (Token,
312                             Privileges->Privilege,
313                             Privileges->PrivilegeCount,
314                             Privileges->Control,
315                             PreviousMode);
316 }
317
318
319 /*
320  * @implemented
321  */
322 BOOLEAN STDCALL
323 SeSinglePrivilegeCheck (IN LUID PrivilegeValue,
324                         IN KPROCESSOR_MODE PreviousMode)
325 {
326   SECURITY_SUBJECT_CONTEXT SubjectContext;
327   PRIVILEGE_SET Priv;
328   BOOLEAN Result;
329
330   SeCaptureSubjectContext (&SubjectContext);
331
332   Priv.PrivilegeCount = 1;
333   Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
334   Priv.Privilege[0].Luid = PrivilegeValue;
335   Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
336
337   Result = SePrivilegeCheck (&Priv,
338                              &SubjectContext,
339                              PreviousMode);
340
341   if (PreviousMode != KernelMode)
342     {
343 #if 0
344       SePrivilegedServiceAuditAlarm (0,
345                                      &SubjectContext,
346                                      &PrivilegeValue);
347 #endif
348     }
349
350   SeReleaseSubjectContext (&SubjectContext);
351
352   return Result;
353 }
354
355 /* EOF */