* Sync up to trunk head (r60691).
[reactos.git] / ntoskrnl / se / semgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/semgr.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: No programmer listed.
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 PSE_EXPORTS SeExports = NULL;
19 SE_EXPORTS SepExports;
20 ULONG SidInTokenCalls = 0;
21
22 extern ULONG ExpInitializationPhase;
23 extern ERESOURCE SepSubjectContextLock;
24
25 /* PRIVATE FUNCTIONS **********************************************************/
26
27 static BOOLEAN
28 INIT_FUNCTION
29 SepInitExports(VOID)
30 {
31 SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
32 SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
33 SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
34 SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
35 SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
36 SepExports.SeTcbPrivilege = SeTcbPrivilege;
37 SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
38 SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
39 SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
40 SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
41 SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
42 SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
43 SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
44 SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
45 SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
46 SepExports.SeBackupPrivilege = SeBackupPrivilege;
47 SepExports.SeRestorePrivilege = SeRestorePrivilege;
48 SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
49 SepExports.SeDebugPrivilege = SeDebugPrivilege;
50 SepExports.SeAuditPrivilege = SeAuditPrivilege;
51 SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
52 SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
53 SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
54
55 SepExports.SeNullSid = SeNullSid;
56 SepExports.SeWorldSid = SeWorldSid;
57 SepExports.SeLocalSid = SeLocalSid;
58 SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
59 SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
60 SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
61 SepExports.SeDialupSid = SeDialupSid;
62 SepExports.SeNetworkSid = SeNetworkSid;
63 SepExports.SeBatchSid = SeBatchSid;
64 SepExports.SeInteractiveSid = SeInteractiveSid;
65 SepExports.SeLocalSystemSid = SeLocalSystemSid;
66 SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
67 SepExports.SeAliasUsersSid = SeAliasUsersSid;
68 SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
69 SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
70 SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
71 SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
72 SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
73 SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
74 SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
75 SepExports.SeRestrictedSid = SeRestrictedSid;
76 SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
77
78 SepExports.SeUndockPrivilege = SeUndockPrivilege;
79 SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
80 SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
81
82 SeExports = &SepExports;
83 return TRUE;
84 }
85
86
87 BOOLEAN
88 NTAPI
89 INIT_FUNCTION
90 SepInitializationPhase0(VOID)
91 {
92 PAGED_CODE();
93
94 ExpInitLuid();
95 if (!SepInitSecurityIDs()) return FALSE;
96 if (!SepInitDACLs()) return FALSE;
97 if (!SepInitSDs()) return FALSE;
98 SepInitPrivileges();
99 if (!SepInitExports()) return FALSE;
100
101 /* Initialize the subject context lock */
102 ExInitializeResource(&SepSubjectContextLock);
103
104 /* Initialize token objects */
105 SepInitializeTokenImplementation();
106
107 /* Clear impersonation info for the idle thread */
108 PsGetCurrentThread()->ImpersonationInfo = NULL;
109 PspClearCrossThreadFlag(PsGetCurrentThread(),
110 CT_ACTIVE_IMPERSONATION_INFO_BIT);
111
112 /* Initialize the boot token */
113 ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
114 ObInitializeFastReference(&PsGetCurrentProcess()->Token,
115 SepCreateSystemProcessToken());
116 return TRUE;
117 }
118
119 BOOLEAN
120 NTAPI
121 INIT_FUNCTION
122 SepInitializationPhase1(VOID)
123 {
124 NTSTATUS Status;
125
126 PAGED_CODE();
127
128 /* Insert the system token into the tree */
129 Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
130 ~MAX_FAST_REFS),
131 NULL,
132 0,
133 0,
134 NULL,
135 NULL);
136 ASSERT(NT_SUCCESS(Status));
137
138 /* FIXME: TODO \\ Security directory */
139 return TRUE;
140 }
141
142 BOOLEAN
143 NTAPI
144 INIT_FUNCTION
145 SeInitSystem(VOID)
146 {
147 /* Check the initialization phase */
148 switch (ExpInitializationPhase)
149 {
150 case 0:
151
152 /* Do Phase 0 */
153 return SepInitializationPhase0();
154
155 case 1:
156
157 /* Do Phase 1 */
158 return SepInitializationPhase1();
159
160 default:
161
162 /* Don't know any other phase! Bugcheck! */
163 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
164 0,
165 ExpInitializationPhase,
166 0,
167 0);
168 return FALSE;
169 }
170 }
171
172 BOOLEAN
173 NTAPI
174 INIT_FUNCTION
175 SeInitSRM(VOID)
176 {
177 OBJECT_ATTRIBUTES ObjectAttributes;
178 UNICODE_STRING Name;
179 HANDLE DirectoryHandle;
180 HANDLE EventHandle;
181 NTSTATUS Status;
182
183 /* Create '\Security' directory */
184 RtlInitUnicodeString(&Name, L"\\Security");
185 InitializeObjectAttributes(&ObjectAttributes,
186 &Name,
187 OBJ_PERMANENT,
188 0,
189 NULL);
190 Status = ZwCreateDirectoryObject(&DirectoryHandle,
191 DIRECTORY_ALL_ACCESS,
192 &ObjectAttributes);
193 if (!NT_SUCCESS(Status))
194 {
195 DPRINT1("Failed to create 'Security' directory!\n");
196 return FALSE;
197 }
198
199 /* Create 'LSA_AUTHENTICATION_INITIALIZED' event */
200 RtlInitUnicodeString(&Name, L"\\LSA_AUTHENTICATION_INITIALIZED");
201 InitializeObjectAttributes(&ObjectAttributes,
202 &Name,
203 OBJ_PERMANENT,
204 DirectoryHandle,
205 SePublicDefaultSd);
206 Status = ZwCreateEvent(&EventHandle,
207 EVENT_ALL_ACCESS,
208 &ObjectAttributes,
209 SynchronizationEvent,
210 FALSE);
211 if (!NT_SUCCESS(Status))
212 {
213 DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITIALIZED' event!\n");
214 NtClose(DirectoryHandle);
215 return FALSE;
216 }
217
218 ZwClose(EventHandle);
219 ZwClose(DirectoryHandle);
220
221 /* FIXME: Create SRM port and listener thread */
222
223 return TRUE;
224 }
225
226 NTSTATUS
227 NTAPI
228 SeDefaultObjectMethod(IN PVOID Object,
229 IN SECURITY_OPERATION_CODE OperationType,
230 IN PSECURITY_INFORMATION SecurityInformation,
231 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
232 IN OUT PULONG ReturnLength OPTIONAL,
233 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
234 IN POOL_TYPE PoolType,
235 IN PGENERIC_MAPPING GenericMapping)
236 {
237 PAGED_CODE();
238
239 /* Select the operation type */
240 switch (OperationType)
241 {
242 /* Setting a new descriptor */
243 case SetSecurityDescriptor:
244
245 /* Sanity check */
246 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
247
248 /* Set the information */
249 return ObSetSecurityDescriptorInfo(Object,
250 SecurityInformation,
251 SecurityDescriptor,
252 OldSecurityDescriptor,
253 PoolType,
254 GenericMapping);
255
256 case QuerySecurityDescriptor:
257
258 /* Query the information */
259 return ObQuerySecurityDescriptorInfo(Object,
260 SecurityInformation,
261 SecurityDescriptor,
262 ReturnLength,
263 OldSecurityDescriptor);
264
265 case DeleteSecurityDescriptor:
266
267 /* De-assign it */
268 return ObDeassignSecurity(OldSecurityDescriptor);
269
270 case AssignSecurityDescriptor:
271
272 /* Assign it */
273 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
274 return STATUS_SUCCESS;
275
276 default:
277
278 /* Bug check */
279 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
280 }
281
282 /* Should never reach here */
283 ASSERT(FALSE);
284 return STATUS_SUCCESS;
285 }
286
287 VOID
288 NTAPI
289 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
290 OUT PACCESS_MASK DesiredAccess)
291 {
292 *DesiredAccess = 0;
293
294 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
295 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
296 {
297 *DesiredAccess |= READ_CONTROL;
298 }
299
300 if (SecurityInformation & SACL_SECURITY_INFORMATION)
301 {
302 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
303 }
304 }
305
306 VOID
307 NTAPI
308 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
309 OUT PACCESS_MASK DesiredAccess)
310 {
311 *DesiredAccess = 0;
312
313 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
314 {
315 *DesiredAccess |= WRITE_OWNER;
316 }
317
318 if (SecurityInformation & DACL_SECURITY_INFORMATION)
319 {
320 *DesiredAccess |= WRITE_DAC;
321 }
322
323 if (SecurityInformation & SACL_SECURITY_INFORMATION)
324 {
325 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
326 }
327 }
328
329
330 #define OLD_ACCESS_CHECK
331
332 BOOLEAN NTAPI
333 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
334 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
335 IN ACCESS_MASK DesiredAccess,
336 IN ACCESS_MASK PreviouslyGrantedAccess,
337 OUT PPRIVILEGE_SET* Privileges,
338 IN PGENERIC_MAPPING GenericMapping,
339 IN KPROCESSOR_MODE AccessMode,
340 OUT PACCESS_MASK GrantedAccess,
341 OUT PNTSTATUS AccessStatus)
342 {
343 LUID_AND_ATTRIBUTES Privilege;
344 #ifdef OLD_ACCESS_CHECK
345 ACCESS_MASK CurrentAccess, AccessMask;
346 #endif
347 ACCESS_MASK RemainingAccess;
348 ACCESS_MASK TempAccess;
349 ACCESS_MASK TempGrantedAccess = 0;
350 ACCESS_MASK TempDeniedAccess = 0;
351 PACCESS_TOKEN Token;
352 ULONG i;
353 PACL Dacl;
354 BOOLEAN Present;
355 BOOLEAN Defaulted;
356 PACE CurrentAce;
357 PSID Sid;
358 NTSTATUS Status;
359 PAGED_CODE();
360
361 /* Check for no access desired */
362 if (!DesiredAccess)
363 {
364 /* Check if we had no previous access */
365 if (!PreviouslyGrantedAccess)
366 {
367 /* Then there's nothing to give */
368 *AccessStatus = STATUS_ACCESS_DENIED;
369 return FALSE;
370 }
371
372 /* Return the previous access only */
373 *GrantedAccess = PreviouslyGrantedAccess;
374 *AccessStatus = STATUS_SUCCESS;
375 *Privileges = NULL;
376 return TRUE;
377 }
378
379 /* Map given accesses */
380 RtlMapGenericMask(&DesiredAccess, GenericMapping);
381 if (PreviouslyGrantedAccess)
382 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
383
384 #ifdef OLD_ACCESS_CHECK
385 CurrentAccess = PreviouslyGrantedAccess;
386 #endif
387 /* Initialize remaining access rights */
388 RemainingAccess = DesiredAccess;
389
390 Token = SubjectSecurityContext->ClientToken ?
391 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
392
393 /* Check for system security access */
394 if (RemainingAccess & ACCESS_SYSTEM_SECURITY)
395 {
396 Privilege.Luid = SeSecurityPrivilege;
397 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
398
399 /* Fail if we do not the SeSecurityPrivilege */
400 if (!SepPrivilegeCheck(Token,
401 &Privilege,
402 1,
403 PRIVILEGE_SET_ALL_NECESSARY,
404 AccessMode))
405 {
406 *AccessStatus = STATUS_PRIVILEGE_NOT_HELD;
407 return FALSE;
408 }
409
410 /* Adjust access rights */
411 RemainingAccess &= ~ACCESS_SYSTEM_SECURITY;
412 PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
413
414 /* Succeed if there are no more rights to grant */
415 if (RemainingAccess == 0)
416 {
417 *GrantedAccess = PreviouslyGrantedAccess;
418 *AccessStatus = STATUS_SUCCESS;
419 return TRUE;
420 }
421 }
422
423 /* Get the DACL */
424 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
425 &Present,
426 &Dacl,
427 &Defaulted);
428 if (!NT_SUCCESS(Status))
429 {
430 *AccessStatus = Status;
431 return FALSE;
432 }
433
434 /* RULE 1: Grant desired access if the object is unprotected */
435 if (Present == FALSE || Dacl == NULL)
436 {
437 if (DesiredAccess & MAXIMUM_ALLOWED)
438 {
439 *GrantedAccess = GenericMapping->GenericAll;
440 *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
441 }
442 else
443 {
444 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
445 }
446
447 *AccessStatus = STATUS_SUCCESS;
448 return TRUE;
449 }
450
451 #ifdef OLD_ACCESS_CHECK
452 CurrentAccess = PreviouslyGrantedAccess;
453 #endif
454
455 /* RULE 2: Check token for 'take ownership' privilege */
456 if (DesiredAccess & WRITE_OWNER)
457 {
458 Privilege.Luid = SeTakeOwnershipPrivilege;
459 Privilege.Attributes = SE_PRIVILEGE_ENABLED;
460
461 if (SepPrivilegeCheck(Token,
462 &Privilege,
463 1,
464 PRIVILEGE_SET_ALL_NECESSARY,
465 AccessMode))
466 {
467 /* Adjust access rights */
468 RemainingAccess &= ~WRITE_OWNER;
469 PreviouslyGrantedAccess |= WRITE_OWNER;
470 #ifdef OLD_ACCESS_CHECK
471 CurrentAccess |= WRITE_OWNER;
472 #endif
473
474 /* Succeed if there are no more rights to grant */
475 if (RemainingAccess == 0)
476 {
477 *GrantedAccess = PreviouslyGrantedAccess;
478 *AccessStatus = STATUS_SUCCESS;
479 return TRUE;
480 }
481 }
482 }
483
484 /* Deny access if the DACL is empty */
485 if (Dacl->AceCount == 0)
486 {
487 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
488 {
489 *GrantedAccess = PreviouslyGrantedAccess;
490 *AccessStatus = STATUS_SUCCESS;
491 return TRUE;
492 }
493 else
494 {
495 *GrantedAccess = 0;
496 *AccessStatus = STATUS_ACCESS_DENIED;
497 return FALSE;
498 }
499 }
500
501 /* Fail if DACL is absent */
502 if (Present == FALSE)
503 {
504 *GrantedAccess = 0;
505 *AccessStatus = STATUS_ACCESS_DENIED;
506 return FALSE;
507 }
508
509 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
510 if (DesiredAccess & MAXIMUM_ALLOWED)
511 {
512 CurrentAce = (PACE)(Dacl + 1);
513 for (i = 0; i < Dacl->AceCount; i++)
514 {
515 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
516 {
517 Sid = (PSID)(CurrentAce + 1);
518 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
519 {
520 if (SepSidInToken(Token, Sid))
521 {
522 /* Map access rights from the ACE */
523 TempAccess = CurrentAce->AccessMask;
524 RtlMapGenericMask(&TempAccess, GenericMapping);
525
526 /* Deny access rights that have not been granted yet */
527 TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
528 }
529 }
530 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
531 {
532 if (SepSidInToken(Token, Sid))
533 {
534 /* Map access rights from the ACE */
535 TempAccess = CurrentAce->AccessMask;
536 RtlMapGenericMask(&TempAccess, GenericMapping);
537
538 /* Grant access rights that have not been denied yet */
539 TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
540 }
541 }
542 else
543 {
544 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
545 }
546 }
547
548 /* Get the next ACE */
549 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
550 }
551
552 /* Fail if some rights have not been granted */
553 RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
554 if (RemainingAccess != 0)
555 {
556 *GrantedAccess = 0;
557 *AccessStatus = STATUS_ACCESS_DENIED;
558 return FALSE;
559 }
560
561 /* Set granted access right and access status */
562 *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess;
563 if (*GrantedAccess != 0)
564 {
565 *AccessStatus = STATUS_SUCCESS;
566 return TRUE;
567 }
568 else
569 {
570 *AccessStatus = STATUS_ACCESS_DENIED;
571 return FALSE;
572 }
573 }
574
575 /* RULE 4: Grant rights according to the DACL */
576 CurrentAce = (PACE)(Dacl + 1);
577 for (i = 0; i < Dacl->AceCount; i++)
578 {
579 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
580 {
581 Sid = (PSID)(CurrentAce + 1);
582 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
583 {
584 if (SepSidInToken(Token, Sid))
585 {
586 #ifdef OLD_ACCESS_CHECK
587 *GrantedAccess = 0;
588 *AccessStatus = STATUS_ACCESS_DENIED;
589 return FALSE;
590 #else
591 /* Map access rights from the ACE */
592 TempAccess = CurrentAce->AccessMask;
593 RtlMapGenericMask(&TempAccess, GenericMapping);
594
595 /* Leave if a remaining right must be denied */
596 if (RemainingAccess & TempAccess)
597 break;
598 #endif
599 }
600 }
601 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
602 {
603 if (SepSidInToken(Token, Sid))
604 {
605 #ifdef OLD_ACCESS_CHECK
606 AccessMask = CurrentAce->AccessMask;
607 RtlMapGenericMask(&AccessMask, GenericMapping);
608 CurrentAccess |= AccessMask;
609 #else
610 /* Map access rights from the ACE */
611 TempAccess = CurrentAce->AccessMask;
612 RtlMapGenericMask(&TempAccess, GenericMapping);
613
614 /* Remove granted rights */
615 RemainingAccess &= ~TempAccess;
616 #endif
617 }
618 }
619 else
620 {
621 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
622 }
623 }
624
625 /* Get the next ACE */
626 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
627 }
628
629 #ifdef OLD_ACCESS_CHECK
630 DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
631 CurrentAccess, DesiredAccess);
632
633 *GrantedAccess = CurrentAccess & DesiredAccess;
634
635 if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
636 (DesiredAccess & ~VALID_INHERIT_FLAGS))
637 {
638 *AccessStatus = STATUS_SUCCESS;
639 return TRUE;
640 }
641 else
642 {
643 DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
644 *GrantedAccess, DesiredAccess, GenericMapping);
645 //*AccessStatus = STATUS_ACCESS_DENIED;
646 //return FALSE;
647 *GrantedAccess = DesiredAccess;
648 *AccessStatus = STATUS_SUCCESS;
649 return TRUE;
650 }
651 #else
652 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
653 DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
654
655 /* Fail if some rights have not been granted */
656 if (RemainingAccess != 0)
657 {
658 *GrantedAccess = 0;
659 *AccessStatus = STATUS_ACCESS_DENIED;
660 return FALSE;
661 }
662
663 /* Set granted access rights */
664 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
665
666 DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
667
668 /* Fail if no rights have been granted */
669 if (*GrantedAccess == 0)
670 {
671 *AccessStatus = STATUS_ACCESS_DENIED;
672 return FALSE;
673 }
674
675 *AccessStatus = STATUS_SUCCESS;
676 return TRUE;
677 #endif
678 }
679
680 static PSID
681 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
682 {
683 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
684 PSID Owner;
685
686 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
687 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
688 (ULONG_PTR)SecurityDescriptor);
689 else
690 Owner = (PSID)SecurityDescriptor->Owner;
691
692 return Owner;
693 }
694
695 static PSID
696 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
697 {
698 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
699 PSID Group;
700
701 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
702 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
703 (ULONG_PTR)SecurityDescriptor);
704 else
705 Group = (PSID)SecurityDescriptor->Group;
706
707 return Group;
708 }
709
710
711 /* PUBLIC FUNCTIONS ***********************************************************/
712
713 /*
714 * @implemented
715 */
716 BOOLEAN
717 NTAPI
718 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
719 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
720 IN BOOLEAN SubjectContextLocked,
721 IN ACCESS_MASK DesiredAccess,
722 IN ACCESS_MASK PreviouslyGrantedAccess,
723 OUT PPRIVILEGE_SET* Privileges,
724 IN PGENERIC_MAPPING GenericMapping,
725 IN KPROCESSOR_MODE AccessMode,
726 OUT PACCESS_MASK GrantedAccess,
727 OUT PNTSTATUS AccessStatus)
728 {
729 BOOLEAN ret;
730
731 PAGED_CODE();
732
733 /* Check if this is kernel mode */
734 if (AccessMode == KernelMode)
735 {
736 /* Check if kernel wants everything */
737 if (DesiredAccess & MAXIMUM_ALLOWED)
738 {
739 /* Give it */
740 *GrantedAccess = GenericMapping->GenericAll;
741 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
742 *GrantedAccess |= PreviouslyGrantedAccess;
743 }
744 else
745 {
746 /* Give the desired and previous access */
747 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
748 }
749
750 /* Success */
751 *AccessStatus = STATUS_SUCCESS;
752 return TRUE;
753 }
754
755 /* Check if we didn't get an SD */
756 if (!SecurityDescriptor)
757 {
758 /* Automatic failure */
759 *AccessStatus = STATUS_ACCESS_DENIED;
760 return FALSE;
761 }
762
763 /* Check for invalid impersonation */
764 if ((SubjectSecurityContext->ClientToken) &&
765 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
766 {
767 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
768 return FALSE;
769 }
770
771 /* Acquire the lock if needed */
772 if (!SubjectContextLocked)
773 SeLockSubjectContext(SubjectSecurityContext);
774
775 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
776 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
777 {
778 PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
779 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
780
781 if (SepTokenIsOwner(Token,
782 SecurityDescriptor,
783 FALSE))
784 {
785 if (DesiredAccess & MAXIMUM_ALLOWED)
786 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
787 else
788 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
789
790 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
791 }
792 }
793
794 if (DesiredAccess == 0)
795 {
796 *GrantedAccess = PreviouslyGrantedAccess;
797 *AccessStatus = STATUS_SUCCESS;
798 ret = TRUE;
799 }
800 else
801 {
802 /* Call the internal function */
803 ret = SepAccessCheck(SecurityDescriptor,
804 SubjectSecurityContext,
805 DesiredAccess,
806 PreviouslyGrantedAccess,
807 Privileges,
808 GenericMapping,
809 AccessMode,
810 GrantedAccess,
811 AccessStatus);
812 }
813
814 /* Release the lock if needed */
815 if (!SubjectContextLocked)
816 SeUnlockSubjectContext(SubjectSecurityContext);
817
818 return ret;
819 }
820
821 /*
822 * @implemented
823 */
824 BOOLEAN
825 NTAPI
826 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
827 IN PACCESS_STATE AccessState,
828 IN ACCESS_MASK DesiredAccess,
829 IN KPROCESSOR_MODE AccessMode)
830 {
831 PACL Dacl;
832 ULONG AceIndex;
833 PKNOWN_ACE Ace;
834
835 PAGED_CODE();
836
837 NT_ASSERT(AccessMode != KernelMode);
838
839 if (SecurityDescriptor == NULL)
840 return FALSE;
841
842 /* Get DACL */
843 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
844 /* If no DACL, grant access */
845 if (Dacl == NULL)
846 return TRUE;
847
848 /* No ACE -> Deny */
849 if (!Dacl->AceCount)
850 return FALSE;
851
852 /* Can't perform the check on restricted token */
853 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
854 return FALSE;
855
856 /* Browse the ACEs */
857 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
858 AceIndex < Dacl->AceCount;
859 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
860 {
861 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
862 continue;
863
864 /* If access-allowed ACE */
865 if (Ace->Header.AceType & ACCESS_ALLOWED_ACE_TYPE)
866 {
867 /* Check if all accesses are granted */
868 if (!(Ace->Mask & DesiredAccess))
869 continue;
870
871 /* Check SID and grant access if matching */
872 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
873 return TRUE;
874 }
875 /* If access-denied ACE */
876 else if (Ace->Header.AceType & ACCESS_DENIED_ACE_TYPE)
877 {
878 /* Here, only check if it denies all the access wanted and deny if so */
879 if (Ace->Mask & DesiredAccess)
880 return FALSE;
881 }
882 }
883
884 /* Faulty, deny */
885 return FALSE;
886 }
887
888 /* SYSTEM CALLS ***************************************************************/
889
890 /*
891 * @implemented
892 */
893 NTSTATUS
894 NTAPI
895 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
896 IN HANDLE TokenHandle,
897 IN ACCESS_MASK DesiredAccess,
898 IN PGENERIC_MAPPING GenericMapping,
899 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
900 IN OUT PULONG PrivilegeSetLength,
901 OUT PACCESS_MASK GrantedAccess,
902 OUT PNTSTATUS AccessStatus)
903 {
904 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
905 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
906 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
907 ACCESS_MASK PreviouslyGrantedAccess = 0;
908 PTOKEN Token;
909 NTSTATUS Status;
910 PAGED_CODE();
911
912 /* Check if this is kernel mode */
913 if (PreviousMode == KernelMode)
914 {
915 /* Check if kernel wants everything */
916 if (DesiredAccess & MAXIMUM_ALLOWED)
917 {
918 /* Give it */
919 *GrantedAccess = GenericMapping->GenericAll;
920 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
921 }
922 else
923 {
924 /* Just give the desired access */
925 *GrantedAccess = DesiredAccess;
926 }
927
928 /* Success */
929 *AccessStatus = STATUS_SUCCESS;
930 return STATUS_SUCCESS;
931 }
932
933 /* Protect probe in SEH */
934 _SEH2_TRY
935 {
936 /* Probe all pointers */
937 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
938 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
939 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
940 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
941 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
942 }
943 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
944 {
945 /* Return the exception code */
946 _SEH2_YIELD(return _SEH2_GetExceptionCode());
947 }
948 _SEH2_END;
949
950 /* Check for unmapped access rights */
951 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
952 return STATUS_GENERIC_NOT_MAPPED;
953
954 /* Reference the token */
955 Status = ObReferenceObjectByHandle(TokenHandle,
956 TOKEN_QUERY,
957 SeTokenObjectType,
958 PreviousMode,
959 (PVOID*)&Token,
960 NULL);
961 if (!NT_SUCCESS(Status))
962 {
963 DPRINT("Failed to reference token (Status %lx)\n", Status);
964 return Status;
965 }
966
967 /* Check token type */
968 if (Token->TokenType != TokenImpersonation)
969 {
970 DPRINT("No impersonation token\n");
971 ObDereferenceObject(Token);
972 return STATUS_NO_IMPERSONATION_TOKEN;
973 }
974
975 /* Check the impersonation level */
976 if (Token->ImpersonationLevel < SecurityIdentification)
977 {
978 DPRINT("Impersonation level < SecurityIdentification\n");
979 ObDereferenceObject(Token);
980 return STATUS_BAD_IMPERSONATION_LEVEL;
981 }
982
983 /* Capture the security descriptor */
984 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
985 PreviousMode,
986 PagedPool,
987 FALSE,
988 &CapturedSecurityDescriptor);
989 if (!NT_SUCCESS(Status))
990 {
991 DPRINT("Failed to capture the Security Descriptor\n");
992 ObDereferenceObject(Token);
993 return Status;
994 }
995
996 /* Check the captured security descriptor */
997 if (CapturedSecurityDescriptor == NULL)
998 {
999 DPRINT("Security Descriptor is NULL\n");
1000 ObDereferenceObject(Token);
1001 return STATUS_INVALID_SECURITY_DESCR;
1002 }
1003
1004 /* Check security descriptor for valid owner and group */
1005 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
1006 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
1007 {
1008 DPRINT("Security Descriptor does not have a valid group or owner\n");
1009 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1010 PreviousMode,
1011 FALSE);
1012 ObDereferenceObject(Token);
1013 return STATUS_INVALID_SECURITY_DESCR;
1014 }
1015
1016 /* Set up the subject context, and lock it */
1017 SeCaptureSubjectContext(&SubjectSecurityContext);
1018
1019 /* Lock the token */
1020 SepAcquireTokenLockShared(Token);
1021
1022 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
1023 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
1024 {
1025 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
1026 {
1027 if (DesiredAccess & MAXIMUM_ALLOWED)
1028 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
1029 else
1030 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
1031
1032 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
1033 }
1034 }
1035
1036 if (DesiredAccess == 0)
1037 {
1038 *GrantedAccess = PreviouslyGrantedAccess;
1039 *AccessStatus = STATUS_SUCCESS;
1040 }
1041 else
1042 {
1043 /* Now perform the access check */
1044 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
1045 &SubjectSecurityContext,
1046 DesiredAccess,
1047 PreviouslyGrantedAccess,
1048 &PrivilegeSet, //FIXME
1049 GenericMapping,
1050 PreviousMode,
1051 GrantedAccess,
1052 AccessStatus);
1053 }
1054
1055 /* Release subject context and unlock the token */
1056 SeReleaseSubjectContext(&SubjectSecurityContext);
1057 SepReleaseTokenLock(Token);
1058
1059 /* Release the captured security descriptor */
1060 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
1061 PreviousMode,
1062 FALSE);
1063
1064 /* Dereference the token */
1065 ObDereferenceObject(Token);
1066
1067 /* Check succeeded */
1068 return STATUS_SUCCESS;
1069 }
1070
1071
1072 NTSTATUS
1073 NTAPI
1074 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1075 IN PSID PrincipalSelfSid,
1076 IN HANDLE ClientToken,
1077 IN ACCESS_MASK DesiredAccess,
1078 IN POBJECT_TYPE_LIST ObjectTypeList,
1079 IN ULONG ObjectTypeLength,
1080 IN PGENERIC_MAPPING GenericMapping,
1081 IN PPRIVILEGE_SET PrivilegeSet,
1082 IN OUT PULONG PrivilegeSetLength,
1083 OUT PACCESS_MASK GrantedAccess,
1084 OUT PNTSTATUS AccessStatus)
1085 {
1086 UNIMPLEMENTED;
1087 return STATUS_NOT_IMPLEMENTED;
1088 }
1089
1090 NTSTATUS
1091 NTAPI
1092 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1093 IN HANDLE HandleId,
1094 IN PUNICODE_STRING ObjectTypeName,
1095 IN PUNICODE_STRING ObjectName,
1096 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1097 IN PSID PrincipalSelfSid,
1098 IN ACCESS_MASK DesiredAccess,
1099 IN AUDIT_EVENT_TYPE AuditType,
1100 IN ULONG Flags,
1101 IN POBJECT_TYPE_LIST ObjectTypeList,
1102 IN ULONG ObjectTypeLength,
1103 IN PGENERIC_MAPPING GenericMapping,
1104 IN BOOLEAN ObjectCreation,
1105 OUT PACCESS_MASK GrantedAccess,
1106 OUT PNTSTATUS AccessStatus,
1107 OUT PBOOLEAN GenerateOnClose)
1108 {
1109 UNIMPLEMENTED;
1110 return STATUS_NOT_IMPLEMENTED;
1111 }
1112
1113 NTSTATUS
1114 NTAPI
1115 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1116 IN PSID PrincipalSelfSid,
1117 IN HANDLE ClientToken,
1118 IN ACCESS_MASK DesiredAccess,
1119 IN POBJECT_TYPE_LIST ObjectTypeList,
1120 IN ULONG ObjectTypeLength,
1121 IN PGENERIC_MAPPING GenericMapping,
1122 IN PPRIVILEGE_SET PrivilegeSet,
1123 IN OUT PULONG PrivilegeSetLength,
1124 OUT PACCESS_MASK GrantedAccess,
1125 OUT PNTSTATUS AccessStatus)
1126 {
1127 UNIMPLEMENTED;
1128 return STATUS_NOT_IMPLEMENTED;
1129 }
1130
1131 NTSTATUS
1132 NTAPI
1133 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
1134 IN HANDLE HandleId,
1135 IN PUNICODE_STRING ObjectTypeName,
1136 IN PUNICODE_STRING ObjectName,
1137 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1138 IN PSID PrincipalSelfSid,
1139 IN ACCESS_MASK DesiredAccess,
1140 IN AUDIT_EVENT_TYPE AuditType,
1141 IN ULONG Flags,
1142 IN POBJECT_TYPE_LIST ObjectTypeList,
1143 IN ULONG ObjectTypeLength,
1144 IN PGENERIC_MAPPING GenericMapping,
1145 IN BOOLEAN ObjectCreation,
1146 OUT PACCESS_MASK GrantedAccess,
1147 OUT PNTSTATUS AccessStatus,
1148 OUT PBOOLEAN GenerateOnClose)
1149 {
1150 UNIMPLEMENTED;
1151 return STATUS_NOT_IMPLEMENTED;
1152 }
1153
1154 NTSTATUS
1155 NTAPI
1156 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
1157 IN HANDLE HandleId,
1158 IN HANDLE ClientToken,
1159 IN PUNICODE_STRING ObjectTypeName,
1160 IN PUNICODE_STRING ObjectName,
1161 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1162 IN PSID PrincipalSelfSid,
1163 IN ACCESS_MASK DesiredAccess,
1164 IN AUDIT_EVENT_TYPE AuditType,
1165 IN ULONG Flags,
1166 IN POBJECT_TYPE_LIST ObjectTypeList,
1167 IN ULONG ObjectTypeLength,
1168 IN PGENERIC_MAPPING GenericMapping,
1169 IN BOOLEAN ObjectCreation,
1170 OUT PACCESS_MASK GrantedAccess,
1171 OUT PNTSTATUS AccessStatus,
1172 OUT PBOOLEAN GenerateOnClose)
1173 {
1174 UNIMPLEMENTED;
1175 return STATUS_NOT_IMPLEMENTED;
1176 }
1177
1178 /* EOF */