Sync tools to 45592
[reactos.git] / reactos / ntoskrnl / se / sd.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/sd.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: David Welch <welch@cwcom.net>
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, SepInitSDs)
18 #endif
19
20 /* GLOBALS ********************************************************************/
21
22 PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
23 PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
24 PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
25 PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
26 PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
27 PSECURITY_DESCRIPTOR SeUnrestrictedSd = NULL;
28
29 /* PRIVATE FUNCTIONS **********************************************************/
30
31 BOOLEAN
32 INIT_FUNCTION
33 NTAPI
34 SepInitSDs(VOID)
35 {
36 /* Create PublicDefaultSd */
37 SePublicDefaultSd = ExAllocatePoolWithTag(PagedPool,
38 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
39 if (SePublicDefaultSd == NULL)
40 return FALSE;
41
42 RtlCreateSecurityDescriptor(SePublicDefaultSd,
43 SECURITY_DESCRIPTOR_REVISION);
44 RtlSetDaclSecurityDescriptor(SePublicDefaultSd,
45 TRUE,
46 SePublicDefaultDacl,
47 FALSE);
48
49 /* Create PublicDefaultUnrestrictedSd */
50 SePublicDefaultUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
51 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
52 if (SePublicDefaultUnrestrictedSd == NULL)
53 return FALSE;
54
55 RtlCreateSecurityDescriptor(SePublicDefaultUnrestrictedSd,
56 SECURITY_DESCRIPTOR_REVISION);
57 RtlSetDaclSecurityDescriptor(SePublicDefaultUnrestrictedSd,
58 TRUE,
59 SePublicDefaultUnrestrictedDacl,
60 FALSE);
61
62 /* Create PublicOpenSd */
63 SePublicOpenSd = ExAllocatePoolWithTag(PagedPool,
64 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
65 if (SePublicOpenSd == NULL)
66 return FALSE;
67
68 RtlCreateSecurityDescriptor(SePublicOpenSd,
69 SECURITY_DESCRIPTOR_REVISION);
70 RtlSetDaclSecurityDescriptor(SePublicOpenSd,
71 TRUE,
72 SePublicOpenDacl,
73 FALSE);
74
75 /* Create PublicOpenUnrestrictedSd */
76 SePublicOpenUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
77 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
78 if (SePublicOpenUnrestrictedSd == NULL)
79 return FALSE;
80
81 RtlCreateSecurityDescriptor(SePublicOpenUnrestrictedSd,
82 SECURITY_DESCRIPTOR_REVISION);
83 RtlSetDaclSecurityDescriptor(SePublicOpenUnrestrictedSd,
84 TRUE,
85 SePublicOpenUnrestrictedDacl,
86 FALSE);
87
88 /* Create SystemDefaultSd */
89 SeSystemDefaultSd = ExAllocatePoolWithTag(PagedPool,
90 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
91 if (SeSystemDefaultSd == NULL)
92 return FALSE;
93
94 RtlCreateSecurityDescriptor(SeSystemDefaultSd,
95 SECURITY_DESCRIPTOR_REVISION);
96 RtlSetDaclSecurityDescriptor(SeSystemDefaultSd,
97 TRUE,
98 SeSystemDefaultDacl,
99 FALSE);
100
101 /* Create UnrestrictedSd */
102 SeUnrestrictedSd = ExAllocatePoolWithTag(PagedPool,
103 sizeof(SECURITY_DESCRIPTOR), TAG_SD);
104 if (SeUnrestrictedSd == NULL)
105 return FALSE;
106
107 RtlCreateSecurityDescriptor(SeUnrestrictedSd,
108 SECURITY_DESCRIPTOR_REVISION);
109 RtlSetDaclSecurityDescriptor(SeUnrestrictedSd,
110 TRUE,
111 SeUnrestrictedDacl,
112 FALSE);
113
114 return TRUE;
115 }
116
117 NTSTATUS
118 NTAPI
119 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
120 PISECURITY_DESCRIPTOR SecurityDescriptor,
121 PULONG BufferLength)
122 {
123 ULONG_PTR Current;
124 ULONG SidSize;
125 ULONG SdSize;
126 NTSTATUS Status;
127 PISECURITY_DESCRIPTOR_RELATIVE SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
128
129 DPRINT("SeSetWorldSecurityDescriptor() called\n");
130
131 if (SecurityInformation == 0)
132 {
133 return STATUS_ACCESS_DENIED;
134 }
135
136 /* calculate the minimum size of the buffer */
137 SidSize = RtlLengthSid(SeWorldSid);
138 SdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
139 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
140 SdSize += SidSize;
141 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
142 SdSize += SidSize;
143 if (SecurityInformation & DACL_SECURITY_INFORMATION)
144 {
145 SdSize += sizeof(ACL) + sizeof(ACE) + SidSize;
146 }
147
148 if (*BufferLength < SdSize)
149 {
150 *BufferLength = SdSize;
151 return STATUS_BUFFER_TOO_SMALL;
152 }
153
154 *BufferLength = SdSize;
155
156 Status = RtlCreateSecurityDescriptorRelative(SdRel,
157 SECURITY_DESCRIPTOR_REVISION);
158 if (!NT_SUCCESS(Status))
159 {
160 return Status;
161 }
162
163 Current = (ULONG_PTR)(SdRel + 1);
164
165 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
166 {
167 RtlCopyMemory((PVOID)Current,
168 SeWorldSid,
169 SidSize);
170 SdRel->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
171 Current += SidSize;
172 }
173
174 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
175 {
176 RtlCopyMemory((PVOID)Current,
177 SeWorldSid,
178 SidSize);
179 SdRel->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
180 Current += SidSize;
181 }
182
183 if (SecurityInformation & DACL_SECURITY_INFORMATION)
184 {
185 PACL Dacl = (PACL)Current;
186 SdRel->Control |= SE_DACL_PRESENT;
187
188 Status = RtlCreateAcl(Dacl,
189 sizeof(ACL) + sizeof(ACE) + SidSize,
190 ACL_REVISION);
191 if (!NT_SUCCESS(Status))
192 return Status;
193
194 Status = RtlAddAccessAllowedAce(Dacl,
195 ACL_REVISION,
196 GENERIC_ALL,
197 SeWorldSid);
198 if (!NT_SUCCESS(Status))
199 return Status;
200
201 SdRel->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
202 }
203
204 if (SecurityInformation & SACL_SECURITY_INFORMATION)
205 {
206 /* FIXME - SdRel->Control |= SE_SACL_PRESENT; */
207 }
208
209 return STATUS_SUCCESS;
210 }
211
212
213 NTSTATUS
214 NTAPI
215 SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
216 IN KPROCESSOR_MODE AccessMode,
217 IN POOL_TYPE PoolType,
218 IN BOOLEAN CaptureIfKernel,
219 OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
220 OUT PBOOLEAN Present)
221 {
222 PSECURITY_QUALITY_OF_SERVICE CapturedQos;
223 NTSTATUS Status = STATUS_SUCCESS;
224
225 PAGED_CODE();
226
227 ASSERT(CapturedSecurityQualityOfService);
228 ASSERT(Present);
229
230 if(ObjectAttributes != NULL)
231 {
232 if(AccessMode != KernelMode)
233 {
234 SECURITY_QUALITY_OF_SERVICE SafeQos;
235
236 _SEH2_TRY
237 {
238 ProbeForRead(ObjectAttributes,
239 sizeof(OBJECT_ATTRIBUTES),
240 sizeof(ULONG));
241 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
242 {
243 if(ObjectAttributes->SecurityQualityOfService != NULL)
244 {
245 ProbeForRead(ObjectAttributes->SecurityQualityOfService,
246 sizeof(SECURITY_QUALITY_OF_SERVICE),
247 sizeof(ULONG));
248
249 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
250 sizeof(SECURITY_QUALITY_OF_SERVICE))
251 {
252 /* don't allocate memory here because ExAllocate should bugcheck
253 the system if it's buggy, SEH would catch that! So make a local
254 copy of the qos structure.*/
255 RtlCopyMemory(&SafeQos,
256 ObjectAttributes->SecurityQualityOfService,
257 sizeof(SECURITY_QUALITY_OF_SERVICE));
258 *Present = TRUE;
259 }
260 else
261 {
262 Status = STATUS_INVALID_PARAMETER;
263 }
264 }
265 else
266 {
267 *CapturedSecurityQualityOfService = NULL;
268 *Present = FALSE;
269 }
270 }
271 else
272 {
273 Status = STATUS_INVALID_PARAMETER;
274 }
275 }
276 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
277 {
278 Status = _SEH2_GetExceptionCode();
279 }
280 _SEH2_END;
281
282 if(NT_SUCCESS(Status))
283 {
284 if(*Present)
285 {
286 CapturedQos = ExAllocatePool(PoolType,
287 sizeof(SECURITY_QUALITY_OF_SERVICE));
288 if(CapturedQos != NULL)
289 {
290 RtlCopyMemory(CapturedQos,
291 &SafeQos,
292 sizeof(SECURITY_QUALITY_OF_SERVICE));
293 *CapturedSecurityQualityOfService = CapturedQos;
294 }
295 else
296 {
297 Status = STATUS_INSUFFICIENT_RESOURCES;
298 }
299 }
300 else
301 {
302 *CapturedSecurityQualityOfService = NULL;
303 }
304 }
305 }
306 else
307 {
308 if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
309 {
310 if(CaptureIfKernel)
311 {
312 if(ObjectAttributes->SecurityQualityOfService != NULL)
313 {
314 if(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
315 sizeof(SECURITY_QUALITY_OF_SERVICE))
316 {
317 CapturedQos = ExAllocatePool(PoolType,
318 sizeof(SECURITY_QUALITY_OF_SERVICE));
319 if(CapturedQos != NULL)
320 {
321 RtlCopyMemory(CapturedQos,
322 ObjectAttributes->SecurityQualityOfService,
323 sizeof(SECURITY_QUALITY_OF_SERVICE));
324 *CapturedSecurityQualityOfService = CapturedQos;
325 *Present = TRUE;
326 }
327 else
328 {
329 Status = STATUS_INSUFFICIENT_RESOURCES;
330 }
331 }
332 else
333 {
334 Status = STATUS_INVALID_PARAMETER;
335 }
336 }
337 else
338 {
339 *CapturedSecurityQualityOfService = NULL;
340 *Present = FALSE;
341 }
342 }
343 else
344 {
345 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
346 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
347 }
348 }
349 else
350 {
351 Status = STATUS_INVALID_PARAMETER;
352 }
353 }
354 }
355 else
356 {
357 *CapturedSecurityQualityOfService = NULL;
358 *Present = FALSE;
359 }
360
361 return Status;
362 }
363
364
365 VOID
366 NTAPI
367 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
368 IN KPROCESSOR_MODE AccessMode,
369 IN BOOLEAN CaptureIfKernel)
370 {
371 PAGED_CODE();
372
373 if(CapturedSecurityQualityOfService != NULL &&
374 (AccessMode != KernelMode || CaptureIfKernel))
375 {
376 ExFreePool(CapturedSecurityQualityOfService);
377 }
378 }
379
380 /* PUBLIC FUNCTIONS ***********************************************************/
381
382 /*
383 * @implemented
384 */
385 NTSTATUS
386 NTAPI
387 SeCaptureSecurityDescriptor(IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
388 IN KPROCESSOR_MODE CurrentMode,
389 IN POOL_TYPE PoolType,
390 IN BOOLEAN CaptureIfKernel,
391 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
392 {
393 PISECURITY_DESCRIPTOR OriginalSecurityDescriptor = _OriginalSecurityDescriptor;
394 SECURITY_DESCRIPTOR DescriptorCopy;
395 PISECURITY_DESCRIPTOR NewDescriptor;
396 ULONG OwnerSAC = 0, GroupSAC = 0;
397 ULONG OwnerSize = 0, GroupSize = 0;
398 ULONG SaclSize = 0, DaclSize = 0;
399 ULONG DescriptorSize = 0;
400 NTSTATUS Status;
401
402 if(OriginalSecurityDescriptor != NULL)
403 {
404 if(CurrentMode != KernelMode)
405 {
406 RtlZeroMemory(&DescriptorCopy, sizeof(DescriptorCopy));
407
408 _SEH2_TRY
409 {
410 /* first only probe and copy until the control field of the descriptor
411 to determine whether it's a self-relative descriptor */
412 DescriptorSize = FIELD_OFFSET(SECURITY_DESCRIPTOR,
413 Owner);
414 ProbeForRead(OriginalSecurityDescriptor,
415 DescriptorSize,
416 sizeof(ULONG));
417
418 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
419 {
420 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
421 }
422
423 /* make a copy on the stack */
424 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
425 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
426 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
427 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
428 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
429
430 /* probe and copy the entire security descriptor structure. The SIDs
431 and ACLs will be probed and copied later though */
432 ProbeForRead(OriginalSecurityDescriptor,
433 DescriptorSize,
434 sizeof(ULONG));
435 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
436 {
437 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
438
439 DescriptorCopy.Owner = (PSID)((PCHAR)RelSD + RelSD->Owner);
440 DescriptorCopy.Group = (PSID)((PCHAR)RelSD + RelSD->Group);
441 DescriptorCopy.Sacl = (PACL)((PCHAR)RelSD + RelSD->Sacl);
442 DescriptorCopy.Dacl = (PACL)((PCHAR)RelSD + RelSD->Dacl);
443 }
444 else
445 {
446 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
447 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
448 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
449 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
450 }
451 }
452 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
453 {
454 /* Return the exception code */
455 _SEH2_YIELD(return _SEH2_GetExceptionCode());
456 }
457 _SEH2_END;
458 }
459 else if(!CaptureIfKernel)
460 {
461 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
462 {
463 return STATUS_UNKNOWN_REVISION;
464 }
465
466 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
467 return STATUS_SUCCESS;
468 }
469 else
470 {
471 if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
472 {
473 return STATUS_UNKNOWN_REVISION;
474 }
475
476 /* make a copy on the stack */
477 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
478 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
479 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
480 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
481 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
482 if(DescriptorCopy.Control & SE_SELF_RELATIVE)
483 {
484 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
485
486 DescriptorCopy.Owner = (PSID)((PCHAR)RelSD + RelSD->Owner);
487 DescriptorCopy.Group = (PSID)((PCHAR)RelSD + RelSD->Group);
488 DescriptorCopy.Sacl = (PACL)((PCHAR)RelSD + RelSD->Sacl);
489 DescriptorCopy.Dacl = (PACL)((PCHAR)RelSD + RelSD->Dacl);
490 }
491 else
492 {
493 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
494 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
495 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
496 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
497 }
498 }
499
500 /* determine the size of the SIDs */
501 #define DetermineSIDSize(SidType) \
502 do { \
503 if(DescriptorCopy.SidType != NULL) \
504 { \
505 SID *SidType = (SID*)DescriptorCopy.SidType; \
506 \
507 if(CurrentMode != KernelMode) \
508 { \
509 /* securely access the buffers! */ \
510 _SEH2_TRY \
511 { \
512 SidType##SAC = ProbeForReadUchar(&SidType->SubAuthorityCount); \
513 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
514 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
515 ProbeForRead(SidType, \
516 SidType##Size, \
517 sizeof(ULONG)); \
518 } \
519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
520 { \
521 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
522 } \
523 _SEH2_END; \
524 \
525 } \
526 else \
527 { \
528 SidType##SAC = SidType->SubAuthorityCount; \
529 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
530 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
531 } \
532 } \
533 } while(0)
534
535 DetermineSIDSize(Owner);
536 DetermineSIDSize(Group);
537
538 #undef DetermineSIDSize
539
540 /* determine the size of the ACLs */
541 #define DetermineACLSize(AclType, AclFlag) \
542 do { \
543 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
544 DescriptorCopy.AclType != NULL) \
545 { \
546 PACL AclType = (PACL)DescriptorCopy.AclType; \
547 \
548 if(CurrentMode != KernelMode) \
549 { \
550 /* securely access the buffers! */ \
551 _SEH2_TRY \
552 { \
553 AclType##Size = ProbeForReadUshort(&AclType->AclSize); \
554 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
555 ProbeForRead(AclType, \
556 AclType##Size, \
557 sizeof(ULONG)); \
558 } \
559 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
560 { \
561 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
562 } \
563 _SEH2_END; \
564 \
565 } \
566 else \
567 { \
568 AclType##Size = AclType->AclSize; \
569 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
570 } \
571 } \
572 else \
573 { \
574 DescriptorCopy.AclType = NULL; \
575 } \
576 } while(0)
577
578 DetermineACLSize(Sacl, SACL);
579 DetermineACLSize(Dacl, DACL);
580
581 #undef DetermineACLSize
582
583 /* allocate enough memory to store a complete copy of a self-relative
584 security descriptor */
585 NewDescriptor = ExAllocatePoolWithTag(PoolType,
586 DescriptorSize,
587 TAG_SD);
588 if(NewDescriptor != NULL)
589 {
590 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
591
592 RtlZeroMemory(NewDescriptor, DescriptorSize);
593 NewDescriptor->Revision = DescriptorCopy.Revision;
594 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
595 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
596
597 _SEH2_TRY
598 {
599 /* setup the offsets and copy the SIDs and ACLs to the new
600 self-relative security descriptor. Probing the pointers is not
601 neccessary anymore as we did that when collecting the sizes!
602 Make sure to validate the SIDs and ACLs *again* as they could have
603 been modified in the meanwhile! */
604 #define CopySID(Type) \
605 do { \
606 if(DescriptorCopy.Type != NULL) \
607 { \
608 NewDescriptor->Type = (PVOID)Offset; \
609 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
610 (ULONG_PTR)NewDescriptor->Type), \
611 DescriptorCopy.Type, \
612 Type##Size); \
613 if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
614 (ULONG_PTR)NewDescriptor->Type))) \
615 { \
616 RtlRaiseStatus(STATUS_INVALID_SID); \
617 } \
618 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
619 } \
620 } while(0)
621
622 CopySID(Owner);
623 CopySID(Group);
624
625 #undef CopySID
626
627 #define CopyACL(Type) \
628 do { \
629 if(DescriptorCopy.Type != NULL) \
630 { \
631 NewDescriptor->Type = (PVOID)Offset; \
632 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
633 (ULONG_PTR)NewDescriptor->Type), \
634 DescriptorCopy.Type, \
635 Type##Size); \
636 if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
637 (ULONG_PTR)NewDescriptor->Type))) \
638 { \
639 RtlRaiseStatus(STATUS_INVALID_ACL); \
640 } \
641 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
642 } \
643 } while(0)
644
645 CopyACL(Sacl);
646 CopyACL(Dacl);
647
648 #undef CopyACL
649 }
650 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
651 {
652 /* we failed to copy the data to the new descriptor */
653 ExFreePool(NewDescriptor);
654 _SEH2_YIELD(return _SEH2_GetExceptionCode());
655 }
656 _SEH2_END;
657
658 /* we're finally done! copy the pointer to the captured descriptor to
659 to the caller */
660 *CapturedSecurityDescriptor = NewDescriptor;
661 return STATUS_SUCCESS;
662
663 }
664 else
665 {
666 Status = STATUS_INSUFFICIENT_RESOURCES;
667 }
668 }
669 else
670 {
671 /* nothing to do... */
672 *CapturedSecurityDescriptor = NULL;
673 }
674
675 return Status;
676 }
677
678 /*
679 * @implemented
680 */
681 NTSTATUS NTAPI
682 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
683 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
684 IN OUT PULONG Length,
685 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
686 {
687 PISECURITY_DESCRIPTOR ObjectSd;
688 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
689 PSID Owner = NULL;
690 PSID Group = NULL;
691 PACL Dacl = NULL;
692 PACL Sacl = NULL;
693 ULONG OwnerLength = 0;
694 ULONG GroupLength = 0;
695 ULONG DaclLength = 0;
696 ULONG SaclLength = 0;
697 ULONG Control = 0;
698 ULONG_PTR Current;
699 ULONG SdLength;
700
701 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
702
703 if (*ObjectsSecurityDescriptor == NULL)
704 {
705 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
706 {
707 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
708 return STATUS_BUFFER_TOO_SMALL;
709 }
710
711 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
712 RtlCreateSecurityDescriptorRelative(RelSD,
713 SECURITY_DESCRIPTOR_REVISION);
714 return STATUS_SUCCESS;
715 }
716
717 ObjectSd = *ObjectsSecurityDescriptor;
718
719 /* Calculate the required security descriptor length */
720 Control = SE_SELF_RELATIVE;
721 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
722 (ObjectSd->Owner != NULL))
723 {
724 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
725 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
726 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
727 }
728
729 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
730 (ObjectSd->Group != NULL))
731 {
732 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
733 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
734 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
735 }
736
737 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
738 (ObjectSd->Control & SE_DACL_PRESENT))
739 {
740 if (ObjectSd->Dacl != NULL)
741 {
742 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
743 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
744 }
745 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
746 }
747
748 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
749 (ObjectSd->Control & SE_SACL_PRESENT))
750 {
751 if (ObjectSd->Sacl != NULL)
752 {
753 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
754 SaclLength = ROUND_UP(Sacl->AclSize, 4);
755 }
756 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
757 }
758
759 SdLength = OwnerLength + GroupLength + DaclLength +
760 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
761 if (*Length < SdLength)
762 {
763 *Length = SdLength;
764 return STATUS_BUFFER_TOO_SMALL;
765 }
766
767 /* Build the new security descrtiptor */
768 RtlCreateSecurityDescriptorRelative(RelSD,
769 SECURITY_DESCRIPTOR_REVISION);
770 RelSD->Control = (USHORT)Control;
771
772 Current = (ULONG_PTR)(RelSD + 1);
773
774 if (OwnerLength != 0)
775 {
776 RtlCopyMemory((PVOID)Current,
777 Owner,
778 OwnerLength);
779 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
780 Current += OwnerLength;
781 }
782
783 if (GroupLength != 0)
784 {
785 RtlCopyMemory((PVOID)Current,
786 Group,
787 GroupLength);
788 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
789 Current += GroupLength;
790 }
791
792 if (DaclLength != 0)
793 {
794 RtlCopyMemory((PVOID)Current,
795 Dacl,
796 DaclLength);
797 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
798 Current += DaclLength;
799 }
800
801 if (SaclLength != 0)
802 {
803 RtlCopyMemory((PVOID)Current,
804 Sacl,
805 SaclLength);
806 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
807 Current += SaclLength;
808 }
809
810 *Length = SdLength;
811
812 return STATUS_SUCCESS;
813 }
814
815 /*
816 * @implemented
817 */
818 NTSTATUS
819 NTAPI
820 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
821 IN KPROCESSOR_MODE CurrentMode,
822 IN BOOLEAN CaptureIfKernelMode)
823 {
824 PAGED_CODE();
825
826 /* WARNING! You need to call this function with the same value for CurrentMode
827 and CaptureIfKernelMode that you previously passed to
828 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
829 if(CapturedSecurityDescriptor != NULL &&
830 (CurrentMode != KernelMode ||
831 (CurrentMode == KernelMode && CaptureIfKernelMode)))
832 {
833 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
834 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
835 }
836
837 return STATUS_SUCCESS;
838 }
839
840 /*
841 * @implemented
842 */
843 NTSTATUS NTAPI
844 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
845 IN PSECURITY_INFORMATION _SecurityInformation,
846 IN PSECURITY_DESCRIPTOR _SecurityDescriptor,
847 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
848 IN POOL_TYPE PoolType,
849 IN PGENERIC_MAPPING GenericMapping)
850 {
851 PISECURITY_DESCRIPTOR ObjectSd;
852 PISECURITY_DESCRIPTOR NewSd;
853 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
854 PSID Owner = 0;
855 PSID Group = 0;
856 PACL Dacl = 0;
857 PACL Sacl = 0;
858 ULONG OwnerLength = 0;
859 ULONG GroupLength = 0;
860 ULONG DaclLength = 0;
861 ULONG SaclLength = 0;
862 ULONG Control = 0;
863 ULONG_PTR Current;
864 SECURITY_INFORMATION SecurityInformation;
865
866 ObjectSd = *ObjectsSecurityDescriptor;
867
868 if (!ObjectSd)
869 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
870
871 SecurityInformation = *_SecurityInformation;
872
873 /* Get owner and owner size */
874 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
875 {
876 if (SecurityDescriptor->Owner != NULL)
877 {
878 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
879 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
880 (ULONG_PTR)SecurityDescriptor);
881 else
882 Owner = (PSID)SecurityDescriptor->Owner;
883 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
884 }
885 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
886 }
887 else
888 {
889 if (ObjectSd->Owner != NULL)
890 {
891 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
892 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
893 }
894 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
895 }
896
897 /* Get group and group size */
898 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
899 {
900 if (SecurityDescriptor->Group != NULL)
901 {
902 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
903 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
904 (ULONG_PTR)SecurityDescriptor);
905 else
906 Group = (PSID)SecurityDescriptor->Group;
907 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
908 }
909 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
910 }
911 else
912 {
913 if (ObjectSd->Group != NULL)
914 {
915 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
916 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
917 }
918 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
919 }
920
921 /* Get DACL and DACL size */
922 if (SecurityInformation & DACL_SECURITY_INFORMATION)
923 {
924 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
925 (SecurityDescriptor->Dacl != NULL))
926 {
927 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
928 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
929 (ULONG_PTR)SecurityDescriptor);
930 else
931 Dacl = (PACL)SecurityDescriptor->Dacl;
932
933 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
934 }
935 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
936 }
937 else
938 {
939 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
940 (ObjectSd->Dacl != NULL))
941 {
942 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
943 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
944 }
945 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
946 }
947
948 /* Get SACL and SACL size */
949 if (SecurityInformation & SACL_SECURITY_INFORMATION)
950 {
951 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
952 (SecurityDescriptor->Sacl != NULL))
953 {
954 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
955 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
956 (ULONG_PTR)SecurityDescriptor);
957 else
958 Sacl = (PACL)SecurityDescriptor->Sacl;
959 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
960 }
961 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
962 }
963 else
964 {
965 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
966 (ObjectSd->Sacl != NULL))
967 {
968 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
969 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
970 }
971 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
972 }
973
974 NewSd = ExAllocatePool(NonPagedPool,
975 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
976 DaclLength + SaclLength);
977 if (NewSd == NULL)
978 {
979 ObDereferenceObject(Object);
980 return STATUS_INSUFFICIENT_RESOURCES;
981 }
982
983 RtlCreateSecurityDescriptor(NewSd,
984 SECURITY_DESCRIPTOR_REVISION1);
985 /* We always build a self-relative descriptor */
986 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
987
988 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
989
990 if (OwnerLength != 0)
991 {
992 RtlCopyMemory((PVOID)Current,
993 Owner,
994 OwnerLength);
995 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
996 Current += OwnerLength;
997 }
998
999 if (GroupLength != 0)
1000 {
1001 RtlCopyMemory((PVOID)Current,
1002 Group,
1003 GroupLength);
1004 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
1005 Current += GroupLength;
1006 }
1007
1008 if (DaclLength != 0)
1009 {
1010 RtlCopyMemory((PVOID)Current,
1011 Dacl,
1012 DaclLength);
1013 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
1014 Current += DaclLength;
1015 }
1016
1017 if (SaclLength != 0)
1018 {
1019 RtlCopyMemory((PVOID)Current,
1020 Sacl,
1021 SaclLength);
1022 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
1023 Current += SaclLength;
1024 }
1025
1026 *ObjectsSecurityDescriptor = NewSd;
1027 return STATUS_SUCCESS;
1028 }
1029
1030 /*
1031 * @unimplemented
1032 */
1033 NTSTATUS
1034 NTAPI
1035 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL,
1036 IN PSECURITY_INFORMATION SecurityInformation,
1037 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
1038 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
1039 IN ULONG AutoInheritFlags,
1040 IN POOL_TYPE PoolType,
1041 IN PGENERIC_MAPPING GenericMapping)
1042 {
1043 PISECURITY_DESCRIPTOR ObjectSd = *ObjectsSecurityDescriptor;
1044
1045 if (!ObjectSd)
1046 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
1047
1048 UNIMPLEMENTED;
1049 return STATUS_NOT_IMPLEMENTED;
1050 }
1051
1052
1053 /*
1054 * @implemented
1055 */
1056 BOOLEAN NTAPI
1057 SeValidSecurityDescriptor(IN ULONG Length,
1058 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1059 {
1060 ULONG SdLength;
1061 PISID Sid;
1062 PACL Acl;
1063 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
1064
1065 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1066 {
1067 DPRINT1("Invalid Security Descriptor revision\n");
1068 return FALSE;
1069 }
1070
1071 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1072 {
1073 DPRINT1("Invalid Security Descriptor revision\n");
1074 return FALSE;
1075 }
1076
1077 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1078 {
1079 DPRINT1("No self-relative Security Descriptor\n");
1080 return FALSE;
1081 }
1082
1083 SdLength = sizeof(SECURITY_DESCRIPTOR);
1084
1085 /* Check Owner SID */
1086 if (SecurityDescriptor->Owner == NULL)
1087 {
1088 DPRINT1("No Owner SID\n");
1089 return FALSE;
1090 }
1091
1092 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
1093 {
1094 DPRINT1("Invalid Owner SID alignment\n");
1095 return FALSE;
1096 }
1097
1098 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
1099 if (Sid->Revision != SID_REVISION)
1100 {
1101 DPRINT1("Invalid Owner SID revision\n");
1102 return FALSE;
1103 }
1104
1105 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1106 if (Length < SdLength)
1107 {
1108 DPRINT1("Invalid Owner SID size\n");
1109 return FALSE;
1110 }
1111
1112 /* Check Group SID */
1113 if (SecurityDescriptor->Group != NULL)
1114 {
1115 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
1116 {
1117 DPRINT1("Invalid Group SID alignment\n");
1118 return FALSE;
1119 }
1120
1121 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
1122 if (Sid->Revision != SID_REVISION)
1123 {
1124 DPRINT1("Invalid Group SID revision\n");
1125 return FALSE;
1126 }
1127
1128 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1129 if (Length < SdLength)
1130 {
1131 DPRINT1("Invalid Group SID size\n");
1132 return FALSE;
1133 }
1134 }
1135
1136 /* Check DACL */
1137 if (SecurityDescriptor->Dacl != NULL)
1138 {
1139 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1140 {
1141 DPRINT1("Invalid DACL alignment\n");
1142 return FALSE;
1143 }
1144
1145 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1146 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1147 (Acl->AclRevision > MAX_ACL_REVISION))
1148 {
1149 DPRINT1("Invalid DACL revision\n");
1150 return FALSE;
1151 }
1152
1153 SdLength += Acl->AclSize;
1154 if (Length < SdLength)
1155 {
1156 DPRINT1("Invalid DACL size\n");
1157 return FALSE;
1158 }
1159 }
1160
1161 /* Check SACL */
1162 if (SecurityDescriptor->Sacl != NULL)
1163 {
1164 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1165 {
1166 DPRINT1("Invalid SACL alignment\n");
1167 return FALSE;
1168 }
1169
1170 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1171 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1172 (Acl->AclRevision > MAX_ACL_REVISION))
1173 {
1174 DPRINT1("Invalid SACL revision\n");
1175 return FALSE;
1176 }
1177
1178 SdLength += Acl->AclSize;
1179 if (Length < SdLength)
1180 {
1181 DPRINT1("Invalid SACL size\n");
1182 return FALSE;
1183 }
1184 }
1185
1186 return TRUE;
1187 }
1188
1189 /*
1190 * @implemented
1191 */
1192 NTSTATUS NTAPI
1193 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
1194 {
1195 PAGED_CODE();
1196
1197 if (*SecurityDescriptor != NULL)
1198 {
1199 ExFreePool(*SecurityDescriptor);
1200 *SecurityDescriptor = NULL;
1201 }
1202
1203 return STATUS_SUCCESS;
1204 }
1205
1206
1207 /*
1208 * @unimplemented
1209 */
1210 NTSTATUS NTAPI
1211 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
1212 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
1213 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
1214 IN GUID *ObjectType OPTIONAL,
1215 IN BOOLEAN IsDirectoryObject,
1216 IN ULONG AutoInheritFlags,
1217 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
1218 IN PGENERIC_MAPPING GenericMapping,
1219 IN POOL_TYPE PoolType)
1220 {
1221 UNIMPLEMENTED;
1222 return STATUS_NOT_IMPLEMENTED;
1223 }
1224
1225 /*
1226 * @implemented
1227 */
1228 NTSTATUS NTAPI
1229 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
1230 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
1231 PSECURITY_DESCRIPTOR *NewDescriptor,
1232 BOOLEAN IsDirectoryObject,
1233 PSECURITY_SUBJECT_CONTEXT SubjectContext,
1234 PGENERIC_MAPPING GenericMapping,
1235 POOL_TYPE PoolType)
1236 {
1237 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1238 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1239 PISECURITY_DESCRIPTOR Descriptor;
1240 PTOKEN Token;
1241 ULONG OwnerLength = 0;
1242 ULONG GroupLength = 0;
1243 ULONG DaclLength = 0;
1244 ULONG SaclLength = 0;
1245 ULONG Length = 0;
1246 ULONG Control = 0;
1247 ULONG_PTR Current;
1248 PSID Owner = NULL;
1249 PSID Group = NULL;
1250 PACL Dacl = NULL;
1251 PACL Sacl = NULL;
1252
1253 PAGED_CODE();
1254
1255 /* Lock subject context */
1256 SeLockSubjectContext(SubjectContext);
1257
1258 if (SubjectContext->ClientToken != NULL)
1259 {
1260 Token = SubjectContext->ClientToken;
1261 }
1262 else
1263 {
1264 Token = SubjectContext->PrimaryToken;
1265 }
1266
1267
1268 /* Inherit the Owner SID */
1269 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
1270 {
1271 DPRINT("Use explicit owner sid!\n");
1272 Owner = ExplicitDescriptor->Owner;
1273
1274 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1275 {
1276 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
1277
1278 }
1279 }
1280 else
1281 {
1282 if (Token != NULL)
1283 {
1284 DPRINT("Use token owner sid!\n");
1285 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1286 }
1287 else
1288 {
1289 DPRINT("Use default owner sid!\n");
1290 Owner = SeLocalSystemSid;
1291 }
1292
1293 Control |= SE_OWNER_DEFAULTED;
1294 }
1295
1296 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
1297
1298
1299 /* Inherit the Group SID */
1300 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
1301 {
1302 DPRINT("Use explicit group sid!\n");
1303 Group = ExplicitDescriptor->Group;
1304 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1305 {
1306 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
1307 }
1308 }
1309 else
1310 {
1311 if (Token != NULL)
1312 {
1313 DPRINT("Use token group sid!\n");
1314 Group = Token->PrimaryGroup;
1315 }
1316 else
1317 {
1318 DPRINT("Use default group sid!\n");
1319 Group = SeLocalSystemSid;
1320 }
1321
1322 Control |= SE_OWNER_DEFAULTED;
1323 }
1324
1325 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
1326
1327
1328 /* Inherit the DACL */
1329 if (ExplicitDescriptor != NULL &&
1330 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1331 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1332 {
1333 DPRINT("Use explicit DACL!\n");
1334 Dacl = ExplicitDescriptor->Dacl;
1335 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1336 {
1337 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
1338 }
1339
1340 Control |= SE_DACL_PRESENT;
1341 }
1342 else if (ParentDescriptor != NULL &&
1343 (ParentDescriptor->Control & SE_DACL_PRESENT))
1344 {
1345 DPRINT("Use parent DACL!\n");
1346 /* FIXME: Inherit */
1347 Dacl = ParentDescriptor->Dacl;
1348 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1349 {
1350 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
1351 }
1352 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1353 }
1354 else if (Token != NULL && Token->DefaultDacl != NULL)
1355 {
1356 DPRINT("Use token default DACL!\n");
1357 /* FIXME: Inherit */
1358 Dacl = Token->DefaultDacl;
1359 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1360 }
1361 else
1362 {
1363 DPRINT("Use NULL DACL!\n");
1364 Dacl = NULL;
1365 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1366 }
1367
1368 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
1369
1370
1371 /* Inherit the SACL */
1372 if (ExplicitDescriptor != NULL &&
1373 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1374 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1375 {
1376 DPRINT("Use explicit SACL!\n");
1377 Sacl = ExplicitDescriptor->Sacl;
1378 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1379 {
1380 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
1381 }
1382
1383 Control |= SE_SACL_PRESENT;
1384 }
1385 else if (ParentDescriptor != NULL &&
1386 (ParentDescriptor->Control & SE_SACL_PRESENT))
1387 {
1388 DPRINT("Use parent SACL!\n");
1389 /* FIXME: Inherit */
1390 Sacl = ParentDescriptor->Sacl;
1391 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1392 {
1393 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
1394 }
1395 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
1396 }
1397
1398 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
1399
1400
1401 /* Allocate and initialize the new security descriptor */
1402 Length = sizeof(SECURITY_DESCRIPTOR) +
1403 OwnerLength + GroupLength + DaclLength + SaclLength;
1404
1405 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
1406 sizeof(SECURITY_DESCRIPTOR),
1407 OwnerLength,
1408 GroupLength,
1409 DaclLength,
1410 SaclLength);
1411
1412 Descriptor = ExAllocatePoolWithTag(PagedPool,
1413 Length,
1414 TAG_SD);
1415 if (Descriptor == NULL)
1416 {
1417 DPRINT1("ExAlloctePool() failed\n");
1418 /* FIXME: Unlock subject context */
1419 return STATUS_INSUFFICIENT_RESOURCES;
1420 }
1421
1422 RtlZeroMemory( Descriptor, Length );
1423 RtlCreateSecurityDescriptor(Descriptor,
1424 SECURITY_DESCRIPTOR_REVISION);
1425
1426 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
1427
1428 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
1429
1430 if (SaclLength != 0)
1431 {
1432 RtlCopyMemory((PVOID)Current,
1433 Sacl,
1434 SaclLength);
1435 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1436 Current += SaclLength;
1437 }
1438
1439 if (DaclLength != 0)
1440 {
1441 RtlCopyMemory((PVOID)Current,
1442 Dacl,
1443 DaclLength);
1444 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1445 Current += DaclLength;
1446 }
1447
1448 if (OwnerLength != 0)
1449 {
1450 RtlCopyMemory((PVOID)Current,
1451 Owner,
1452 OwnerLength);
1453 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1454 Current += OwnerLength;
1455 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
1456 }
1457 else
1458 DPRINT("Owner of %x is zero length\n", Descriptor);
1459
1460 if (GroupLength != 0)
1461 {
1462 memmove((PVOID)Current,
1463 Group,
1464 GroupLength);
1465 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1466 }
1467
1468 /* Unlock subject context */
1469 SeUnlockSubjectContext(SubjectContext);
1470
1471 *NewDescriptor = Descriptor;
1472
1473 DPRINT("Descrptor %x\n", Descriptor);
1474 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1475
1476 return STATUS_SUCCESS;
1477 }
1478
1479 /* EOF */