ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

semgr.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/se/semgr.c
00005  * PURPOSE:         Security manager
00006  *
00007  * PROGRAMMERS:     No programmer listed.
00008  */
00009 
00010 /* INCLUDES *******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* GLOBALS ********************************************************************/
00017 
00018 PSE_EXPORTS SeExports = NULL;
00019 SE_EXPORTS SepExports;
00020 ULONG SidInTokenCalls = 0;
00021 
00022 extern ULONG ExpInitializationPhase;
00023 extern ERESOURCE SepSubjectContextLock;
00024 
00025 /* PRIVATE FUNCTIONS **********************************************************/
00026 
00027 static BOOLEAN
00028 INIT_FUNCTION
00029 SepInitExports(VOID)
00030 {
00031     SepExports.SeCreateTokenPrivilege = SeCreateTokenPrivilege;
00032     SepExports.SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege;
00033     SepExports.SeLockMemoryPrivilege = SeLockMemoryPrivilege;
00034     SepExports.SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege;
00035     SepExports.SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege;
00036     SepExports.SeTcbPrivilege = SeTcbPrivilege;
00037     SepExports.SeSecurityPrivilege = SeSecurityPrivilege;
00038     SepExports.SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege;
00039     SepExports.SeLoadDriverPrivilege = SeLoadDriverPrivilege;
00040     SepExports.SeCreatePagefilePrivilege = SeCreatePagefilePrivilege;
00041     SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
00042     SepExports.SeSystemProfilePrivilege = SeSystemProfilePrivilege;
00043     SepExports.SeSystemtimePrivilege = SeSystemtimePrivilege;
00044     SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
00045     SepExports.SeCreatePermanentPrivilege = SeCreatePermanentPrivilege;
00046     SepExports.SeBackupPrivilege = SeBackupPrivilege;
00047     SepExports.SeRestorePrivilege = SeRestorePrivilege;
00048     SepExports.SeShutdownPrivilege = SeShutdownPrivilege;
00049     SepExports.SeDebugPrivilege = SeDebugPrivilege;
00050     SepExports.SeAuditPrivilege = SeAuditPrivilege;
00051     SepExports.SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege;
00052     SepExports.SeChangeNotifyPrivilege = SeChangeNotifyPrivilege;
00053     SepExports.SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege;
00054 
00055     SepExports.SeNullSid = SeNullSid;
00056     SepExports.SeWorldSid = SeWorldSid;
00057     SepExports.SeLocalSid = SeLocalSid;
00058     SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
00059     SepExports.SeCreatorGroupSid = SeCreatorGroupSid;
00060     SepExports.SeNtAuthoritySid = SeNtAuthoritySid;
00061     SepExports.SeDialupSid = SeDialupSid;
00062     SepExports.SeNetworkSid = SeNetworkSid;
00063     SepExports.SeBatchSid = SeBatchSid;
00064     SepExports.SeInteractiveSid = SeInteractiveSid;
00065     SepExports.SeLocalSystemSid = SeLocalSystemSid;
00066     SepExports.SeAliasAdminsSid = SeAliasAdminsSid;
00067     SepExports.SeAliasUsersSid = SeAliasUsersSid;
00068     SepExports.SeAliasGuestsSid = SeAliasGuestsSid;
00069     SepExports.SeAliasPowerUsersSid = SeAliasPowerUsersSid;
00070     SepExports.SeAliasAccountOpsSid = SeAliasAccountOpsSid;
00071     SepExports.SeAliasSystemOpsSid = SeAliasSystemOpsSid;
00072     SepExports.SeAliasPrintOpsSid = SeAliasPrintOpsSid;
00073     SepExports.SeAliasBackupOpsSid = SeAliasBackupOpsSid;
00074     SepExports.SeAuthenticatedUsersSid = SeAuthenticatedUsersSid;
00075     SepExports.SeRestrictedSid = SeRestrictedSid;
00076     SepExports.SeAnonymousLogonSid = SeAnonymousLogonSid;
00077 
00078     SepExports.SeUndockPrivilege = SeUndockPrivilege;
00079     SepExports.SeSyncAgentPrivilege = SeSyncAgentPrivilege;
00080     SepExports.SeEnableDelegationPrivilege = SeEnableDelegationPrivilege;
00081 
00082     SeExports = &SepExports;
00083     return TRUE;
00084 }
00085 
00086 
00087 BOOLEAN
00088 NTAPI
00089 INIT_FUNCTION
00090 SepInitializationPhase0(VOID)
00091 {
00092     PAGED_CODE();
00093 
00094     ExpInitLuid();
00095     if (!SepInitSecurityIDs()) return FALSE;
00096     if (!SepInitDACLs()) return FALSE;
00097     if (!SepInitSDs()) return FALSE;
00098     SepInitPrivileges();
00099     if (!SepInitExports()) return FALSE;
00100 
00101     /* Initialize the subject context lock */
00102     ExInitializeResource(&SepSubjectContextLock);
00103 
00104     /* Initialize token objects */
00105     SepInitializeTokenImplementation();
00106 
00107     /* Clear impersonation info for the idle thread */
00108     PsGetCurrentThread()->ImpersonationInfo = NULL;
00109     PspClearCrossThreadFlag(PsGetCurrentThread(),
00110                             CT_ACTIVE_IMPERSONATION_INFO_BIT);
00111 
00112     /* Initialize the boot token */
00113     ObInitializeFastReference(&PsGetCurrentProcess()->Token, NULL);
00114     ObInitializeFastReference(&PsGetCurrentProcess()->Token,
00115                               SepCreateSystemProcessToken());
00116     return TRUE;
00117 }
00118 
00119 BOOLEAN
00120 NTAPI
00121 INIT_FUNCTION
00122 SepInitializationPhase1(VOID)
00123 {
00124     NTSTATUS Status;
00125 
00126     PAGED_CODE();
00127 
00128     /* Insert the system token into the tree */
00129     Status = ObInsertObject((PVOID)(PsGetCurrentProcess()->Token.Value &
00130                                     ~MAX_FAST_REFS),
00131                             NULL,
00132                             0,
00133                             0,
00134                             NULL,
00135                             NULL);
00136     ASSERT(NT_SUCCESS(Status));
00137 
00138     /* FIXME: TODO \\ Security directory */
00139     return TRUE;
00140 }
00141 
00142 BOOLEAN
00143 NTAPI
00144 INIT_FUNCTION
00145 SeInitSystem(VOID)
00146 {
00147     /* Check the initialization phase */
00148     switch (ExpInitializationPhase)
00149     {
00150         case 0:
00151 
00152             /* Do Phase 0 */
00153             return SepInitializationPhase0();
00154 
00155         case 1:
00156 
00157             /* Do Phase 1 */
00158             return SepInitializationPhase1();
00159 
00160         default:
00161 
00162             /* Don't know any other phase! Bugcheck! */
00163             KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
00164                          0,
00165                          ExpInitializationPhase,
00166                          0,
00167                          0);
00168             return FALSE;
00169     }
00170 }
00171 
00172 BOOLEAN
00173 NTAPI
00174 INIT_FUNCTION
00175 SeInitSRM(VOID)
00176 {
00177     OBJECT_ATTRIBUTES ObjectAttributes;
00178     UNICODE_STRING Name;
00179     HANDLE DirectoryHandle;
00180     HANDLE EventHandle;
00181     NTSTATUS Status;
00182 
00183     /* Create '\Security' directory */
00184     RtlInitUnicodeString(&Name,
00185                          L"\\Security");
00186     InitializeObjectAttributes(&ObjectAttributes,
00187                                &Name,
00188                                OBJ_PERMANENT,
00189                                0,
00190                                NULL);
00191     Status = ZwCreateDirectoryObject(&DirectoryHandle,
00192                                      DIRECTORY_ALL_ACCESS,
00193                                      &ObjectAttributes);
00194     if (!NT_SUCCESS(Status))
00195     {
00196         DPRINT1("Failed to create 'Security' directory!\n");
00197         return FALSE;
00198     }
00199 
00200     /* Create 'LSA_AUTHENTICATION_INITALIZED' event */
00201     RtlInitUnicodeString(&Name,
00202                          L"\\LSA_AUTHENTICATION_INITALIZED");
00203     InitializeObjectAttributes(&ObjectAttributes,
00204                                &Name,
00205                                OBJ_PERMANENT,
00206                                DirectoryHandle,
00207                                SePublicDefaultSd);
00208     Status = ZwCreateEvent(&EventHandle,
00209                            EVENT_ALL_ACCESS,
00210                            &ObjectAttributes,
00211                            SynchronizationEvent,
00212                            FALSE);
00213     if (!NT_SUCCESS(Status))
00214     {
00215         DPRINT1("Failed to create 'LSA_AUTHENTICATION_INITALIZED' event!\n");
00216         NtClose(DirectoryHandle);
00217         return FALSE;
00218     }
00219 
00220     ZwClose(EventHandle);
00221     ZwClose(DirectoryHandle);
00222 
00223     /* FIXME: Create SRM port and listener thread */
00224 
00225     return TRUE;
00226 }
00227 
00228 NTSTATUS
00229 NTAPI
00230 SeDefaultObjectMethod(IN PVOID Object,
00231                       IN SECURITY_OPERATION_CODE OperationType,
00232                       IN PSECURITY_INFORMATION SecurityInformation,
00233                       IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
00234                       IN OUT PULONG ReturnLength OPTIONAL,
00235                       IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
00236                       IN POOL_TYPE PoolType,
00237                       IN PGENERIC_MAPPING GenericMapping)
00238 {
00239     PAGED_CODE();
00240 
00241     /* Select the operation type */
00242     switch (OperationType)
00243     {
00244             /* Setting a new descriptor */
00245         case SetSecurityDescriptor:
00246 
00247             /* Sanity check */
00248             ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
00249 
00250             /* Set the information */
00251             return ObSetSecurityDescriptorInfo(Object,
00252                                                SecurityInformation,
00253                                                SecurityDescriptor,
00254                                                OldSecurityDescriptor,
00255                                                PoolType,
00256                                                GenericMapping);
00257 
00258         case QuerySecurityDescriptor:
00259 
00260             /* Query the information */
00261             return ObQuerySecurityDescriptorInfo(Object,
00262                                                  SecurityInformation,
00263                                                  SecurityDescriptor,
00264                                                  ReturnLength,
00265                                                  OldSecurityDescriptor);
00266 
00267         case DeleteSecurityDescriptor:
00268 
00269             /* De-assign it */
00270             return ObDeassignSecurity(OldSecurityDescriptor);
00271 
00272         case AssignSecurityDescriptor:
00273 
00274             /* Assign it */
00275             ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
00276             return STATUS_SUCCESS;
00277 
00278         default:
00279 
00280             /* Bug check */
00281             KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0);
00282     }
00283 
00284     /* Should never reach here */
00285     ASSERT(FALSE);
00286     return STATUS_SUCCESS;
00287 }
00288 
00289 static BOOLEAN
00290 SepSidInToken(PACCESS_TOKEN _Token,
00291               PSID Sid)
00292 {
00293     ULONG i;
00294     PTOKEN Token = (PTOKEN)_Token;
00295 
00296     PAGED_CODE();
00297 
00298     SidInTokenCalls++;
00299     if (!(SidInTokenCalls % 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls);
00300 
00301     if (Token->UserAndGroupCount == 0)
00302     {
00303         return FALSE;
00304     }
00305 
00306     for (i=0; i<Token->UserAndGroupCount; i++)
00307     {
00308         if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
00309         {
00310             if ((i == 0)|| (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED))
00311             {
00312                 return TRUE;
00313             }
00314 
00315             return FALSE;
00316         }
00317     }
00318 
00319     return FALSE;
00320 }
00321 
00322 static BOOLEAN
00323 SepTokenIsOwner(PACCESS_TOKEN Token,
00324                 PSECURITY_DESCRIPTOR SecurityDescriptor)
00325 {
00326     NTSTATUS Status;
00327     PSID Sid = NULL;
00328     BOOLEAN Defaulted;
00329 
00330     Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
00331                                            &Sid,
00332                                            &Defaulted);
00333     if (!NT_SUCCESS(Status))
00334     {
00335         DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
00336         return FALSE;
00337     }
00338 
00339     if (Sid == NULL)
00340     {
00341         DPRINT1("Owner Sid is NULL\n");
00342         return FALSE;
00343     }
00344 
00345     return SepSidInToken(Token, Sid);
00346 }
00347 
00348 VOID
00349 NTAPI
00350 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
00351                           OUT PACCESS_MASK DesiredAccess)
00352 {
00353     *DesiredAccess = 0;
00354 
00355     if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
00356                                GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
00357     {
00358         *DesiredAccess |= READ_CONTROL;
00359     }
00360 
00361     if (SecurityInformation & SACL_SECURITY_INFORMATION)
00362     {
00363         *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
00364     }
00365 }
00366 
00367 VOID
00368 NTAPI
00369 SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
00370                         OUT PACCESS_MASK DesiredAccess)
00371 {
00372     *DesiredAccess = 0;
00373 
00374     if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
00375     {
00376         *DesiredAccess |= WRITE_OWNER;
00377     }
00378 
00379     if (SecurityInformation & DACL_SECURITY_INFORMATION)
00380     {
00381         *DesiredAccess |= WRITE_DAC;
00382     }
00383 
00384     if (SecurityInformation & SACL_SECURITY_INFORMATION)
00385     {
00386         *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
00387     }
00388 }
00389 
00390 
00391 #define OLD_ACCESS_CHECK
00392 
00393 BOOLEAN NTAPI
00394 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
00395                IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
00396                IN ACCESS_MASK DesiredAccess,
00397                IN ACCESS_MASK PreviouslyGrantedAccess,
00398                OUT PPRIVILEGE_SET* Privileges,
00399                IN PGENERIC_MAPPING GenericMapping,
00400                IN KPROCESSOR_MODE AccessMode,
00401                OUT PACCESS_MASK GrantedAccess,
00402                OUT PNTSTATUS AccessStatus)
00403 {
00404     LUID_AND_ATTRIBUTES Privilege;
00405 #ifdef OLD_ACCESS_CHECK
00406     ACCESS_MASK CurrentAccess, AccessMask;
00407 #endif
00408     ACCESS_MASK RemainingAccess;
00409     ACCESS_MASK TempAccess;
00410     ACCESS_MASK TempGrantedAccess = 0;
00411     ACCESS_MASK TempDeniedAccess = 0;
00412     PACCESS_TOKEN Token;
00413     ULONG i;
00414     PACL Dacl;
00415     BOOLEAN Present;
00416     BOOLEAN Defaulted;
00417     PACE CurrentAce;
00418     PSID Sid;
00419     NTSTATUS Status;
00420     PAGED_CODE();
00421 
00422     /* Check for no access desired */
00423     if (!DesiredAccess)
00424     {
00425         /* Check if we had no previous access */
00426         if (!PreviouslyGrantedAccess)
00427         {
00428             /* Then there's nothing to give */
00429             *AccessStatus = STATUS_ACCESS_DENIED;
00430             return FALSE;
00431         }
00432 
00433         /* Return the previous access only */
00434         *GrantedAccess = PreviouslyGrantedAccess;
00435         *AccessStatus = STATUS_SUCCESS;
00436         *Privileges = NULL;
00437         return TRUE;
00438     }
00439 
00440     /* Map given accesses */
00441     RtlMapGenericMask(&DesiredAccess, GenericMapping);
00442     if (PreviouslyGrantedAccess)
00443         RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
00444 
00445 #ifdef OLD_ACCESS_CHECK
00446     CurrentAccess = PreviouslyGrantedAccess;
00447 #endif
00448     /* Initialize remaining access rights */
00449     RemainingAccess = DesiredAccess;
00450 
00451     Token = SubjectSecurityContext->ClientToken ?
00452     SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
00453 
00454     /* Check for system security access */
00455     if (RemainingAccess & ACCESS_SYSTEM_SECURITY)
00456     {
00457         Privilege.Luid = SeSecurityPrivilege;
00458         Privilege.Attributes = SE_PRIVILEGE_ENABLED;
00459 
00460         /* Fail if we do not the SeSecurityPrivilege */
00461         if (!SepPrivilegeCheck(Token,
00462                                &Privilege,
00463                                1,
00464                                PRIVILEGE_SET_ALL_NECESSARY,
00465                                AccessMode))
00466         {
00467             *AccessStatus = STATUS_PRIVILEGE_NOT_HELD;
00468             return FALSE;
00469         }
00470 
00471         /* Adjust access rights */
00472         RemainingAccess &= ~ACCESS_SYSTEM_SECURITY;
00473         PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
00474 
00475         /* Succeed if there are no more rights to grant */
00476         if (RemainingAccess == 0)
00477         {
00478             *GrantedAccess = PreviouslyGrantedAccess;
00479             *AccessStatus = STATUS_SUCCESS;
00480             return TRUE;
00481         }
00482     }
00483 
00484     /* Get the DACL */
00485     Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
00486                                           &Present,
00487                                           &Dacl,
00488                                           &Defaulted);
00489     if (!NT_SUCCESS(Status))
00490     {
00491         *AccessStatus = Status;
00492         return FALSE;
00493     }
00494 
00495     /* RULE 1: Grant desired access if the object is unprotected */
00496     if (Present == FALSE || Dacl == NULL)
00497     {
00498         if (DesiredAccess & MAXIMUM_ALLOWED)
00499         {
00500             *GrantedAccess = GenericMapping->GenericAll;
00501             *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
00502         }
00503         else
00504         {
00505             *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
00506         }
00507 
00508         *AccessStatus = STATUS_SUCCESS;
00509         return TRUE;
00510     }
00511 
00512 #ifdef OLD_ACCESS_CHECK
00513     CurrentAccess = PreviouslyGrantedAccess;
00514 #endif
00515 
00516     /* RULE 2: Check token for 'take ownership' privilege */
00517     if (DesiredAccess & WRITE_OWNER)
00518     {
00519         Privilege.Luid = SeTakeOwnershipPrivilege;
00520         Privilege.Attributes = SE_PRIVILEGE_ENABLED;
00521 
00522         if (SepPrivilegeCheck(Token,
00523                               &Privilege,
00524                               1,
00525                               PRIVILEGE_SET_ALL_NECESSARY,
00526                               AccessMode))
00527         {
00528             /* Adjust access rights */
00529             RemainingAccess &= ~WRITE_OWNER;
00530             PreviouslyGrantedAccess |= WRITE_OWNER;
00531 #ifdef OLD_ACCESS_CHECK
00532             CurrentAccess |= WRITE_OWNER;
00533 #endif
00534 
00535             /* Succeed if there are no more rights to grant */
00536             if (RemainingAccess == 0)
00537             {
00538                 *GrantedAccess = PreviouslyGrantedAccess;
00539                 *AccessStatus = STATUS_SUCCESS;
00540                 return TRUE;
00541             }
00542         }
00543     }
00544 
00545     /* Deny access if the DACL is empty */
00546     if (Dacl->AceCount == 0)
00547     {
00548         if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
00549         {
00550             *GrantedAccess = PreviouslyGrantedAccess;
00551             *AccessStatus = STATUS_SUCCESS;
00552             return TRUE;
00553         }
00554         else
00555         {
00556             *GrantedAccess = 0;
00557             *AccessStatus = STATUS_ACCESS_DENIED;
00558             return FALSE;
00559         }
00560     }
00561 
00562     /* Fail if DACL is absent */
00563     if (Present == FALSE)
00564     {
00565         *GrantedAccess = 0;
00566         *AccessStatus = STATUS_ACCESS_DENIED;
00567         return FALSE;
00568     }
00569 
00570     /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
00571     if (DesiredAccess & MAXIMUM_ALLOWED)
00572     {
00573         CurrentAce = (PACE)(Dacl + 1);
00574         for (i = 0; i < Dacl->AceCount; i++)
00575         {
00576             if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
00577             {
00578                 Sid = (PSID)(CurrentAce + 1);
00579                 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
00580                 {
00581                     if (SepSidInToken(Token, Sid))
00582                     {
00583                         /* Map access rights from the ACE */
00584                         TempAccess = CurrentAce->AccessMask;
00585                         RtlMapGenericMask(&TempAccess, GenericMapping);
00586 
00587                         /* Deny access rights that have not been granted yet */
00588                         TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
00589                     }
00590                 }
00591                 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
00592                 {
00593                     if (SepSidInToken(Token, Sid))
00594                     {
00595                         /* Map access rights from the ACE */
00596                         TempAccess = CurrentAce->AccessMask;
00597                         RtlMapGenericMask(&TempAccess, GenericMapping);
00598 
00599                         /* Grant access rights that have not been denied yet */
00600                         TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
00601                     }
00602                 }
00603                 else
00604                 {
00605                     DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
00606                 }
00607             }
00608 
00609             /* Get the next ACE */
00610             CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
00611         }
00612 
00613         /* Fail if some rights have not been granted */
00614         RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
00615         if (RemainingAccess != 0)
00616         {
00617             *GrantedAccess = 0;
00618             *AccessStatus = STATUS_ACCESS_DENIED;
00619             return FALSE;
00620         }
00621 
00622         /* Set granted access right and access status */
00623         *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess;
00624         if (*GrantedAccess != 0)
00625         {
00626             *AccessStatus = STATUS_SUCCESS;
00627             return TRUE;
00628         }
00629         else
00630         {
00631             *AccessStatus = STATUS_ACCESS_DENIED;
00632             return FALSE;
00633         }
00634     }
00635 
00636     /* RULE 4: Grant rights according to the DACL */
00637     CurrentAce = (PACE)(Dacl + 1);
00638     for (i = 0; i < Dacl->AceCount; i++)
00639     {
00640         if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
00641         {
00642             Sid = (PSID)(CurrentAce + 1);
00643             if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
00644             {
00645                 if (SepSidInToken(Token, Sid))
00646                 {
00647 #ifdef OLD_ACCESS_CHECK
00648                     *GrantedAccess = 0;
00649                     *AccessStatus = STATUS_ACCESS_DENIED;
00650                     return FALSE;
00651 #else
00652                     /* Map access rights from the ACE */
00653                     TempAccess = CurrentAce->AccessMask;
00654                     RtlMapGenericMask(&TempAccess, GenericMapping);
00655 
00656                     /* Leave if a remaining right must be denied */
00657                     if (RemainingAccess & TempAccess)
00658                         break;
00659 #endif
00660                 }
00661             }
00662             else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
00663             {
00664                 if (SepSidInToken(Token, Sid))
00665                 {
00666 #ifdef OLD_ACCESS_CHECK
00667                     AccessMask = CurrentAce->AccessMask;
00668                     RtlMapGenericMask(&AccessMask, GenericMapping);
00669                     CurrentAccess |= AccessMask;
00670 #else
00671                     /* Map access rights from the ACE */
00672                     TempAccess = CurrentAce->AccessMask;
00673                     RtlMapGenericMask(&TempAccess, GenericMapping);
00674 
00675                     /* Remove granted rights */
00676                     RemainingAccess &= ~TempAccess;
00677 #endif
00678                 }
00679             }
00680             else
00681             {
00682                 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
00683             }
00684         }
00685 
00686         /* Get the next ACE */
00687         CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
00688     }
00689 
00690 #ifdef OLD_ACCESS_CHECK
00691     DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
00692            CurrentAccess, DesiredAccess);
00693 
00694     *GrantedAccess = CurrentAccess & DesiredAccess;
00695 
00696     if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) == 
00697         (DesiredAccess & ~VALID_INHERIT_FLAGS))
00698     {
00699         *AccessStatus = STATUS_SUCCESS;
00700         return TRUE;
00701     }
00702     else
00703     {
00704         DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n",
00705                 *GrantedAccess, DesiredAccess, GenericMapping);
00706         //*AccessStatus = STATUS_ACCESS_DENIED;
00707         //return FALSE;
00708         *GrantedAccess = DesiredAccess;
00709         *AccessStatus = STATUS_SUCCESS;
00710         return TRUE;
00711     }
00712 #else
00713     DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
00714            DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
00715 
00716     /* Fail if some rights have not been granted */
00717     if (RemainingAccess != 0)
00718     {
00719         *GrantedAccess = 0;
00720         *AccessStatus = STATUS_ACCESS_DENIED;
00721         return FALSE;
00722     }
00723 
00724     /* Set granted access rights */
00725     *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
00726 
00727     DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
00728 
00729     /* Fail if no rights have been granted */
00730     if (*GrantedAccess == 0)
00731     {
00732         *AccessStatus = STATUS_ACCESS_DENIED;
00733         return FALSE;
00734     }
00735 
00736     *AccessStatus = STATUS_SUCCESS;
00737     return TRUE;
00738 #endif
00739 }
00740 
00741 static PSID
00742 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
00743 {
00744     PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
00745     PSID Owner;
00746 
00747     if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
00748         Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
00749                        (ULONG_PTR)SecurityDescriptor);
00750     else
00751         Owner = (PSID)SecurityDescriptor->Owner;
00752 
00753     return Owner;
00754 }
00755 
00756 static PSID
00757 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
00758 {
00759     PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
00760     PSID Group;
00761 
00762     if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
00763         Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
00764                        (ULONG_PTR)SecurityDescriptor);
00765     else
00766         Group = (PSID)SecurityDescriptor->Group;
00767 
00768     return Group;
00769 }
00770 
00771 
00772 /* PUBLIC FUNCTIONS ***********************************************************/
00773 
00774 /*
00775  * @implemented
00776  */
00777 BOOLEAN
00778 NTAPI
00779 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
00780               IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
00781               IN BOOLEAN SubjectContextLocked,
00782               IN ACCESS_MASK DesiredAccess,
00783               IN ACCESS_MASK PreviouslyGrantedAccess,
00784               OUT PPRIVILEGE_SET* Privileges,
00785               IN PGENERIC_MAPPING GenericMapping,
00786               IN KPROCESSOR_MODE AccessMode,
00787               OUT PACCESS_MASK GrantedAccess,
00788               OUT PNTSTATUS AccessStatus)
00789 {
00790     BOOLEAN ret;
00791 
00792     PAGED_CODE();
00793 
00794     /* Check if this is kernel mode */
00795     if (AccessMode == KernelMode)
00796     {
00797         /* Check if kernel wants everything */
00798         if (DesiredAccess & MAXIMUM_ALLOWED)
00799         {
00800             /* Give it */
00801             *GrantedAccess = GenericMapping->GenericAll;
00802             *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
00803             *GrantedAccess |= PreviouslyGrantedAccess;
00804         }
00805         else
00806         {
00807             /* Give the desired and previous access */
00808             *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
00809         }
00810 
00811         /* Success */
00812         *AccessStatus = STATUS_SUCCESS;
00813         return TRUE;
00814     }
00815 
00816     /* Check if we didn't get an SD */
00817     if (!SecurityDescriptor)
00818     {
00819         /* Automatic failure */
00820         *AccessStatus = STATUS_ACCESS_DENIED;
00821         return FALSE;
00822     }
00823 
00824     /* Check for invalid impersonation */
00825     if ((SubjectSecurityContext->ClientToken) &&
00826         (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
00827     {
00828         *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
00829         return FALSE;
00830     }
00831 
00832     /* Acquire the lock if needed */
00833     if (!SubjectContextLocked)
00834         SeLockSubjectContext(SubjectSecurityContext);
00835 
00836     /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
00837     if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
00838     {
00839          PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
00840              SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
00841 
00842         if (SepTokenIsOwner(Token,
00843                             SecurityDescriptor))
00844         {
00845             if (DesiredAccess & MAXIMUM_ALLOWED)
00846                 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
00847             else
00848                 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
00849 
00850             DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
00851         }
00852     }
00853 
00854     if (DesiredAccess == 0)
00855     {
00856         *GrantedAccess = PreviouslyGrantedAccess;
00857         *AccessStatus = STATUS_SUCCESS;
00858         ret = TRUE;
00859     }
00860     else
00861     {
00862         /* Call the internal function */
00863         ret = SepAccessCheck(SecurityDescriptor,
00864                              SubjectSecurityContext,
00865                              DesiredAccess,
00866                              PreviouslyGrantedAccess,
00867                              Privileges,
00868                              GenericMapping,
00869                              AccessMode,
00870                              GrantedAccess,
00871                              AccessStatus);
00872     }
00873 
00874     /* Release the lock if needed */
00875     if (!SubjectContextLocked)
00876         SeUnlockSubjectContext(SubjectSecurityContext);
00877 
00878     return ret;
00879 }
00880 
00881 /* SYSTEM CALLS ***************************************************************/
00882 
00883 /*
00884  * @implemented
00885  */
00886 NTSTATUS
00887 NTAPI
00888 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
00889               IN HANDLE TokenHandle,
00890               IN ACCESS_MASK DesiredAccess,
00891               IN PGENERIC_MAPPING GenericMapping,
00892               OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
00893               IN OUT PULONG PrivilegeSetLength,
00894               OUT PACCESS_MASK GrantedAccess,
00895               OUT PNTSTATUS AccessStatus)
00896 {
00897     PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
00898     SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
00899     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
00900     ACCESS_MASK PreviouslyGrantedAccess = 0;
00901     PTOKEN Token;
00902     NTSTATUS Status;
00903     PAGED_CODE();
00904 
00905     /* Check if this is kernel mode */
00906     if (PreviousMode == KernelMode)
00907     {
00908         /* Check if kernel wants everything */
00909         if (DesiredAccess & MAXIMUM_ALLOWED)
00910         {
00911             /* Give it */
00912             *GrantedAccess = GenericMapping->GenericAll;
00913             *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
00914         }
00915         else
00916         {
00917             /* Just give the desired access */
00918             *GrantedAccess = DesiredAccess;
00919         }
00920 
00921         /* Success */
00922         *AccessStatus = STATUS_SUCCESS;
00923         return STATUS_SUCCESS;
00924     }
00925 
00926     /* Protect probe in SEH */
00927     _SEH2_TRY
00928     {
00929         /* Probe all pointers */
00930         ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
00931         ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
00932         ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
00933         ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
00934         ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
00935     }
00936     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00937     {
00938         /* Return the exception code */
00939         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00940     }
00941     _SEH2_END;
00942 
00943     /* Check for unmapped access rights */
00944     if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
00945         return STATUS_GENERIC_NOT_MAPPED;
00946 
00947     /* Reference the token */
00948     Status = ObReferenceObjectByHandle(TokenHandle,
00949                                        TOKEN_QUERY,
00950                                        SeTokenObjectType,
00951                                        PreviousMode,
00952                                        (PVOID*)&Token,
00953                                        NULL);
00954     if (!NT_SUCCESS(Status))
00955     {
00956         DPRINT("Failed to reference token (Status %lx)\n", Status);
00957         return Status;
00958     }
00959 
00960     /* Check token type */
00961     if (Token->TokenType != TokenImpersonation)
00962     {
00963         DPRINT("No impersonation token\n");
00964         ObDereferenceObject(Token);
00965         return STATUS_NO_IMPERSONATION_TOKEN;
00966     }
00967 
00968     /* Check the impersonation level */
00969     if (Token->ImpersonationLevel < SecurityIdentification)
00970     {
00971         DPRINT("Impersonation level < SecurityIdentification\n");
00972         ObDereferenceObject(Token);
00973         return STATUS_BAD_IMPERSONATION_LEVEL;
00974     }
00975 
00976     /* Capture the security descriptor */
00977     Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
00978                                          PreviousMode,
00979                                          PagedPool,
00980                                          FALSE,
00981                                          &CapturedSecurityDescriptor);
00982     if (!NT_SUCCESS(Status))
00983     {
00984         DPRINT("Failed to capture the Security Descriptor\n");
00985         ObDereferenceObject(Token);
00986         return Status;
00987     }
00988 
00989     /* Check the captured security descriptor */
00990     if (CapturedSecurityDescriptor == NULL)
00991     {
00992         DPRINT("Security Descriptor is NULL\n");
00993         ObDereferenceObject(Token);
00994         return STATUS_INVALID_SECURITY_DESCR;
00995     }
00996 
00997     /* Check security descriptor for valid owner and group */
00998     if (SepGetSDOwner(SecurityDescriptor) == NULL ||  // FIXME: use CapturedSecurityDescriptor
00999         SepGetSDGroup(SecurityDescriptor) == NULL)    // FIXME: use CapturedSecurityDescriptor
01000     {
01001         DPRINT("Security Descriptor does not have a valid group or owner\n");
01002         SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
01003                                     PreviousMode,
01004                                     FALSE);
01005         ObDereferenceObject(Token);
01006         return STATUS_INVALID_SECURITY_DESCR;
01007     }
01008 
01009     /* Set up the subject context, and lock it */
01010     SubjectSecurityContext.ClientToken = Token;
01011     SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
01012     SubjectSecurityContext.PrimaryToken = NULL;
01013     SubjectSecurityContext.ProcessAuditId = NULL;
01014     SeLockSubjectContext(&SubjectSecurityContext);
01015 
01016     /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
01017     if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
01018     {
01019         if (SepTokenIsOwner(Token, SecurityDescriptor)) // FIXME: use CapturedSecurityDescriptor
01020         {
01021             if (DesiredAccess & MAXIMUM_ALLOWED)
01022                 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
01023             else
01024                 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
01025 
01026             DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
01027         }
01028     }
01029 
01030     if (DesiredAccess == 0)
01031     {
01032         *GrantedAccess = PreviouslyGrantedAccess;
01033         *AccessStatus = STATUS_SUCCESS;
01034     }
01035     else
01036     {
01037         /* Now perform the access check */
01038         SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
01039                        &SubjectSecurityContext,
01040                        DesiredAccess,
01041                        PreviouslyGrantedAccess,
01042                        &PrivilegeSet, //FIXME
01043                        GenericMapping,
01044                        PreviousMode,
01045                        GrantedAccess,
01046                        AccessStatus);
01047     }
01048 
01049     /* Unlock subject context */
01050     SeUnlockSubjectContext(&SubjectSecurityContext);
01051 
01052     /* Release the captured security descriptor */
01053     SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
01054                                 PreviousMode,
01055                                 FALSE);
01056 
01057     /* Dereference the token */
01058     ObDereferenceObject(Token);
01059 
01060     /* Check succeeded */
01061     return STATUS_SUCCESS;
01062 }
01063 
01064 
01065 NTSTATUS
01066 NTAPI
01067 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
01068                     IN PSID PrincipalSelfSid,
01069                     IN HANDLE ClientToken,
01070                     IN ACCESS_MASK DesiredAccess,
01071                     IN POBJECT_TYPE_LIST ObjectTypeList,
01072                     IN ULONG ObjectTypeLength,
01073                     IN PGENERIC_MAPPING GenericMapping,
01074                     IN PPRIVILEGE_SET PrivilegeSet,
01075                     IN ULONG PrivilegeSetLength,
01076                     OUT PACCESS_MASK GrantedAccess,
01077                     OUT PNTSTATUS AccessStatus)
01078 {
01079     UNIMPLEMENTED;
01080     return STATUS_NOT_IMPLEMENTED;
01081 }
01082 
01083 NTSTATUS
01084 NTAPI
01085 NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
01086                                  IN HANDLE HandleId,
01087                                  IN PUNICODE_STRING ObjectTypeName,
01088                                  IN PUNICODE_STRING ObjectName,
01089                                  IN PSECURITY_DESCRIPTOR SecurityDescriptor,
01090                                  IN PSID PrincipalSelfSid,
01091                                  IN ACCESS_MASK DesiredAccess,
01092                                  IN AUDIT_EVENT_TYPE AuditType,
01093                                  IN ULONG Flags,
01094                                  IN POBJECT_TYPE_LIST ObjectTypeList,
01095                                  IN ULONG ObjectTypeLength,
01096                                  IN PGENERIC_MAPPING GenericMapping,
01097                                  IN BOOLEAN ObjectCreation,
01098                                  OUT PACCESS_MASK GrantedAccess,
01099                                  OUT PNTSTATUS AccessStatus,
01100                                  OUT PBOOLEAN GenerateOnClose)
01101 {
01102     UNIMPLEMENTED;
01103     return STATUS_NOT_IMPLEMENTED;
01104 }
01105 
01106 NTSTATUS
01107 NTAPI
01108 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
01109                               IN PSID PrincipalSelfSid,
01110                               IN HANDLE ClientToken,
01111                               IN ACCESS_MASK DesiredAccess,
01112                               IN POBJECT_TYPE_LIST ObjectTypeList,
01113                               IN ULONG ObjectTypeLength,
01114                               IN PGENERIC_MAPPING GenericMapping,
01115                               IN PPRIVILEGE_SET PrivilegeSet,
01116                               IN ULONG PrivilegeSetLength,
01117                               OUT PACCESS_MASK GrantedAccess,
01118                               OUT PNTSTATUS AccessStatus)
01119 {
01120     UNIMPLEMENTED;
01121     return STATUS_NOT_IMPLEMENTED;
01122 }
01123 
01124 NTSTATUS
01125 NTAPI
01126 NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
01127                                            IN HANDLE HandleId,
01128                                            IN PUNICODE_STRING ObjectTypeName,
01129                                            IN PUNICODE_STRING ObjectName,
01130                                            IN PSECURITY_DESCRIPTOR SecurityDescriptor,
01131                                            IN PSID PrincipalSelfSid,
01132                                            IN ACCESS_MASK DesiredAccess,
01133                                            IN AUDIT_EVENT_TYPE AuditType,
01134                                            IN ULONG Flags,
01135                                            IN POBJECT_TYPE_LIST ObjectTypeList,
01136                                            IN ULONG ObjectTypeLength,
01137                                            IN PGENERIC_MAPPING GenericMapping,
01138                                            IN BOOLEAN ObjectCreation,
01139                                            OUT PACCESS_MASK GrantedAccess,
01140                                            OUT PNTSTATUS AccessStatus,
01141                                            OUT PBOOLEAN GenerateOnClose)
01142 {
01143     UNIMPLEMENTED;
01144     return STATUS_NOT_IMPLEMENTED;
01145 }
01146 
01147 NTSTATUS
01148 NTAPI
01149 NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
01150                                                    IN HANDLE HandleId,
01151                                                    IN HANDLE ClientToken,
01152                                                    IN PUNICODE_STRING ObjectTypeName,
01153                                                    IN PUNICODE_STRING ObjectName,
01154                                                    IN PSECURITY_DESCRIPTOR SecurityDescriptor,
01155                                                    IN PSID PrincipalSelfSid,
01156                                                    IN ACCESS_MASK DesiredAccess,
01157                                                    IN AUDIT_EVENT_TYPE AuditType,
01158                                                    IN ULONG Flags,
01159                                                    IN POBJECT_TYPE_LIST ObjectTypeList,
01160                                                    IN ULONG ObjectTypeLength,
01161                                                    IN PGENERIC_MAPPING GenericMapping,
01162                                                    IN BOOLEAN ObjectCreation,
01163                                                    OUT PACCESS_MASK GrantedAccess,
01164                                                    OUT PNTSTATUS AccessStatus,
01165                                                    OUT PBOOLEAN GenerateOnClose)
01166 {
01167     UNIMPLEMENTED;
01168     return STATUS_NOT_IMPLEMENTED;
01169 }
01170 
01171 /* EOF */

Generated on Sun May 27 2012 04:37:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.