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