Timo/Physicus: Please validate for AMD64.
[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)RelSD->Owner;
440 DescriptorCopy.Group = (PSID)RelSD->Group;
441 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
442 DescriptorCopy.Dacl = (PACL)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)RelSD->Owner;
487 DescriptorCopy.Group = (PSID)RelSD->Group;
488 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
489 DescriptorCopy.Dacl = (PACL)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 if (DescriptorCopy.Control & SE_SELF_RELATIVE)
501 {
502 /* in case we're dealing with a self-relative descriptor, do a basic convert
503 to an absolute descriptor. We do this so we can simply access the data
504 using the pointers without calculating them again. */
505 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
506 if (DescriptorCopy.Owner != NULL)
507 {
508 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
509 }
510 if (DescriptorCopy.Group != NULL)
511 {
512 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
513 }
514 if (DescriptorCopy.Dacl != NULL)
515 {
516 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
517 }
518 if (DescriptorCopy.Sacl != NULL)
519 {
520 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
521 }
522 }
523
524 /* determine the size of the SIDs */
525 #define DetermineSIDSize(SidType) \
526 do { \
527 if(DescriptorCopy.SidType != NULL) \
528 { \
529 SID *SidType = (SID*)DescriptorCopy.SidType; \
530 \
531 if(CurrentMode != KernelMode) \
532 { \
533 /* securely access the buffers! */ \
534 _SEH2_TRY \
535 { \
536 SidType##SAC = ProbeForReadUchar(&SidType->SubAuthorityCount); \
537 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
538 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
539 ProbeForRead(SidType, \
540 SidType##Size, \
541 sizeof(ULONG)); \
542 } \
543 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
544 { \
545 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
546 } \
547 _SEH2_END; \
548 \
549 } \
550 else \
551 { \
552 SidType##SAC = SidType->SubAuthorityCount; \
553 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
554 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
555 } \
556 } \
557 } while(0)
558
559 DetermineSIDSize(Owner);
560 DetermineSIDSize(Group);
561
562 #undef DetermineSIDSize
563
564 /* determine the size of the ACLs */
565 #define DetermineACLSize(AclType, AclFlag) \
566 do { \
567 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
568 DescriptorCopy.AclType != NULL) \
569 { \
570 PACL AclType = (PACL)DescriptorCopy.AclType; \
571 \
572 if(CurrentMode != KernelMode) \
573 { \
574 /* securely access the buffers! */ \
575 _SEH2_TRY \
576 { \
577 AclType##Size = ProbeForReadUshort(&AclType->AclSize); \
578 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
579 ProbeForRead(AclType, \
580 AclType##Size, \
581 sizeof(ULONG)); \
582 } \
583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
584 { \
585 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
586 } \
587 _SEH2_END; \
588 \
589 } \
590 else \
591 { \
592 AclType##Size = AclType->AclSize; \
593 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
594 } \
595 } \
596 else \
597 { \
598 DescriptorCopy.AclType = NULL; \
599 } \
600 } while(0)
601
602 DetermineACLSize(Sacl, SACL);
603 DetermineACLSize(Dacl, DACL);
604
605 #undef DetermineACLSize
606
607 /* allocate enough memory to store a complete copy of a self-relative
608 security descriptor */
609 NewDescriptor = ExAllocatePoolWithTag(PoolType,
610 DescriptorSize,
611 TAG_SD);
612 if(NewDescriptor != NULL)
613 {
614 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
615
616 RtlZeroMemory(NewDescriptor, DescriptorSize);
617 NewDescriptor->Revision = DescriptorCopy.Revision;
618 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
619 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
620
621 _SEH2_TRY
622 {
623 /* setup the offsets and copy the SIDs and ACLs to the new
624 self-relative security descriptor. Probing the pointers is not
625 neccessary anymore as we did that when collecting the sizes!
626 Make sure to validate the SIDs and ACLs *again* as they could have
627 been modified in the meanwhile! */
628 #define CopySID(Type) \
629 do { \
630 if(DescriptorCopy.Type != NULL) \
631 { \
632 NewDescriptor->Type = (PVOID)Offset; \
633 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
634 (ULONG_PTR)NewDescriptor->Type), \
635 DescriptorCopy.Type, \
636 Type##Size); \
637 if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
638 (ULONG_PTR)NewDescriptor->Type))) \
639 { \
640 RtlRaiseStatus(STATUS_INVALID_SID); \
641 } \
642 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
643 } \
644 } while(0)
645
646 CopySID(Owner);
647 CopySID(Group);
648
649 #undef CopySID
650
651 #define CopyACL(Type) \
652 do { \
653 if(DescriptorCopy.Type != NULL) \
654 { \
655 NewDescriptor->Type = (PVOID)Offset; \
656 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
657 (ULONG_PTR)NewDescriptor->Type), \
658 DescriptorCopy.Type, \
659 Type##Size); \
660 if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
661 (ULONG_PTR)NewDescriptor->Type))) \
662 { \
663 RtlRaiseStatus(STATUS_INVALID_ACL); \
664 } \
665 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
666 } \
667 } while(0)
668
669 CopyACL(Sacl);
670 CopyACL(Dacl);
671
672 #undef CopyACL
673 }
674 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
675 {
676 /* we failed to copy the data to the new descriptor */
677 ExFreePool(NewDescriptor);
678 _SEH2_YIELD(return _SEH2_GetExceptionCode());
679 }
680 _SEH2_END;
681
682 /* we're finally done! copy the pointer to the captured descriptor to
683 to the caller */
684 *CapturedSecurityDescriptor = NewDescriptor;
685 return STATUS_SUCCESS;
686 }
687 else
688 {
689 Status = STATUS_INSUFFICIENT_RESOURCES;
690 }
691 }
692 else
693 {
694 /* nothing to do... */
695 *CapturedSecurityDescriptor = NULL;
696 }
697
698 return Status;
699 }
700
701 /*
702 * @implemented
703 */
704 NTSTATUS NTAPI
705 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
706 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
707 IN OUT PULONG Length,
708 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
709 {
710 PISECURITY_DESCRIPTOR ObjectSd;
711 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
712 PSID Owner = NULL;
713 PSID Group = NULL;
714 PACL Dacl = NULL;
715 PACL Sacl = NULL;
716 ULONG OwnerLength = 0;
717 ULONG GroupLength = 0;
718 ULONG DaclLength = 0;
719 ULONG SaclLength = 0;
720 ULONG Control = 0;
721 ULONG_PTR Current;
722 ULONG SdLength;
723
724 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
725
726 if (*ObjectsSecurityDescriptor == NULL)
727 {
728 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
729 {
730 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
731 return STATUS_BUFFER_TOO_SMALL;
732 }
733
734 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
735 RtlCreateSecurityDescriptorRelative(RelSD,
736 SECURITY_DESCRIPTOR_REVISION);
737 return STATUS_SUCCESS;
738 }
739
740 ObjectSd = *ObjectsSecurityDescriptor;
741
742 /* Calculate the required security descriptor length */
743 Control = SE_SELF_RELATIVE;
744 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
745 (ObjectSd->Owner != NULL))
746 {
747 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
748 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
749 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
750 }
751
752 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
753 (ObjectSd->Group != NULL))
754 {
755 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
756 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
757 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
758 }
759
760 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
761 (ObjectSd->Control & SE_DACL_PRESENT))
762 {
763 if (ObjectSd->Dacl != NULL)
764 {
765 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
766 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
767 }
768 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
769 }
770
771 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
772 (ObjectSd->Control & SE_SACL_PRESENT))
773 {
774 if (ObjectSd->Sacl != NULL)
775 {
776 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
777 SaclLength = ROUND_UP(Sacl->AclSize, 4);
778 }
779 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
780 }
781
782 SdLength = OwnerLength + GroupLength + DaclLength +
783 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
784 if (*Length < SdLength)
785 {
786 *Length = SdLength;
787 return STATUS_BUFFER_TOO_SMALL;
788 }
789
790 /* Build the new security descrtiptor */
791 RtlCreateSecurityDescriptorRelative(RelSD,
792 SECURITY_DESCRIPTOR_REVISION);
793 RelSD->Control = (USHORT)Control;
794
795 Current = (ULONG_PTR)(RelSD + 1);
796
797 if (OwnerLength != 0)
798 {
799 RtlCopyMemory((PVOID)Current,
800 Owner,
801 OwnerLength);
802 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
803 Current += OwnerLength;
804 }
805
806 if (GroupLength != 0)
807 {
808 RtlCopyMemory((PVOID)Current,
809 Group,
810 GroupLength);
811 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
812 Current += GroupLength;
813 }
814
815 if (DaclLength != 0)
816 {
817 RtlCopyMemory((PVOID)Current,
818 Dacl,
819 DaclLength);
820 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
821 Current += DaclLength;
822 }
823
824 if (SaclLength != 0)
825 {
826 RtlCopyMemory((PVOID)Current,
827 Sacl,
828 SaclLength);
829 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
830 Current += SaclLength;
831 }
832
833 *Length = SdLength;
834
835 return STATUS_SUCCESS;
836 }
837
838 /*
839 * @implemented
840 */
841 NTSTATUS
842 NTAPI
843 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
844 IN KPROCESSOR_MODE CurrentMode,
845 IN BOOLEAN CaptureIfKernelMode)
846 {
847 PAGED_CODE();
848
849 /* WARNING! You need to call this function with the same value for CurrentMode
850 and CaptureIfKernelMode that you previously passed to
851 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
852 if(CapturedSecurityDescriptor != NULL &&
853 (CurrentMode != KernelMode ||
854 (CurrentMode == KernelMode && CaptureIfKernelMode)))
855 {
856 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
857 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
858 }
859
860 return STATUS_SUCCESS;
861 }
862
863 /*
864 * @implemented
865 */
866 NTSTATUS NTAPI
867 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
868 IN PSECURITY_INFORMATION _SecurityInformation,
869 IN PSECURITY_DESCRIPTOR _SecurityDescriptor,
870 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
871 IN POOL_TYPE PoolType,
872 IN PGENERIC_MAPPING GenericMapping)
873 {
874 PISECURITY_DESCRIPTOR ObjectSd;
875 PISECURITY_DESCRIPTOR NewSd;
876 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
877 PSID Owner = 0;
878 PSID Group = 0;
879 PACL Dacl = 0;
880 PACL Sacl = 0;
881 ULONG OwnerLength = 0;
882 ULONG GroupLength = 0;
883 ULONG DaclLength = 0;
884 ULONG SaclLength = 0;
885 ULONG Control = 0;
886 ULONG_PTR Current;
887 SECURITY_INFORMATION SecurityInformation;
888
889 ObjectSd = *ObjectsSecurityDescriptor;
890
891 if (!ObjectSd)
892 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
893
894 SecurityInformation = *_SecurityInformation;
895
896 /* Get owner and owner size */
897 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
898 {
899 if (SecurityDescriptor->Owner != NULL)
900 {
901 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
902 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
903 (ULONG_PTR)SecurityDescriptor);
904 else
905 Owner = (PSID)SecurityDescriptor->Owner;
906 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
907 }
908
909 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
910 }
911 else
912 {
913 if (ObjectSd->Owner != NULL)
914 {
915 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
916 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
917 }
918
919 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
920 }
921
922 /* Get group and group size */
923 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
924 {
925 if (SecurityDescriptor->Group != NULL)
926 {
927 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
928 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
929 (ULONG_PTR)SecurityDescriptor);
930 else
931 Group = (PSID)SecurityDescriptor->Group;
932 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
933 }
934
935 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
936 }
937 else
938 {
939 if (ObjectSd->Group != NULL)
940 {
941 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
942 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
943 }
944
945 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
946 }
947
948 /* Get DACL and DACL size */
949 if (SecurityInformation & DACL_SECURITY_INFORMATION)
950 {
951 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
952 (SecurityDescriptor->Dacl != NULL))
953 {
954 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
955 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
956 (ULONG_PTR)SecurityDescriptor);
957 else
958 Dacl = (PACL)SecurityDescriptor->Dacl;
959
960 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
961 }
962
963 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
964 }
965 else
966 {
967 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
968 (ObjectSd->Dacl != NULL))
969 {
970 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
971 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
972 }
973
974 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
975 }
976
977 /* Get SACL and SACL size */
978 if (SecurityInformation & SACL_SECURITY_INFORMATION)
979 {
980 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
981 (SecurityDescriptor->Sacl != NULL))
982 {
983 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
984 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
985 (ULONG_PTR)SecurityDescriptor);
986 else
987 Sacl = (PACL)SecurityDescriptor->Sacl;
988 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
989 }
990
991 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
992 }
993 else
994 {
995 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
996 (ObjectSd->Sacl != NULL))
997 {
998 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
999 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
1000 }
1001
1002 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
1003 }
1004
1005 NewSd = ExAllocatePool(NonPagedPool,
1006 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
1007 DaclLength + SaclLength);
1008 if (NewSd == NULL)
1009 {
1010 ObDereferenceObject(Object);
1011 return STATUS_INSUFFICIENT_RESOURCES;
1012 }
1013
1014 RtlCreateSecurityDescriptor(NewSd,
1015 SECURITY_DESCRIPTOR_REVISION1);
1016
1017 /* We always build a self-relative descriptor */
1018 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
1019
1020 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
1021
1022 if (OwnerLength != 0)
1023 {
1024 RtlCopyMemory((PVOID)Current,
1025 Owner,
1026 OwnerLength);
1027 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
1028 Current += OwnerLength;
1029 }
1030
1031 if (GroupLength != 0)
1032 {
1033 RtlCopyMemory((PVOID)Current,
1034 Group,
1035 GroupLength);
1036 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
1037 Current += GroupLength;
1038 }
1039
1040 if (DaclLength != 0)
1041 {
1042 RtlCopyMemory((PVOID)Current,
1043 Dacl,
1044 DaclLength);
1045 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
1046 Current += DaclLength;
1047 }
1048
1049 if (SaclLength != 0)
1050 {
1051 RtlCopyMemory((PVOID)Current,
1052 Sacl,
1053 SaclLength);
1054 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
1055 Current += SaclLength;
1056 }
1057
1058 *ObjectsSecurityDescriptor = NewSd;
1059 return STATUS_SUCCESS;
1060 }
1061
1062 /*
1063 * @unimplemented
1064 */
1065 NTSTATUS
1066 NTAPI
1067 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL,
1068 IN PSECURITY_INFORMATION SecurityInformation,
1069 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
1070 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
1071 IN ULONG AutoInheritFlags,
1072 IN POOL_TYPE PoolType,
1073 IN PGENERIC_MAPPING GenericMapping)
1074 {
1075 PISECURITY_DESCRIPTOR ObjectSd = *ObjectsSecurityDescriptor;
1076
1077 if (!ObjectSd)
1078 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
1079
1080 UNIMPLEMENTED;
1081 return STATUS_NOT_IMPLEMENTED;
1082 }
1083
1084
1085 /*
1086 * @implemented
1087 */
1088 BOOLEAN NTAPI
1089 SeValidSecurityDescriptor(IN ULONG Length,
1090 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1091 {
1092 ULONG SdLength;
1093 PISID Sid;
1094 PACL Acl;
1095 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
1096
1097 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1098 {
1099 DPRINT1("Invalid Security Descriptor revision\n");
1100 return FALSE;
1101 }
1102
1103 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1104 {
1105 DPRINT1("Invalid Security Descriptor revision\n");
1106 return FALSE;
1107 }
1108
1109 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1110 {
1111 DPRINT1("No self-relative Security Descriptor\n");
1112 return FALSE;
1113 }
1114
1115 SdLength = sizeof(SECURITY_DESCRIPTOR);
1116
1117 /* Check Owner SID */
1118 if (SecurityDescriptor->Owner == NULL)
1119 {
1120 DPRINT1("No Owner SID\n");
1121 return FALSE;
1122 }
1123
1124 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
1125 {
1126 DPRINT1("Invalid Owner SID alignment\n");
1127 return FALSE;
1128 }
1129
1130 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
1131 if (Sid->Revision != SID_REVISION)
1132 {
1133 DPRINT1("Invalid Owner SID revision\n");
1134 return FALSE;
1135 }
1136
1137 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1138 if (Length < SdLength)
1139 {
1140 DPRINT1("Invalid Owner SID size\n");
1141 return FALSE;
1142 }
1143
1144 /* Check Group SID */
1145 if (SecurityDescriptor->Group != NULL)
1146 {
1147 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
1148 {
1149 DPRINT1("Invalid Group SID alignment\n");
1150 return FALSE;
1151 }
1152
1153 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
1154 if (Sid->Revision != SID_REVISION)
1155 {
1156 DPRINT1("Invalid Group SID revision\n");
1157 return FALSE;
1158 }
1159
1160 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1161 if (Length < SdLength)
1162 {
1163 DPRINT1("Invalid Group SID size\n");
1164 return FALSE;
1165 }
1166 }
1167
1168 /* Check DACL */
1169 if (SecurityDescriptor->Dacl != NULL)
1170 {
1171 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1172 {
1173 DPRINT1("Invalid DACL alignment\n");
1174 return FALSE;
1175 }
1176
1177 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1178 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1179 (Acl->AclRevision > MAX_ACL_REVISION))
1180 {
1181 DPRINT1("Invalid DACL revision\n");
1182 return FALSE;
1183 }
1184
1185 SdLength += Acl->AclSize;
1186 if (Length < SdLength)
1187 {
1188 DPRINT1("Invalid DACL size\n");
1189 return FALSE;
1190 }
1191 }
1192
1193 /* Check SACL */
1194 if (SecurityDescriptor->Sacl != NULL)
1195 {
1196 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1197 {
1198 DPRINT1("Invalid SACL alignment\n");
1199 return FALSE;
1200 }
1201
1202 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1203 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1204 (Acl->AclRevision > MAX_ACL_REVISION))
1205 {
1206 DPRINT1("Invalid SACL revision\n");
1207 return FALSE;
1208 }
1209
1210 SdLength += Acl->AclSize;
1211 if (Length < SdLength)
1212 {
1213 DPRINT1("Invalid SACL size\n");
1214 return FALSE;
1215 }
1216 }
1217
1218 return TRUE;
1219 }
1220
1221 /*
1222 * @implemented
1223 */
1224 NTSTATUS NTAPI
1225 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
1226 {
1227 PAGED_CODE();
1228
1229 if (*SecurityDescriptor != NULL)
1230 {
1231 ExFreePool(*SecurityDescriptor);
1232 *SecurityDescriptor = NULL;
1233 }
1234
1235 return STATUS_SUCCESS;
1236 }
1237
1238
1239 /*
1240 * @unimplemented
1241 */
1242 NTSTATUS NTAPI
1243 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
1244 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
1245 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
1246 IN GUID *ObjectType OPTIONAL,
1247 IN BOOLEAN IsDirectoryObject,
1248 IN ULONG AutoInheritFlags,
1249 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
1250 IN PGENERIC_MAPPING GenericMapping,
1251 IN POOL_TYPE PoolType)
1252 {
1253 UNIMPLEMENTED;
1254 return STATUS_NOT_IMPLEMENTED;
1255 }
1256
1257 /*
1258 * @implemented
1259 */
1260 NTSTATUS NTAPI
1261 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
1262 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
1263 PSECURITY_DESCRIPTOR *NewDescriptor,
1264 BOOLEAN IsDirectoryObject,
1265 PSECURITY_SUBJECT_CONTEXT SubjectContext,
1266 PGENERIC_MAPPING GenericMapping,
1267 POOL_TYPE PoolType)
1268 {
1269 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1270 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1271 PISECURITY_DESCRIPTOR Descriptor;
1272 PTOKEN Token;
1273 ULONG OwnerLength = 0;
1274 ULONG GroupLength = 0;
1275 ULONG DaclLength = 0;
1276 ULONG SaclLength = 0;
1277 ULONG Length = 0;
1278 ULONG Control = 0;
1279 ULONG_PTR Current;
1280 PSID Owner = NULL;
1281 PSID Group = NULL;
1282 PACL Dacl = NULL;
1283 PACL Sacl = NULL;
1284
1285 PAGED_CODE();
1286
1287 /* Lock subject context */
1288 SeLockSubjectContext(SubjectContext);
1289
1290 if (SubjectContext->ClientToken != NULL)
1291 {
1292 Token = SubjectContext->ClientToken;
1293 }
1294 else
1295 {
1296 Token = SubjectContext->PrimaryToken;
1297 }
1298
1299 /* Inherit the Owner SID */
1300 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
1301 {
1302 DPRINT("Use explicit owner sid!\n");
1303 Owner = ExplicitDescriptor->Owner;
1304
1305 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1306 {
1307 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
1308 }
1309 }
1310 else
1311 {
1312 if (Token != NULL)
1313 {
1314 DPRINT("Use token owner sid!\n");
1315 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1316 }
1317 else
1318 {
1319 DPRINT("Use default owner sid!\n");
1320 Owner = SeLocalSystemSid;
1321 }
1322
1323 Control |= SE_OWNER_DEFAULTED;
1324 }
1325
1326 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
1327
1328 /* Inherit the Group SID */
1329 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
1330 {
1331 DPRINT("Use explicit group sid!\n");
1332 Group = ExplicitDescriptor->Group;
1333 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1334 {
1335 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
1336 }
1337 }
1338 else
1339 {
1340 if (Token != NULL)
1341 {
1342 DPRINT("Use token group sid!\n");
1343 Group = Token->PrimaryGroup;
1344 }
1345 else
1346 {
1347 DPRINT("Use default group sid!\n");
1348 Group = SeLocalSystemSid;
1349 }
1350
1351 Control |= SE_OWNER_DEFAULTED;
1352 }
1353
1354 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
1355
1356 /* Inherit the DACL */
1357 if (ExplicitDescriptor != NULL &&
1358 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1359 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1360 {
1361 DPRINT("Use explicit DACL!\n");
1362 Dacl = ExplicitDescriptor->Dacl;
1363 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1364 {
1365 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
1366 }
1367
1368 Control |= SE_DACL_PRESENT;
1369 }
1370 else if (ParentDescriptor != NULL &&
1371 (ParentDescriptor->Control & SE_DACL_PRESENT))
1372 {
1373 DPRINT("Use parent DACL!\n");
1374 /* FIXME: Inherit */
1375 Dacl = ParentDescriptor->Dacl;
1376 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1377 {
1378 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
1379 }
1380
1381 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1382 }
1383 else if (Token != NULL && Token->DefaultDacl != NULL)
1384 {
1385 DPRINT("Use token default DACL!\n");
1386 /* FIXME: Inherit */
1387 Dacl = Token->DefaultDacl;
1388 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1389 }
1390 else
1391 {
1392 DPRINT("Use NULL DACL!\n");
1393 Dacl = NULL;
1394 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1395 }
1396
1397 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
1398
1399 /* Inherit the SACL */
1400 if (ExplicitDescriptor != NULL &&
1401 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1402 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1403 {
1404 DPRINT("Use explicit SACL!\n");
1405 Sacl = ExplicitDescriptor->Sacl;
1406 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1407 {
1408 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
1409 }
1410
1411 Control |= SE_SACL_PRESENT;
1412 }
1413 else if (ParentDescriptor != NULL &&
1414 (ParentDescriptor->Control & SE_SACL_PRESENT))
1415 {
1416 DPRINT("Use parent SACL!\n");
1417 /* FIXME: Inherit */
1418 Sacl = ParentDescriptor->Sacl;
1419 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1420 {
1421 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
1422 }
1423
1424 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
1425 }
1426
1427 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
1428
1429 /* Allocate and initialize the new security descriptor */
1430 Length = sizeof(SECURITY_DESCRIPTOR) +
1431 OwnerLength + GroupLength + DaclLength + SaclLength;
1432
1433 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
1434 sizeof(SECURITY_DESCRIPTOR),
1435 OwnerLength,
1436 GroupLength,
1437 DaclLength,
1438 SaclLength);
1439
1440 Descriptor = ExAllocatePoolWithTag(PagedPool,
1441 Length,
1442 TAG_SD);
1443 if (Descriptor == NULL)
1444 {
1445 DPRINT1("ExAlloctePool() failed\n");
1446 /* FIXME: Unlock subject context */
1447 return STATUS_INSUFFICIENT_RESOURCES;
1448 }
1449
1450 RtlZeroMemory( Descriptor, Length );
1451 RtlCreateSecurityDescriptor(Descriptor,
1452 SECURITY_DESCRIPTOR_REVISION);
1453
1454 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
1455
1456 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
1457
1458 if (SaclLength != 0)
1459 {
1460 RtlCopyMemory((PVOID)Current,
1461 Sacl,
1462 SaclLength);
1463 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1464 Current += SaclLength;
1465 }
1466
1467 if (DaclLength != 0)
1468 {
1469 RtlCopyMemory((PVOID)Current,
1470 Dacl,
1471 DaclLength);
1472 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1473 Current += DaclLength;
1474 }
1475
1476 if (OwnerLength != 0)
1477 {
1478 RtlCopyMemory((PVOID)Current,
1479 Owner,
1480 OwnerLength);
1481 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1482 Current += OwnerLength;
1483 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
1484 }
1485 else
1486 {
1487 DPRINT("Owner of %x is zero length\n", Descriptor);
1488 }
1489
1490 if (GroupLength != 0)
1491 {
1492 memmove((PVOID)Current,
1493 Group,
1494 GroupLength);
1495 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1496 }
1497
1498 /* Unlock subject context */
1499 SeUnlockSubjectContext(SubjectContext);
1500
1501 *NewDescriptor = Descriptor;
1502
1503 DPRINT("Descrptor %x\n", Descriptor);
1504 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1505
1506 return STATUS_SUCCESS;
1507 }
1508
1509 /* EOF */