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