- Use ULONG_PTR instead of ULONG for integer arithmetics on pointers.
[reactos.git] / reactos / ntoskrnl / se / semgr.c
1 /* $Id: semgr.c,v 1.41 2004/08/28 22:22:39 navaraf 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 * @unimplemented
288 */
289 NTSTATUS
290 STDCALL
291 SeAssignSecurityEx(
292 IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
293 IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
294 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
295 IN GUID *ObjectType OPTIONAL,
296 IN BOOLEAN IsDirectoryObject,
297 IN ULONG AutoInheritFlags,
298 IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
299 IN PGENERIC_MAPPING GenericMapping,
300 IN POOL_TYPE PoolType
301 )
302 {
303 UNIMPLEMENTED;
304 return STATUS_NOT_IMPLEMENTED;
305 }
306
307 /*
308 * FUNCTION: Creates a security descriptor for a new object.
309 * ARGUMENTS:
310 * ParentDescriptor =
311 * ExplicitDescriptor =
312 * NewDescriptor =
313 * IsDirectoryObject =
314 * SubjectContext =
315 * GeneralMapping =
316 * PoolType =
317 * RETURNS: Status
318 *
319 * @implemented
320 */
321 NTSTATUS STDCALL
322 SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
323 PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
324 PSECURITY_DESCRIPTOR *NewDescriptor,
325 BOOLEAN IsDirectoryObject,
326 PSECURITY_SUBJECT_CONTEXT SubjectContext,
327 PGENERIC_MAPPING GenericMapping,
328 POOL_TYPE PoolType)
329 {
330 PSECURITY_DESCRIPTOR Descriptor;
331 PACCESS_TOKEN Token;
332 ULONG OwnerLength = 0;
333 ULONG GroupLength = 0;
334 ULONG DaclLength = 0;
335 ULONG SaclLength = 0;
336 ULONG Length = 0;
337 ULONG Control = 0;
338 ULONG_PTR Current;
339 PSID Owner = NULL;
340 PSID Group = NULL;
341 PACL Dacl = NULL;
342 PACL Sacl = NULL;
343
344 /* FIXME: Lock subject context */
345
346 if (SubjectContext->ClientToken != NULL)
347 {
348 Token = SubjectContext->ClientToken;
349 }
350 else
351 {
352 Token = SubjectContext->PrimaryToken;
353 }
354
355
356 /* Inherit the Owner SID */
357 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
358 {
359 DPRINT("Use explicit owner sid!\n");
360 Owner = ExplicitDescriptor->Owner;
361 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
362 {
363 Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
364 }
365 }
366 else
367 {
368 if (Token != NULL)
369 {
370 DPRINT("Use token owner sid!\n");
371 Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid;
372 }
373 else
374 {
375 DPRINT("Use default owner sid!\n");
376 Owner = SeLocalSystemSid;
377 }
378
379 Control |= SE_OWNER_DEFAULTED;
380 }
381
382 OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
383
384
385 /* Inherit the Group SID */
386 if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
387 {
388 DPRINT("Use explicit group sid!\n");
389 Group = ExplicitDescriptor->Group;
390 if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
391 {
392 Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
393 }
394 }
395 else
396 {
397 if (Token != NULL)
398 {
399 DPRINT("Use token group sid!\n");
400 Group = Token->PrimaryGroup;
401 }
402 else
403 {
404 DPRINT("Use default group sid!\n");
405 Group = SeLocalSystemSid;
406 }
407
408 Control |= SE_OWNER_DEFAULTED;
409 }
410
411 GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
412
413
414 /* Inherit the DACL */
415 if (ExplicitDescriptor != NULL &&
416 (ExplicitDescriptor->Control & SE_DACL_PRESENT) &&
417 !(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
418 {
419 DPRINT("Use explicit DACL!\n");
420 Dacl = ExplicitDescriptor->Dacl;
421 if (Dacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
422 {
423 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
424 }
425
426 Control |= SE_DACL_PRESENT;
427 }
428 else if (ParentDescriptor != NULL &&
429 (ParentDescriptor->Control & SE_DACL_PRESENT))
430 {
431 DPRINT("Use parent DACL!\n");
432 /* FIXME: Inherit */
433 Dacl = ParentDescriptor->Dacl;
434 if (Dacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
435 {
436 Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
437 }
438 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
439 }
440 else if (Token != NULL && Token->DefaultDacl != NULL)
441 {
442 DPRINT("Use token default DACL!\n");
443 /* FIXME: Inherit */
444 Dacl = Token->DefaultDacl;
445 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
446 }
447 else
448 {
449 DPRINT("Use NULL DACL!\n");
450 Dacl = NULL;
451 Control |= (SE_DACL_PRESENT & SE_DACL_DEFAULTED);
452 }
453
454 DaclLength = (Dacl != NULL) ? ROUND_UP(Dacl->AclSize, 4) : 0;
455
456
457 /* Inherit the SACL */
458 if (ExplicitDescriptor != NULL &&
459 (ExplicitDescriptor->Control & SE_SACL_PRESENT) &&
460 !(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
461 {
462 DPRINT("Use explicit SACL!\n");
463 Sacl = ExplicitDescriptor->Sacl;
464 if (Sacl != NULL && (ExplicitDescriptor->Control & SE_SELF_RELATIVE))
465 {
466 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
467 }
468
469 Control |= SE_SACL_PRESENT;
470 }
471 else if (ParentDescriptor != NULL &&
472 (ParentDescriptor->Control & SE_SACL_PRESENT))
473 {
474 DPRINT("Use parent SACL!\n");
475 /* FIXME: Inherit */
476 Sacl = ParentDescriptor->Sacl;
477 if (Sacl != NULL && (ParentDescriptor->Control & SE_SELF_RELATIVE))
478 {
479 Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
480 }
481 Control |= (SE_SACL_PRESENT & SE_SACL_DEFAULTED);
482 }
483
484 SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
485
486
487 /* Allocate and initialize the new security descriptor */
488 Length = sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength + DaclLength + SaclLength;
489
490 Descriptor = ExAllocatePool(NonPagedPool,
491 Length);
492 if (Descriptor == NULL)
493 {
494 DPRINT1("ExAlloctePool() failed\n");
495 /* FIXME: Unlock subject context */
496 return STATUS_INSUFFICIENT_RESOURCES;
497 }
498
499 RtlCreateSecurityDescriptor(Descriptor,
500 SECURITY_DESCRIPTOR_REVISION);
501
502 Descriptor->Control = Control | SE_SELF_RELATIVE;
503
504 Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
505
506 if (SaclLength != 0)
507 {
508 RtlCopyMemory((PVOID)Current,
509 Sacl,
510 SaclLength);
511 Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
512 Current += SaclLength;
513 }
514
515 if (DaclLength != 0)
516 {
517 RtlCopyMemory((PVOID)Current,
518 Dacl,
519 DaclLength);
520 Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
521 Current += DaclLength;
522 }
523
524 if (OwnerLength != 0)
525 {
526 RtlCopyMemory((PVOID)Current,
527 Owner,
528 OwnerLength);
529 Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
530 Current += OwnerLength;
531 }
532
533 if (GroupLength != 0)
534 {
535 memmove((PVOID)Current,
536 Group,
537 GroupLength);
538 Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
539 }
540
541 /* FIXME: Unlock subject context */
542
543 *NewDescriptor = Descriptor;
544
545 return STATUS_SUCCESS;
546 }
547
548
549 static BOOLEAN
550 SepSidInToken(PACCESS_TOKEN Token,
551 PSID Sid)
552 {
553 ULONG i;
554
555 if (Token->UserAndGroupCount == 0)
556 {
557 return FALSE;
558 }
559
560 for (i=0; i<Token->UserAndGroupCount; i++)
561 {
562 if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
563 {
564 if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
565 {
566 return TRUE;
567 }
568
569 return FALSE;
570 }
571 }
572
573 return FALSE;
574 }
575
576
577 /*
578 * FUNCTION: Determines whether the requested access rights can be granted
579 * to an object protected by a security descriptor and an object owner
580 * ARGUMENTS:
581 * SecurityDescriptor = Security descriptor protecting the object
582 * SubjectSecurityContext = Subject's captured security context
583 * SubjectContextLocked = Indicates the user's subject context is locked
584 * DesiredAccess = Access rights the caller is trying to acquire
585 * PreviouslyGrantedAccess = Specified the access rights already granted
586 * Privileges = ?
587 * GenericMapping = Generic mapping associated with the object
588 * AccessMode = Access mode used for the check
589 * GrantedAccess (OUT) = On return specifies the access granted
590 * AccessStatus (OUT) = Status indicating why access was denied
591 * RETURNS: If access was granted, returns TRUE
592 *
593 * @implemented
594 */
595 BOOLEAN STDCALL
596 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
597 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
598 IN BOOLEAN SubjectContextLocked,
599 IN ACCESS_MASK DesiredAccess,
600 IN ACCESS_MASK PreviouslyGrantedAccess,
601 OUT PPRIVILEGE_SET* Privileges,
602 IN PGENERIC_MAPPING GenericMapping,
603 IN KPROCESSOR_MODE AccessMode,
604 OUT PACCESS_MASK GrantedAccess,
605 OUT PNTSTATUS AccessStatus)
606 {
607 LUID_AND_ATTRIBUTES Privilege;
608 ACCESS_MASK CurrentAccess;
609 PACCESS_TOKEN Token;
610 ULONG i;
611 PACL Dacl;
612 BOOLEAN Present;
613 BOOLEAN Defaulted;
614 PACE CurrentAce;
615 PSID Sid;
616 NTSTATUS Status;
617
618 CurrentAccess = PreviouslyGrantedAccess;
619
620 Token = SubjectSecurityContext->ClientToken ?
621 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
622
623 /* Get the DACL */
624 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
625 &Present,
626 &Dacl,
627 &Defaulted);
628 if (!NT_SUCCESS(Status))
629 {
630 *AccessStatus = Status;
631 return FALSE;
632 }
633
634 /* RULE 1: Grant desired access if the object is unprotected */
635 if (Dacl == NULL)
636 {
637 *GrantedAccess = DesiredAccess;
638 *AccessStatus = STATUS_SUCCESS;
639 return TRUE;
640 }
641
642 CurrentAccess = PreviouslyGrantedAccess;
643
644 /* RULE 2: Check token for 'take ownership' privilege */
645 Privilege.Luid = SeTakeOwnershipPrivilege;
646 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
647
648 if (SepPrivilegeCheck(Token,
649 &Privilege,
650 1,
651 PRIVILEGE_SET_ALL_NECESSARY,
652 AccessMode))
653 {
654 CurrentAccess |= WRITE_OWNER;
655 if (DesiredAccess == CurrentAccess)
656 {
657 *GrantedAccess = CurrentAccess;
658 *AccessStatus = STATUS_SUCCESS;
659 return TRUE;
660 }
661 }
662
663 /* RULE 3: Check whether the token is the owner */
664 Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
665 &Sid,
666 &Defaulted);
667 if (!NT_SUCCESS(Status))
668 {
669 DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
670 *AccessStatus = Status;
671 return FALSE;
672 }
673
674 if (SepSidInToken(Token, Sid))
675 {
676 CurrentAccess |= (READ_CONTROL | WRITE_DAC);
677 if (DesiredAccess == CurrentAccess)
678 {
679 *GrantedAccess = CurrentAccess;
680 *AccessStatus = STATUS_SUCCESS;
681 return TRUE;
682 }
683 }
684
685 /* RULE 4: Grant rights according to the DACL */
686 CurrentAce = (PACE)(Dacl + 1);
687 for (i = 0; i < Dacl->AceCount; i++)
688 {
689 Sid = (PSID)(CurrentAce + 1);
690 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
691 {
692 if (SepSidInToken(Token, Sid))
693 {
694 *GrantedAccess = 0;
695 *AccessStatus = STATUS_ACCESS_DENIED;
696 return TRUE;
697 }
698 }
699
700 if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
701 {
702 if (SepSidInToken(Token, Sid))
703 {
704 CurrentAccess |= CurrentAce->AccessMask;
705 }
706 }
707 }
708
709 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
710 CurrentAccess, DesiredAccess);
711
712 *GrantedAccess = CurrentAccess & DesiredAccess;
713
714 *AccessStatus =
715 (*GrantedAccess == DesiredAccess) ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
716
717 return TRUE;
718 }
719
720
721 NTSTATUS STDCALL
722 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
723 IN HANDLE TokenHandle,
724 IN ACCESS_MASK DesiredAccess,
725 IN PGENERIC_MAPPING GenericMapping,
726 OUT PPRIVILEGE_SET PrivilegeSet,
727 OUT PULONG ReturnLength,
728 OUT PACCESS_MASK GrantedAccess,
729 OUT PNTSTATUS AccessStatus)
730 {
731 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
732 KPROCESSOR_MODE PreviousMode;
733 PACCESS_TOKEN Token;
734 NTSTATUS Status;
735
736 DPRINT("NtAccessCheck() called\n");
737
738 PreviousMode = KeGetPreviousMode();
739 if (PreviousMode == KernelMode)
740 {
741 *GrantedAccess = DesiredAccess;
742 *AccessStatus = STATUS_SUCCESS;
743 return STATUS_SUCCESS;
744 }
745
746 Status = ObReferenceObjectByHandle(TokenHandle,
747 TOKEN_QUERY,
748 SepTokenObjectType,
749 PreviousMode,
750 (PVOID*)&Token,
751 NULL);
752 if (!NT_SUCCESS(Status))
753 {
754 DPRINT1("Failed to reference token (Status %lx)\n", Status);
755 return Status;
756 }
757
758 /* Check token type */
759 if (Token->TokenType != TokenImpersonation)
760 {
761 DPRINT1("No impersonation token\n");
762 ObDereferenceObject(Token);
763 return STATUS_ACCESS_VIOLATION;
764 }
765
766 /* Check impersonation level */
767 if (Token->ImpersonationLevel < SecurityAnonymous)
768 {
769 DPRINT1("Invalid impersonation level\n");
770 ObDereferenceObject(Token);
771 return STATUS_ACCESS_VIOLATION;
772 }
773
774 RtlZeroMemory(&SubjectSecurityContext,
775 sizeof(SECURITY_SUBJECT_CONTEXT));
776 SubjectSecurityContext.ClientToken = Token;
777 SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
778
779 /* FIXME: Lock subject context */
780
781 if (!SeAccessCheck(SecurityDescriptor,
782 &SubjectSecurityContext,
783 TRUE,
784 DesiredAccess,
785 0,
786 &PrivilegeSet,
787 GenericMapping,
788 PreviousMode,
789 GrantedAccess,
790 AccessStatus))
791 {
792 Status = *AccessStatus;
793 }
794 else
795 {
796 Status = STATUS_ACCESS_DENIED;
797 }
798
799 /* FIXME: Unlock subject context */
800
801 ObDereferenceObject(Token);
802
803 DPRINT("NtAccessCheck() done\n");
804
805 return Status;
806 }
807
808 /* EOF */