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