- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[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 PAGED_CODE();
32
33 /* Build the new security descriptor */
34 Status = SeAssignSecurity(SecurityDescriptor,
35 AccessState->SecurityDescriptor,
36 &NewDescriptor,
37 (Type == ObDirectoryType),
38 &AccessState->SubjectSecurityContext,
39 &Type->TypeInfo.GenericMapping,
40 PagedPool);
41 if (!NT_SUCCESS(Status))
42 return Status;
43
44 /* Call the security method */
45 Status = Type->TypeInfo.SecurityProcedure(Object,
46 AssignSecurityDescriptor,
47 0,
48 NewDescriptor,
49 NULL,
50 NULL,
51 NonPagedPool,
52 NULL);
53
54 /* Release the new security descriptor */
55 SeDeassignSecurity(&NewDescriptor);
56
57 return Status;
58 }
59
60
61 /*
62 * @implemented
63 */
64 NTSTATUS STDCALL
65 ObGetObjectSecurity(IN PVOID Object,
66 OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
67 OUT PBOOLEAN MemoryAllocated)
68 {
69 PROS_OBJECT_HEADER Header;
70 ULONG Length;
71 NTSTATUS Status;
72
73 PAGED_CODE();
74
75 Header = BODY_TO_HEADER(Object);
76 if (Header->Type == NULL)
77 return STATUS_UNSUCCESSFUL;
78
79 if (Header->Type->TypeInfo.SecurityProcedure == NULL)
80 {
81 ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor);
82 *SecurityDescriptor = Header->SecurityDescriptor;
83 *MemoryAllocated = FALSE;
84 return STATUS_SUCCESS;
85 }
86
87 /* Get the security descriptor size */
88 Length = 0;
89 Status = Header->Type->TypeInfo.SecurityProcedure(Object,
90 QuerySecurityDescriptor,
91 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
92 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
93 NULL,
94 &Length,
95 NULL,
96 NonPagedPool,
97 NULL);
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->Type->TypeInfo.SecurityProcedure(Object,
109 QuerySecurityDescriptor,
110 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
111 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
112 *SecurityDescriptor,
113 &Length,
114 NULL,
115 NonPagedPool,
116 NULL);
117 if (!NT_SUCCESS(Status))
118 {
119 ExFreePool(*SecurityDescriptor);
120 return Status;
121 }
122
123 *MemoryAllocated = TRUE;
124
125 return STATUS_SUCCESS;
126 }
127
128
129 /*
130 * @implemented
131 */
132 VOID STDCALL
133 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
134 IN BOOLEAN MemoryAllocated)
135 {
136 PAGED_CODE();
137
138 if (SecurityDescriptor == NULL)
139 return;
140
141 if (MemoryAllocated)
142 {
143 ExFreePool(SecurityDescriptor);
144 }
145 else
146 {
147 ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor);
148 }
149 }
150
151
152 /*
153 * @implemented
154 */
155 NTSTATUS STDCALL
156 NtQuerySecurityObject(IN HANDLE Handle,
157 IN SECURITY_INFORMATION SecurityInformation,
158 OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
159 IN ULONG Length,
160 OUT PULONG ResultLength)
161 {
162 KPROCESSOR_MODE PreviousMode;
163 PVOID Object;
164 PROS_OBJECT_HEADER Header;
165 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
166 NTSTATUS Status = STATUS_SUCCESS;
167
168 PAGED_CODE();
169
170 PreviousMode = ExGetPreviousMode();
171
172 if (PreviousMode != KernelMode)
173 {
174 _SEH_TRY
175 {
176 ProbeForWrite(SecurityDescriptor,
177 Length,
178 sizeof(ULONG));
179 ProbeForWriteUlong(ResultLength);
180 }
181 _SEH_HANDLE
182 {
183 Status = _SEH_GetExceptionCode();
184 }
185 _SEH_END;
186
187 if (!NT_SUCCESS(Status)) return Status;
188 }
189
190 /* get the required access rights for the operation */
191 SeQuerySecurityAccessMask(SecurityInformation,
192 &DesiredAccess);
193
194 Status = ObReferenceObjectByHandle(Handle,
195 DesiredAccess,
196 NULL,
197 PreviousMode,
198 &Object,
199 NULL);
200
201 if (NT_SUCCESS(Status))
202 {
203 Header = BODY_TO_HEADER(Object);
204 ASSERT(Header->Type != NULL);
205
206 Status = Header->Type->TypeInfo.SecurityProcedure(Object,
207 QuerySecurityDescriptor,
208 SecurityInformation,
209 SecurityDescriptor,
210 &Length,
211 &Header->SecurityDescriptor,
212 Header->Type->TypeInfo.PoolType,
213 &Header->Type->TypeInfo.GenericMapping);
214
215 ObDereferenceObject(Object);
216
217 /* return the required length */
218 _SEH_TRY
219 {
220 *ResultLength = Length;
221 }
222 _SEH_HANDLE
223 {
224 Status = _SEH_GetExceptionCode();
225 }
226 _SEH_END;
227 }
228
229 return Status;
230 }
231
232
233 /*
234 * @implemented
235 */
236 NTSTATUS STDCALL
237 NtSetSecurityObject(IN HANDLE Handle,
238 IN SECURITY_INFORMATION SecurityInformation,
239 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
240 {
241 KPROCESSOR_MODE PreviousMode;
242 PVOID Object;
243 PROS_OBJECT_HEADER Header;
244 SECURITY_DESCRIPTOR_RELATIVE *CapturedSecurityDescriptor;
245 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
246 NTSTATUS Status;
247
248 PAGED_CODE();
249
250 /* make sure the caller doesn't pass a NULL security descriptor! */
251 if (SecurityDescriptor == NULL)
252 {
253 return STATUS_ACCESS_DENIED;
254 }
255
256 PreviousMode = ExGetPreviousMode();
257
258 /* capture and make a copy of the security descriptor */
259 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
260 PreviousMode,
261 PagedPool,
262 TRUE,
263 (PSECURITY_DESCRIPTOR*)&CapturedSecurityDescriptor);
264 if (!NT_SUCCESS(Status))
265 {
266 DPRINT1("Capturing the security descriptor failed! Status: 0x%lx\n", Status);
267 return Status;
268 }
269
270 /* make sure the security descriptor passed by the caller
271 is valid for the operation we're about to perform */
272 if (((SecurityInformation & OWNER_SECURITY_INFORMATION) &&
273 (CapturedSecurityDescriptor->Owner == 0)) ||
274 ((SecurityInformation & GROUP_SECURITY_INFORMATION) &&
275 (CapturedSecurityDescriptor->Group == 0)))
276 {
277 Status = STATUS_INVALID_SECURITY_DESCR;
278 }
279 else
280 {
281 /* get the required access rights for the operation */
282 SeSetSecurityAccessMask(SecurityInformation,
283 &DesiredAccess);
284
285 Status = ObReferenceObjectByHandle(Handle,
286 DesiredAccess,
287 NULL,
288 PreviousMode,
289 &Object,
290 NULL);
291
292 if (NT_SUCCESS(Status))
293 {
294 Header = BODY_TO_HEADER(Object);
295 ASSERT(Header->Type != NULL);
296
297 Status = Header->Type->TypeInfo.SecurityProcedure(Object,
298 SetSecurityDescriptor,
299 SecurityInformation,
300 (PSECURITY_DESCRIPTOR)SecurityDescriptor,
301 NULL,
302 &Header->SecurityDescriptor,
303 Header->Type->TypeInfo.PoolType,
304 &Header->Type->TypeInfo.GenericMapping);
305
306 ObDereferenceObject(Object);
307 }
308 }
309
310 /* release the descriptor */
311 SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedSecurityDescriptor,
312 PreviousMode,
313 TRUE);
314
315 return Status;
316 }
317
318
319 /*
320 * @unimplemented
321 */
322 NTSTATUS STDCALL
323 ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
324 OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
325 IN ULONG RefBias)
326 {
327 /* HACK: Return the same descriptor back */
328 PISECURITY_DESCRIPTOR SdCopy;
329 DPRINT1("ObLogSecurityDescriptor is not implemented!\n", InputSecurityDescriptor);
330
331 SdCopy = ExAllocatePool(PagedPool, sizeof(*SdCopy));
332 RtlMoveMemory(SdCopy, InputSecurityDescriptor, sizeof(*SdCopy));
333 *OutputSecurityDescriptor = SdCopy;
334 return STATUS_SUCCESS;
335 }
336
337
338 /*
339 * @unimplemented
340 */
341 VOID STDCALL
342 ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
343 IN ULONG Count)
344 {
345 DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n");
346 }
347
348 /* EOF */