Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / ntoskrnl / se / priv.c
1 /* $Id: priv.c,v 1.4 2002/09/07 15:13:06 chorns Exp $
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 <ntoskrnl.h>
15
16 #define NDEBUG
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(PIACCESS_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_ARRAY 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 PIACCESS_TOKEN iToken;
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*)&iToken,
210 NULL);
211 if (!NT_SUCCESS(Status))
212 {
213 return(Status);
214 }
215 if (iToken->TokenType == TokenImpersonation &&
216 iToken->ImpersonationLevel < SecurityAnonymous)
217 {
218 ObDereferenceObject(iToken);
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(iToken);
236 return(STATUS_UNSUCCESSFUL);
237 }
238 TResult = SepPrivilegeCheck(iToken,
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 PIACCESS_TOKEN iToken = NULL;
255
256 if (SubjectContext->ClientToken == NULL)
257 {
258 iToken = SubjectContext->PrimaryToken;
259 }
260 else
261 {
262 iToken = SubjectContext->ClientToken;
263 if (SubjectContext->ImpersonationLevel < 2)
264 {
265 return(FALSE);
266 }
267 }
268
269 return(SepPrivilegeCheck(iToken,
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