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