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