- Initialize more fields when creating an Object Type
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/se/semgr.c
6 * PURPOSE: Security manager
7 *
8 * PROGRAMMERS: No programmer listed.
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PSE_EXPORTS SeExports = NULL;
20 SE_EXPORTS SepExports;
21
22 static ERESOURCE SepSubjectContextLock;
23
24
25 /* PROTOTYPES ***************************************************************/
26
27 static BOOLEAN SepInitExports(VOID);
28
29
30 /* FUNCTIONS ****************************************************************/
31
32 BOOLEAN INIT_FUNCTION
33 SeInit1(VOID)
34 {
35 SepInitLuid();
36
37 if (!SepInitSecurityIDs())
38 return FALSE;
39
40 if (!SepInitDACLs())
41 return FALSE;
42
43 if (!SepInitSDs())
44 return FALSE;
45
46 SepInitPrivileges();
47
48 if (!SepInitExports())
49 return FALSE;
50
51 /* Initialize the subject context lock */
52 ExInitializeResource(&SepSubjectContextLock);
53
54 return TRUE;
55 }
56
57
58 BOOLEAN INIT_FUNCTION
59 SeInit2(VOID)
60 {
61 SepInitializeTokenImplementation();
62
63 return TRUE;
64 }
65
66
67 BOOLEAN
68 SeInitSRM(VOID)
69 {
70 OBJECT_ATTRIBUTES ObjectAttributes;
71 UNICODE_STRING Name;
72 HANDLE DirectoryHandle;
73 HANDLE EventHandle;
74 NTSTATUS Status;
75
76 /* Create '\Security' directory */
77 RtlInitUnicodeString(&Name,
78 L"\\Security");
79 InitializeObjectAttributes(&ObjectAttributes,
80 &Name,
81 OBJ_PERMANENT,
82 0,
83 NULL);
84 Status = ZwCreateDirectoryObject(&DirectoryHandle,
85 DIRECTORY_ALL_ACCESS,
86 &ObjectAttributes);
87 if (!NT_SUCCESS(Status))
88 {
89 DPRINT1("Failed to create 'Security' directory!\n");
90 return FALSE;
91 }
92
93 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
94 RtlInitUnicodeString(&Name,
95 L"\\LSA_AUTHENTICATION_INITALIZED");
96 InitializeObjectAttributes(&ObjectAttributes,
97 &Name,
98 OBJ_PERMANENT,
99 DirectoryHandle,
100 SePublicDefaultSd);
101 Status = ZwCreateEvent(&EventHandle,
102 EVENT_ALL_ACCESS,
103 &ObjectAttributes,
104 SynchronizationEvent,
105 FALSE);
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
109 NtClose(DirectoryHandle);
110 return FALSE;
111 }
112
113 ZwClose(EventHandle);
114 ZwClose(DirectoryHandle);
115
116 /* FIXME: Create SRM port and listener thread */
117
118 return TRUE;
119 }
120
121
122 static BOOLEAN INIT_FUNCTION
123 SepInitExports(VOID)
124 {
125 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
126 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
127 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
128 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
129 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
130 SepExports.SeTcbPrivilege = SeTcbPrivilege;
131 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
132 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
133 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
134 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
135 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
136 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
137 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
138 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
139 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
140 SepExports.SeBackupPrivilege = SeBackupPrivilege;
141 SepExports.SeRestorePrivilege = SeRestorePrivilege;
142 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
143 SepExports.SeDebugPrivilege = SeDebugPrivilege;
144 SepExports.SeAuditPrivilege = SeAuditPrivilege;
145 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
146 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
147 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
148
149 SepExports.SeNullSid = SeNullSid;
150 SepExports.SeWorldSid = SeWorldSid;
151 SepExports.SeLocalSid = SeLocalSid;
152 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
153 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
154 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
155 SepExports.SeDialupSid = SeDialupSid;
156 SepExports.SeNetworkSid = SeNetworkSid;
157 SepExports.SeBatchSid = SeBatchSid;
158 SepExports.SeInteractiveSid = SeInteractiveSid;
159 SepExports.SeLocalSystemSid = SeLocalSystemSid;
160 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
161 SepExports.SeAliasUsersSid = SeAliasUsersSid;
162 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
163 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
164 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
165 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
166 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
167 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
168 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
169 SepExports.SeRestrictedSid = SeRestrictedSid;
170 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
171
172 SepExports.SeUndockPrivilege = SeUndockPrivilege;
173 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
174 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
175
176 SeExports = &SepExports;
177 return TRUE;
178 }
179
180
181 VOID SepReferenceLogonSession(PLUID AuthenticationId)
182 {
183 UNIMPLEMENTED;
184 }
185
186 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
187 {
188 UNIMPLEMENTED;
189 }
190
191 NTSTATUS
192 STDCALL
193 SeDefaultObjectMethod(PVOID Object,
194 SECURITY_OPERATION_CODE OperationType,
195 SECURITY_INFORMATION SecurityInformation,
196 PSECURITY_DESCRIPTOR SecurityDescriptor,
197 PULONG ReturnLength,
198 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
199 POOL_TYPE PoolType,
200 PGENERIC_MAPPING GenericMapping)
201 {
202 PSECURITY_DESCRIPTOR ObjectSd;
203 PSECURITY_DESCRIPTOR NewSd;
204 POBJECT_HEADER Header = BODY_TO_HEADER(Object);
205 PSID Owner = 0;
206 PSID Group = 0;
207 PACL Dacl = 0;
208 PACL Sacl = 0;
209 ULONG OwnerLength = 0;
210 ULONG GroupLength = 0;
211 ULONG DaclLength = 0;
212 ULONG SaclLength = 0;
213 ULONG Control = 0;
214 ULONG_PTR Current;
215 NTSTATUS Status;
216
217 if (OperationType == SetSecurityDescriptor)
218 {
219 ObjectSd = Header->SecurityDescriptor;
220
221 /* Get owner and owner size */
222 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
223 {
224 if (SecurityDescriptor->Owner != NULL)
225 {
226 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
227 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
228 (ULONG_PTR)SecurityDescriptor);
229 else
230 Owner = (PSID)SecurityDescriptor->Owner;
231 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
232 }
233 Control |= (SecurityDescriptor->Control & SE_OWNER_DEFAULTED);
234 }
235 else
236 {
237 if (ObjectSd->Owner != NULL)
238 {
239 Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
240 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
241 }
242 Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
243 }
244
245 /* Get group and group size */
246 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
247 {
248 if (SecurityDescriptor->Group != NULL)
249 {
250 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
251 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
252 (ULONG_PTR)SecurityDescriptor);
253 else
254 Group = (PSID)SecurityDescriptor->Group;
255 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
256 }
257 Control |= (SecurityDescriptor->Control & SE_GROUP_DEFAULTED);
258 }
259 else
260 {
261 if (ObjectSd->Group != NULL)
262 {
263 Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
264 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
265 }
266 Control |= (ObjectSd->Control & SE_GROUP_DEFAULTED);
267 }
268
269 /* Get DACL and DACL size */
270 if (SecurityInformation & DACL_SECURITY_INFORMATION)
271 {
272 if ((SecurityDescriptor->Control & SE_DACL_PRESENT) &&
273 (SecurityDescriptor->Dacl != NULL))
274 {
275 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
276 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor->Dacl +
277 (ULONG_PTR)SecurityDescriptor);
278 else
279 Dacl = (PACL)SecurityDescriptor->Dacl;
280
281 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
282 }
283 Control |= (SecurityDescriptor->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
284 }
285 else
286 {
287 if ((ObjectSd->Control & SE_DACL_PRESENT) &&
288 (ObjectSd->Dacl != NULL))
289 {
290 Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
291 DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
292 }
293 Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
294 }
295
296 /* Get SACL and SACL size */
297 if (SecurityInformation & SACL_SECURITY_INFORMATION)
298 {
299 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
300 (SecurityDescriptor->Sacl != NULL))
301 {
302 if( SecurityDescriptor->Control & SE_SELF_RELATIVE )
303 Sacl = (PACL)((ULONG_PTR)SecurityDescriptor->Sacl +
304 (ULONG_PTR)SecurityDescriptor);
305 else
306 Sacl = (PACL)SecurityDescriptor->Sacl;
307 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
308 }
309 Control |= (SecurityDescriptor->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
310 }
311 else
312 {
313 if ((ObjectSd->Control & SE_SACL_PRESENT) &&
314 (ObjectSd->Sacl != NULL))
315 {
316 Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
317 SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
318 }
319 Control |= (ObjectSd->Control & (SE_SACL_DEFAULTED | SE_SACL_PRESENT));
320 }
321
322 NewSd = ExAllocatePool(NonPagedPool,
323 sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
324 DaclLength + SaclLength);
325 if (NewSd == NULL)
326 {
327 ObDereferenceObject(Object);
328 return STATUS_INSUFFICIENT_RESOURCES;
329 }
330
331 RtlCreateSecurityDescriptor(NewSd,
332 SECURITY_DESCRIPTOR_REVISION1);
333 /* We always build a self-relative descriptor */
334 NewSd->Control = Control | SE_SELF_RELATIVE;
335
336 Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
337
338 if (OwnerLength != 0)
339 {
340 RtlCopyMemory((PVOID)Current,
341 Owner,
342 OwnerLength);
343 NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
344 Current += OwnerLength;
345 }
346
347 if (GroupLength != 0)
348 {
349 RtlCopyMemory((PVOID)Current,
350 Group,
351 GroupLength);
352 NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
353 Current += GroupLength;
354 }
355
356 if (DaclLength != 0)
357 {
358 RtlCopyMemory((PVOID)Current,
359 Dacl,
360 DaclLength);
361 NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
362 Current += DaclLength;
363 }
364
365 if (SaclLength != 0)
366 {
367 RtlCopyMemory((PVOID)Current,
368 Sacl,
369 SaclLength);
370 NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
371 Current += SaclLength;
372 }
373
374 /* Add the new SD */
375 Status = ObpAddSecurityDescriptor(NewSd,
376 &Header->SecurityDescriptor);
377 if (NT_SUCCESS(Status))
378 {
379 /* Remove the old security descriptor */
380 ObpRemoveSecurityDescriptor(ObjectSd);
381 }
382 else
383 {
384 /* Restore the old security descriptor */
385 Header->SecurityDescriptor = ObjectSd;
386 }
387
388 ExFreePool(NewSd);
389 }
390 else if (OperationType == QuerySecurityDescriptor)
391 {
392 Status = SeQuerySecurityDescriptorInfo(&SecurityInformation,
393 SecurityDescriptor,
394 ReturnLength,
395 &Header->SecurityDescriptor);
396 }
397 else if (OperationType == AssignSecurityDescriptor)
398 {
399 /* Assign the security descriptor to the object header */
400 Status = ObpAddSecurityDescriptor(SecurityDescriptor,
401 &Header->SecurityDescriptor);
402 }
403
404
405 return STATUS_SUCCESS;
406 }
407
408 /*
409 * @implemented
410 */
411 VOID STDCALL
412 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
413 {
414 PETHREAD Thread;
415 BOOLEAN CopyOnOpen;
416 BOOLEAN EffectiveOnly;
417
418 PAGED_CODE();
419
420 Thread = PsGetCurrentThread();
421 if (Thread == NULL)
422 {
423 SubjectContext->ProcessAuditId = 0;
424 SubjectContext->PrimaryToken = NULL;
425 SubjectContext->ClientToken = NULL;
426 SubjectContext->ImpersonationLevel = 0;
427 }
428 else
429 {
430 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
431 SubjectContext->ClientToken =
432 PsReferenceImpersonationToken(Thread,
433 &CopyOnOpen,
434 &EffectiveOnly,
435 &SubjectContext->ImpersonationLevel);
436 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
437 }
438 }
439
440
441 /*
442 * @implemented
443 */
444 VOID STDCALL
445 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
446 {
447 PAGED_CODE();
448
449 KeEnterCriticalRegion();
450 ExAcquireResourceExclusiveLite(&SepSubjectContextLock, TRUE);
451 }
452
453
454 /*
455 * @implemented
456 */
457 VOID STDCALL
458 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
459 {
460 PAGED_CODE();
461
462 ExReleaseResourceLite(&SepSubjectContextLock);
463 KeLeaveCriticalRegion();
464 }
465
466
467 /*
468 * @implemented
469 */
470 VOID STDCALL
471 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
472 {
473 PAGED_CODE();
474
475 if (SubjectContext->PrimaryToken != NULL)
476 {
477 ObDereferenceObject(SubjectContext->PrimaryToken);
478 }
479
480 if (SubjectContext->ClientToken != NULL)
481 {
482 ObDereferenceObject(SubjectContext->ClientToken);
483 }
484 }
485
486
487 /*
488 * @implemented
489 */
490 NTSTATUS STDCALL
491 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
492 {
493 PAGED_CODE();
494
495 if (*SecurityDescriptor != NULL)
496 {
497 ExFreePool(*SecurityDescriptor);
498 *SecurityDescriptor = NULL;
499 }
500
501 return STATUS_SUCCESS;
502 }
503
504
505 /*
506 * @unimplemented
507 */
508 NTSTATUS STDCALL
509 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
510 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
511 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
512 IN GUID *ObjectType OPTIONAL,
513 IN BOOLEAN IsDirectoryObject,
514 IN ULONG AutoInheritFlags,
515 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
516 IN PGENERIC_MAPPING GenericMapping,
517 IN POOL_TYPE PoolType)
518 {
519 UNIMPLEMENTED;
520 return STATUS_NOT_IMPLEMENTED;
521 }
522
523
524 /*
525 * FUNCTION: Creates a security descriptor for a new object.
526 * ARGUMENTS:
527 * ParentDescriptor =
528 * ExplicitDescriptor =
529 * NewDescriptor =
530 * IsDirectoryObject =
531 * SubjectContext =
532 * GeneralMapping =
533 * PoolType =
534 * RETURNS: Status
535 *
536 * @implemented
537 */
538 NTSTATUS STDCALL
539 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
540 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
541 PSECURITY_DESCRIPTOR *NewDescriptor,
542 BOOLEAN IsDirectoryObject,
543 PSECURITY_SUBJECT_CONTEXT SubjectContext,
544 PGENERIC_MAPPING GenericMapping,
545 POOL_TYPE PoolType)
546 {
547 PSECURITY_DESCRIPTOR Descriptor;
548 PTOKEN Token;
549 ULONG OwnerLength = 0;
550 ULONG GroupLength = 0;
551 ULONG DaclLength = 0;
552 ULONG SaclLength = 0;
553 ULONG Length = 0;
554 ULONG Control = 0;
555 ULONG_PTR Current;
556 PSID Owner = NULL;
557 PSID Group = NULL;
558 PACL Dacl = NULL;
559 PACL Sacl = NULL;
560
561 PAGED_CODE();
562
563 /* Lock subject context */
564 SeLockSubjectContext(SubjectContext);
565
566 if (SubjectContext->ClientToken != NULL)
567 {
568 Token = SubjectContext->ClientToken;
569 }
570 else
571 {
572 Token = SubjectContext->PrimaryToken;
573 }
574
575
576 /* Inherit the Owner SID */
577 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
578 {
579 DPRINT("Use explicit owner sid!\n");
580 Owner = ExplicitDescriptor->Owner;
581
582 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
583 {
584 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
585
586 }
587 }
588 else
589 {
590 if (Token != NULL)
591 {
592 DPRINT("Use token owner sid!\n");
593 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
594 }
595 else
596 {
597 DPRINT("Use default owner sid!\n");
598 Owner = SeLocalSystemSid;
599 }
600
601 Control |= SE_OWNER_DEFAULTED;
602 }
603
604 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
605
606
607 /* Inherit the Group SID */
608 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
609 {
610 DPRINT("Use explicit group sid!\n");
611 Group = ExplicitDescriptor->Group;
612 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
613 {
614 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
615 }
616 }
617 else
618 {
619 if (Token != NULL)
620 {
621 DPRINT("Use token group sid!\n");
622 Group = Token->PrimaryGroup;
623 }
624 else
625 {
626 DPRINT("Use default group sid!\n");
627 Group = SeLocalSystemSid;
628 }
629
630 Control |= SE_OWNER_DEFAULTED;
631 }
632
633 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
634
635
636 /* Inherit the DACL */
637 if (ExplicitDescriptor != NULL &&
638 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
639 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
640 {
641 DPRINT("Use explicit DACL!\n");
642 Dacl = ExplicitDescriptor->Dacl;
643 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
644 {
645 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
646 }
647
648 Control |= SE_DACL_PRESENT;
649 }
650 else if (ParentDescriptor != NULL &&
651 (ParentDescriptor->Control & SE_DACL_PRESENT))
652 {
653 DPRINT("Use parent DACL!\n");
654 /* FIXME: Inherit */
655 Dacl = ParentDescriptor->Dacl;
656 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
657 {
658 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
659 }
660 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
661 }
662 else if (Token != NULL && Token->DefaultDacl != NULL)
663 {
664 DPRINT("Use token default DACL!\n");
665 /* FIXME: Inherit */
666 Dacl = Token->DefaultDacl;
667 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
668 }
669 else
670 {
671 DPRINT("Use NULL DACL!\n");
672 Dacl = NULL;
673 Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
674 }
675
676 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
677
678
679 /* Inherit the SACL */
680 if (ExplicitDescriptor != NULL &&
681 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
682 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
683 {
684 DPRINT("Use explicit SACL!\n");
685 Sacl = ExplicitDescriptor->Sacl;
686 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
687 {
688 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
689 }
690
691 Control |= SE_SACL_PRESENT;
692 }
693 else if (ParentDescriptor != NULL &&
694 (ParentDescriptor->Control & SE_SACL_PRESENT))
695 {
696 DPRINT("Use parent SACL!\n");
697 /* FIXME: Inherit */
698 Sacl = ParentDescriptor->Sacl;
699 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
700 {
701 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
702 }
703 Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
704 }
705
706 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
707
708
709 /* Allocate and initialize the new security descriptor */
710 Length = sizeof(SECURITY_DESCRIPTOR) +
711 OwnerLength + GroupLength + DaclLength + SaclLength;
712
713 DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d DaclLength %d SaclLength %d\n",
714 sizeof(SECURITY_DESCRIPTOR),
715 OwnerLength,
716 GroupLength,
717 DaclLength,
718 SaclLength);
719
720 Descriptor = ExAllocatePool(PagedPool,
721 Length);
722 RtlZeroMemory( Descriptor, Length );
723
724 if (Descriptor == NULL)
725 {
726 DPRINT1("ExAlloctePool() failed\n");
727 /* FIXME: Unlock subject context */
728 return STATUS_INSUFFICIENT_RESOURCES;
729 }
730
731 RtlCreateSecurityDescriptor(Descriptor,
732 SECURITY_DESCRIPTOR_REVISION);
733
734 Descriptor->Control = Control | SE_SELF_RELATIVE;
735
736 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
737
738 if (SaclLength != 0)
739 {
740 RtlCopyMemory((PVOID)Current,
741 Sacl,
742 SaclLength);
743 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
744 Current += SaclLength;
745 }
746
747 if (DaclLength != 0)
748 {
749 RtlCopyMemory((PVOID)Current,
750 Dacl,
751 DaclLength);
752 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
753 Current += DaclLength;
754 }
755
756 if (OwnerLength != 0)
757 {
758 RtlCopyMemory((PVOID)Current,
759 Owner,
760 OwnerLength);
761 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
762 Current += OwnerLength;
763 DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
764 }
765 else
766 DPRINT("Owner of %x is zero length\n", Descriptor);
767
768 if (GroupLength != 0)
769 {
770 memmove((PVOID)Current,
771 Group,
772 GroupLength);
773 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
774 }
775
776 /* Unlock subject context */
777 SeUnlockSubjectContext(SubjectContext);
778
779 *NewDescriptor = Descriptor;
780
781 DPRINT("Descrptor %x\n", Descriptor);
782 ASSERT(RtlLengthSecurityDescriptor(Descriptor));
783
784 return STATUS_SUCCESS;
785 }
786
787
788 static BOOLEAN
789 SepSidInToken(PACCESS_TOKEN _Token,
790 PSID Sid)
791 {
792 ULONG i;
793 PTOKEN Token = (PTOKEN)_Token;
794
795 PAGED_CODE();
796
797 if (Token->UserAndGroupCount == 0)
798 {
799 return FALSE;
800 }
801
802 for (i=0; i<Token->UserAndGroupCount; i++)
803 {
804 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
805 {
806 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
807 {
808 return TRUE;
809 }
810
811 return FALSE;
812 }
813 }
814
815 return FALSE;
816 }
817
818
819 /*
820 * FUNCTION: Determines whether the requested access rights can be granted
821 * to an object protected by a security descriptor and an object owner
822 * ARGUMENTS:
823 * SecurityDescriptor = Security descriptor protecting the object
824 * SubjectSecurityContext = Subject's captured security context
825 * SubjectContextLocked = Indicates the user's subject context is locked
826 * DesiredAccess = Access rights the caller is trying to acquire
827 * PreviouslyGrantedAccess = Specified the access rights already granted
828 * Privileges = ?
829 * GenericMapping = Generic mapping associated with the object
830 * AccessMode = Access mode used for the check
831 * GrantedAccess (OUT) = On return specifies the access granted
832 * AccessStatus (OUT) = Status indicating why access was denied
833 * RETURNS: If access was granted, returns TRUE
834 *
835 * @implemented
836 */
837 BOOLEAN STDCALL
838 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
839 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
840 IN BOOLEAN SubjectContextLocked,
841 IN ACCESS_MASK DesiredAccess,
842 IN ACCESS_MASK PreviouslyGrantedAccess,
843 OUT PPRIVILEGE_SET* Privileges,
844 IN PGENERIC_MAPPING GenericMapping,
845 IN KPROCESSOR_MODE AccessMode,
846 OUT PACCESS_MASK GrantedAccess,
847 OUT PNTSTATUS AccessStatus)
848 {
849 LUID_AND_ATTRIBUTES Privilege;
850 ACCESS_MASK CurrentAccess;
851 PACCESS_TOKEN Token;
852 ULONG i;
853 PACL Dacl;
854 BOOLEAN Present;
855 BOOLEAN Defaulted;
856 PACE CurrentAce;
857 PSID Sid;
858 NTSTATUS Status;
859
860 PAGED_CODE();
861
862 CurrentAccess = PreviouslyGrantedAccess;
863
864 if (SubjectContextLocked == FALSE)
865 {
866 SeLockSubjectContext(SubjectSecurityContext);
867 }
868
869 Token = SubjectSecurityContext->ClientToken ?
870 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
871
872 /* Get the DACL */
873 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
874 &Present,
875 &Dacl,
876 &Defaulted);
877 if (!NT_SUCCESS(Status))
878 {
879 if (SubjectContextLocked == FALSE)
880 {
881 SeUnlockSubjectContext(SubjectSecurityContext);
882 }
883
884 *AccessStatus = Status;
885 return FALSE;
886 }
887
888 /* RULE 1: Grant desired access if the object is unprotected */
889 if (Present == TRUE && Dacl == NULL)
890 {
891 if (SubjectContextLocked == FALSE)
892 {
893 SeUnlockSubjectContext(SubjectSecurityContext);
894 }
895
896 *GrantedAccess = DesiredAccess;
897 *AccessStatus = STATUS_SUCCESS;
898 return TRUE;
899 }
900
901 CurrentAccess = PreviouslyGrantedAccess;
902
903 /* RULE 2: Check token for 'take ownership' privilege */
904 Privilege.Luid = SeTakeOwnershipPrivilege;
905 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
906
907 if (SepPrivilegeCheck(Token,
908 &Privilege,
909 1,
910 PRIVILEGE_SET_ALL_NECESSARY,
911 AccessMode))
912 {
913 CurrentAccess |= WRITE_OWNER;
914 if (DesiredAccess == CurrentAccess)
915 {
916 if (SubjectContextLocked == FALSE)
917 {
918 SeUnlockSubjectContext(SubjectSecurityContext);
919 }
920
921 *GrantedAccess = CurrentAccess;
922 *AccessStatus = STATUS_SUCCESS;
923 return TRUE;
924 }
925 }
926
927 /* RULE 3: Check whether the token is the owner */
928 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
929 &Sid,
930 &Defaulted);
931 if (!NT_SUCCESS(Status))
932 {
933 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
934 if (SubjectContextLocked == FALSE)
935 {
936 SeUnlockSubjectContext(SubjectSecurityContext);
937 }
938
939 *AccessStatus = Status;
940 return FALSE;
941 }
942
943 if (SepSidInToken(Token, Sid))
944 {
945 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
946 if (DesiredAccess == CurrentAccess)
947 {
948 if (SubjectContextLocked == FALSE)
949 {
950 SeUnlockSubjectContext(SubjectSecurityContext);
951 }
952
953 *GrantedAccess = CurrentAccess;
954 *AccessStatus = STATUS_SUCCESS;
955 return TRUE;
956 }
957 }
958
959 /* Fail if DACL is absent */
960 if (Present == FALSE)
961 {
962 if (SubjectContextLocked == FALSE)
963 {
964 SeUnlockSubjectContext(SubjectSecurityContext);
965 }
966
967 *GrantedAccess = 0;
968 *AccessStatus = STATUS_ACCESS_DENIED;
969 return TRUE;
970 }
971
972 /* RULE 4: Grant rights according to the DACL */
973 CurrentAce = (PACE)(Dacl + 1);
974 for (i = 0; i < Dacl->AceCount; i++)
975 {
976 Sid = (PSID)(CurrentAce + 1);
977 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
978 {
979 if (SepSidInToken(Token, Sid))
980 {
981 if (SubjectContextLocked == FALSE)
982 {
983 SeUnlockSubjectContext(SubjectSecurityContext);
984 }
985
986 *GrantedAccess = 0;
987 *AccessStatus = STATUS_ACCESS_DENIED;
988 return TRUE;
989 }
990 }
991
992 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
993 {
994 if (SepSidInToken(Token, Sid))
995 {
996 CurrentAccess |= CurrentAce->AccessMask;
997 }
998 }
999 }
1000
1001 if (SubjectContextLocked == FALSE)
1002 {
1003 SeUnlockSubjectContext(SubjectSecurityContext);
1004 }
1005
1006 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
1007 CurrentAccess, DesiredAccess);
1008
1009 *GrantedAccess = CurrentAccess & DesiredAccess;
1010
1011 *AccessStatus =
1012 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
1013
1014 return TRUE;
1015 }
1016
1017
1018 NTSTATUS STDCALL
1019 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1020 IN HANDLE TokenHandle,
1021 IN ACCESS_MASK DesiredAccess,
1022 IN PGENERIC_MAPPING GenericMapping,
1023 OUT PPRIVILEGE_SET PrivilegeSet,
1024 OUT PULONG ReturnLength,
1025 OUT PACCESS_MASK GrantedAccess,
1026 OUT PNTSTATUS AccessStatus)
1027 {
1028 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
1029 KPROCESSOR_MODE PreviousMode;
1030 PTOKEN Token;
1031 NTSTATUS Status;
1032
1033 PAGED_CODE();
1034
1035 DPRINT("NtAccessCheck() called\n");
1036
1037 PreviousMode = KeGetPreviousMode();
1038 if (PreviousMode == KernelMode)
1039 {
1040 *GrantedAccess = DesiredAccess;
1041 *AccessStatus = STATUS_SUCCESS;
1042 return STATUS_SUCCESS;
1043 }
1044
1045 Status = ObReferenceObjectByHandle(TokenHandle,
1046 TOKEN_QUERY,
1047 SepTokenObjectType,
1048 PreviousMode,
1049 (PVOID*)&Token,
1050 NULL);
1051 if (!NT_SUCCESS(Status))
1052 {
1053 DPRINT1("Failed to reference token (Status %lx)\n", Status);
1054 return Status;
1055 }
1056
1057 /* Check token type */
1058 if (Token->TokenType != TokenImpersonation)
1059 {
1060 DPRINT1("No impersonation token\n");
1061 ObDereferenceObject(Token);
1062 return STATUS_ACCESS_VIOLATION;
1063 }
1064
1065 /* Check impersonation level */
1066 if (Token->ImpersonationLevel < SecurityAnonymous)
1067 {
1068 DPRINT1("Invalid impersonation level\n");
1069 ObDereferenceObject(Token);
1070 return STATUS_ACCESS_VIOLATION;
1071 }
1072
1073 RtlZeroMemory(&SubjectSecurityContext,
1074 sizeof(SECURITY_SUBJECT_CONTEXT));
1075 SubjectSecurityContext.ClientToken = Token;
1076 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
1077
1078 /* Lock subject context */
1079 SeLockSubjectContext(&SubjectSecurityContext);
1080
1081 if (SeAccessCheck(SecurityDescriptor,
1082 &SubjectSecurityContext,
1083 TRUE,
1084 DesiredAccess,
1085 0,
1086 &PrivilegeSet,
1087 GenericMapping,
1088 PreviousMode,
1089 GrantedAccess,
1090 AccessStatus))
1091 {
1092 Status = *AccessStatus;
1093 }
1094 else
1095 {
1096 Status = STATUS_ACCESS_DENIED;
1097 }
1098
1099 /* Unlock subject context */
1100 SeUnlockSubjectContext(&SubjectSecurityContext);
1101
1102 ObDereferenceObject(Token);
1103
1104 DPRINT("NtAccessCheck() done\n");
1105
1106 return Status;
1107 }
1108
1109 /* EOF */