- Make use of _SEH2_YIELD in Ex, Io, Ob, Ps and Se.
[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 }
688 else
689 {
690 Status = STATUS_INSUFFICIENT_RESOURCES;
691 }
692 }
693 else
694 {
695 /* nothing to do... */
696 *CapturedSecurityDescriptor = NULL;
697 }
698
699 return Status;
700 }
701
702 /*
703 * @implemented
704 */
705 NTSTATUS NTAPI
706 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
707 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
708 IN OUT PULONG Length,
709 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
710 {
711 PISECURITY_DESCRIPTOR ObjectSd;
712 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
713 PSID Owner = NULL;
714 PSID Group = NULL;
715 PACL Dacl = NULL;
716 PACL Sacl = NULL;
717 ULONG OwnerLength = 0;
718 ULONG GroupLength = 0;
719 ULONG DaclLength = 0;
720 ULONG SaclLength = 0;
721 ULONG Control = 0;
722 ULONG_PTR Current;
723 ULONG SdLength;
724
725 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
726
727 if (*ObjectsSecurityDescriptor == NULL)
728 {
729 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
730 {
731 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
732 return STATUS_BUFFER_TOO_SMALL;
733 }
734
735 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
736 RtlCreateSecurityDescriptorRelative(RelSD,
737 SECURITY_DESCRIPTOR_REVISION);
738 return STATUS_SUCCESS;
739 }
740
741 ObjectSd = *ObjectsSecurityDescriptor;
742
743 /* Calculate the required security descriptor length */
744 Control = SE_SELF_RELATIVE;
745 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
746 (ObjectSd->Owner != NULL))
747 {
748 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
749 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
750 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
751 }
752
753 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
754 (ObjectSd->Group != NULL))
755 {
756 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
757 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
758 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
759 }
760
761 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
762 (ObjectSd->Control & SE_DACL_PRESENT))
763 {
764 if (ObjectSd->Dacl != NULL)
765 {
766 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
767 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
768 }
769 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
770 }
771
772 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
773 (ObjectSd->Control & SE_SACL_PRESENT))
774 {
775 if (ObjectSd->Sacl != NULL)
776 {
777 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
778 SaclLength = ROUND_UP(Sacl->AclSize, 4);
779 }
780 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
781 }
782
783 SdLength = OwnerLength + GroupLength + DaclLength +
784 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
785 if (*Length < SdLength)
786 {
787 *Length = SdLength;
788 return STATUS_BUFFER_TOO_SMALL;
789 }
790
791 /* Build the new security descrtiptor */
792 RtlCreateSecurityDescriptorRelative(RelSD,
793 SECURITY_DESCRIPTOR_REVISION);
794 RelSD->Control = (USHORT)Control;
795
796 Current = (ULONG_PTR)(RelSD + 1);
797
798 if (OwnerLength != 0)
799 {
800 RtlCopyMemory((PVOID)Current,
801 Owner,
802 OwnerLength);
803 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
804 Current += OwnerLength;
805 }
806
807 if (GroupLength != 0)
808 {
809 RtlCopyMemory((PVOID)Current,
810 Group,
811 GroupLength);
812 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
813 Current += GroupLength;
814 }
815
816 if (DaclLength != 0)
817 {
818 RtlCopyMemory((PVOID)Current,
819 Dacl,
820 DaclLength);
821 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
822 Current += DaclLength;
823 }
824
825 if (SaclLength != 0)
826 {
827 RtlCopyMemory((PVOID)Current,
828 Sacl,
829 SaclLength);
830 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
831 Current += SaclLength;
832 }
833
834 *Length = SdLength;
835
836 return STATUS_SUCCESS;
837 }
838
839 /*
840 * @implemented
841 */
842 NTSTATUS
843 NTAPI
844 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
845 IN KPROCESSOR_MODE CurrentMode,
846 IN BOOLEAN CaptureIfKernelMode)
847 {
848 PAGED_CODE();
849
850 /* WARNING! You need to call this function with the same value for CurrentMode
851 and CaptureIfKernelMode that you previously passed to
852 SeCaptureSecurityDescriptor() in order to avoid memory leaks! */
853 if(CapturedSecurityDescriptor != NULL &&
854 (CurrentMode != KernelMode ||
855 (CurrentMode == KernelMode && CaptureIfKernelMode)))
856 {
857 /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
858 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
859 }
860
861 return STATUS_SUCCESS;
862 }
863
864 /*
865 * @implemented
866 */
867 NTSTATUS NTAPI
868 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
869 IN PSECURITY_INFORMATION _SecurityInformation,
870 IN PSECURITY_DESCRIPTOR _SecurityDescriptor,
871 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
872 IN POOL_TYPE PoolType,
873 IN PGENERIC_MAPPING GenericMapping)
874 {
875 PISECURITY_DESCRIPTOR ObjectSd;
876 PISECURITY_DESCRIPTOR NewSd;
877 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
878 PSID Owner = 0;
879 PSID Group = 0;
880 PACL Dacl = 0;
881 PACL Sacl = 0;
882 ULONG OwnerLength = 0;
883 ULONG GroupLength = 0;
884 ULONG DaclLength = 0;
885 ULONG SaclLength = 0;
886 ULONG Control = 0;
887 ULONG_PTR Current;
888 SECURITY_INFORMATION SecurityInformation;
889
890 ObjectSd = *ObjectsSecurityDescriptor;
891
892 if (!ObjectSd)
893 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
894
895 SecurityInformation = *_SecurityInformation;
896
897 /* Get owner and owner size */
898 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
899 {
900 if (SecurityDescriptor->Owner != NULL)
901 {
902 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
903 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
904 (ULONG_PTR)SecurityDescriptor);
905 else
906 Owner = (PSID)SecurityDescriptor->Owner;
907 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
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 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
919 }
920
921 /* Get group and group size */
922 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
923 {
924 if (SecurityDescriptor->Group != NULL)
925 {
926 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
927 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
928 (ULONG_PTR)SecurityDescriptor);
929 else
930 Group = (PSID)SecurityDescriptor->Group;
931 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
932 }
933 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
934 }
935 else
936 {
937 if (ObjectSd->Group != NULL)
938 {
939 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
940 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
941 }
942 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
943 }
944
945 /* Get DACL and DACL size */
946 if (SecurityInformation & DACL_SECURITY_INFORMATION)
947 {
948 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
949 (SecurityDescriptor->Dacl != NULL))
950 {
951 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
952 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
953 (ULONG_PTR)SecurityDescriptor);
954 else
955 Dacl = (PACL)SecurityDescriptor->Dacl;
956
957 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
958 }
959 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
960 }
961 else
962 {
963 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
964 (ObjectSd->Dacl != NULL))
965 {
966 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
967 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
968 }
969 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
970 }
971
972 /* Get SACL and SACL size */
973 if (SecurityInformation & SACL_SECURITY_INFORMATION)
974 {
975 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
976 (SecurityDescriptor->Sacl != NULL))
977 {
978 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
979 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
980 (ULONG_PTR)SecurityDescriptor);
981 else
982 Sacl = (PACL)SecurityDescriptor->Sacl;
983 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
984 }
985 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
986 }
987 else
988 {
989 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
990 (ObjectSd->Sacl != NULL))
991 {
992 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
993 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
994 }
995 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
996 }
997
998 NewSd = ExAllocatePool(NonPagedPool,
999 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
1000 DaclLength + SaclLength);
1001 if (NewSd == NULL)
1002 {
1003 ObDereferenceObject(Object);
1004 return STATUS_INSUFFICIENT_RESOURCES;
1005 }
1006
1007 RtlCreateSecurityDescriptor(NewSd,
1008 SECURITY_DESCRIPTOR_REVISION1);
1009 /* We always build a self-relative descriptor */
1010 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
1011
1012 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
1013
1014 if (OwnerLength != 0)
1015 {
1016 RtlCopyMemory((PVOID)Current,
1017 Owner,
1018 OwnerLength);
1019 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
1020 Current += OwnerLength;
1021 }
1022
1023 if (GroupLength != 0)
1024 {
1025 RtlCopyMemory((PVOID)Current,
1026 Group,
1027 GroupLength);
1028 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
1029 Current += GroupLength;
1030 }
1031
1032 if (DaclLength != 0)
1033 {
1034 RtlCopyMemory((PVOID)Current,
1035 Dacl,
1036 DaclLength);
1037 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
1038 Current += DaclLength;
1039 }
1040
1041 if (SaclLength != 0)
1042 {
1043 RtlCopyMemory((PVOID)Current,
1044 Sacl,
1045 SaclLength);
1046 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
1047 Current += SaclLength;
1048 }
1049
1050 *ObjectsSecurityDescriptor = NewSd;
1051 return STATUS_SUCCESS;
1052 }
1053
1054 /*
1055 * @unimplemented
1056 */
1057 NTSTATUS
1058 NTAPI
1059 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL,
1060 IN PSECURITY_INFORMATION SecurityInformation,
1061 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
1062 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
1063 IN ULONG AutoInheritFlags,
1064 IN POOL_TYPE PoolType,
1065 IN PGENERIC_MAPPING GenericMapping)
1066 {
1067 PISECURITY_DESCRIPTOR ObjectSd = *ObjectsSecurityDescriptor;
1068
1069 if (!ObjectSd)
1070 return STATUS_NO_SECURITY_ON_OBJECT; // The object does not have a security descriptor.
1071
1072 UNIMPLEMENTED;
1073 return STATUS_NOT_IMPLEMENTED;
1074 }
1075
1076
1077 /*
1078 * @implemented
1079 */
1080 BOOLEAN NTAPI
1081 SeValidSecurityDescriptor(IN ULONG Length,
1082 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1083 {
1084 ULONG SdLength;
1085 PISID Sid;
1086 PACL Acl;
1087 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
1088
1089 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1090 {
1091 DPRINT1("Invalid Security Descriptor revision\n");
1092 return FALSE;
1093 }
1094
1095 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1096 {
1097 DPRINT1("Invalid Security Descriptor revision\n");
1098 return FALSE;
1099 }
1100
1101 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1102 {
1103 DPRINT1("No self-relative Security Descriptor\n");
1104 return FALSE;
1105 }
1106
1107 SdLength = sizeof(SECURITY_DESCRIPTOR);
1108
1109 /* Check Owner SID */
1110 if (SecurityDescriptor->Owner == NULL)
1111 {
1112 DPRINT1("No Owner SID\n");
1113 return FALSE;
1114 }
1115
1116 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
1117 {
1118 DPRINT1("Invalid Owner SID alignment\n");
1119 return FALSE;
1120 }
1121
1122 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
1123 if (Sid->Revision != SID_REVISION)
1124 {
1125 DPRINT1("Invalid Owner SID revision\n");
1126 return FALSE;
1127 }
1128
1129 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1130 if (Length < SdLength)
1131 {
1132 DPRINT1("Invalid Owner SID size\n");
1133 return FALSE;
1134 }
1135
1136 /* Check Group SID */
1137 if (SecurityDescriptor->Group != NULL)
1138 {
1139 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
1140 {
1141 DPRINT1("Invalid Group SID alignment\n");
1142 return FALSE;
1143 }
1144
1145 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
1146 if (Sid->Revision != SID_REVISION)
1147 {
1148 DPRINT1("Invalid Group SID revision\n");
1149 return FALSE;
1150 }
1151
1152 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1153 if (Length < SdLength)
1154 {
1155 DPRINT1("Invalid Group SID size\n");
1156 return FALSE;
1157 }
1158 }
1159
1160 /* Check DACL */
1161 if (SecurityDescriptor->Dacl != NULL)
1162 {
1163 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1164 {
1165 DPRINT1("Invalid DACL alignment\n");
1166 return FALSE;
1167 }
1168
1169 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1170 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1171 (Acl->AclRevision > MAX_ACL_REVISION))
1172 {
1173 DPRINT1("Invalid DACL revision\n");
1174 return FALSE;
1175 }
1176
1177 SdLength += Acl->AclSize;
1178 if (Length < SdLength)
1179 {
1180 DPRINT1("Invalid DACL size\n");
1181 return FALSE;
1182 }
1183 }
1184
1185 /* Check SACL */
1186 if (SecurityDescriptor->Sacl != NULL)
1187 {
1188 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1189 {
1190 DPRINT1("Invalid SACL alignment\n");
1191 return FALSE;
1192 }
1193
1194 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1195 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1196 (Acl->AclRevision > MAX_ACL_REVISION))
1197 {
1198 DPRINT1("Invalid SACL revision\n");
1199 return FALSE;
1200 }
1201
1202 SdLength += Acl->AclSize;
1203 if (Length < SdLength)
1204 {
1205 DPRINT1("Invalid SACL size\n");
1206 return FALSE;
1207 }
1208 }
1209
1210 return TRUE;
1211 }
1212
1213 /*
1214 * @implemented
1215 */
1216 NTSTATUS NTAPI
1217 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
1218 {
1219 PAGED_CODE();
1220
1221 if (*SecurityDescriptor != NULL)
1222 {
1223 ExFreePool(*SecurityDescriptor);
1224 *SecurityDescriptor = NULL;
1225 }
1226
1227 return STATUS_SUCCESS;
1228 }
1229
1230
1231 /*
1232 * @unimplemented
1233 */
1234 NTSTATUS NTAPI
1235 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
1236 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
1237 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
1238 IN GUID *ObjectType OPTIONAL,
1239 IN BOOLEAN IsDirectoryObject,
1240 IN ULONG AutoInheritFlags,
1241 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
1242 IN PGENERIC_MAPPING GenericMapping,
1243 IN POOL_TYPE PoolType)
1244 {
1245 UNIMPLEMENTED;
1246 return STATUS_NOT_IMPLEMENTED;
1247 }
1248
1249 /*
1250 * @implemented
1251 */
1252 NTSTATUS NTAPI
1253 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
1254 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
1255 PSECURITY_DESCRIPTOR *NewDescriptor,
1256 BOOLEAN IsDirectoryObject,
1257 PSECURITY_SUBJECT_CONTEXT SubjectContext,
1258 PGENERIC_MAPPING GenericMapping,
1259 POOL_TYPE PoolType)
1260 {
1261 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1262 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1263 PISECURITY_DESCRIPTOR Descriptor;
1264 PTOKEN Token;
1265 ULONG OwnerLength = 0;
1266 ULONG GroupLength = 0;
1267 ULONG DaclLength = 0;
1268 ULONG SaclLength = 0;
1269 ULONG Length = 0;
1270 ULONG Control = 0;
1271 ULONG_PTR Current;
1272 PSID Owner = NULL;
1273 PSID Group = NULL;
1274 PACL Dacl = NULL;
1275 PACL Sacl = NULL;
1276
1277 PAGED_CODE();
1278
1279 /* Lock subject context */
1280 SeLockSubjectContext(SubjectContext);
1281
1282 if (SubjectContext->ClientToken != NULL)
1283 {
1284 Token = SubjectContext->ClientToken;
1285 }
1286 else
1287 {
1288 Token = SubjectContext->PrimaryToken;
1289 }
1290
1291
1292 /* Inherit the Owner SID */
1293 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
1294 {
1295 DPRINT("Use explicit owner sid!\n");
1296 Owner = ExplicitDescriptor->Owner;
1297
1298 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1299 {
1300 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
1301
1302 }
1303 }
1304 else
1305 {
1306 if (Token != NULL)
1307 {
1308 DPRINT("Use token owner sid!\n");
1309 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1310 }
1311 else
1312 {
1313 DPRINT("Use default owner sid!\n");
1314 Owner = SeLocalSystemSid;
1315 }
1316
1317 Control |= SE_OWNER_DEFAULTED;
1318 }
1319
1320 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
1321
1322
1323 /* Inherit the Group SID */
1324 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
1325 {
1326 DPRINT("Use explicit group sid!\n");
1327 Group = ExplicitDescriptor->Group;
1328 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1329 {
1330 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
1331 }
1332 }
1333 else
1334 {
1335 if (Token != NULL)
1336 {
1337 DPRINT("Use token group sid!\n");
1338 Group = Token->PrimaryGroup;
1339 }
1340 else
1341 {
1342 DPRINT("Use default group sid!\n");
1343 Group = SeLocalSystemSid;
1344 }
1345
1346 Control |= SE_OWNER_DEFAULTED;
1347 }
1348
1349 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
1350
1351
1352 /* Inherit the DACL */
1353 if (ExplicitDescriptor != NULL &&
1354 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1355 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1356 {
1357 DPRINT("Use explicit DACL!\n");
1358 Dacl = ExplicitDescriptor->Dacl;
1359 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1360 {
1361 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
1362 }
1363
1364 Control |= SE_DACL_PRESENT;
1365 }
1366 else if (ParentDescriptor != NULL &&
1367 (ParentDescriptor->Control & SE_DACL_PRESENT))
1368 {
1369 DPRINT("Use parent DACL!\n");
1370 /* FIXME: Inherit */
1371 Dacl = ParentDescriptor->Dacl;
1372 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1373 {
1374 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
1375 }
1376 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1377 }
1378 else if (Token != NULL && Token->DefaultDacl != NULL)
1379 {
1380 DPRINT("Use token default DACL!\n");
1381 /* FIXME: Inherit */
1382 Dacl = Token->DefaultDacl;
1383 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1384 }
1385 else
1386 {
1387 DPRINT("Use NULL DACL!\n");
1388 Dacl = NULL;
1389 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1390 }
1391
1392 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
1393
1394
1395 /* Inherit the SACL */
1396 if (ExplicitDescriptor != NULL &&
1397 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1398 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1399 {
1400 DPRINT("Use explicit SACL!\n");
1401 Sacl = ExplicitDescriptor->Sacl;
1402 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1403 {
1404 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
1405 }
1406
1407 Control |= SE_SACL_PRESENT;
1408 }
1409 else if (ParentDescriptor != NULL &&
1410 (ParentDescriptor->Control & SE_SACL_PRESENT))
1411 {
1412 DPRINT("Use parent SACL!\n");
1413 /* FIXME: Inherit */
1414 Sacl = ParentDescriptor->Sacl;
1415 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1416 {
1417 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
1418 }
1419 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
1420 }
1421
1422 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
1423
1424
1425 /* Allocate and initialize the new security descriptor */
1426 Length = sizeof(SECURITY_DESCRIPTOR) +
1427 OwnerLength + GroupLength + DaclLength + SaclLength;
1428
1429 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
1430 sizeof(SECURITY_DESCRIPTOR),
1431 OwnerLength,
1432 GroupLength,
1433 DaclLength,
1434 SaclLength);
1435
1436 Descriptor = ExAllocatePoolWithTag(PagedPool,
1437 Length,
1438 TAG_SD);
1439 if (Descriptor == NULL)
1440 {
1441 DPRINT1("ExAlloctePool() failed\n");
1442 /* FIXME: Unlock subject context */
1443 return STATUS_INSUFFICIENT_RESOURCES;
1444 }
1445
1446 RtlZeroMemory( Descriptor, Length );
1447 RtlCreateSecurityDescriptor(Descriptor,
1448 SECURITY_DESCRIPTOR_REVISION);
1449
1450 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
1451
1452 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
1453
1454 if (SaclLength != 0)
1455 {
1456 RtlCopyMemory((PVOID)Current,
1457 Sacl,
1458 SaclLength);
1459 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1460 Current += SaclLength;
1461 }
1462
1463 if (DaclLength != 0)
1464 {
1465 RtlCopyMemory((PVOID)Current,
1466 Dacl,
1467 DaclLength);
1468 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1469 Current += DaclLength;
1470 }
1471
1472 if (OwnerLength != 0)
1473 {
1474 RtlCopyMemory((PVOID)Current,
1475 Owner,
1476 OwnerLength);
1477 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1478 Current += OwnerLength;
1479 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
1480 }
1481 else
1482 DPRINT("Owner of %x is zero length\n", Descriptor);
1483
1484 if (GroupLength != 0)
1485 {
1486 memmove((PVOID)Current,
1487 Group,
1488 GroupLength);
1489 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1490 }
1491
1492 /* Unlock subject context */
1493 SeUnlockSubjectContext(SubjectContext);
1494
1495 *NewDescriptor = Descriptor;
1496
1497 DPRINT("Descrptor %x\n", Descriptor);
1498 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1499
1500 return STATUS_SUCCESS;
1501 }
1502
1503 /* EOF */