Implement NtQuerySecurityObject() for objects that keep the security in the object...
[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;
161 PSID Group;
162 PACL Dacl;
163 PACL Sacl;
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 * @unimplemented
312 */
313 NTSTATUS STDCALL
314 NtSetSecurityObject(IN HANDLE Handle,
315 IN SECURITY_INFORMATION SecurityInformation,
316 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
317 {
318 POBJECT_HEADER Header;
319 PVOID Object;
320 NTSTATUS Status;
321
322 Status = ObReferenceObjectByHandle(Handle,
323 (SecurityInformation & SACL_SECURITY_INFORMATION) ? ACCESS_SYSTEM_SECURITY : 0,
324 NULL,
325 KeGetPreviousMode(),
326 &Object,
327 NULL);
328 if (!NT_SUCCESS(Status))
329 {
330 return Status;
331 }
332
333 Header = BODY_TO_HEADER(Object);
334 if (Header->ObjectType != NULL)
335 {
336 ObDereferenceObject(Object);
337 return STATUS_UNSUCCESSFUL;
338 }
339
340 if (Header->ObjectType->Security != NULL)
341 {
342 Status = Header->ObjectType->Security(Object,
343 SetSecurityDescriptor,
344 SecurityInformation,
345 SecurityDescriptor,
346 NULL);
347 }
348 else
349 {
350 Status = STATUS_NOT_IMPLEMENTED;
351 }
352
353 ObDereferenceObject(Object);
354
355 return Status;
356 }
357
358 /* EOF */