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