[CMAKE]
[reactos.git] / 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 /*
253 * Don't allocate memory here because ExAllocate should bugcheck
254 * the system if it's buggy, SEH would catch that! So make a local
255 * copy of the qos structure.
256 */
257 RtlCopyMemory(&SafeQos,
258 ObjectAttributes->SecurityQualityOfService,
259 sizeof(SECURITY_QUALITY_OF_SERVICE));
260 *Present = TRUE;
261 }
262 else
263 {
264 Status = STATUS_INVALID_PARAMETER;
265 }
266 }
267 else
268 {
269 *CapturedSecurityQualityOfService = NULL;
270 *Present = FALSE;
271 }
272 }
273 else
274 {
275 Status = STATUS_INVALID_PARAMETER;
276 }
277 }
278 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
279 {
280 Status = _SEH2_GetExceptionCode();
281 }
282 _SEH2_END;
283
284 if (NT_SUCCESS(Status))
285 {
286 if (*Present)
287 {
288 CapturedQos = ExAllocatePool(PoolType,
289 sizeof(SECURITY_QUALITY_OF_SERVICE));
290 if (CapturedQos != NULL)
291 {
292 RtlCopyMemory(CapturedQos,
293 &SafeQos,
294 sizeof(SECURITY_QUALITY_OF_SERVICE));
295 *CapturedSecurityQualityOfService = CapturedQos;
296 }
297 else
298 {
299 Status = STATUS_INSUFFICIENT_RESOURCES;
300 }
301 }
302 else
303 {
304 *CapturedSecurityQualityOfService = NULL;
305 }
306 }
307 }
308 else
309 {
310 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
311 {
312 if (CaptureIfKernel)
313 {
314 if (ObjectAttributes->SecurityQualityOfService != NULL)
315 {
316 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
317 sizeof(SECURITY_QUALITY_OF_SERVICE))
318 {
319 CapturedQos = ExAllocatePool(PoolType,
320 sizeof(SECURITY_QUALITY_OF_SERVICE));
321 if (CapturedQos != NULL)
322 {
323 RtlCopyMemory(CapturedQos,
324 ObjectAttributes->SecurityQualityOfService,
325 sizeof(SECURITY_QUALITY_OF_SERVICE));
326 *CapturedSecurityQualityOfService = CapturedQos;
327 *Present = TRUE;
328 }
329 else
330 {
331 Status = STATUS_INSUFFICIENT_RESOURCES;
332 }
333 }
334 else
335 {
336 Status = STATUS_INVALID_PARAMETER;
337 }
338 }
339 else
340 {
341 *CapturedSecurityQualityOfService = NULL;
342 *Present = FALSE;
343 }
344 }
345 else
346 {
347 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
348 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
349 }
350 }
351 else
352 {
353 Status = STATUS_INVALID_PARAMETER;
354 }
355 }
356 }
357 else
358 {
359 *CapturedSecurityQualityOfService = NULL;
360 *Present = FALSE;
361 }
362
363 return Status;
364 }
365
366
367 VOID
368 NTAPI
369 SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL,
370 IN KPROCESSOR_MODE AccessMode,
371 IN BOOLEAN CaptureIfKernel)
372 {
373 PAGED_CODE();
374
375 if (CapturedSecurityQualityOfService != NULL &&
376 (AccessMode != KernelMode || CaptureIfKernel))
377 {
378 ExFreePool(CapturedSecurityQualityOfService);
379 }
380 }
381
382 /* PUBLIC FUNCTIONS ***********************************************************/
383
384 /*
385 * @implemented
386 */
387 NTSTATUS
388 NTAPI
389 SeCaptureSecurityDescriptor(IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
390 IN KPROCESSOR_MODE CurrentMode,
391 IN POOL_TYPE PoolType,
392 IN BOOLEAN CaptureIfKernel,
393 OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
394 {
395 PISECURITY_DESCRIPTOR OriginalSecurityDescriptor = _OriginalSecurityDescriptor;
396 SECURITY_DESCRIPTOR DescriptorCopy;
397 PISECURITY_DESCRIPTOR NewDescriptor;
398 ULONG OwnerSAC = 0, GroupSAC = 0;
399 ULONG OwnerSize = 0, GroupSize = 0;
400 ULONG SaclSize = 0, DaclSize = 0;
401 ULONG DescriptorSize = 0;
402 NTSTATUS Status;
403
404 if (OriginalSecurityDescriptor != NULL)
405 {
406 if (CurrentMode != KernelMode)
407 {
408 RtlZeroMemory(&DescriptorCopy, sizeof(DescriptorCopy));
409
410 _SEH2_TRY
411 {
412 /*
413 * First only probe and copy until the control field of the descriptor
414 * to determine whether it's a self-relative descriptor
415 */
416 DescriptorSize = FIELD_OFFSET(SECURITY_DESCRIPTOR,
417 Owner);
418 ProbeForRead(OriginalSecurityDescriptor,
419 DescriptorSize,
420 sizeof(ULONG));
421
422 if (OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
423 {
424 _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
425 }
426
427 /* Make a copy on the stack */
428 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
429 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
430 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
431 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
432 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
433
434 /*
435 * Probe and copy the entire security descriptor structure. The SIDs
436 * and ACLs will be probed and copied later though
437 */
438 ProbeForRead(OriginalSecurityDescriptor,
439 DescriptorSize,
440 sizeof(ULONG));
441 if (DescriptorCopy.Control & SE_SELF_RELATIVE)
442 {
443 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
444
445 DescriptorCopy.Owner = (PSID)RelSD->Owner;
446 DescriptorCopy.Group = (PSID)RelSD->Group;
447 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
448 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
449 }
450 else
451 {
452 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
453 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
454 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
455 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
456 }
457 }
458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
459 {
460 /* Return the exception code */
461 _SEH2_YIELD(return _SEH2_GetExceptionCode());
462 }
463 _SEH2_END;
464 }
465 else if (!CaptureIfKernel)
466 {
467 if (OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
468 {
469 return STATUS_UNKNOWN_REVISION;
470 }
471
472 *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
473 return STATUS_SUCCESS;
474 }
475 else
476 {
477 if (OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
478 {
479 return STATUS_UNKNOWN_REVISION;
480 }
481
482 /* Make a copy on the stack */
483 DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
484 DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
485 DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
486 DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
487 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR));
488 if (DescriptorCopy.Control & SE_SELF_RELATIVE)
489 {
490 PISECURITY_DESCRIPTOR_RELATIVE RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
491
492 DescriptorCopy.Owner = (PSID)RelSD->Owner;
493 DescriptorCopy.Group = (PSID)RelSD->Group;
494 DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
495 DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
496 }
497 else
498 {
499 DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
500 DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
501 DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
502 DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
503 }
504 }
505
506 if (DescriptorCopy.Control & SE_SELF_RELATIVE)
507 {
508 /*
509 * In case we're dealing with a self-relative descriptor, do a basic convert
510 * to an absolute descriptor. We do this so we can simply access the data
511 * using the pointers without calculating them again.
512 */
513 DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
514 if (DescriptorCopy.Owner != NULL)
515 {
516 DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner);
517 }
518 if (DescriptorCopy.Group != NULL)
519 {
520 DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group);
521 }
522 if (DescriptorCopy.Dacl != NULL)
523 {
524 DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl);
525 }
526 if (DescriptorCopy.Sacl != NULL)
527 {
528 DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl);
529 }
530 }
531
532 /* Determine the size of the SIDs */
533 #define DetermineSIDSize(SidType) \
534 do { \
535 if(DescriptorCopy.SidType != NULL) \
536 { \
537 SID *SidType = (SID*)DescriptorCopy.SidType; \
538 \
539 if(CurrentMode != KernelMode) \
540 { \
541 /* Securely access the buffers! */ \
542 _SEH2_TRY \
543 { \
544 SidType##SAC = ProbeForReadUchar(&SidType->SubAuthorityCount); \
545 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
546 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
547 ProbeForRead(SidType, \
548 SidType##Size, \
549 sizeof(ULONG)); \
550 } \
551 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
552 { \
553 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
554 } \
555 _SEH2_END; \
556 \
557 } \
558 else \
559 { \
560 SidType##SAC = SidType->SubAuthorityCount; \
561 SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
562 DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
563 } \
564 } \
565 } while(0)
566
567 DetermineSIDSize(Owner);
568 DetermineSIDSize(Group);
569
570 #undef DetermineSIDSize
571
572 /* Determine the size of the ACLs */
573 #define DetermineACLSize(AclType, AclFlag) \
574 do { \
575 if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
576 DescriptorCopy.AclType != NULL) \
577 { \
578 PACL AclType = (PACL)DescriptorCopy.AclType; \
579 \
580 if(CurrentMode != KernelMode) \
581 { \
582 /* Securely access the buffers! */ \
583 _SEH2_TRY \
584 { \
585 AclType##Size = ProbeForReadUshort(&AclType->AclSize); \
586 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
587 ProbeForRead(AclType, \
588 AclType##Size, \
589 sizeof(ULONG)); \
590 } \
591 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
592 { \
593 _SEH2_YIELD(return _SEH2_GetExceptionCode()); \
594 } \
595 _SEH2_END; \
596 \
597 } \
598 else \
599 { \
600 AclType##Size = AclType->AclSize; \
601 DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
602 } \
603 } \
604 else \
605 { \
606 DescriptorCopy.AclType = NULL; \
607 } \
608 } while(0)
609
610 DetermineACLSize(Sacl, SACL);
611 DetermineACLSize(Dacl, DACL);
612
613 #undef DetermineACLSize
614
615 /*
616 * Allocate enough memory to store a complete copy of a self-relative
617 * security descriptor
618 */
619 NewDescriptor = ExAllocatePoolWithTag(PoolType,
620 DescriptorSize,
621 TAG_SD);
622 if (NewDescriptor != NULL)
623 {
624 ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
625
626 RtlZeroMemory(NewDescriptor, DescriptorSize);
627 NewDescriptor->Revision = DescriptorCopy.Revision;
628 NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
629 NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
630
631 _SEH2_TRY
632 {
633 /*
634 * Setup the offsets and copy the SIDs and ACLs to the new
635 * self-relative security descriptor. Probing the pointers is not
636 * neccessary anymore as we did that when collecting the sizes!
637 * Make sure to validate the SIDs and ACLs *again* as they could have
638 * been modified in the meanwhile!
639 */
640 #define CopySID(Type) \
641 do { \
642 if(DescriptorCopy.Type != NULL) \
643 { \
644 NewDescriptor->Type = (PVOID)Offset; \
645 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
646 (ULONG_PTR)NewDescriptor->Type), \
647 DescriptorCopy.Type, \
648 Type##Size); \
649 if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
650 (ULONG_PTR)NewDescriptor->Type))) \
651 { \
652 RtlRaiseStatus(STATUS_INVALID_SID); \
653 } \
654 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
655 } \
656 } while(0)
657
658 CopySID(Owner);
659 CopySID(Group);
660
661 #undef CopySID
662
663 #define CopyACL(Type) \
664 do { \
665 if(DescriptorCopy.Type != NULL) \
666 { \
667 NewDescriptor->Type = (PVOID)Offset; \
668 RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
669 (ULONG_PTR)NewDescriptor->Type), \
670 DescriptorCopy.Type, \
671 Type##Size); \
672 if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
673 (ULONG_PTR)NewDescriptor->Type))) \
674 { \
675 RtlRaiseStatus(STATUS_INVALID_ACL); \
676 } \
677 Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
678 } \
679 } while(0)
680
681 CopyACL(Sacl);
682 CopyACL(Dacl);
683
684 #undef CopyACL
685 }
686 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
687 {
688 /* We failed to copy the data to the new descriptor */
689 ExFreePool(NewDescriptor);
690 _SEH2_YIELD(return _SEH2_GetExceptionCode());
691 }
692 _SEH2_END;
693
694 /*
695 * We're finally done!
696 * Copy the pointer to the captured descriptor to to the caller.
697 */
698 *CapturedSecurityDescriptor = NewDescriptor;
699 return STATUS_SUCCESS;
700 }
701 else
702 {
703 Status = STATUS_INSUFFICIENT_RESOURCES;
704 }
705 }
706 else
707 {
708 /* Nothing to do... */
709 *CapturedSecurityDescriptor = NULL;
710 }
711
712 return Status;
713 }
714
715 /*
716 * @implemented
717 */
718 NTSTATUS NTAPI
719 SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation,
720 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
721 IN OUT PULONG Length,
722 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL)
723 {
724 PISECURITY_DESCRIPTOR ObjectSd;
725 PISECURITY_DESCRIPTOR_RELATIVE RelSD;
726 PSID Owner = NULL;
727 PSID Group = NULL;
728 PACL Dacl = NULL;
729 PACL Sacl = NULL;
730 ULONG OwnerLength = 0;
731 ULONG GroupLength = 0;
732 ULONG DaclLength = 0;
733 ULONG SaclLength = 0;
734 ULONG Control = 0;
735 ULONG_PTR Current;
736 ULONG SdLength;
737
738 RelSD = (PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
739
740 if (*ObjectsSecurityDescriptor == NULL)
741 {
742 if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE))
743 {
744 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
745 return STATUS_BUFFER_TOO_SMALL;
746 }
747
748 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
749 RtlCreateSecurityDescriptorRelative(RelSD,
750 SECURITY_DESCRIPTOR_REVISION);
751 return STATUS_SUCCESS;
752 }
753
754 ObjectSd = *ObjectsSecurityDescriptor;
755
756 /* Calculate the required security descriptor length */
757 Control = SE_SELF_RELATIVE;
758 if ((*SecurityInformation & OWNER_SECURITY_INFORMATION) &&
759 (ObjectSd->Owner != NULL))
760 {
761 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
762 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
763 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
764 }
765
766 if ((*SecurityInformation & GROUP_SECURITY_INFORMATION) &&
767 (ObjectSd->Group != NULL))
768 {
769 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
770 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
771 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
772 }
773
774 if ((*SecurityInformation & DACL_SECURITY_INFORMATION) &&
775 (ObjectSd->Control & SE_DACL_PRESENT))
776 {
777 if (ObjectSd->Dacl != NULL)
778 {
779 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
780 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
781 }
782
783 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
784 }
785
786 if ((*SecurityInformation & SACL_SECURITY_INFORMATION) &&
787 (ObjectSd->Control & SE_SACL_PRESENT))
788 {
789 if (ObjectSd->Sacl != NULL)
790 {
791 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
792 SaclLength = ROUND_UP(Sacl->AclSize, 4);
793 }
794
795 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
796 }
797
798 SdLength = OwnerLength + GroupLength + DaclLength +
799 SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
800 if (*Length < SdLength)
801 {
802 *Length = SdLength;
803 return STATUS_BUFFER_TOO_SMALL;
804 }
805
806 /* Build the new security descrtiptor */
807 RtlCreateSecurityDescriptorRelative(RelSD,
808 SECURITY_DESCRIPTOR_REVISION);
809 RelSD->Control = (USHORT)Control;
810
811 Current = (ULONG_PTR)(RelSD + 1);
812
813 if (OwnerLength != 0)
814 {
815 RtlCopyMemory((PVOID)Current,
816 Owner,
817 OwnerLength);
818 RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
819 Current += OwnerLength;
820 }
821
822 if (GroupLength != 0)
823 {
824 RtlCopyMemory((PVOID)Current,
825 Group,
826 GroupLength);
827 RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
828 Current += GroupLength;
829 }
830
831 if (DaclLength != 0)
832 {
833 RtlCopyMemory((PVOID)Current,
834 Dacl,
835 DaclLength);
836 RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
837 Current += DaclLength;
838 }
839
840 if (SaclLength != 0)
841 {
842 RtlCopyMemory((PVOID)Current,
843 Sacl,
844 SaclLength);
845 RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor);
846 Current += SaclLength;
847 }
848
849 *Length = SdLength;
850
851 return STATUS_SUCCESS;
852 }
853
854 /*
855 * @implemented
856 */
857 NTSTATUS
858 NTAPI
859 SeReleaseSecurityDescriptor(IN PSECURITY_DESCRIPTOR CapturedSecurityDescriptor,
860 IN KPROCESSOR_MODE CurrentMode,
861 IN BOOLEAN CaptureIfKernelMode)
862 {
863 PAGED_CODE();
864
865 /*
866 * WARNING! You need to call this function with the same value for CurrentMode
867 * and CaptureIfKernelMode that you previously passed to
868 * SeCaptureSecurityDescriptor() in order to avoid memory leaks!
869 */
870 if (CapturedSecurityDescriptor != NULL &&
871 (CurrentMode != KernelMode ||
872 (CurrentMode == KernelMode && CaptureIfKernelMode)))
873 {
874 /* Only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */
875 ExFreePoolWithTag(CapturedSecurityDescriptor, TAG_SD);
876 }
877
878 return STATUS_SUCCESS;
879 }
880
881 /*
882 * @implemented
883 */
884 NTSTATUS NTAPI
885 SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL,
886 IN PSECURITY_INFORMATION _SecurityInformation,
887 IN PSECURITY_DESCRIPTOR _SecurityDescriptor,
888 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
889 IN POOL_TYPE PoolType,
890 IN PGENERIC_MAPPING GenericMapping)
891 {
892 PISECURITY_DESCRIPTOR ObjectSd;
893 PISECURITY_DESCRIPTOR NewSd;
894 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
895 PSID Owner = 0;
896 PSID Group = 0;
897 PACL Dacl = 0;
898 PACL Sacl = 0;
899 ULONG OwnerLength = 0;
900 ULONG GroupLength = 0;
901 ULONG DaclLength = 0;
902 ULONG SaclLength = 0;
903 ULONG Control = 0;
904 ULONG_PTR Current;
905 SECURITY_INFORMATION SecurityInformation;
906
907 ObjectSd = *ObjectsSecurityDescriptor;
908
909 /* The object does not have a security descriptor. */
910 if (!ObjectSd)
911 return STATUS_NO_SECURITY_ON_OBJECT;
912
913 SecurityInformation = *_SecurityInformation;
914
915 /* Get owner and owner size */
916 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
917 {
918 if (SecurityDescriptor->Owner != NULL)
919 {
920 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
921 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
922 (ULONG_PTR)SecurityDescriptor);
923 else
924 Owner = (PSID)SecurityDescriptor->Owner;
925 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
926 }
927
928 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
929 }
930 else
931 {
932 if (ObjectSd->Owner != NULL)
933 {
934 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
935 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
936 }
937
938 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
939 }
940
941 /* Get group and group size */
942 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
943 {
944 if (SecurityDescriptor->Group != NULL)
945 {
946 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
947 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
948 (ULONG_PTR)SecurityDescriptor);
949 else
950 Group = (PSID)SecurityDescriptor->Group;
951 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
952 }
953
954 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
955 }
956 else
957 {
958 if (ObjectSd->Group != NULL)
959 {
960 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
961 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
962 }
963
964 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
965 }
966
967 /* Get DACL and DACL size */
968 if (SecurityInformation & DACL_SECURITY_INFORMATION)
969 {
970 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
971 (SecurityDescriptor->Dacl != NULL))
972 {
973 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
974 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
975 (ULONG_PTR)SecurityDescriptor);
976 else
977 Dacl = (PACL)SecurityDescriptor->Dacl;
978
979 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
980 }
981
982 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
983 }
984 else
985 {
986 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
987 (ObjectSd->Dacl != NULL))
988 {
989 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
990 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
991 }
992
993 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
994 }
995
996 /* Get SACL and SACL size */
997 if (SecurityInformation & SACL_SECURITY_INFORMATION)
998 {
999 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
1000 (SecurityDescriptor->Sacl != NULL))
1001 {
1002 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
1003 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
1004 (ULONG_PTR)SecurityDescriptor);
1005 else
1006 Sacl = (PACL)SecurityDescriptor->Sacl;
1007 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
1008 }
1009
1010 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
1011 }
1012 else
1013 {
1014 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
1015 (ObjectSd->Sacl != NULL))
1016 {
1017 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
1018 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
1019 }
1020
1021 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
1022 }
1023
1024 NewSd = ExAllocatePool(NonPagedPool,
1025 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
1026 DaclLength + SaclLength);
1027 if (NewSd == NULL)
1028 {
1029 ObDereferenceObject(Object);
1030 return STATUS_INSUFFICIENT_RESOURCES;
1031 }
1032
1033 RtlCreateSecurityDescriptor(NewSd,
1034 SECURITY_DESCRIPTOR_REVISION1);
1035
1036 /* We always build a self-relative descriptor */
1037 NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
1038
1039 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
1040
1041 if (OwnerLength != 0)
1042 {
1043 RtlCopyMemory((PVOID)Current,
1044 Owner,
1045 OwnerLength);
1046 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
1047 Current += OwnerLength;
1048 }
1049
1050 if (GroupLength != 0)
1051 {
1052 RtlCopyMemory((PVOID)Current,
1053 Group,
1054 GroupLength);
1055 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
1056 Current += GroupLength;
1057 }
1058
1059 if (DaclLength != 0)
1060 {
1061 RtlCopyMemory((PVOID)Current,
1062 Dacl,
1063 DaclLength);
1064 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
1065 Current += DaclLength;
1066 }
1067
1068 if (SaclLength != 0)
1069 {
1070 RtlCopyMemory((PVOID)Current,
1071 Sacl,
1072 SaclLength);
1073 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
1074 Current += SaclLength;
1075 }
1076
1077 *ObjectsSecurityDescriptor = NewSd;
1078 return STATUS_SUCCESS;
1079 }
1080
1081 /*
1082 * @unimplemented
1083 */
1084 NTSTATUS
1085 NTAPI
1086 SeSetSecurityDescriptorInfoEx(IN PVOID Object OPTIONAL,
1087 IN PSECURITY_INFORMATION SecurityInformation,
1088 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
1089 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
1090 IN ULONG AutoInheritFlags,
1091 IN POOL_TYPE PoolType,
1092 IN PGENERIC_MAPPING GenericMapping)
1093 {
1094 PISECURITY_DESCRIPTOR ObjectSd = *ObjectsSecurityDescriptor;
1095
1096 /* The object does not have a security descriptor. */
1097 if (!ObjectSd)
1098 return STATUS_NO_SECURITY_ON_OBJECT;
1099
1100 UNIMPLEMENTED;
1101 return STATUS_NOT_IMPLEMENTED;
1102 }
1103
1104
1105 /*
1106 * @implemented
1107 */
1108 BOOLEAN NTAPI
1109 SeValidSecurityDescriptor(IN ULONG Length,
1110 IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
1111 {
1112 ULONG SdLength;
1113 PISID Sid;
1114 PACL Acl;
1115 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
1116
1117 if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
1118 {
1119 DPRINT1("Invalid Security Descriptor revision\n");
1120 return FALSE;
1121 }
1122
1123 if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
1124 {
1125 DPRINT1("Invalid Security Descriptor revision\n");
1126 return FALSE;
1127 }
1128
1129 if (!(SecurityDescriptor->Control & SE_SELF_RELATIVE))
1130 {
1131 DPRINT1("No self-relative Security Descriptor\n");
1132 return FALSE;
1133 }
1134
1135 SdLength = sizeof(SECURITY_DESCRIPTOR);
1136
1137 /* Check Owner SID */
1138 if (SecurityDescriptor->Owner == NULL)
1139 {
1140 DPRINT1("No Owner SID\n");
1141 return FALSE;
1142 }
1143
1144 if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
1145 {
1146 DPRINT1("Invalid Owner SID alignment\n");
1147 return FALSE;
1148 }
1149
1150 Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner);
1151 if (Sid->Revision != SID_REVISION)
1152 {
1153 DPRINT1("Invalid Owner SID revision\n");
1154 return FALSE;
1155 }
1156
1157 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1158 if (Length < SdLength)
1159 {
1160 DPRINT1("Invalid Owner SID size\n");
1161 return FALSE;
1162 }
1163
1164 /* Check Group SID */
1165 if (SecurityDescriptor->Group != NULL)
1166 {
1167 if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
1168 {
1169 DPRINT1("Invalid Group SID alignment\n");
1170 return FALSE;
1171 }
1172
1173 Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Group);
1174 if (Sid->Revision != SID_REVISION)
1175 {
1176 DPRINT1("Invalid Group SID revision\n");
1177 return FALSE;
1178 }
1179
1180 SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
1181 if (Length < SdLength)
1182 {
1183 DPRINT1("Invalid Group SID size\n");
1184 return FALSE;
1185 }
1186 }
1187
1188 /* Check DACL */
1189 if (SecurityDescriptor->Dacl != NULL)
1190 {
1191 if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
1192 {
1193 DPRINT1("Invalid DACL alignment\n");
1194 return FALSE;
1195 }
1196
1197 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Dacl);
1198 if ((Acl->AclRevision < MIN_ACL_REVISION) &&
1199 (Acl->AclRevision > MAX_ACL_REVISION))
1200 {
1201 DPRINT1("Invalid DACL revision\n");
1202 return FALSE;
1203 }
1204
1205 SdLength += Acl->AclSize;
1206 if (Length < SdLength)
1207 {
1208 DPRINT1("Invalid DACL size\n");
1209 return FALSE;
1210 }
1211 }
1212
1213 /* Check SACL */
1214 if (SecurityDescriptor->Sacl != NULL)
1215 {
1216 if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
1217 {
1218 DPRINT1("Invalid SACL alignment\n");
1219 return FALSE;
1220 }
1221
1222 Acl = (PACL)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Sacl);
1223 if ((Acl->AclRevision < MIN_ACL_REVISION) ||
1224 (Acl->AclRevision > MAX_ACL_REVISION))
1225 {
1226 DPRINT1("Invalid SACL revision\n");
1227 return FALSE;
1228 }
1229
1230 SdLength += Acl->AclSize;
1231 if (Length < SdLength)
1232 {
1233 DPRINT1("Invalid SACL size\n");
1234 return FALSE;
1235 }
1236 }
1237
1238 return TRUE;
1239 }
1240
1241 /*
1242 * @implemented
1243 */
1244 NTSTATUS NTAPI
1245 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
1246 {
1247 PAGED_CODE();
1248
1249 if (*SecurityDescriptor != NULL)
1250 {
1251 ExFreePool(*SecurityDescriptor);
1252 *SecurityDescriptor = NULL;
1253 }
1254
1255 return STATUS_SUCCESS;
1256 }
1257
1258
1259 /*
1260 * @unimplemented
1261 */
1262 NTSTATUS NTAPI
1263 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
1264 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
1265 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
1266 IN GUID *ObjectType OPTIONAL,
1267 IN BOOLEAN IsDirectoryObject,
1268 IN ULONG AutoInheritFlags,
1269 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
1270 IN PGENERIC_MAPPING GenericMapping,
1271 IN POOL_TYPE PoolType)
1272 {
1273 UNIMPLEMENTED;
1274 return STATUS_NOT_IMPLEMENTED;
1275 }
1276
1277 /*
1278 * @implemented
1279 */
1280 NTSTATUS NTAPI
1281 SeAssignSecurity(PSECURITY_DESCRIPTOR _ParentDescriptor OPTIONAL,
1282 PSECURITY_DESCRIPTOR _ExplicitDescriptor OPTIONAL,
1283 PSECURITY_DESCRIPTOR *NewDescriptor,
1284 BOOLEAN IsDirectoryObject,
1285 PSECURITY_SUBJECT_CONTEXT SubjectContext,
1286 PGENERIC_MAPPING GenericMapping,
1287 POOL_TYPE PoolType)
1288 {
1289 PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
1290 PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
1291 PISECURITY_DESCRIPTOR Descriptor;
1292 PTOKEN Token;
1293 ULONG OwnerLength = 0;
1294 ULONG GroupLength = 0;
1295 ULONG DaclLength = 0;
1296 ULONG SaclLength = 0;
1297 ULONG Length = 0;
1298 ULONG Control = 0;
1299 ULONG_PTR Current;
1300 PSID Owner = NULL;
1301 PSID Group = NULL;
1302 PACL Dacl = NULL;
1303 PACL Sacl = NULL;
1304
1305 PAGED_CODE();
1306
1307 /* Lock subject context */
1308 SeLockSubjectContext(SubjectContext);
1309
1310 if (SubjectContext->ClientToken != NULL)
1311 {
1312 Token = SubjectContext->ClientToken;
1313 }
1314 else
1315 {
1316 Token = SubjectContext->PrimaryToken;
1317 }
1318
1319 /* Inherit the Owner SID */
1320 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
1321 {
1322 DPRINT("Use explicit owner sid!\n");
1323 Owner = ExplicitDescriptor->Owner;
1324
1325 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1326 {
1327 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
1328 }
1329 }
1330 else
1331 {
1332 if (Token != NULL)
1333 {
1334 DPRINT("Use token owner sid!\n");
1335 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
1336 }
1337 else
1338 {
1339 DPRINT("Use default owner sid!\n");
1340 Owner = SeLocalSystemSid;
1341 }
1342
1343 Control |= SE_OWNER_DEFAULTED;
1344 }
1345
1346 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
1347
1348 /* Inherit the Group SID */
1349 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
1350 {
1351 DPRINT("Use explicit group sid!\n");
1352 Group = ExplicitDescriptor->Group;
1353 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
1354 {
1355 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
1356 }
1357 }
1358 else
1359 {
1360 if (Token != NULL)
1361 {
1362 DPRINT("Use token group sid!\n");
1363 Group = Token->PrimaryGroup;
1364 }
1365 else
1366 {
1367 DPRINT("Use default group sid!\n");
1368 Group = SeLocalSystemSid;
1369 }
1370
1371 Control |= SE_OWNER_DEFAULTED;
1372 }
1373
1374 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
1375
1376 /* Inherit the DACL */
1377 if (ExplicitDescriptor != NULL &&
1378 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
1379 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
1380 {
1381 DPRINT("Use explicit DACL!\n");
1382 Dacl = ExplicitDescriptor->Dacl;
1383 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1384 {
1385 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
1386 }
1387
1388 Control |= SE_DACL_PRESENT;
1389 }
1390 else if (ParentDescriptor != NULL &&
1391 (ParentDescriptor->Control & SE_DACL_PRESENT))
1392 {
1393 DPRINT("Use parent DACL!\n");
1394 /* FIXME: Inherit */
1395 Dacl = ParentDescriptor->Dacl;
1396 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1397 {
1398 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
1399 }
1400
1401 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1402 }
1403 else if (Token != NULL && Token->DefaultDacl != NULL)
1404 {
1405 DPRINT("Use token default DACL!\n");
1406 /* FIXME: Inherit */
1407 Dacl = Token->DefaultDacl;
1408 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1409 }
1410 else
1411 {
1412 DPRINT("Use NULL DACL!\n");
1413 Dacl = NULL;
1414 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
1415 }
1416
1417 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
1418
1419 /* Inherit the SACL */
1420 if (ExplicitDescriptor != NULL &&
1421 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
1422 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
1423 {
1424 DPRINT("Use explicit SACL!\n");
1425 Sacl = ExplicitDescriptor->Sacl;
1426 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
1427 {
1428 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
1429 }
1430
1431 Control |= SE_SACL_PRESENT;
1432 }
1433 else if (ParentDescriptor != NULL &&
1434 (ParentDescriptor->Control & SE_SACL_PRESENT))
1435 {
1436 DPRINT("Use parent SACL!\n");
1437 /* FIXME: Inherit */
1438 Sacl = ParentDescriptor->Sacl;
1439 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
1440 {
1441 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
1442 }
1443
1444 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
1445 }
1446
1447 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
1448
1449 /* Allocate and initialize the new security descriptor */
1450 Length = sizeof(SECURITY_DESCRIPTOR) +
1451 OwnerLength + GroupLength + DaclLength + SaclLength;
1452
1453 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
1454 sizeof(SECURITY_DESCRIPTOR),
1455 OwnerLength,
1456 GroupLength,
1457 DaclLength,
1458 SaclLength);
1459
1460 Descriptor = ExAllocatePoolWithTag(PagedPool,
1461 Length,
1462 TAG_SD);
1463 if (Descriptor == NULL)
1464 {
1465 DPRINT1("ExAlloctePool() failed\n");
1466 /* FIXME: Unlock subject context */
1467 return STATUS_INSUFFICIENT_RESOURCES;
1468 }
1469
1470 RtlZeroMemory( Descriptor, Length );
1471 RtlCreateSecurityDescriptor(Descriptor,
1472 SECURITY_DESCRIPTOR_REVISION);
1473
1474 Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
1475
1476 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
1477
1478 if (SaclLength != 0)
1479 {
1480 RtlCopyMemory((PVOID)Current,
1481 Sacl,
1482 SaclLength);
1483 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1484 Current += SaclLength;
1485 }
1486
1487 if (DaclLength != 0)
1488 {
1489 RtlCopyMemory((PVOID)Current,
1490 Dacl,
1491 DaclLength);
1492 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1493 Current += DaclLength;
1494 }
1495
1496 if (OwnerLength != 0)
1497 {
1498 RtlCopyMemory((PVOID)Current,
1499 Owner,
1500 OwnerLength);
1501 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1502 Current += OwnerLength;
1503 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
1504 }
1505 else
1506 {
1507 DPRINT("Owner of %x is zero length\n", Descriptor);
1508 }
1509
1510 if (GroupLength != 0)
1511 {
1512 memmove((PVOID)Current,
1513 Group,
1514 GroupLength);
1515 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
1516 }
1517
1518 /* Unlock subject context */
1519 SeUnlockSubjectContext(SubjectContext);
1520
1521 *NewDescriptor = Descriptor;
1522
1523 DPRINT("Descrptor %x\n", Descriptor);
1524 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
1525
1526 return STATUS_SUCCESS;
1527 }
1528
1529 /* EOF */