Fix Compiler warning with -O2
[reactos.git] / reactos / ntoskrnl / ob / security.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Security manager
5 * FILE: ntoskrnl/ob/security.c
6 * PROGRAMER: ?
7 * REVISION HISTORY:
8 * 26/07/98: Added stubs for security functions
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
15
16 #include <internal/debug.h>
17
18 /* FUNCTIONS ***************************************************************/
19
20 /*
21 * @implemented
22 */
23 NTSTATUS STDCALL
24 ObAssignSecurity(IN PACCESS_STATE AccessState,
25 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
26 IN PVOID Object,
27 IN POBJECT_TYPE Type)
28 {
29 PSECURITY_DESCRIPTOR NewDescriptor;
30 NTSTATUS Status;
31
32 /* Build the new security descriptor */
33 Status = SeAssignSecurity(SecurityDescriptor,
34 AccessState->SecurityDescriptor,
35 &NewDescriptor,
36 (Type == ObDirectoryType),
37 &AccessState->SubjectSecurityContext,
38 Type->Mapping,
39 PagedPool);
40 if (!NT_SUCCESS(Status))
41 return Status;
42
43 if (Type->Security != NULL)
44 {
45 /* Call the security method */
46 Status = Type->Security(Object,
47 AssignSecurityDescriptor,
48 0,
49 NewDescriptor,
50 NULL);
51 }
52 else
53 {
54 /* Assign the security descriptor to the object header */
55 Status = ObpAddSecurityDescriptor(NewDescriptor,
56 &(BODY_TO_HEADER(Object)->SecurityDescriptor));
57 }
58
59 /* Release the new security descriptor */
60 SeDeassignSecurity(&NewDescriptor);
61
62 return Status;
63 }
64
65
66 /*
67 * @implemented
68 */
69 NTSTATUS STDCALL
70 ObGetObjectSecurity(IN PVOID Object,
71 OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
72 OUT PBOOLEAN MemoryAllocated)
73 {
74 POBJECT_HEADER Header;
75 ULONG Length;
76 NTSTATUS Status;
77
78 Header = BODY_TO_HEADER(Object);
79 if (Header->ObjectType == NULL)
80 return STATUS_UNSUCCESSFUL;
81
82 if (Header->ObjectType->Security == NULL)
83 {
84 ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor);
85 *SecurityDescriptor = Header->SecurityDescriptor;
86 *MemoryAllocated = FALSE;
87 return STATUS_SUCCESS;
88 }
89
90 /* Get the security descriptor size */
91 Length = 0;
92 Status = Header->ObjectType->Security(Object,
93 QuerySecurityDescriptor,
94 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
95 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
96 NULL,
97 &Length);
98 if (Status != STATUS_BUFFER_TOO_SMALL)
99 return Status;
100
101 /* Allocate security descriptor */
102 *SecurityDescriptor = ExAllocatePool(NonPagedPool,
103 Length);
104 if (*SecurityDescriptor == NULL)
105 return STATUS_INSUFFICIENT_RESOURCES;
106
107 /* Query security descriptor */
108 Status = Header->ObjectType->Security(Object,
109 QuerySecurityDescriptor,
110 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
111 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
112 *SecurityDescriptor,
113 &Length);
114 if (!NT_SUCCESS(Status))
115 {
116 ExFreePool(*SecurityDescriptor);
117 return Status;
118 }
119
120 *MemoryAllocated = TRUE;
121
122 return STATUS_SUCCESS;
123 }
124
125
126 /*
127 * @implemented
128 */
129 VOID STDCALL
130 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
131 IN BOOLEAN MemoryAllocated)
132 {
133 if (SecurityDescriptor == NULL)
134 return;
135
136 if (MemoryAllocated)
137 {
138 ExFreePool(SecurityDescriptor);
139 }
140 else
141 {
142 ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor);
143 }
144 }
145
146
147 /*
148 * @implemented
149 */
150 NTSTATUS STDCALL
151 NtQuerySecurityObject(IN HANDLE Handle,
152 IN SECURITY_INFORMATION SecurityInformation,
153 OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
154 IN ULONG Length,
155 OUT PULONG ResultLength)
156 {
157 POBJECT_HEADER Header;
158 PVOID Object;
159 PSECURITY_DESCRIPTOR ObjectSd;
160 PSID Owner = 0;
161 PSID Group = 0;
162 PACL Dacl = 0;
163 PACL Sacl = 0;
164 ULONG OwnerLength = 0;
165 ULONG GroupLength = 0;
166 ULONG DaclLength = 0;
167 ULONG SaclLength = 0;
168 ULONG Control = 0;
169 ULONG_PTR Current;
170 NTSTATUS Status;
171
172 Status = ObReferenceObjectByHandle(Handle,
173 (SecurityInformation & SACL_SECURITY_INFORMATION) ? ACCESS_SYSTEM_SECURITY : 0,
174 NULL,
175 KeGetPreviousMode(),
176 &Object,
177 NULL);
178 if (!NT_SUCCESS(Status))
179 {
180 return Status;
181 }
182
183 Header = BODY_TO_HEADER(Object);
184 if (Header->ObjectType == NULL)
185 {
186 ObDereferenceObject(Object);
187 return STATUS_UNSUCCESSFUL;
188 }
189
190 if (Header->ObjectType->Security != NULL)
191 {
192 Status = Header->ObjectType->Security(Object,
193 QuerySecurityDescriptor,
194 SecurityInformation,
195 SecurityDescriptor,
196 &Length);
197 *ResultLength = Length;
198 }
199 else
200 {
201 ObjectSd = Header->SecurityDescriptor;
202
203 if (ObjectSd != NULL)
204 {
205 Control = SE_SELF_RELATIVE;
206 if ((SecurityInformation & OWNER_SECURITY_INFORMATION) &&
207 (ObjectSd->Owner != NULL))
208 {
209 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
210 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
211 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
212 }
213
214 if ((SecurityInformation & GROUP_SECURITY_INFORMATION) &&
215 (ObjectSd->Group != NULL))
216 {
217 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
218 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
219 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
220 }
221
222 if ((SecurityInformation & DACL_SECURITY_INFORMATION) &&
223 (ObjectSd->Control & SE_DACL_PRESENT))
224 {
225 if (ObjectSd->Dacl != NULL)
226 {
227 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
228 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
229 }
230 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
231 }
232
233 if ((SecurityInformation & SACL_SECURITY_INFORMATION) &&
234 (ObjectSd->Control & SE_SACL_PRESENT))
235 {
236 if (ObjectSd->Sacl != NULL)
237 {
238 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
239 SaclLength = ROUND_UP(Sacl->AclSize, 4);
240 }
241 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
242 }
243
244 *ResultLength = OwnerLength + GroupLength +
245 DaclLength + SaclLength + sizeof(SECURITY_DESCRIPTOR);
246 if (Length >= *ResultLength)
247 {
248 RtlCreateSecurityDescriptor(SecurityDescriptor,
249 SECURITY_DESCRIPTOR_REVISION1);
250 SecurityDescriptor->Control = Control;
251
252 Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
253
254 if (OwnerLength != 0)
255 {
256 RtlCopyMemory((PVOID)Current,
257 Owner,
258 OwnerLength);
259 SecurityDescriptor->Owner = (PSID)(Current - (ULONG_PTR)SecurityDescriptor);
260 Current += OwnerLength;
261 }
262
263 if (GroupLength != 0)
264 {
265 RtlCopyMemory((PVOID)Current,
266 Group,
267 GroupLength);
268 SecurityDescriptor->Group = (PSID)(Current - (ULONG_PTR)SecurityDescriptor);
269 Current += GroupLength;
270 }
271
272 if (DaclLength != 0)
273 {
274 RtlCopyMemory((PVOID)Current,
275 Dacl,
276 DaclLength);
277 SecurityDescriptor->Dacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor);
278 Current += DaclLength;
279 }
280
281 if (SaclLength != 0)
282 {
283 RtlCopyMemory((PVOID)Current,
284 Sacl,
285 SaclLength);
286 SecurityDescriptor->Sacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor);
287 Current += SaclLength;
288 }
289
290 Status = STATUS_SUCCESS;
291 }
292 else
293 {
294 Status = STATUS_BUFFER_TOO_SMALL;
295 }
296 }
297 else
298 {
299 *ResultLength = 0;
300 Status = STATUS_UNSUCCESSFUL;
301 }
302 }
303
304 ObDereferenceObject(Object);
305
306 return Status;
307 }
308
309
310 /*
311 * @implemented
312 */
313 NTSTATUS STDCALL
314 NtSetSecurityObject(IN HANDLE Handle,
315 IN SECURITY_INFORMATION SecurityInformation,
316 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
317 {
318 PSECURITY_DESCRIPTOR ObjectSd;
319 PSECURITY_DESCRIPTOR NewSd;
320 POBJECT_HEADER Header;
321 PVOID Object;
322 PSID Owner;
323 PSID Group;
324 PACL Dacl;
325 PACL Sacl;
326 ULONG OwnerLength = 0;
327 ULONG GroupLength = 0;
328 ULONG DaclLength = 0;
329 ULONG SaclLength = 0;
330 ULONG Control = 0;
331 ULONG_PTR Current;
332 NTSTATUS Status;
333
334 Status = ObReferenceObjectByHandle(Handle,
335 (SecurityInformation & SACL_SECURITY_INFORMATION) ? ACCESS_SYSTEM_SECURITY : 0,
336 NULL,
337 KeGetPreviousMode(),
338 &Object,
339 NULL);
340 if (!NT_SUCCESS(Status))
341 {
342 return Status;
343 }
344
345 Header = BODY_TO_HEADER(Object);
346 if (Header->ObjectType != NULL)
347 {
348 ObDereferenceObject(Object);
349 return STATUS_UNSUCCESSFUL;
350 }
351
352 if (Header->ObjectType->Security != NULL)
353 {
354 Status = Header->ObjectType->Security(Object,
355 SetSecurityDescriptor,
356 SecurityInformation,
357 SecurityDescriptor,
358 NULL);
359 }
360 else
361 {
362 ObjectSd = Header->SecurityDescriptor;
363
364 /* Get owner and owner size */
365 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
366 {
367 if (SecurityDescriptor->Owner != NULL)
368 {
369 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner + (ULONG_PTR)SecurityDescriptor);
370 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
371 }
372 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
373 }
374 else
375 {
376 if (ObjectSd->Owner != NULL)
377 {
378 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
379 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
380 }
381 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
382 }
383
384 /* Get group and group size */
385 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
386 {
387 if (SecurityDescriptor->Group != NULL)
388 {
389 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group + (ULONG_PTR)SecurityDescriptor);
390 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
391 }
392 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
393 }
394 else
395 {
396 if (ObjectSd->Group != NULL)
397 {
398 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
399 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
400 }
401 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
402 }
403
404 /* Get DACL and DACL size */
405 if (SecurityInformation & DACL_SECURITY_INFORMATION)
406 {
407 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
408 (SecurityDescriptor->Dacl != NULL))
409 {
410 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl + (ULONG_PTR)SecurityDescriptor);
411 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
412 }
413 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
414 }
415 else
416 {
417 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
418 (ObjectSd->Dacl != NULL))
419 {
420 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
421 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
422 }
423 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
424 }
425
426 /* Get SACL and SACL size */
427 if (SecurityInformation & SACL_SECURITY_INFORMATION)
428 {
429 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
430 (SecurityDescriptor->Sacl != NULL))
431 {
432 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl + (ULONG_PTR)SecurityDescriptor);
433 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
434 }
435 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
436 }
437 else
438 {
439 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
440 (ObjectSd->Sacl != NULL))
441 {
442 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
443 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
444 }
445 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
446 }
447
448 NewSd = ExAllocatePool(NonPagedPool,
449 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
450 DaclLength + SaclLength);
451 if (NewSd == NULL)
452 {
453 ObDereferenceObject(Object);
454 return STATUS_INSUFFICIENT_RESOURCES;
455 }
456
457 RtlCreateSecurityDescriptor(NewSd,
458 SECURITY_DESCRIPTOR_REVISION1);
459 NewSd->Control = Control;
460
461 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
462
463 if (OwnerLength != 0)
464 {
465 RtlCopyMemory((PVOID)Current,
466 Owner,
467 OwnerLength);
468 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
469 Current += OwnerLength;
470 }
471
472 if (GroupLength != 0)
473 {
474 RtlCopyMemory((PVOID)Current,
475 Group,
476 GroupLength);
477 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
478 Current += GroupLength;
479 }
480
481 if (DaclLength != 0)
482 {
483 RtlCopyMemory((PVOID)Current,
484 Dacl,
485 DaclLength);
486 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
487 Current += DaclLength;
488 }
489
490 if (SaclLength != 0)
491 {
492 RtlCopyMemory((PVOID)Current,
493 Sacl,
494 SaclLength);
495 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
496 Current += SaclLength;
497 }
498
499 /* Add the new SD */
500 Status = ObpAddSecurityDescriptor(NewSd,
501 &Header->SecurityDescriptor);
502 if (NT_SUCCESS(Status))
503 {
504 /* Remove the old security descriptor */
505 ObpRemoveSecurityDescriptor(ObjectSd);
506 }
507 else
508 {
509 /* Restore the old security descriptor */
510 Header->SecurityDescriptor = ObjectSd;
511 }
512
513 ExFreePool(NewSd);
514 }
515
516 ObDereferenceObject(Object);
517
518 return Status;
519 }
520
521 /* EOF */