- Use SeQuerySecurityDescriptorInfo() to retrieve an objects security descriptor.
[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 #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 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner + (ULONG_PTR)SecurityDescriptor);
270 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
271 }
272 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
273 }
274 else
275 {
276 if (ObjectSd->Owner != NULL)
277 {
278 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
279 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
280 }
281 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
282 }
283
284 /* Get group and group size */
285 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
286 {
287 if (SecurityDescriptor->Group != NULL)
288 {
289 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group + (ULONG_PTR)SecurityDescriptor);
290 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
291 }
292 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
293 }
294 else
295 {
296 if (ObjectSd->Group != NULL)
297 {
298 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
299 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
300 }
301 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
302 }
303
304 /* Get DACL and DACL size */
305 if (SecurityInformation & DACL_SECURITY_INFORMATION)
306 {
307 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
308 (SecurityDescriptor->Dacl != NULL))
309 {
310 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl + (ULONG_PTR)SecurityDescriptor);
311 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
312 }
313 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
314 }
315 else
316 {
317 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
318 (ObjectSd->Dacl != NULL))
319 {
320 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
321 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
322 }
323 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
324 }
325
326 /* Get SACL and SACL size */
327 if (SecurityInformation & SACL_SECURITY_INFORMATION)
328 {
329 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
330 (SecurityDescriptor->Sacl != NULL))
331 {
332 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl + (ULONG_PTR)SecurityDescriptor);
333 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
334 }
335 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
336 }
337 else
338 {
339 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
340 (ObjectSd->Sacl != NULL))
341 {
342 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
343 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
344 }
345 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
346 }
347
348 NewSd = ExAllocatePool(NonPagedPool,
349 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
350 DaclLength + SaclLength);
351 if (NewSd == NULL)
352 {
353 ObDereferenceObject(Object);
354 return STATUS_INSUFFICIENT_RESOURCES;
355 }
356
357 RtlCreateSecurityDescriptor(NewSd,
358 SECURITY_DESCRIPTOR_REVISION1);
359 NewSd->Control = Control;
360
361 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
362
363 if (OwnerLength != 0)
364 {
365 RtlCopyMemory((PVOID)Current,
366 Owner,
367 OwnerLength);
368 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
369 Current += OwnerLength;
370 }
371
372 if (GroupLength != 0)
373 {
374 RtlCopyMemory((PVOID)Current,
375 Group,
376 GroupLength);
377 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
378 Current += GroupLength;
379 }
380
381 if (DaclLength != 0)
382 {
383 RtlCopyMemory((PVOID)Current,
384 Dacl,
385 DaclLength);
386 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
387 Current += DaclLength;
388 }
389
390 if (SaclLength != 0)
391 {
392 RtlCopyMemory((PVOID)Current,
393 Sacl,
394 SaclLength);
395 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
396 Current += SaclLength;
397 }
398
399 /* Add the new SD */
400 Status = ObpAddSecurityDescriptor(NewSd,
401 &Header->SecurityDescriptor);
402 if (NT_SUCCESS(Status))
403 {
404 /* Remove the old security descriptor */
405 ObpRemoveSecurityDescriptor(ObjectSd);
406 }
407 else
408 {
409 /* Restore the old security descriptor */
410 Header->SecurityDescriptor = ObjectSd;
411 }
412
413 ExFreePool(NewSd);
414 }
415
416 ObDereferenceObject(Object);
417
418 return Status;
419 }
420
421 /* EOF */