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