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