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