- Fix a typo in NtSetSecurityObject().
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id: semgr.c,v 1.43 2004/09/08 11:39:59 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Security manager
6 * FILE: kernel/se/semgr.c
7 * PROGRAMER: ?
8 * REVISION HISTORY:
9 * 26/07/98: Added stubs for security functions
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 #define TAG_SXPT TAG('S', 'X', 'P', 'T')
19
20
21 /* GLOBALS ******************************************************************/
22
23 PSE_EXPORTS EXPORTED SeExports = NULL;
24
25
26 /* PROTOTYPES ***************************************************************/
27
28 static BOOLEAN SepInitExports(VOID);
29
30 /* FUNCTIONS ****************************************************************/
31
32
33 BOOLEAN INIT_FUNCTION
34 SeInit1(VOID)
35 {
36 SepInitLuid();
37
38 if (!SepInitSecurityIDs())
39 return FALSE;
40
41 if (!SepInitDACLs())
42 return FALSE;
43
44 if (!SepInitSDs())
45 return FALSE;
46
47 SepInitPrivileges();
48
49 if (!SepInitExports())
50 return FALSE;
51
52 return TRUE;
53 }
54
55
56 BOOLEAN INIT_FUNCTION
57 SeInit2(VOID)
58 {
59 SepInitializeTokenImplementation();
60
61 return TRUE;
62 }
63
64
65 BOOLEAN
66 SeInitSRM(VOID)
67 {
68 OBJECT_ATTRIBUTES ObjectAttributes;
69 UNICODE_STRING Name;
70 HANDLE DirectoryHandle;
71 HANDLE EventHandle;
72 NTSTATUS Status;
73
74 /* Create '\Security' directory */
75 RtlInitUnicodeString(&Name,
76 L"\\Security");
77 InitializeObjectAttributes(&ObjectAttributes,
78 &Name,
79 OBJ_PERMANENT,
80 0,
81 NULL);
82 Status = NtCreateDirectoryObject(&DirectoryHandle,
83 DIRECTORY_ALL_ACCESS,
84 &ObjectAttributes);
85 if (!NT_SUCCESS(Status))
86 {
87 DPRINT1("Failed to create 'Security' directory!\n");
88 return FALSE;
89 }
90
91 /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
92 RtlInitUnicodeString(&Name,
93 L"\\LSA_AUTHENTICATION_INITALIZED");
94 InitializeObjectAttributes(&ObjectAttributes,
95 &Name,
96 OBJ_PERMANENT,
97 DirectoryHandle,
98 SePublicDefaultSd);
99 Status = NtCreateEvent(&EventHandle,
100 EVENT_ALL_ACCESS,
101 &ObjectAttributes,
102 FALSE,
103 FALSE);
104 if (!NT_SUCCESS(Status))
105 {
106 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
107 NtClose(DirectoryHandle);
108 return FALSE;
109 }
110
111 NtClose(EventHandle);
112 NtClose(DirectoryHandle);
113
114 /* FIXME: Create SRM port and listener thread */
115
116 return TRUE;
117 }
118
119
120 static BOOLEAN INIT_FUNCTION
121 SepInitExports(VOID)
122 {
123 SeExports = ExAllocatePoolWithTag(NonPagedPool,
124 sizeof(SE_EXPORTS),
125 TAG_SXPT);
126 if (SeExports == NULL)
127 return FALSE;
128
129 SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege;
130 SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
131 SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege;
132 SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
133 SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
134 SeExports->SeTcbPrivilege = SeTcbPrivilege;
135 SeExports->SeSecurityPrivilege = SeSecurityPrivilege;
136 SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
137 SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege;
138 SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
139 SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
140 SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege;
141 SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege;
142 SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
143 SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
144 SeExports->SeBackupPrivilege = SeBackupPrivilege;
145 SeExports->SeRestorePrivilege = SeRestorePrivilege;
146 SeExports->SeShutdownPrivilege = SeShutdownPrivilege;
147 SeExports->SeDebugPrivilege = SeDebugPrivilege;
148 SeExports->SeAuditPrivilege = SeAuditPrivilege;
149 SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
150 SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
151 SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
152
153 SeExports->SeNullSid = SeNullSid;
154 SeExports->SeWorldSid = SeWorldSid;
155 SeExports->SeLocalSid = SeLocalSid;
156 SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid;
157 SeExports->SeCreatorGroupSid = SeCreatorGroupSid;
158 SeExports->SeNtAuthoritySid = SeNtAuthoritySid;
159 SeExports->SeDialupSid = SeDialupSid;
160 SeExports->SeNetworkSid = SeNetworkSid;
161 SeExports->SeBatchSid = SeBatchSid;
162 SeExports->SeInteractiveSid = SeInteractiveSid;
163 SeExports->SeLocalSystemSid = SeLocalSystemSid;
164 SeExports->SeAliasAdminsSid = SeAliasAdminsSid;
165 SeExports->SeAliasUsersSid = SeAliasUsersSid;
166 SeExports->SeAliasGuestsSid = SeAliasGuestsSid;
167 SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid;
168 SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid;
169 SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid;
170 SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid;
171 SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid;
172
173 return TRUE;
174 }
175
176
177 VOID SepReferenceLogonSession(PLUID AuthenticationId)
178 {
179 UNIMPLEMENTED;
180 }
181
182 VOID SepDeReferenceLogonSession(PLUID AuthenticationId)
183 {
184 UNIMPLEMENTED;
185 }
186
187
188
189 /*
190 * @unimplemented
191 */
192 NTSTATUS STDCALL
193 NtAllocateUuids(PULARGE_INTEGER Time,
194 PULONG Range,
195 PULONG Sequence)
196 {
197 UNIMPLEMENTED;
198 return(STATUS_NOT_IMPLEMENTED);
199 }
200
201
202 /*
203 * @implemented
204 */
205 VOID STDCALL
206 SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
207 {
208 PETHREAD Thread;
209 BOOLEAN CopyOnOpen;
210 BOOLEAN EffectiveOnly;
211
212 Thread = PsGetCurrentThread();
213 if (Thread == NULL)
214 {
215 SubjectContext->ProcessAuditId = 0;
216 SubjectContext->PrimaryToken = NULL;
217 SubjectContext->ClientToken = NULL;
218 SubjectContext->ImpersonationLevel = 0;
219 }
220 else
221 {
222 SubjectContext->ProcessAuditId = Thread->ThreadsProcess;
223 SubjectContext->ClientToken =
224 PsReferenceImpersonationToken(Thread,
225 &CopyOnOpen,
226 &EffectiveOnly,
227 &SubjectContext->ImpersonationLevel);
228 SubjectContext->PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
229 }
230 }
231
232
233 /*
234 * @unimplemented
235 */
236 VOID STDCALL
237 SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
238 {
239 UNIMPLEMENTED;
240 }
241
242
243 /*
244 * @implemented
245 */
246 VOID STDCALL
247 SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
248 {
249 if (SubjectContext->PrimaryToken != NULL)
250 {
251 ObDereferenceObject(SubjectContext->PrimaryToken);
252 }
253
254 if (SubjectContext->ClientToken != NULL)
255 {
256 ObDereferenceObject(SubjectContext->ClientToken);
257 }
258 }
259
260
261 /*
262 * @unimplemented
263 */
264 VOID STDCALL
265 SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
266 {
267 UNIMPLEMENTED;
268 }
269
270
271 /*
272 * @implemented
273 */
274 NTSTATUS STDCALL
275 SeDeassignSecurity(PSECURITY_DESCRIPTOR *SecurityDescriptor)
276 {
277 if (*SecurityDescriptor != NULL)
278 {
279 ExFreePool(*SecurityDescriptor);
280 *SecurityDescriptor = NULL;
281 }
282
283 return STATUS_SUCCESS;
284 }
285
286
287 /*
288 * @unimplemented
289 */
290 NTSTATUS STDCALL
291 SeAssignSecurityEx(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
292 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
293 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
294 IN GUID *ObjectType OPTIONAL,
295 IN BOOLEAN IsDirectoryObject,
296 IN ULONG AutoInheritFlags,
297 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
298 IN PGENERIC_MAPPING GenericMapping,
299 IN POOL_TYPE PoolType)
300 {
301 UNIMPLEMENTED;
302 return STATUS_NOT_IMPLEMENTED;
303 }
304
305
306 /*
307 * FUNCTION: Creates a security descriptor for a new object.
308 * ARGUMENTS:
309 * ParentDescriptor =
310 * ExplicitDescriptor =
311 * NewDescriptor =
312 * IsDirectoryObject =
313 * SubjectContext =
314 * GeneralMapping =
315 * PoolType =
316 * RETURNS: Status
317 *
318 * @implemented
319 */
320 NTSTATUS STDCALL
321 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
322 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
323 PSECURITY_DESCRIPTOR *NewDescriptor,
324 BOOLEAN IsDirectoryObject,
325 PSECURITY_SUBJECT_CONTEXT SubjectContext,
326 PGENERIC_MAPPING GenericMapping,
327 POOL_TYPE PoolType)
328 {
329 PSECURITY_DESCRIPTOR Descriptor;
330 PACCESS_TOKEN Token;
331 ULONG OwnerLength = 0;
332 ULONG GroupLength = 0;
333 ULONG DaclLength = 0;
334 ULONG SaclLength = 0;
335 ULONG Length = 0;
336 ULONG Control = 0;
337 ULONG_PTR Current;
338 PSID Owner = NULL;
339 PSID Group = NULL;
340 PACL Dacl = NULL;
341 PACL Sacl = NULL;
342
343 /* FIXME: Lock subject context */
344
345 if (SubjectContext->ClientToken != NULL)
346 {
347 Token = SubjectContext->ClientToken;
348 }
349 else
350 {
351 Token = SubjectContext->PrimaryToken;
352 }
353
354
355 /* Inherit the Owner SID */
356 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
357 {
358 DPRINT("Use explicit owner sid!\n");
359 Owner = ExplicitDescriptor->Owner;
360 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
361 {
362 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
363 }
364 }
365 else
366 {
367 if (Token != NULL)
368 {
369 DPRINT("Use token owner sid!\n");
370 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
371 }
372 else
373 {
374 DPRINT("Use default owner sid!\n");
375 Owner = SeLocalSystemSid;
376 }
377
378 Control |= SE_OWNER_DEFAULTED;
379 }
380
381 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
382
383
384 /* Inherit the Group SID */
385 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
386 {
387 DPRINT("Use explicit group sid!\n");
388 Group = ExplicitDescriptor->Group;
389 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
390 {
391 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
392 }
393 }
394 else
395 {
396 if (Token != NULL)
397 {
398 DPRINT("Use token group sid!\n");
399 Group = Token->PrimaryGroup;
400 }
401 else
402 {
403 DPRINT("Use default group sid!\n");
404 Group = SeLocalSystemSid;
405 }
406
407 Control |= SE_OWNER_DEFAULTED;
408 }
409
410 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
411
412
413 /* Inherit the DACL */
414 if (ExplicitDescriptor != NULL &&
415 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
416 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
417 {
418 DPRINT("Use explicit DACL!\n");
419 Dacl = ExplicitDescriptor->Dacl;
420 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
421 {
422 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
423 }
424
425 Control |= SE_DACL_PRESENT;
426 }
427 else if (ParentDescriptor != NULL &&
428 (ParentDescriptor->Control & SE_DACL_PRESENT))
429 {
430 DPRINT("Use parent DACL!\n");
431 /* FIXME: Inherit */
432 Dacl = ParentDescriptor->Dacl;
433 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
434 {
435 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
436 }
437 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
438 }
439 else if (Token != NULL && Token->DefaultDacl != NULL)
440 {
441 DPRINT("Use token default DACL!\n");
442 /* FIXME: Inherit */
443 Dacl = Token->DefaultDacl;
444 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
445 }
446 else
447 {
448 DPRINT("Use NULL DACL!\n");
449 Dacl = NULL;
450 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
451 }
452
453 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
454
455
456 /* Inherit the SACL */
457 if (ExplicitDescriptor != NULL &&
458 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
459 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
460 {
461 DPRINT("Use explicit SACL!\n");
462 Sacl = ExplicitDescriptor->Sacl;
463 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
464 {
465 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
466 }
467
468 Control |= SE_SACL_PRESENT;
469 }
470 else if (ParentDescriptor != NULL &&
471 (ParentDescriptor->Control & SE_SACL_PRESENT))
472 {
473 DPRINT("Use parent SACL!\n");
474 /* FIXME: Inherit */
475 Sacl = ParentDescriptor->Sacl;
476 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
477 {
478 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
479 }
480 Control |= (SE_SACL_PRESENT & SE_SACL_DEFAULTED);
481 }
482
483 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
484
485
486 /* Allocate and initialize the new security descriptor */
487 Length = sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength + DaclLength + SaclLength;
488
489 Descriptor = ExAllocatePool(NonPagedPool,
490 Length);
491 if (Descriptor == NULL)
492 {
493 DPRINT1("ExAlloctePool() failed\n");
494 /* FIXME: Unlock subject context */
495 return STATUS_INSUFFICIENT_RESOURCES;
496 }
497
498 RtlCreateSecurityDescriptor(Descriptor,
499 SECURITY_DESCRIPTOR_REVISION);
500
501 Descriptor->Control = Control | SE_SELF_RELATIVE;
502
503 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
504
505 if (SaclLength != 0)
506 {
507 RtlCopyMemory((PVOID)Current,
508 Sacl,
509 SaclLength);
510 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
511 Current += SaclLength;
512 }
513
514 if (DaclLength != 0)
515 {
516 RtlCopyMemory((PVOID)Current,
517 Dacl,
518 DaclLength);
519 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
520 Current += DaclLength;
521 }
522
523 if (OwnerLength != 0)
524 {
525 RtlCopyMemory((PVOID)Current,
526 Owner,
527 OwnerLength);
528 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
529 Current += OwnerLength;
530 }
531
532 if (GroupLength != 0)
533 {
534 memmove((PVOID)Current,
535 Group,
536 GroupLength);
537 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
538 }
539
540 /* FIXME: Unlock subject context */
541
542 *NewDescriptor = Descriptor;
543
544 return STATUS_SUCCESS;
545 }
546
547
548 static BOOLEAN
549 SepSidInToken(PACCESS_TOKEN Token,
550 PSID Sid)
551 {
552 ULONG i;
553
554 if (Token->UserAndGroupCount == 0)
555 {
556 return FALSE;
557 }
558
559 for (i=0; i<Token->UserAndGroupCount; i++)
560 {
561 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
562 {
563 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
564 {
565 return TRUE;
566 }
567
568 return FALSE;
569 }
570 }
571
572 return FALSE;
573 }
574
575
576 /*
577 * FUNCTION: Determines whether the requested access rights can be granted
578 * to an object protected by a security descriptor and an object owner
579 * ARGUMENTS:
580 * SecurityDescriptor = Security descriptor protecting the object
581 * SubjectSecurityContext = Subject's captured security context
582 * SubjectContextLocked = Indicates the user's subject context is locked
583 * DesiredAccess = Access rights the caller is trying to acquire
584 * PreviouslyGrantedAccess = Specified the access rights already granted
585 * Privileges = ?
586 * GenericMapping = Generic mapping associated with the object
587 * AccessMode = Access mode used for the check
588 * GrantedAccess (OUT) = On return specifies the access granted
589 * AccessStatus (OUT) = Status indicating why access was denied
590 * RETURNS: If access was granted, returns TRUE
591 *
592 * @implemented
593 */
594 BOOLEAN STDCALL
595 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
596 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
597 IN BOOLEAN SubjectContextLocked,
598 IN ACCESS_MASK DesiredAccess,
599 IN ACCESS_MASK PreviouslyGrantedAccess,
600 OUT PPRIVILEGE_SET* Privileges,
601 IN PGENERIC_MAPPING GenericMapping,
602 IN KPROCESSOR_MODE AccessMode,
603 OUT PACCESS_MASK GrantedAccess,
604 OUT PNTSTATUS AccessStatus)
605 {
606 LUID_AND_ATTRIBUTES Privilege;
607 ACCESS_MASK CurrentAccess;
608 PACCESS_TOKEN Token;
609 ULONG i;
610 PACL Dacl;
611 BOOLEAN Present;
612 BOOLEAN Defaulted;
613 PACE CurrentAce;
614 PSID Sid;
615 NTSTATUS Status;
616
617 CurrentAccess = PreviouslyGrantedAccess;
618
619 Token = SubjectSecurityContext->ClientToken ?
620 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
621
622 /* Get the DACL */
623 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
624 &Present,
625 &Dacl,
626 &Defaulted);
627 if (!NT_SUCCESS(Status))
628 {
629 *AccessStatus = Status;
630 return FALSE;
631 }
632
633 /* RULE 1: Grant desired access if the object is unprotected */
634 if (Dacl == NULL)
635 {
636 *GrantedAccess = DesiredAccess;
637 *AccessStatus = STATUS_SUCCESS;
638 return TRUE;
639 }
640
641 CurrentAccess = PreviouslyGrantedAccess;
642
643 /* RULE 2: Check token for 'take ownership' privilege */
644 Privilege.Luid = SeTakeOwnershipPrivilege;
645 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
646
647 if (SepPrivilegeCheck(Token,
648 &Privilege,
649 1,
650 PRIVILEGE_SET_ALL_NECESSARY,
651 AccessMode))
652 {
653 CurrentAccess |= WRITE_OWNER;
654 if (DesiredAccess == CurrentAccess)
655 {
656 *GrantedAccess = CurrentAccess;
657 *AccessStatus = STATUS_SUCCESS;
658 return TRUE;
659 }
660 }
661
662 /* RULE 3: Check whether the token is the owner */
663 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
664 &Sid,
665 &Defaulted);
666 if (!NT_SUCCESS(Status))
667 {
668 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
669 *AccessStatus = Status;
670 return FALSE;
671 }
672
673 if (SepSidInToken(Token, Sid))
674 {
675 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
676 if (DesiredAccess == CurrentAccess)
677 {
678 *GrantedAccess = CurrentAccess;
679 *AccessStatus = STATUS_SUCCESS;
680 return TRUE;
681 }
682 }
683
684 /* RULE 4: Grant rights according to the DACL */
685 CurrentAce = (PACE)(Dacl + 1);
686 for (i = 0; i < Dacl->AceCount; i++)
687 {
688 Sid = (PSID)(CurrentAce + 1);
689 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
690 {
691 if (SepSidInToken(Token, Sid))
692 {
693 *GrantedAccess = 0;
694 *AccessStatus = STATUS_ACCESS_DENIED;
695 return TRUE;
696 }
697 }
698
699 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
700 {
701 if (SepSidInToken(Token, Sid))
702 {
703 CurrentAccess |= CurrentAce->AccessMask;
704 }
705 }
706 }
707
708 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
709 CurrentAccess, DesiredAccess);
710
711 *GrantedAccess = CurrentAccess & DesiredAccess;
712
713 *AccessStatus =
714 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
715
716 return TRUE;
717 }
718
719
720 NTSTATUS STDCALL
721 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
722 IN HANDLE TokenHandle,
723 IN ACCESS_MASK DesiredAccess,
724 IN PGENERIC_MAPPING GenericMapping,
725 OUT PPRIVILEGE_SET PrivilegeSet,
726 OUT PULONG ReturnLength,
727 OUT PACCESS_MASK GrantedAccess,
728 OUT PNTSTATUS AccessStatus)
729 {
730 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
731 KPROCESSOR_MODE PreviousMode;
732 PACCESS_TOKEN Token;
733 NTSTATUS Status;
734
735 DPRINT("NtAccessCheck() called\n");
736
737 PreviousMode = KeGetPreviousMode();
738 if (PreviousMode == KernelMode)
739 {
740 *GrantedAccess = DesiredAccess;
741 *AccessStatus = STATUS_SUCCESS;
742 return STATUS_SUCCESS;
743 }
744
745 Status = ObReferenceObjectByHandle(TokenHandle,
746 TOKEN_QUERY,
747 SepTokenObjectType,
748 PreviousMode,
749 (PVOID*)&Token,
750 NULL);
751 if (!NT_SUCCESS(Status))
752 {
753 DPRINT1("Failed to reference token (Status %lx)\n", Status);
754 return Status;
755 }
756
757 /* Check token type */
758 if (Token->TokenType != TokenImpersonation)
759 {
760 DPRINT1("No impersonation token\n");
761 ObDereferenceObject(Token);
762 return STATUS_ACCESS_VIOLATION;
763 }
764
765 /* Check impersonation level */
766 if (Token->ImpersonationLevel < SecurityAnonymous)
767 {
768 DPRINT1("Invalid impersonation level\n");
769 ObDereferenceObject(Token);
770 return STATUS_ACCESS_VIOLATION;
771 }
772
773 RtlZeroMemory(&SubjectSecurityContext,
774 sizeof(SECURITY_SUBJECT_CONTEXT));
775 SubjectSecurityContext.ClientToken = Token;
776 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
777
778 /* FIXME: Lock subject context */
779
780 if (!SeAccessCheck(SecurityDescriptor,
781 &SubjectSecurityContext,
782 TRUE,
783 DesiredAccess,
784 0,
785 &PrivilegeSet,
786 GenericMapping,
787 PreviousMode,
788 GrantedAccess,
789 AccessStatus))
790 {
791 Status = *AccessStatus;
792 }
793 else
794 {
795 Status = STATUS_ACCESS_DENIED;
796 }
797
798 /* FIXME: Unlock subject context */
799
800 ObDereferenceObject(Token);
801
802 DPRINT("NtAccessCheck() done\n");
803
804 return Status;
805 }
806
807 /* EOF */