fixed some warnings with gcc4 (mostly assignment differs in signedness warnings)
[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 RtlZeroMemory(&DescriptorCopy, sizeof(DescriptorCopy));
305
306 _SEH_TRY
307 {
308 /* first only probe and copy until the control field of the descriptor
309 to determine whether it's a self-relative descriptor */
310 DescriptorSize = (ULONG)((ULONG_PTR)&OriginalSecurityDescriptor->Control -
311 (ULONG_PTR)OriginalSecurityDescriptor) +
312 sizeof(OriginalSecurityDescriptor->Control);
313 ProbeForRead(OriginalSecurityDescriptor,
314 DescriptorSize,
315 sizeof(ULONG));
316
317 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
318 {
319 Status = STATUS_UNKNOWN_REVISION;
320 _SEH_LEAVE;
321 }
322
323 /* make a copy on the stack */
324 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
325 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
326 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
327 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
328 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
329
330 /* probe and copy the entire security descriptor structure. The SIDs
331 and ACLs will be probed and copied later though */
332 ProbeForRead(OriginalSecurityDescriptor,
333 DescriptorSize,
334 sizeof(ULONG));
335 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
336 {
337 PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
338
339 DescriptorCopy.Owner = (PSID)RelSD->Owner;
340 DescriptorCopy.Group = (PSID)RelSD->Group;
341 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
342 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
343 }
344 else
345 {
346 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
347 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
348 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
349 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
350 }
351 }
352 _SEH_HANDLE
353 {
354 Status = _SEH_GetExceptionCode();
355 }
356 _SEH_END;
357
358 if(!NT_SUCCESS(Status))
359 {
360 return Status;
361 }
362 }
363 else if(!CaptureIfKernel)
364 {
365 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
366 {
367 return STATUS_UNKNOWN_REVISION;
368 }
369
370 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
371 return STATUS_SUCCESS;
372 }
373 else
374 {
375 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
376 {
377 return STATUS_UNKNOWN_REVISION;
378 }
379
380 /* make a copy on the stack */
381 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
382 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
383 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
384 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
385 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
386 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
387 {
388 PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
389
390 DescriptorCopy.Owner = (PSID)RelSD->Owner;
391 DescriptorCopy.Group = (PSID)RelSD->Group;
392 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
393 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
394 }
395 else
396 {
397 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
398 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
399 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
400 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
401 }
402 }
403
404 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
405 {
406 /* in case we're dealing with a self-relative descriptor, do a basic convert
407 to an absolute descriptor. We do this so we can simply access the data
408 using the pointers without calculating them again. */
409 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
410 if(DescriptorCopy.Owner != NULL)
411 {
412 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
413 }
414 if(DescriptorCopy.Group != NULL)
415 {
416 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
417 }
418 if(DescriptorCopy.Dacl != NULL)
419 {
420 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
421 }
422 if(DescriptorCopy.Sacl != NULL)
423 {
424 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
425 }
426 }
427
428 /* determine the size of the SIDs */
429 #define DetermineSIDSize(SidType) \
430 do { \
431 if(DescriptorCopy.SidType != NULL) \
432 { \
433 SID *SidType = (SID*)DescriptorCopy.SidType; \
434 \
435 if(CurrentMode != KernelMode) \
436 { \
437 /* securely access the buffers! */ \
438 _SEH_TRY \
439 { \
440 ProbeForRead(&SidType->SubAuthorityCount, \
441 sizeof(SidType->SubAuthorityCount), \
442 1); \
443 SidType##SAC = SidType->SubAuthorityCount; \
444 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
445 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
446 ProbeForRead(SidType, \
447 SidType##Size, \
448 sizeof(ULONG)); \
449 if(!RtlValidSid(SidType)) \
450 { \
451 Status = STATUS_INVALID_SID; \
452 } \
453 } \
454 _SEH_HANDLE \
455 { \
456 Status = _SEH_GetExceptionCode(); \
457 } \
458 _SEH_END; \
459 \
460 if(!NT_SUCCESS(Status)) \
461 { \
462 return Status; \
463 } \
464 } \
465 else \
466 { \
467 SidType##SAC = SidType->SubAuthorityCount; \
468 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
469 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
470 } \
471 } \
472 } while(0)
473
474 DetermineSIDSize(Owner);
475 DetermineSIDSize(Group);
476
477 /* determine the size of the ACLs */
478 #define DetermineACLSize(AclType, AclFlag) \
479 do { \
480 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
481 DescriptorCopy.AclType != NULL) \
482 { \
483 PACL AclType = (PACL)DescriptorCopy.AclType; \
484 \
485 if(CurrentMode != KernelMode) \
486 { \
487 /* securely access the buffers! */ \
488 _SEH_TRY \
489 { \
490 ProbeForRead(&AclType->AclSize, \
491 sizeof(AclType->AclSize), \
492 1); \
493 AclType##Size = AclType->AclSize; \
494 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
495 ProbeForRead(AclType, \
496 AclType##Size, \
497 sizeof(ULONG)); \
498 if(!RtlValidAcl(AclType)) \
499 { \
500 Status = STATUS_INVALID_ACL; \
501 } \
502 } \
503 _SEH_HANDLE \
504 { \
505 Status = _SEH_GetExceptionCode(); \
506 } \
507 _SEH_END; \
508 \
509 if(!NT_SUCCESS(Status)) \
510 { \
511 return Status; \
512 } \
513 } \
514 else \
515 { \
516 AclType##Size = AclType->AclSize; \
517 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
518 } \
519 } \
520 else \
521 { \
522 DescriptorCopy.AclType = NULL; \
523 } \
524 } while(0)
525
526 DetermineACLSize(Sacl, SACL);
527 DetermineACLSize(Dacl, DACL);
528
529 /* allocate enough memory to store a complete copy of a self-relative
530 security descriptor */
531 NewDescriptor = ExAllocatePool(PoolType,
532 DescriptorSize);
533 if(NewDescriptor != NULL)
534 {
535 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
536
537 NewDescriptor->Revision = DescriptorCopy.Revision;
538 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
539 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
540
541 _SEH_TRY
542 {
543 /* setup the offsets and copy the SIDs and ACLs to the new
544 self-relative security descriptor. Probing the pointers is not
545 neccessary anymore as we did that when collecting the sizes! */
546 #define CopySIDOrACL(Type) \
547 do { \
548 if(DescriptorCopy.Type != NULL) \
549 { \
550 NewDescriptor->Type = (PVOID)Offset; \
551 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
552 (ULONG_PTR)NewDescriptor->Type), \
553 DescriptorCopy.Type, \
554 Type##Size); \
555 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
556 } \
557 } while(0)
558
559 CopySIDOrACL(Owner);
560 CopySIDOrACL(Group);
561 CopySIDOrACL(Sacl);
562 CopySIDOrACL(Dacl);
563 }
564 _SEH_HANDLE
565 {
566 Status = _SEH_GetExceptionCode();
567 }
568 _SEH_END;
569
570 if(NT_SUCCESS(Status))
571 {
572 /* we're finally done! copy the pointer to the captured descriptor to
573 to the caller */
574 *CapturedSecurityDescriptor = NewDescriptor;
575 return STATUS_SUCCESS;
576 }
577 else
578 {
579 /* we failed to copy the data to the new descriptor */
580 ExFreePool(NewDescriptor);
581 }
582 }
583 else
584 {
585 Status = STATUS_INSUFFICIENT_RESOURCES;
586 }
587 }
588 else
589 {
590 /* nothing to do... */
591 *CapturedSecurityDescriptor = NULL;
592 }
593
594 return Status;
595 }
596
597 /*
598 * @implemented
599 */
600 NTSTATUS STDCALL
601 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
602 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
603 IN OUT PULONG Length,
604 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
605 {
606 PSECURITY_DESCRIPTOR ObjectSd;
607 PSECURITY_DESCRIPTOR_RELATIVE RelSD;
608 PSID Owner = NULL;
609 PSID Group = NULL;
610 PACL Dacl = NULL;
611 PACL Sacl = NULL;
612 ULONG OwnerLength = 0;
613 ULONG GroupLength = 0;
614 ULONG DaclLength = 0;
615 ULONG SaclLength = 0;
616 ULONG Control = 0;
617 ULONG_PTR Current;
618 ULONG SdLength;
619
620 RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
621
622 if (*ObjectsSecurityDescriptor == NULL)
623 {
624 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
625 {
626 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
627 return STATUS_BUFFER_TOO_SMALL;
628 }
629
630 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
631 RtlCreateSecurityDescriptorRelative(RelSD,
632 SECURITY_DESCRIPTOR_REVISION);
633 return STATUS_SUCCESS;
634 }
635
636 ObjectSd = *ObjectsSecurityDescriptor;
637
638 /* Calculate the required security descriptor length */
639 Control = SE_SELF_RELATIVE;
640 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
641 (ObjectSd->Owner != NULL))
642 {
643 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
644 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
645 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
646 }
647
648 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
649 (ObjectSd->Group != NULL))
650 {
651 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
652 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
653 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
654 }
655
656 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
657 (ObjectSd->Control & SE_DACL_PRESENT))
658 {
659 if (ObjectSd->Dacl != NULL)
660 {
661 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
662 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
663 }
664 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
665 }
666
667 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
668 (ObjectSd->Control & SE_SACL_PRESENT))
669 {
670 if (ObjectSd->Sacl != NULL)
671 {
672 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
673 SaclLength = ROUND_UP(Sacl->AclSize, 4);
674 }
675 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
676 }
677
678 SdLength = OwnerLength + GroupLength + DaclLength +
679 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
680 if (*Length < SdLength)
681 {
682 *Length = SdLength;
683 return STATUS_BUFFER_TOO_SMALL;
684 }
685
686 /* Build the new security descrtiptor */
687 RtlCreateSecurityDescriptorRelative(RelSD,
688 SECURITY_DESCRIPTOR_REVISION);
689 RelSD->Control = Control;
690
691 Current = (ULONG_PTR)(RelSD + 1);
692
693 if (OwnerLength != 0)
694 {
695 RtlCopyMemory((PVOID)Current,
696 Owner,
697 OwnerLength);
698 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
699 Current += OwnerLength;
700 }
701
702 if (GroupLength != 0)
703 {
704 RtlCopyMemory((PVOID)Current,
705 Group,
706 GroupLength);
707 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
708 Current += GroupLength;
709 }
710
711 if (DaclLength != 0)
712 {
713 RtlCopyMemory((PVOID)Current,
714 Dacl,
715 DaclLength);
716 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
717 Current += DaclLength;
718 }
719
720 if (SaclLength != 0)
721 {
722 RtlCopyMemory((PVOID)Current,
723 Sacl,
724 SaclLength);
725 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
726 Current += SaclLength;
727 }
728
729 *Length = SdLength;
730
731 return STATUS_SUCCESS;
732 }
733
734 /*
735 * @implemented
736 */
737 NTSTATUS
738 STDCALL
739 SeReleaseSecurityDescriptor(
740 IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
741 IN KPROCESSOR_MODE CurrentMode,
742 IN BOOLEAN CaptureIfKernelMode
743 )
744 {
745 PAGED_CODE();
746
747 /* WARNING! You need to call this function with the same value for CurrentMode
748 and CaptureIfKernelMode that you previously passed to
749 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
750 if(CapturedSecurityDescriptor != NULL &&
751 (CurrentMode == UserMode ||
752 (CurrentMode == KernelMode && CaptureIfKernelMode)))
753 {
754 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
755 ExFreePool(CapturedSecurityDescriptor);
756 }
757
758 return STATUS_SUCCESS;
759 }
760
761 /*
762 * @unimplemented
763 */
764 NTSTATUS STDCALL
765 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
766 IN PSECURITY_INFORMATION SecurityInformation,
767 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
768 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
769 IN POOL_TYPE PoolType,
770 IN PGENERIC_MAPPING GenericMapping)
771 {
772 UNIMPLEMENTED;
773 return STATUS_NOT_IMPLEMENTED;
774 }
775
776 /*
777 * @unimplemented
778 */
779 NTSTATUS
780 STDCALL
781 SeSetSecurityDescriptorInfoEx(
782 IN PVOID Object OPTIONAL,
783 IN PSECURITY_INFORMATION SecurityInformation,
784 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
785 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
786 IN ULONG AutoInheritFlags,
787 IN POOL_TYPE PoolType,
788 IN PGENERIC_MAPPING GenericMapping
789 )
790 {
791 UNIMPLEMENTED;
792 return STATUS_NOT_IMPLEMENTED;
793 }
794
795
796 /*
797 * @implemented
798 */
799 BOOLEAN STDCALL
800 SeValidSecurityDescriptor(IN ULONG Length,
801 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
802 {
803 ULONG SdLength;
804 PISID Sid;
805 PACL Acl;
806
807 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
808 {
809 DPRINT1("Invalid Security Descriptor revision\n");
810 return FALSE;
811 }
812
813 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
814 {
815 DPRINT1("Invalid Security Descriptor revision\n");
816 return FALSE;
817 }
818
819 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
820 {
821 DPRINT1("No self-relative Security Descriptor\n");
822 return FALSE;
823 }
824
825 SdLength = sizeof(SECURITY_DESCRIPTOR);
826
827 /* Check Owner SID */
828 if (SecurityDescriptor->Owner == NULL)
829 {
830 DPRINT1("No Owner SID\n");
831 return FALSE;
832 }
833
834 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
835 {
836 DPRINT1("Invalid Owner SID alignment\n");
837 return FALSE;
838 }
839
840 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
841 if (Sid->Revision != SID_REVISION)
842 {
843 DPRINT1("Invalid Owner SID revision\n");
844 return FALSE;
845 }
846
847 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
848 if (Length < SdLength)
849 {
850 DPRINT1("Invalid Owner SID size\n");
851 return FALSE;
852 }
853
854 /* Check Group SID */
855 if (SecurityDescriptor->Group != NULL)
856 {
857 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
858 {
859 DPRINT1("Invalid Group SID alignment\n");
860 return FALSE;
861 }
862
863 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
864 if (Sid->Revision != SID_REVISION)
865 {
866 DPRINT1("Invalid Group SID revision\n");
867 return FALSE;
868 }
869
870 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
871 if (Length < SdLength)
872 {
873 DPRINT1("Invalid Group SID size\n");
874 return FALSE;
875 }
876 }
877
878 /* Check DACL */
879 if (SecurityDescriptor->Dacl != NULL)
880 {
881 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
882 {
883 DPRINT1("Invalid DACL alignment\n");
884 return FALSE;
885 }
886
887 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
888 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
889 (Acl->AclRevision > MAX_ACL_REVISION))
890 {
891 DPRINT1("Invalid DACL revision\n");
892 return FALSE;
893 }
894
895 SdLength += Acl->AclSize;
896 if (Length < SdLength)
897 {
898 DPRINT1("Invalid DACL size\n");
899 return FALSE;
900 }
901 }
902
903 /* Check SACL */
904 if (SecurityDescriptor->Sacl != NULL)
905 {
906 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
907 {
908 DPRINT1("Invalid SACL alignment\n");
909 return FALSE;
910 }
911
912 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
913 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
914 (Acl->AclRevision > MAX_ACL_REVISION))
915 {
916 DPRINT1("Invalid SACL revision\n");
917 return FALSE;
918 }
919
920 SdLength += Acl->AclSize;
921 if (Length < SdLength)
922 {
923 DPRINT1("Invalid SACL size\n");
924 return FALSE;
925 }
926 }
927
928 return TRUE;
929 }
930
931 /* EOF */