Thomas Weidenmueller <w3seek@reactos.com>
[reactos.git] / reactos / ntoskrnl / se / sd.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/sd.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: David Welch <welch@cwcom.net>
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #include <internal/debug.h>
15
16 /* GLOBALS ******************************************************************/
17
18 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
19 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
20 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
21 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
22 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
23 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
24
25 /* FUNCTIONS ***************************************************************/
26
27 BOOLEAN INIT_FUNCTION
28 SepInitSDs(VOID)
29 {
30 /* Create PublicDefaultSd */
31 SePublicDefaultSd = ExAllocatePool(NonPagedPool,
32 sizeof(SECURITY_DESCRIPTOR));
33 if (SePublicDefaultSd == NULL)
34 return FALSE;
35
36 RtlCreateSecurityDescriptor(SePublicDefaultSd,
37 SECURITY_DESCRIPTOR_REVISION);
38 RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
39 TRUE,
40 SePublicDefaultDacl,
41 FALSE);
42
43 /* Create PublicDefaultUnrestrictedSd */
44 SePublicDefaultUnrestrictedSd = ExAllocatePool(NonPagedPool,
45 sizeof(SECURITY_DESCRIPTOR));
46 if (SePublicDefaultUnrestrictedSd == NULL)
47 return FALSE;
48
49 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
50 SECURITY_DESCRIPTOR_REVISION);
51 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
52 TRUE,
53 SePublicDefaultUnrestrictedDacl,
54 FALSE);
55
56 /* Create PublicOpenSd */
57 SePublicOpenSd = ExAllocatePool(NonPagedPool,
58 sizeof(SECURITY_DESCRIPTOR));
59 if (SePublicOpenSd == NULL)
60 return FALSE;
61
62 RtlCreateSecurityDescriptor(SePublicOpenSd,
63 SECURITY_DESCRIPTOR_REVISION);
64 RtlSetDaclSecurityDescriptor(SePublicOpenSd,
65 TRUE,
66 SePublicOpenDacl,
67 FALSE);
68
69 /* Create PublicOpenUnrestrictedSd */
70 SePublicOpenUnrestrictedSd = ExAllocatePool(NonPagedPool,
71 sizeof(SECURITY_DESCRIPTOR));
72 if (SePublicOpenUnrestrictedSd == NULL)
73 return FALSE;
74
75 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
76 SECURITY_DESCRIPTOR_REVISION);
77 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
78 TRUE,
79 SePublicOpenUnrestrictedDacl,
80 FALSE);
81
82 /* Create SystemDefaultSd */
83 SeSystemDefaultSd = ExAllocatePool(NonPagedPool,
84 sizeof(SECURITY_DESCRIPTOR));
85 if (SeSystemDefaultSd == NULL)
86 return FALSE;
87
88 RtlCreateSecurityDescriptor(SeSystemDefaultSd,
89 SECURITY_DESCRIPTOR_REVISION);
90 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
91 TRUE,
92 SeSystemDefaultDacl,
93 FALSE);
94
95 /* Create UnrestrictedSd */
96 SeUnrestrictedSd = ExAllocatePool(NonPagedPool,
97 sizeof(SECURITY_DESCRIPTOR));
98 if (SeUnrestrictedSd == NULL)
99 return FALSE;
100
101 RtlCreateSecurityDescriptor(SeUnrestrictedSd,
102 SECURITY_DESCRIPTOR_REVISION);
103 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
104 TRUE,
105 SeUnrestrictedDacl,
106 FALSE);
107
108 return TRUE;
109 }
110
111
112 NTSTATUS
113 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
114 IN KPROCESSOR_MODE AccessMode,
115 IN POOL_TYPE PoolType,
116 IN BOOLEAN CaptureIfKernel,
117 OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
118 OUT PBOOLEAN Present)
119 {
120 PSECURITY_QUALITY_OF_SERVICE CapturedQos;
121 NTSTATUS Status = STATUS_SUCCESS;
122
123 PAGED_CODE();
124
125 ASSERT(CapturedSecurityQualityOfService);
126 ASSERT(Present);
127
128 if(ObjectAttributes != NULL)
129 {
130 if(AccessMode != KernelMode)
131 {
132 SECURITY_QUALITY_OF_SERVICE SafeQos;
133
134 _SEH_TRY
135 {
136 ProbeForRead(ObjectAttributes,
137 sizeof(ObjectAttributes),
138 sizeof(ULONG));
139 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
140 {
141 if(ObjectAttributes->SecurityQualityOfService != NULL)
142 {
143 ProbeForRead(ObjectAttributes->SecurityQualityOfService,
144 sizeof(SECURITY_QUALITY_OF_SERVICE),
145 sizeof(ULONG));
146
147 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
148 sizeof(SECURITY_QUALITY_OF_SERVICE))
149 {
150 /* don't allocate memory here because ExAllocate should bugcheck
151 the system if it's buggy, SEH would catch that! So make a local
152 copy of the qos structure.*/
153 RtlCopyMemory(&SafeQos,
154 ObjectAttributes->SecurityQualityOfService,
155 sizeof(SECURITY_QUALITY_OF_SERVICE));
156 *Present = TRUE;
157 }
158 else
159 {
160 Status = STATUS_INVALID_PARAMETER;
161 }
162 }
163 else
164 {
165 *CapturedSecurityQualityOfService = NULL;
166 *Present = FALSE;
167 }
168 }
169 else
170 {
171 Status = STATUS_INVALID_PARAMETER;
172 }
173 }
174 _SEH_HANDLE
175 {
176 Status = _SEH_GetExceptionCode();
177 }
178 _SEH_END;
179
180 if(NT_SUCCESS(Status))
181 {
182 if(*Present)
183 {
184 CapturedQos = ExAllocatePool(PoolType,
185 sizeof(SECURITY_QUALITY_OF_SERVICE));
186 if(CapturedQos != NULL)
187 {
188 RtlCopyMemory(CapturedQos,
189 &SafeQos,
190 sizeof(SECURITY_QUALITY_OF_SERVICE));
191 *CapturedSecurityQualityOfService = CapturedQos;
192 }
193 else
194 {
195 Status = STATUS_INSUFFICIENT_RESOURCES;
196 }
197 }
198 else
199 {
200 *CapturedSecurityQualityOfService = NULL;
201 }
202 }
203 }
204 else
205 {
206 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
207 {
208 if(CaptureIfKernel)
209 {
210 if(ObjectAttributes->SecurityQualityOfService != NULL)
211 {
212 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
213 sizeof(SECURITY_QUALITY_OF_SERVICE))
214 {
215 CapturedQos = ExAllocatePool(PoolType,
216 sizeof(SECURITY_QUALITY_OF_SERVICE));
217 if(CapturedQos != NULL)
218 {
219 RtlCopyMemory(CapturedQos,
220 ObjectAttributes->SecurityQualityOfService,
221 sizeof(SECURITY_QUALITY_OF_SERVICE));
222 *CapturedSecurityQualityOfService = CapturedQos;
223 *Present = TRUE;
224 }
225 else
226 {
227 Status = STATUS_INSUFFICIENT_RESOURCES;
228 }
229 }
230 else
231 {
232 Status = STATUS_INVALID_PARAMETER;
233 }
234 }
235 else
236 {
237 *CapturedSecurityQualityOfService = NULL;
238 *Present = FALSE;
239 }
240 }
241 else
242 {
243 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
244 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
245 }
246 }
247 else
248 {
249 Status = STATUS_INVALID_PARAMETER;
250 }
251 }
252 }
253 else
254 {
255 *CapturedSecurityQualityOfService = NULL;
256 *Present = FALSE;
257 }
258
259 return Status;
260 }
261
262
263 VOID
264 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
265 IN KPROCESSOR_MODE AccessMode,
266 IN BOOLEAN CaptureIfKernel)
267 {
268 PAGED_CODE();
269
270 if(CapturedSecurityQualityOfService != NULL &&
271 (AccessMode == UserMode ||
272 (AccessMode == KernelMode && CaptureIfKernel)))
273 {
274 ExFreePool(CapturedSecurityQualityOfService);
275 }
276 }
277
278
279 /*
280 * @implemented
281 */
282 NTSTATUS
283 STDCALL
284 SeCaptureSecurityDescriptor(
285 IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
286 IN KPROCESSOR_MODE CurrentMode,
287 IN POOL_TYPE PoolType,
288 IN BOOLEAN CaptureIfKernel,
289 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
290 )
291 {
292 SECURITY_DESCRIPTOR DescriptorCopy;
293 PSECURITY_DESCRIPTOR NewDescriptor;
294 ULONG OwnerSAC = 0, GroupSAC = 0;
295 ULONG OwnerSize = 0, GroupSize = 0;
296 ULONG SaclSize = 0, DaclSize = 0;
297 ULONG DescriptorSize = 0;
298 NTSTATUS Status = STATUS_SUCCESS;
299
300 if(OriginalSecurityDescriptor != NULL)
301 {
302 if(CurrentMode != KernelMode)
303 {
304 _SEH_TRY
305 {
306 /* first only probe and copy until the control field of the descriptor
307 to determine whether it's a self-relative descriptor */
308 DescriptorSize = (ULONG)((ULONG_PTR)&OriginalSecurityDescriptor->Control -
309 (ULONG_PTR)OriginalSecurityDescriptor) +
310 sizeof(OriginalSecurityDescriptor->Control);
311 ProbeForRead(OriginalSecurityDescriptor,
312 DescriptorSize,
313 sizeof(ULONG));
314
315 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
316 {
317 Status = STATUS_UNKNOWN_REVISION;
318 _SEH_LEAVE;
319 }
320
321 /* make a copy on the stack */
322 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
323 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
324 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
325 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
326 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
327
328 /* probe and copy the entire security descriptor structure. The SIDs
329 and ACLs will be probed and copied later though */
330 ProbeForRead(OriginalSecurityDescriptor,
331 DescriptorSize,
332 sizeof(ULONG));
333 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
334 {
335 PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
336
337 DescriptorCopy.Owner = (PSID)RelSD->Owner;
338 DescriptorCopy.Group = (PSID)RelSD->Group;
339 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
340 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
341 }
342 else
343 {
344 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
345 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
346 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
347 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
348 }
349 }
350 _SEH_HANDLE
351 {
352 Status = _SEH_GetExceptionCode();
353 }
354 _SEH_END;
355
356 if(!NT_SUCCESS(Status))
357 {
358 return Status;
359 }
360 }
361 else if(!CaptureIfKernel)
362 {
363 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
364 {
365 return STATUS_UNKNOWN_REVISION;
366 }
367
368 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
369 return STATUS_SUCCESS;
370 }
371 else
372 {
373 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
374 {
375 return STATUS_UNKNOWN_REVISION;
376 }
377
378 /* make a copy on the stack */
379 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
380 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
381 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
382 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
383 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
384 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
385 {
386 PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
387
388 DescriptorCopy.Owner = (PSID)RelSD->Owner;
389 DescriptorCopy.Group = (PSID)RelSD->Group;
390 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
391 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
392 }
393 else
394 {
395 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
396 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
397 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
398 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
399 }
400 }
401
402 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
403 {
404 /* in case we're dealing with a self-relative descriptor, do a basic convert
405 to an absolute descriptor. We do this so we can simply access the data
406 using the pointers without calculating them again. */
407 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
408 if(DescriptorCopy.Owner != NULL)
409 {
410 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
411 }
412 if(DescriptorCopy.Group != NULL)
413 {
414 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
415 }
416 if(DescriptorCopy.Dacl != NULL)
417 {
418 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
419 }
420 if(DescriptorCopy.Sacl != NULL)
421 {
422 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
423 }
424 }
425
426 /* determine the size of the SIDs */
427 #define DetermineSIDSize(SidType) \
428 do { \
429 if(DescriptorCopy.SidType != NULL) \
430 { \
431 SID *SidType = (SID*)DescriptorCopy.SidType; \
432 \
433 if(CurrentMode != KernelMode) \
434 { \
435 /* securely access the buffers! */ \
436 _SEH_TRY \
437 { \
438 ProbeForRead(&SidType->SubAuthorityCount, \
439 sizeof(SidType->SubAuthorityCount), \
440 1); \
441 SidType##SAC = SidType->SubAuthorityCount; \
442 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
443 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
444 ProbeForRead(SidType, \
445 SidType##Size, \
446 sizeof(ULONG)); \
447 if(!RtlValidSid(SidType)) \
448 { \
449 Status = STATUS_INVALID_SID; \
450 } \
451 } \
452 _SEH_HANDLE \
453 { \
454 Status = _SEH_GetExceptionCode(); \
455 } \
456 _SEH_END; \
457 \
458 if(!NT_SUCCESS(Status)) \
459 { \
460 return Status; \
461 } \
462 } \
463 else \
464 { \
465 SidType##SAC = SidType->SubAuthorityCount; \
466 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
467 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
468 } \
469 } \
470 } while(0)
471
472 DetermineSIDSize(Owner);
473 DetermineSIDSize(Group);
474
475 /* determine the size of the ACLs */
476 #define DetermineACLSize(AclType, AclFlag) \
477 do { \
478 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
479 DescriptorCopy.AclType != NULL) \
480 { \
481 PACL AclType = (PACL)DescriptorCopy.AclType; \
482 \
483 if(CurrentMode != KernelMode) \
484 { \
485 /* securely access the buffers! */ \
486 _SEH_TRY \
487 { \
488 ProbeForRead(&AclType->AclSize, \
489 sizeof(AclType->AclSize), \
490 1); \
491 AclType##Size = AclType->AclSize; \
492 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
493 ProbeForRead(AclType, \
494 AclType##Size, \
495 sizeof(ULONG)); \
496 if(!RtlValidAcl(AclType)) \
497 { \
498 Status = STATUS_INVALID_ACL; \
499 } \
500 } \
501 _SEH_HANDLE \
502 { \
503 Status = _SEH_GetExceptionCode(); \
504 } \
505 _SEH_END; \
506 \
507 if(!NT_SUCCESS(Status)) \
508 { \
509 return Status; \
510 } \
511 } \
512 else \
513 { \
514 AclType##Size = AclType->AclSize; \
515 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
516 } \
517 } \
518 else \
519 { \
520 DescriptorCopy.AclType = NULL; \
521 } \
522 } while(0)
523
524 DetermineACLSize(Sacl, SACL);
525 DetermineACLSize(Dacl, DACL);
526
527 /* allocate enough memory to store a complete copy of a self-relative
528 security descriptor */
529 NewDescriptor = ExAllocatePool(PoolType,
530 DescriptorSize);
531 if(NewDescriptor != NULL)
532 {
533 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
534
535 NewDescriptor->Revision = DescriptorCopy.Revision;
536 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
537 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
538
539 _SEH_TRY
540 {
541 /* setup the offsets and copy the SIDs and ACLs to the new
542 self-relative security descriptor. Probing the pointers is not
543 neccessary anymore as we did that when collecting the sizes! */
544 #define CopySIDOrACL(Type) \
545 do { \
546 if(DescriptorCopy.Type != NULL) \
547 { \
548 NewDescriptor->Type = (PVOID)Offset; \
549 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
550 (ULONG_PTR)NewDescriptor->Type), \
551 DescriptorCopy.Type, \
552 Type##Size); \
553 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
554 } \
555 } while(0)
556
557 CopySIDOrACL(Owner);
558 CopySIDOrACL(Group);
559 CopySIDOrACL(Sacl);
560 CopySIDOrACL(Dacl);
561 }
562 _SEH_HANDLE
563 {
564 Status = _SEH_GetExceptionCode();
565 }
566 _SEH_END;
567
568 if(NT_SUCCESS(Status))
569 {
570 /* we're finally done! copy the pointer to the captured descriptor to
571 to the caller */
572 *CapturedSecurityDescriptor = NewDescriptor;
573 return STATUS_SUCCESS;
574 }
575 else
576 {
577 /* we failed to copy the data to the new descriptor */
578 ExFreePool(NewDescriptor);
579 }
580 }
581 else
582 {
583 Status = STATUS_INSUFFICIENT_RESOURCES;
584 }
585 }
586 else
587 {
588 /* nothing to do... */
589 *CapturedSecurityDescriptor = NULL;
590 }
591
592 return Status;
593 }
594
595 /*
596 * @implemented
597 */
598 NTSTATUS STDCALL
599 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
600 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
601 IN OUT PULONG Length,
602 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
603 {
604 PSECURITY_DESCRIPTOR ObjectSd;
605 PSECURITY_DESCRIPTOR_RELATIVE RelSD;
606 PSID Owner = NULL;
607 PSID Group = NULL;
608 PACL Dacl = NULL;
609 PACL Sacl = NULL;
610 ULONG OwnerLength = 0;
611 ULONG GroupLength = 0;
612 ULONG DaclLength = 0;
613 ULONG SaclLength = 0;
614 ULONG Control = 0;
615 ULONG_PTR Current;
616 ULONG SdLength;
617
618 RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
619
620 if (*ObjectsSecurityDescriptor == NULL)
621 {
622 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
623 {
624 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
625 return STATUS_BUFFER_TOO_SMALL;
626 }
627
628 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
629 RtlCreateSecurityDescriptorRelative(RelSD,
630 SECURITY_DESCRIPTOR_REVISION);
631 return STATUS_SUCCESS;
632 }
633
634 ObjectSd = *ObjectsSecurityDescriptor;
635
636 /* Calculate the required security descriptor length */
637 Control = SE_SELF_RELATIVE;
638 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
639 (ObjectSd->Owner != NULL))
640 {
641 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
642 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
643 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
644 }
645
646 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
647 (ObjectSd->Group != NULL))
648 {
649 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
650 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
651 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
652 }
653
654 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
655 (ObjectSd->Control & SE_DACL_PRESENT))
656 {
657 if (ObjectSd->Dacl != NULL)
658 {
659 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
660 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
661 }
662 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
663 }
664
665 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
666 (ObjectSd->Control & SE_SACL_PRESENT))
667 {
668 if (ObjectSd->Sacl != NULL)
669 {
670 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
671 SaclLength = ROUND_UP(Sacl->AclSize, 4);
672 }
673 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
674 }
675
676 SdLength = OwnerLength + GroupLength + DaclLength +
677 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
678 if (*Length < SdLength)
679 {
680 *Length = SdLength;
681 return STATUS_BUFFER_TOO_SMALL;
682 }
683
684 /* Build the new security descrtiptor */
685 RtlCreateSecurityDescriptorRelative(RelSD,
686 SECURITY_DESCRIPTOR_REVISION);
687 RelSD->Control = Control;
688
689 Current = (ULONG_PTR)(RelSD + 1);
690
691 if (OwnerLength != 0)
692 {
693 RtlCopyMemory((PVOID)Current,
694 Owner,
695 OwnerLength);
696 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
697 Current += OwnerLength;
698 }
699
700 if (GroupLength != 0)
701 {
702 RtlCopyMemory((PVOID)Current,
703 Group,
704 GroupLength);
705 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
706 Current += GroupLength;
707 }
708
709 if (DaclLength != 0)
710 {
711 RtlCopyMemory((PVOID)Current,
712 Dacl,
713 DaclLength);
714 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
715 Current += DaclLength;
716 }
717
718 if (SaclLength != 0)
719 {
720 RtlCopyMemory((PVOID)Current,
721 Sacl,
722 SaclLength);
723 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
724 Current += SaclLength;
725 }
726
727 *Length = SdLength;
728
729 return STATUS_SUCCESS;
730 }
731
732 /*
733 * @implemented
734 */
735 NTSTATUS
736 STDCALL
737 SeReleaseSecurityDescriptor(
738 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
739 IN KPROCESSOR_MODE CurrentMode,
740 IN BOOLEAN CaptureIfKernelMode
741 )
742 {
743 PAGED_CODE();
744
745 /* WARNING! You need to call this function with the same value for CurrentMode
746 and CaptureIfKernelMode that you previously passed to
747 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
748 if(CapturedSecurityDescriptor != NULL &&
749 (CurrentMode == UserMode ||
750 (CurrentMode == KernelMode && CaptureIfKernelMode)))
751 {
752 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
753 ExFreePool(CapturedSecurityDescriptor);
754 }
755
756 return STATUS_SUCCESS;
757 }
758
759 /*
760 * @unimplemented
761 */
762 NTSTATUS STDCALL
763 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
764 IN PSECURITY_INFORMATION SecurityInformation,
765 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
766 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
767 IN POOL_TYPE PoolType,
768 IN PGENERIC_MAPPING GenericMapping)
769 {
770 UNIMPLEMENTED;
771 return STATUS_NOT_IMPLEMENTED;
772 }
773
774 /*
775 * @unimplemented
776 */
777 NTSTATUS
778 STDCALL
779 SeSetSecurityDescriptorInfoEx(
780 IN PVOID Object OPTIONAL,
781 IN PSECURITY_INFORMATION SecurityInformation,
782 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
783 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
784 IN ULONG AutoInheritFlags,
785 IN POOL_TYPE PoolType,
786 IN PGENERIC_MAPPING GenericMapping
787 )
788 {
789 UNIMPLEMENTED;
790 return STATUS_NOT_IMPLEMENTED;
791 }
792
793
794 /*
795 * @implemented
796 */
797 BOOLEAN STDCALL
798 SeValidSecurityDescriptor(IN ULONG Length,
799 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
800 {
801 ULONG SdLength;
802 PISID Sid;
803 PACL Acl;
804
805 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
806 {
807 DPRINT1("Invalid Security Descriptor revision\n");
808 return FALSE;
809 }
810
811 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
812 {
813 DPRINT1("Invalid Security Descriptor revision\n");
814 return FALSE;
815 }
816
817 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
818 {
819 DPRINT1("No self-relative Security Descriptor\n");
820 return FALSE;
821 }
822
823 SdLength = sizeof(SECURITY_DESCRIPTOR);
824
825 /* Check Owner SID */
826 if (SecurityDescriptor->Owner == NULL)
827 {
828 DPRINT1("No Owner SID\n");
829 return FALSE;
830 }
831
832 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
833 {
834 DPRINT1("Invalid Owner SID alignment\n");
835 return FALSE;
836 }
837
838 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
839 if (Sid->Revision != SID_REVISION)
840 {
841 DPRINT1("Invalid Owner SID revision\n");
842 return FALSE;
843 }
844
845 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
846 if (Length < SdLength)
847 {
848 DPRINT1("Invalid Owner SID size\n");
849 return FALSE;
850 }
851
852 /* Check Group SID */
853 if (SecurityDescriptor->Group != NULL)
854 {
855 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
856 {
857 DPRINT1("Invalid Group SID alignment\n");
858 return FALSE;
859 }
860
861 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
862 if (Sid->Revision != SID_REVISION)
863 {
864 DPRINT1("Invalid Group SID revision\n");
865 return FALSE;
866 }
867
868 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
869 if (Length < SdLength)
870 {
871 DPRINT1("Invalid Group SID size\n");
872 return FALSE;
873 }
874 }
875
876 /* Check DACL */
877 if (SecurityDescriptor->Dacl != NULL)
878 {
879 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
880 {
881 DPRINT1("Invalid DACL alignment\n");
882 return FALSE;
883 }
884
885 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
886 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
887 (Acl->AclRevision > MAX_ACL_REVISION))
888 {
889 DPRINT1("Invalid DACL revision\n");
890 return FALSE;
891 }
892
893 SdLength += Acl->AclSize;
894 if (Length < SdLength)
895 {
896 DPRINT1("Invalid DACL size\n");
897 return FALSE;
898 }
899 }
900
901 /* Check SACL */
902 if (SecurityDescriptor->Sacl != NULL)
903 {
904 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
905 {
906 DPRINT1("Invalid SACL alignment\n");
907 return FALSE;
908 }
909
910 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
911 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
912 (Acl->AclRevision > MAX_ACL_REVISION))
913 {
914 DPRINT1("Invalid SACL revision\n");
915 return FALSE;
916 }
917
918 SdLength += Acl->AclSize;
919 if (Length < SdLength)
920 {
921 DPRINT1("Invalid SACL size\n");
922 return FALSE;
923 }
924 }
925
926 return TRUE;
927 }
928
929 /* EOF */