NTSTATUS NTAPI SamIConnect(IN PSAMPR_SERVER_NAME ServerName, OUT SAMPR_HANDLE *ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted) { PSAM_DB_OBJECT ServerObject; NTSTATUS Status; TRACE("SamIConnect(%p %p %lx %ld)\n", ServerName, ServerHandle, DesiredAccess, Trusted); /* Map generic access rights */ RtlMapGenericMask(&DesiredAccess, pServerMapping); /* Open the Server Object */ Status = SampOpenDbObject(NULL, NULL, L"SAM", 0, SamDbServerObject, DesiredAccess, &ServerObject); if (NT_SUCCESS(Status)) { ServerObject->Trusted = Trusted; *ServerHandle = (SAMPR_HANDLE)ServerObject; } TRACE("SamIConnect done (Status 0x%08lx)\n", Status); return Status; }
/* * @implemented */ NTSTATUS NTAPI SeCreateAccessStateEx(IN PETHREAD Thread, IN PEPROCESS Process, IN OUT PACCESS_STATE AccessState, IN PAUX_ACCESS_DATA AuxData, IN ACCESS_MASK Access, IN PGENERIC_MAPPING GenericMapping) { ACCESS_MASK AccessMask = Access; PTOKEN Token; PAGED_CODE(); /* Map the Generic Acess to Specific Access if we have a Mapping */ if ((Access & GENERIC_ACCESS) && (GenericMapping)) { RtlMapGenericMask(&AccessMask, GenericMapping); } /* Initialize the Access State */ RtlZeroMemory(AccessState, sizeof(ACCESS_STATE)); /* Capture the Subject Context */ SeCaptureSubjectContextEx(Thread, Process, &AccessState->SubjectSecurityContext); /* Set Access State Data */ AccessState->AuxData = AuxData; AccessState->RemainingDesiredAccess = AccessMask; AccessState->OriginalDesiredAccess = AccessMask; ExpAllocateLocallyUniqueId(&AccessState->OperationID); /* Get the Token to use */ Token = AccessState->SubjectSecurityContext.ClientToken ? (PTOKEN)&AccessState->SubjectSecurityContext.ClientToken : (PTOKEN)&AccessState->SubjectSecurityContext.PrimaryToken; /* Check for Travers Privilege */ if (Token->TokenFlags & TOKEN_HAS_TRAVERSE_PRIVILEGE) { /* Preserve the Traverse Privilege */ AccessState->Flags = TOKEN_HAS_TRAVERSE_PRIVILEGE; } /* Set the Auxiliary Data */ AuxData->PrivilegeSet = (PPRIVILEGE_SET)((ULONG_PTR)AccessState + FIELD_OFFSET(ACCESS_STATE, Privileges)); if (GenericMapping) AuxData->GenericMapping = *GenericMapping; /* Return Sucess */ return STATUS_SUCCESS; }
HRESULT STDMETHODCALLTYPE MapGeneric( _In_ IObjectSecurity * This, _In_ const GUID *pguidObjectType, _In_ UCHAR *pAceFlags, _In_ ACCESS_MASK *pMask ) { UNREFERENCED_PARAMETER(pguidObjectType); UNREFERENCED_PARAMETER(pAceFlags); RtlMapGenericMask(pMask, &This->GenericMapping); return S_OK; }
ACCESS_MASK PvfsGetGrantedAccessForNewObject( ACCESS_MASK DesiredAccess ) { ACCESS_MASK GrantedAccess = DesiredAccess; // TODO: This function probably needs to be more complicated. if (IsSetFlag(DesiredAccess, MAXIMUM_ALLOWED)) { GrantedAccess = FILE_ALL_ACCESS; } RtlMapGenericMask(&GrantedAccess, &gPvfsDriverState.GenericSecurityMap); return GrantedAccess; }
BOOLEAN NTAPI SepAccessCheckEx(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, IN ACCESS_MASK PreviouslyGrantedAccess, OUT PPRIVILEGE_SET* Privileges, IN PGENERIC_MAPPING GenericMapping, IN KPROCESSOR_MODE AccessMode, OUT PACCESS_MASK GrantedAccessList, OUT PNTSTATUS AccessStatusList, IN BOOLEAN UseResultList) { ACCESS_MASK RemainingAccess; ACCESS_MASK TempAccess; ACCESS_MASK TempGrantedAccess = 0; ACCESS_MASK TempDeniedAccess = 0; PACCESS_TOKEN Token; ULONG i, ResultListLength; PACL Dacl; BOOLEAN Present; BOOLEAN Defaulted; PACE CurrentAce; PSID Sid; NTSTATUS Status; PAGED_CODE(); DPRINT("SepAccessCheckEx()\n"); /* Check for no access desired */ if (!DesiredAccess) { /* Check if we had no previous access */ if (!PreviouslyGrantedAccess) { /* Then there's nothing to give */ Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } /* Return the previous access only */ Status = STATUS_SUCCESS; *Privileges = NULL; goto ReturnCommonStatus; } /* Map given accesses */ RtlMapGenericMask(&DesiredAccess, GenericMapping); if (PreviouslyGrantedAccess) RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping); /* Initialize remaining access rights */ RemainingAccess = DesiredAccess; Token = SubjectSecurityContext->ClientToken ? SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */ Status = SePrivilegePolicyCheck(&RemainingAccess, &PreviouslyGrantedAccess, NULL, Token, NULL, UserMode); if (!NT_SUCCESS(Status)) { goto ReturnCommonStatus; } /* Succeed if there are no more rights to grant */ if (RemainingAccess == 0) { Status = STATUS_SUCCESS; goto ReturnCommonStatus; } /* Get the DACL */ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &Present, &Dacl, &Defaulted); if (!NT_SUCCESS(Status)) { goto ReturnCommonStatus; } /* RULE 1: Grant desired access if the object is unprotected */ if (Present == FALSE || Dacl == NULL) { PreviouslyGrantedAccess |= RemainingAccess; if (RemainingAccess & MAXIMUM_ALLOWED) { PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED; PreviouslyGrantedAccess |= GenericMapping->GenericAll; } Status = STATUS_SUCCESS; goto ReturnCommonStatus; } /* Deny access if the DACL is empty */ if (Dacl->AceCount == 0) { if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0) { Status = STATUS_SUCCESS; } else { PreviouslyGrantedAccess = 0; Status = STATUS_ACCESS_DENIED; } goto ReturnCommonStatus; } /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */ if (DesiredAccess & MAXIMUM_ALLOWED) { CurrentAce = (PACE)(Dacl + 1); for (i = 0; i < Dacl->AceCount; i++) { if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) { Sid = (PSID)(CurrentAce + 1); if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Deny access rights that have not been granted yet */ TempDeniedAccess |= (TempAccess & ~TempGrantedAccess); } } else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Grant access rights that have not been denied yet */ TempGrantedAccess |= (TempAccess & ~TempDeniedAccess); } } else { DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); } } /* Get the next ACE */ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); } /* Fail if some rights have not been granted */ RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess); if (RemainingAccess != 0) { PreviouslyGrantedAccess = 0; Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } /* Set granted access right and access status */ PreviouslyGrantedAccess |= TempGrantedAccess; if (PreviouslyGrantedAccess != 0) { Status = STATUS_SUCCESS; } else { Status = STATUS_ACCESS_DENIED; } goto ReturnCommonStatus; } /* RULE 4: Grant rights according to the DACL */ CurrentAce = (PACE)(Dacl + 1); for (i = 0; i < Dacl->AceCount; i++) { if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) { Sid = (PSID)(CurrentAce + 1); if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Leave if a remaining right must be denied */ if (RemainingAccess & TempAccess) break; } } else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; DPRINT("TempAccess 0x%08lx\n", TempAccess); RtlMapGenericMask(&TempAccess, GenericMapping); /* Remove granted rights */ DPRINT("RemainingAccess 0x%08lx TempAccess 0x%08lx\n", RemainingAccess, TempAccess); RemainingAccess &= ~TempAccess; DPRINT("RemainingAccess 0x%08lx\n", RemainingAccess); } } else { DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); } } /* Get the next ACE */ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); } DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n", DesiredAccess, PreviouslyGrantedAccess, RemainingAccess); /* Fail if some rights have not been granted */ if (RemainingAccess != 0) { DPRINT1("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess); #if 0 /* HACK HACK HACK */ Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; #endif } /* Set granted access rights */ PreviouslyGrantedAccess |= DesiredAccess; /* Fail if no rights have been granted */ if (PreviouslyGrantedAccess == 0) { DPRINT1("PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess); Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } Status = STATUS_SUCCESS; goto ReturnCommonStatus; ReturnCommonStatus: ResultListLength = UseResultList ? ObjectTypeListLength : 1; for (i = 0; i < ResultListLength; i++) { GrantedAccessList[i] = PreviouslyGrantedAccess; AccessStatusList[i] = Status; } return NT_SUCCESS(Status); }
BOOLEAN RtlAccessCheckEx( IN PSECURITY_DESCRIPTOR_ABSOLUTE SecurityDescriptor, IN PACCESS_TOKEN AccessToken, IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK PreviouslyGrantedAccess, IN PGENERIC_MAPPING GenericMapping, OUT PACCESS_MASK RemainingDesiredAccess, OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus ) { NTSTATUS status = STATUS_ACCESS_DENIED; BOOLEAN isLocked = FALSE; ACCESS_MASK grantedAccess = PreviouslyGrantedAccess; ACCESS_MASK deniedAccess = 0; ACCESS_MASK desiredAccess = DesiredAccess; BOOLEAN wantMaxAllowed = FALSE; USHORT aclSizeUsed = 0; USHORT aceOffset = 0; PACE_HEADER aceHeader = NULL; union { SID Sid; BYTE Buffer[SID_MAX_SIZE]; } sidBuffer; ULONG ulSidSize = sizeof(sidBuffer); if (!SecurityDescriptor || !AccessToken || !GenericMapping) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!LW_IS_VALID_FLAGS(DesiredAccess, VALID_DESIRED_ACCESS_MASK)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!LW_IS_VALID_FLAGS(PreviouslyGrantedAccess, VALID_GRANTED_ACCESS_MASK)) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if ((SecurityDescriptor->Owner == NULL) || (SecurityDescriptor->Group == NULL)) { status = STATUS_INVALID_SECURITY_DESCR; GOTO_CLEANUP(); } wantMaxAllowed = IsSetFlag(desiredAccess, MAXIMUM_ALLOWED); ClearFlag(desiredAccess, MAXIMUM_ALLOWED); RtlMapGenericMask(&desiredAccess, GenericMapping); // // NT AUTHORITY\SYSTEM is always allowed an access // status = RtlCreateWellKnownSid(WinLocalSystemSid, NULL, &sidBuffer.Sid, &ulSidSize); GOTO_CLEANUP_ON_STATUS(status); SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked); if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid)) { if (wantMaxAllowed) { SetFlag(desiredAccess, STANDARD_RIGHTS_ALL); SetFlag(desiredAccess, GENERIC_ALL); RtlMapGenericMask(&desiredAccess, GenericMapping); } SetFlag(grantedAccess, desiredAccess); desiredAccess = 0; status = STATUS_SUCCESS; GOTO_CLEANUP(); } if (wantMaxAllowed || IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY)) { // TODO-Handle ACCESS_SYSTEM_SECURITY by checking SE_SECURITY_NAME // privilege. For now, requesting ACCESS_SYSTEM_SECURITY is not // allowed. ulSidSize = sizeof(sidBuffer); status = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &sidBuffer.Sid, &ulSidSize); GOTO_CLEANUP_ON_STATUS(status); if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid)) { SetFlag(grantedAccess, ACCESS_SYSTEM_SECURITY); ClearFlag(desiredAccess, ACCESS_SYSTEM_SECURITY); } else if (IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY)) { status = STATUS_PRIVILEGE_NOT_HELD; GOTO_CLEANUP(); } } if (wantMaxAllowed || IsSetFlag(desiredAccess, WRITE_OWNER)) { // TODO-Allow WRITE_OWNER if have SE_TAKE_OWNERSHIP_NAME regardless // of DACL. // // BUILTIN\Administrators are always allowed WRITE_OWNER // ulSidSize = sizeof(sidBuffer); status = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &sidBuffer.Sid, &ulSidSize); GOTO_CLEANUP_ON_STATUS(status); if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid)) { SetFlag(grantedAccess, WRITE_OWNER); ClearFlag(desiredAccess, WRITE_OWNER); } } // // Owner can always read the SD and write the DACL. // if (wantMaxAllowed || IsSetFlag(desiredAccess, READ_CONTROL | WRITE_DAC)) { if (RtlIsSidMemberOfToken(AccessToken, SecurityDescriptor->Owner)) { if (wantMaxAllowed) { desiredAccess |= (READ_CONTROL | WRITE_DAC); } SetFlag(grantedAccess, (READ_CONTROL | WRITE_DAC) & desiredAccess); ClearFlag(desiredAccess, grantedAccess); } } // TODO-MAXIMUM_ALLOWED wrt privileges and WRITE_OWNER and // ACCESS_SYSTEM_SECURITY above. if (!SecurityDescriptor->Dacl) { // TODO-Interplay with special bits above? if (wantMaxAllowed) { SetFlag(desiredAccess, STANDARD_RIGHTS_ALL); SetFlag(desiredAccess, GENERIC_ALL); RtlMapGenericMask(&desiredAccess, GenericMapping); } SetFlag(grantedAccess, desiredAccess); desiredAccess = 0; status = STATUS_SUCCESS; GOTO_CLEANUP(); } if (!RtlValidAcl(SecurityDescriptor->Dacl, &aclSizeUsed)) { status = STATUS_INVALID_ACL; GOTO_CLEANUP(); } while (wantMaxAllowed || desiredAccess) { status = RtlIterateAce(SecurityDescriptor->Dacl, aclSizeUsed, &aceOffset, &aceHeader); if (STATUS_NO_MORE_ENTRIES == status) { break; } GOTO_CLEANUP_ON_STATUS(status); // Check ACE switch (aceHeader->AceType) { case ACCESS_ALLOWED_ACE_TYPE: { PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader; ACCESS_MASK mask = ace->Mask; RtlMapGenericMask(&mask, GenericMapping); if (wantMaxAllowed || IsSetFlag(desiredAccess, mask)) { // SID in token => add bits to granted bits PSID sid = RtlpGetSidAccessAllowedAce(ace); if (RtlIsSidMemberOfToken(AccessToken, sid)) { if (wantMaxAllowed) { SetFlag(grantedAccess, mask & ~deniedAccess); } else { SetFlag(grantedAccess, mask & desiredAccess); } ClearFlag(desiredAccess, grantedAccess); } } break; } case ACCESS_DENIED_ACE_TYPE: { // Allowed and deny ACEs are isomorphic. PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader; ACCESS_MASK mask = ace->Mask; RtlMapGenericMask(&mask, GenericMapping); if (wantMaxAllowed || IsSetFlag(desiredAccess, mask)) { // SID in token => exit with STATUS_ACCESS_DENIED PSID sid = RtlpGetSidAccessAllowedAce(ace); if (RtlIsSidMemberOfToken(AccessToken, sid)) { if (wantMaxAllowed) { SetFlag(deniedAccess, mask); } else { status = STATUS_ACCESS_DENIED; GOTO_CLEANUP(); } ClearFlag(desiredAccess, deniedAccess); } } break; } default: // ignore break; } } status = desiredAccess ? STATUS_ACCESS_DENIED : STATUS_SUCCESS; cleanup: UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked); if (NT_SUCCESS(status) && !LW_IS_VALID_FLAGS(grantedAccess, VALID_GRANTED_ACCESS_MASK)) { status = STATUS_ASSERTION_FAILURE; } if (!NT_SUCCESS(status)) { grantedAccess = PreviouslyGrantedAccess; } if (RemainingDesiredAccess) { *RemainingDesiredAccess = desiredAccess; } *GrantedAccess = grantedAccess; *AccessStatus = status; return NT_SUCCESS(status) ? TRUE : FALSE; }
NTSTATUS AfdBuildDeviceAcl( OUT PACL *DeviceAcl ) /*++ Routine Description: This routine builds an ACL which gives Administrators and LocalSystem principals full access. All other principals have no access. Arguments: DeviceAcl - Output pointer to the new ACL. Return Value: STATUS_SUCCESS or an appropriate error code. --*/ { PGENERIC_MAPPING GenericMapping; PSID AdminsSid; PSID SystemSid; ULONG AclLength; NTSTATUS Status; ACCESS_MASK AccessMask = GENERIC_ALL; PACL NewAcl; // // Enable access to all the globally defined SIDs // GenericMapping = IoGetFileObjectGenericMapping(); RtlMapGenericMask( &AccessMask, GenericMapping ); SeEnableAccessToExports(); AdminsSid = SeExports->SeAliasAdminsSid; SystemSid = SeExports->SeLocalSystemSid; AclLength = sizeof( ACL ) + 2 * sizeof( ACCESS_ALLOWED_ACE ) + RtlLengthSid( AdminsSid ) + RtlLengthSid( SystemSid ) - 2 * sizeof( ULONG ); NewAcl = AFD_ALLOCATE_POOL( PagedPool, AclLength, AFD_SECURITY_POOL_TAG ); if (NewAcl == NULL) { return( STATUS_INSUFFICIENT_RESOURCES ); } Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION ); if (!NT_SUCCESS( Status )) { AFD_FREE_POOL( NewAcl, AFD_SECURITY_POOL_TAG ); return( Status ); } Status = RtlAddAccessAllowedAce ( NewAcl, ACL_REVISION2, AccessMask, AdminsSid ); ASSERT( NT_SUCCESS( Status )); Status = RtlAddAccessAllowedAce ( NewAcl, ACL_REVISION2, AccessMask, SystemSid ); ASSERT( NT_SUCCESS( Status )); *DeviceAcl = NewAcl; return( STATUS_SUCCESS ); } // AfdBuildDeviceAcl