static void print_dacl (PACL dacl) { DWORD i; cyglsa_printf ("DefaultDacl: (0x%08x) ", (INT_PTR) dacl); if (!dacl) cyglsa_printf ("NULL\n"); else if (IsBadReadPtr (dacl, sizeof (ACL))) cyglsa_printf ("INVALID POINTER\n"); else if (IsBadReadPtr (dacl, dacl->AclSize)) cyglsa_printf ("INVALID POINTER SPACE\n"); else { cyglsa_printf ("Rev: %d, Count: %d\n", dacl->AclRevision, dacl->AceCount); for (i = 0; i < dacl->AceCount; ++i) { PVOID vace; PACCESS_ALLOWED_ACE ace; if (!GetAce (dacl, i, &vace)) cyglsa_printf ("[%lu] GetAce error %lu\n", i, GetLastError ()); else { ace = (PACCESS_ALLOWED_ACE) vace; cyglsa_printf ("Type: %x, Flags: %x, Access: %lx,", ace->Header.AceType, ace->Header.AceFlags, (DWORD) ace->Mask); print_sid (" ", i, (PISID) &ace->SidStart); } } } }
void vncExportACL::PrintAce(int index, PACL acl) { ACE_HEADER *ace; TCHAR *type; PSID psid; if (!GetAce(acl, index, (void **) &ace)) { _tprintf(_T("DACL, entry %d: GetAce() failed, gle == %lu\n"), index, GetLastError()); return; } switch ( ace->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: type = _T("allow"); psid = &((ACCESS_ALLOWED_ACE *) ace)->SidStart; break; case ACCESS_DENIED_ACE_TYPE: type = _T("deny"); psid = &((ACCESS_DENIED_ACE *) ace)->SidStart; break; default: type = _T("invalid"); psid = &((ACCESS_ALLOWED_ACE *) ace)->SidStart; break; } _tprintf(_T("%s\t"), type); _tprintf(_T("0x%08lX\t"), ((ACCESS_ALLOWED_ACE *) ace)->Mask); PrintSid( psid ); }
void vncImportACL::ReadAce(int index, PACL pACL){ ACE_HEADER *ace; //char *type; //PSID psid; ACE_DATA * pACEdata; if (!GetAce( pACL, index, (void **) &ace)) { _ftprintf(stderr, _T("DACL, entry %d: GetAce() failed, gle == %lu\n"), index, GetLastError()); return; } pACEdata = new ACE_DATA; switch ( ace->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: pACEdata->type = ACCESS_ALLOWED; pACEdata->pSID = CopySID(&((ACCESS_ALLOWED_ACE *) ace)->SidStart); pACEdata->mask = ((ACCESS_ALLOWED_ACE *) ace)->Mask; pACEdata->next = lastAllowACE; lastAllowACE = pACEdata; break; case ACCESS_DENIED_ACE_TYPE: pACEdata->type = ACCESS_DENIED; pACEdata->pSID = CopySID(&((ACCESS_DENIED_ACE *) ace)->SidStart); pACEdata->mask = ((ACCESS_DENIED_ACE *) ace)->Mask; pACEdata->next = lastDenyACE; lastDenyACE = pACEdata; break; default: _ftprintf(stderr, _T("Error: Unknown ACE type\n")); delete pACEdata; break; } }
HRESULT COpcSecurity::CopyACL(PACL pDest, PACL pSrc) { ACL_SIZE_INFORMATION aclSizeInfo; LPVOID pAce; ACE_HEADER *aceHeader; if (pSrc == NULL) return S_OK; if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) return HRESULT_FROM_WIN32(GetLastError()); // Copy all of the ACEs to the new ACL for (UINT i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pSrc, i, &pAce)) return HRESULT_FROM_WIN32(GetLastError()); aceHeader = (ACE_HEADER *) pAce; if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; }
void DumpSD(PSECURITY_DESCRIPTOR pSD) { DWORD dwSize = GetSecurityDescriptorLength(pSD); printf("\nSecurity Descriptor is of size %d", dwSize); BOOL DaclPresent, DaclDefaulted; PACL pDacl; if(GetSecurityDescriptorDacl(pSD, &DaclPresent, &pDacl, &DaclDefaulted) && DaclPresent) { // Dump the aces ACL_SIZE_INFORMATION inf; DWORD dwNumAces; if(GetAclInformation( pDacl, &inf, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation )) { dwNumAces = inf.AceCount; printf("\nThe DACL has %d ACEs", dwNumAces); for(DWORD dwCnt = 0; dwCnt < dwNumAces; dwCnt++) { ACCESS_ALLOWED_ACE * pAce; if(GetAce(pDacl, dwCnt, (LPVOID *)&pAce)) DumpAce(pAce); } } } }
int registryLogAces(PACL pDacl) { int iReturnCode = EDT_OK; DWORD i = 0; LPVOID pAce = NULL; PACE_HEADER pAceheader=NULL; LOG_ENTER(); for(;i<pDacl->AceCount;i++) { GetAce(pDacl,i,&pAce); pAceheader = (PACE_HEADER)pAce; pAceheader->AceType; pAceheader->AceSize; LOG(L"-------------------\n",pAceheader->AceFlags); LOG(L"AceFlags are 0x%.2x\n",pAceheader->AceFlags); RegistryLogAceFlags(pAceheader->AceFlags); LOG(L"AceSize is 0x%.2x\n",pAceheader->AceSize); LOG(L"AceType is 0x%.2x\n",pAceheader->AceType); switch(pAceheader->AceType) { case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: //case SYSTEM_MANDATORY_LABEL_ACE: { PACCESS_ALLOWED_ACE pAccessAllowedAce = (PACCESS_ALLOWED_ACE)pAce; LOG(L"AceMask is 0x%.8x, this means access permissions are:\n",pAccessAllowedAce->Mask); RegistryLogAceMask(pAccessAllowedAce->Mask); LOG(L"The above access permissions are given to following SID'S:\n"); RegistryLogAceSidStart( &(pAccessAllowedAce->SidStart)); } break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE: { PACCESS_ALLOWED_OBJECT_ACE pAccessAllowedAce = (PACCESS_ALLOWED_OBJECT_ACE)pAce; LOG(L"AceMask is 0x%.8x, this means access permissions are:\n",pAccessAllowedAce->Mask); RegistryLogAceMask(pAccessAllowedAce->Mask); LOG(L"The above access permissions are given to following SID'S:\n"); RegistryLogAceSidStart( &(pAccessAllowedAce->SidStart)); } break; default: LOG_BASIC(L"AceType unknow\n"); LOG(L"Don't know the ACE type, cannot parse the ACE"); break; }; } LOG_EXIT(iReturnCode); return iReturnCode; }
// This goes through every ACE in 'acl', sums the size of the inheritable // ACEs, and puts it in dwSizeNeeded. HRESULT GetSizeOfAllInheritableAces(PACL acl, DWORD &dwSizeNeeded) { BOOL bResult; DWORD errorCode = S_OK; HRESULT hr = S_OK; ACL_SIZE_INFORMATION aclInformation; DWORD totalCount; LPVOID ace; BYTE aceFlags; if ( !ARGUMENT_PRESENT(acl) ) { return E_INVALIDARG; } bResult = GetAclInformation( acl, &aclInformation, sizeof(aclInformation), AclSizeInformation ); FailGracefullyGLE(bResult, L"GetAclInformation"); totalCount = aclInformation.AceCount; // Start with zero as the size. We'll only initialize this // to sizeof(ACL) if we find an inheritable ACE. dwSizeNeeded = 0; for ( DWORD aceIndex = 0; aceIndex < totalCount; aceIndex ++ ) { bResult = GetAce( acl, aceIndex, &ace ); FailGracefullyGLE(bResult, L"GetAce"); aceFlags = ((PACE_HEADER)ace)->AceFlags; // Only count the inheritable ACEs if (IsInheritableAce(aceFlags)) { // Initialize the size now that we've found an inheritable ACE if ( dwSizeNeeded == 0 ) { dwSizeNeeded = sizeof(ACL); } dwSizeNeeded += ((PACE_HEADER)ace)->AceSize; } } exit_gracefully: return hr; }
HRESULT RemoveAllInheritedAces(PACL *ppAcl) { BOOL bResult = FALSE; DWORD errorCode = S_OK; HRESULT hr = S_OK; ACL_SIZE_INFORMATION aclInformation; DWORD totalCount; DWORD aceIndex = 0; LPVOID ace = nullptr; BYTE aceFlags = 0; if ( !ARGUMENT_PRESENT(*ppAcl) ) { return E_INVALIDARG; } bResult = GetAclInformation( *ppAcl, &aclInformation, sizeof(aclInformation), AclSizeInformation ); FailGracefullyGLE(bResult, L"GetAclInformation"); totalCount = aclInformation.AceCount; while ( aceIndex < totalCount ) { bResult = GetAce( *ppAcl, aceIndex, &ace ); FailGracefullyGLE(bResult, L"GetAce"); aceFlags = ((PACE_HEADER)ace)->AceFlags; if (IS_FLAG_SET(aceFlags,INHERITED_ACE)) { bResult = DeleteAce( *ppAcl, aceIndex); FailGracefullyGLE(bResult, L"DeleteAce"); totalCount--; } else { aceIndex++; } } exit_gracefully: return hr; }
//Store the mask and username in the file_perms structure. //call lookup_sid to get the username void acl_info( PACL pACL, ULONG AceCount, file_perms fp[]){ for (ULONG acl_index = 0;acl_index < AceCount;acl_index++){ ACCESS_ALLOWED_ACE* pACE; if (GetAce(pACL, acl_index, (PVOID*)&pACE)) { char user_domain[2050]=""; lookup_sid(pACE,user_domain); strcpy(fp[acl_index].user_domain,user_domain); fp[acl_index].user_mask=(ULONG)pACE->Mask; } } }
/* * Returns JNI_TRUE if the specified owner is the only SID will access * to the file. */ static jboolean isAccessUserOnly(JNIEnv* env, SID* owner, ACL* acl) { ACL_SIZE_INFORMATION acl_size_info; DWORD i; /* * If there's no DACL then there's no access to the file */ if (acl == NULL) { return JNI_TRUE; } /* * Get the ACE count */ if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation)) { JNU_ThrowIOExceptionWithLastError(env, "GetAclInformation failed"); return JNI_FALSE; } /* * Iterate over the ACEs. For each "allow" type check that the SID * matches the owner, and check that the access is read only. */ for (i = 0; i < acl_size_info.AceCount; i++) { void* ace; ACCESS_ALLOWED_ACE *access; SID* sid; if (!GetAce(acl, i, &ace)) { JNU_ThrowIOExceptionWithLastError(env, "GetAce failed"); return -1; } if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) { continue; } access = (ACCESS_ALLOWED_ACE *)ace; sid = (SID *) &access->SidStart; if (!EqualSid(owner, sid)) { /* * If the ACE allows any access then the file is not secure. */ if (access->Mask & ANY_ACCESS) { return JNI_FALSE; } } } return JNI_TRUE; }
DWORD CopyACL( PACL OldACL, PACL NewACL) { ACL_SIZE_INFORMATION aclSizeInfo; LPVOID ace; ACE_HEADER *aceHeader; ULONG i; GetAclInformation( OldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation); // // Copy all of the ACEs to the new ACL // for (i = 0; i < aclSizeInfo.AceCount; i++) { // // Get the ACE and header info // if (!GetAce (OldACL, i, &ace)) { return GetLastError(); } aceHeader = (ACE_HEADER *) ace; // // Add the ACE to the new list // if (!AddAce( NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize)) { return GetLastError(); } } return ERROR_SUCCESS; }
void Process::fillAceList(){ ACL_SIZE_INFORMATION aclSizeInfo; ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); ACL_REVISION_INFORMATION aclRevisionInformation; ZeroMemory(&aclRevisionInformation,sizeof(ACL_REVISION_INFORMATION)); GetAclInformation( _dacl, (LPVOID)&aclRevisionInformation, sizeof(ACL_REVISION_INFORMATION), AclRevisionInformation); DWORD dwRtnCode = GetAclInformation(//Узнаем всю информацию о ACL. - Кол-во ACE в ней _dacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation); if (!dwRtnCode) throw(ProcessException("GetAclInformation error =",GetLastError())); PVOID pAce; for (DWORD i=0;i<aclSizeInfo.AceCount;++i){//По всем ACE if (GetAce(_dacl,i,&pAce)){ switch (((ACE_HEADER*)pAce)->AceType) { case ACCESS_ALLOWED_ACE_TYPE: _allowedACEs.push_back((ACCESS_ALLOWED_ACE*)pAce); break; case ACCESS_DENIED_ACE_TYPE: _deniedACEs.push_back((ACCESS_DENIED_ACE*)pAce); break; default: printf("Undefined type\n"); break; } }else throw(ProcessException("GetAce ERROR = ", GetLastError())); } }
HRESULT COpcSecurity::RemovePrincipalFromACL(PACL pAcl, LPCTSTR pszPrincipal) { ACL_SIZE_INFORMATION aclSizeInfo; ULONG i; LPVOID ace; ACCESS_ALLOWED_ACE *accessAllowedAce; ACCESS_DENIED_ACE *accessDeniedAce; SYSTEM_AUDIT_ACE *systemAuditAce; PSID principalSID; DWORD returnValue; ACE_HEADER *aceHeader; returnValue = GetPrincipalSID(pszPrincipal, &principalSID); if (FAILED(returnValue)) return returnValue; GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation); for (i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pAcl, i, &ace)) { free(principalSID); return HRESULT_FROM_WIN32(GetLastError()); } aceHeader = (ACE_HEADER *) ace; if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace; if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { accessDeniedAce = (ACCESS_DENIED_ACE *) ace; if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } else if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) { systemAuditAce = (SYSTEM_AUDIT_ACE *) ace; if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart)) { DeleteAce(pAcl, i); free(principalSID); return S_OK; } } } free(principalSID); return S_OK; }
void PrintPermissionsTok( PACL DACL) { DWORD dwCount=0; ACCESS_ALLOWED_ACE *ACE; // http://msdn2.microsoft.com/en-us/library/aa379142.aspx if(IsValidAcl(DACL) == TRUE){ fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +-+-> Default DACL for new objects created by this user\n"); // Now for each ACE in the DACL for(dwCount=0;dwCount<DACL->AceCount;dwCount++){ // http://msdn2.microsoft.com/en-us/library/aa446634.aspx // http://msdn2.microsoft.com/en-us/library/aa379608.aspx if(GetAce(DACL,dwCount,(LPVOID*)&ACE)){ // http://msdn2.microsoft.com/en-us/library/aa374892.aspx SID *sSID = (SID*)&(ACE->SidStart); if(sSID != NULL) { DWORD dwSize = 2048; char lpName[2048]; char lpDomain[2048]; SID_NAME_USE SNU; switch(ACE->Header.AceType){ // Allowed ACE case ACCESS_ALLOWED_ACE_TYPE: // Lookup the account name and print it. // http://msdn2.microsoft.com/en-us/library/aa379554.aspx if( !LookupAccountSidA( NULL, sSID, lpName, &dwSize, lpDomain, &dwSize, &SNU ) ) { DWORD dwResult = GetLastError(); if( dwResult == ERROR_NONE_MAPPED ){ fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +---+-> Allowed - NONMAPPED - SID %s\n", sidToTextTok(sSID)); } else if (dwResult != ERROR_NONE_MAPPED){ fprintf(stderr,"[!] LookupAccountSid Error %u\n", GetLastError()); fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +---+-> Allowed - ERROR - SID %s\n", sidToTextTok(sSID)); //return; } else { continue; } } else { fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +---+-> Allowed - %s\\%s\n",lpDomain,lpName); char strUserFromPID[1024]; memset(strUserFromPID,0x00,1024); if(!strcmp(lpDomain,"BUILTIN")==0 && !strcmp(lpName,"OWNER RIGHTS")==0 && !strcmp(lpDomain,"NT AUTHORITY")==0 && !strcmp(lpDomain,"NT SERVICE")==0) { fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +-+-+-> Alert!\n"); } } // print out the ACE mask fprintf(stdout,"[i] |\n"); fprintf(stdout,"[i] +-> Permissions - "); if(ACE->Mask & GENERIC_ALL) fprintf(stdout,",All"); if(ACE->Mask & GENERIC_EXECUTE) fprintf(stdout,",Execute"); if(ACE->Mask & GENERIC_READ) fprintf(stdout,",Read"); if(ACE->Mask & GENERIC_WRITE) fprintf(stdout,",Write"); if(ACE->Mask & DELETE) fprintf(stdout,",Delete"); if(ACE->Mask & READ_CONTROL) fprintf(stdout,",Read control"); if(ACE->Mask & SYNCHRONIZE) fprintf(stdout,",Sync"); if(ACE->Mask & WRITE_DAC) fprintf(stdout,",Modify DACL"); if(ACE->Mask & WRITE_OWNER) fprintf(stdout,",Write Owner"); if(ACE->Mask & STANDARD_RIGHTS_ALL) fprintf(stdout,",All"); if(ACE->Mask & STANDARD_RIGHTS_EXECUTE) fprintf(stdout,",Execute"); if(ACE->Mask & STANDARD_RIGHTS_READ) fprintf(stdout,",Read Control"); if(ACE->Mask & STANDARD_RIGHTS_REQUIRED) fprintf(stdout,",Write"); if(ACE->Mask & STANDARD_RIGHTS_WRITE) fprintf(stdout,",Read Control"); fprintf(stdout,"\n"); break; // Denied ACE case ACCESS_DENIED_ACE_TYPE: break; // Uh oh default: break; } } } else { DWORD dwError = GetLastError(); fprintf(stderr,"[!] Error - %d - GetAce\n", dwError); return; } } } else { DWORD dwError = GetLastError(); fprintf(stderr,"[!] Error - %d - IsValidAcl\n", dwError); return; } }
HRESULT COpcSecurity::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) { PACL pDACL = NULL; PACL pSACL = NULL; BOOL bDACLPresent, bSACLPresent; BOOL bDefaulted; PACL m_pDACL = NULL; ACCESS_ALLOWED_ACE* pACE; HRESULT hr; PSID pUserSid; PSID pGroupSid; hr = Initialize(); if(FAILED(hr)) return hr; // get the existing DACL. if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) goto failed; if (bDACLPresent) { if (pDACL) { // allocate new DACL. m_pDACL = (PACL) malloc(pDACL->AclSize); if (m_pDACL == NULL) { hr = E_OUTOFMEMORY; goto failedMemory; } // initialize the DACL if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) goto failed; // copy the ACES for (int i = 0; i < pDACL->AceCount; i++) { if (!GetAce(pDACL, i, (void **)&pACE)) goto failed; if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; } if (!IsValidAcl(m_pDACL)) goto failed; } // set the DACL if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted)) goto failed; } // get the existing SACL. if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) goto failed; if (bSACLPresent) { if (pSACL) { // allocate new SACL. m_pSACL = (PACL) malloc(pSACL->AclSize); if (m_pSACL == NULL) { hr = E_OUTOFMEMORY; goto failedMemory; } // initialize the SACL if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) goto failed; // copy the ACES for (int i = 0; i < pSACL->AceCount; i++) { if (!GetAce(pSACL, i, (void **)&pACE)) goto failed; if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; } if (!IsValidAcl(m_pSACL)) goto failed; } // set the SACL if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted)) goto failed; } if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted)) goto failed; if (FAILED(SetOwner(pUserSid, bDefaulted))) goto failed; if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted)) goto failed; if (FAILED(SetGroup(pGroupSid, bDefaulted))) goto failed; if (!IsValidSecurityDescriptor(m_pSD)) goto failed; return hr; failed: hr = HRESULT_FROM_WIN32(hr); failedMemory: if (m_pDACL) { free(m_pDACL); m_pDACL = NULL; } if (m_pSD) { free(m_pSD); m_pSD = NULL; } return hr; }
/*---------------------------------------------------------------------------*\ * NAME: ListACL * * --------------------------------------------------------------------------* * DESCRIPTION: \*---------------------------------------------------------------------------*/ void ListACL ( PACL Acl, DWORD dwSDType ) { ACL_SIZE_INFORMATION aclSizeInfo = {0}; ACL_REVISION_INFORMATION aclRevInfo = {0}; ULONG i; LPVOID pvAce = NULL; ACE_HEADER *pAceHeader = NULL; ACCESS_ALLOWED_ACE *pAccessAllowedAce = NULL; ACCESS_DENIED_ACE *pAccessDeniedAce = NULL; TCHAR tszDomainName [SIZE_NAME_BUFFER] = {0}; TCHAR tszUserName [SIZE_NAME_BUFFER] = {0}; DWORD cchName = 0; SID_NAME_USE snu; if (!GetAclInformation (Acl, &aclSizeInfo, sizeof (ACL_SIZE_INFORMATION), AclSizeInformation)) { _tprintf (_T("Could not get AclSizeInformation")); return; } if (!GetAclInformation (Acl, &aclRevInfo, sizeof (ACL_REVISION_INFORMATION), AclRevisionInformation)) { _tprintf (_T("Could not get AclRevisionInformation")); return; } for (i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce (Acl, i, &pvAce)) return; pAceHeader = (ACE_HEADER *) pvAce; if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { pAccessAllowedAce = (ACCESS_ALLOWED_ACE *) pvAce; cchName = SIZE_NAME_BUFFER-1; LookupAccountSid (NULL, &pAccessAllowedAce->SidStart, tszUserName, &cchName, tszDomainName, &cchName, &snu); DisplayAccess(pAccessAllowedAce->Mask, dwSDType, _T("permitted"), tszUserName, tszDomainName); } else if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { pAccessDeniedAce = (ACCESS_DENIED_ACE *) pvAce; cchName = SIZE_NAME_BUFFER-1; LookupAccountSid (NULL, &pAccessDeniedAce->SidStart, tszUserName, &cchName, tszDomainName, &cchName, &snu); DisplayAccess(pAccessDeniedAce->Mask, dwSDType, _T("denied"), tszUserName, tszDomainName); } } }
bool CSecRunAsUser::SetObjectPermission(CString strDirFile, DWORD lGrantedAccess){ if (!m_hADVAPI32_DLL){ ASSERT ( false ); return false; } if ( strDirFile.IsEmpty() ) return true; SID_NAME_USE snuType; TCHAR* szDomain = NULL; LPVOID pUserSID = NULL; PACL pNewACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; BOOL fAPISuccess; try { // get user sid DWORD cbDomain = 0; DWORD cbUserSID = 0; fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if ( (!fAPISuccess) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName() failed,")); pUserSID = MHeapAlloc(cbUserSID); if (!pUserSID) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); szDomain = (TCHAR*)MHeapAlloc(cbDomain * sizeof(TCHAR)); if (!szDomain) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if (!fAPISuccess) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName()2 failed")); if (CStringW(szDomain) != m_strDomain) throw CString(_T("Run as unpriveleged user: Logical Error: Domainname mismatch")); // get old ACL PACL pOldACL = NULL; fAPISuccess = GetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldACL, NULL, &pSD); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS){ throw CString(_T("Run as unpriveleged user: Error: GetNamedSecurityInfo() failed")); } // calculate size for new ACL ACL_SIZE_INFORMATION AclInfo; AclInfo.AceCount = 0; // Assume NULL DACL. AclInfo.AclBytesFree = 0; AclInfo.AclBytesInUse = sizeof(ACL); if (pOldACL != NULL && !GetAclInformation(pOldACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) throw CString(_T("Run as unpriveleged user: Error: GetAclInformation() failed")); // Create new ACL DWORD cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - sizeof(DWORD); pNewACL = (PACL)MHeapAlloc(cbNewACL); if (!pNewACL) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); // copy the entries form the old acl into the new one and enter a new ace in the right order uint32 newAceIndex = 0; uint32 CurrentAceIndex = 0; if (AclInfo.AceCount) { for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce() failed,")); if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags & INHERITED_ACE) break; // no multiple entries if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) continue; if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()1 failed,")); newAceIndex++; } } // here we add the actually entry if (!AddAccessAllowedAceEx(pNewACL, ACL_REVISION2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, lGrantedAccess, pUserSID)) throw CString(_T("Run as unpriveleged user: Error: AddAccessAllowedAceEx() failed,")); // copy the rest if (AclInfo.AceCount) { for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce()2 failed,")); if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()2 failed,")); } } fAPISuccess = SetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS) throw CString(_T("Run as unpriveleged user: Error: SetNamedSecurityInfo() failed,")); fAPISuccess = TRUE; } catch(CString error){ fAPISuccess = FALSE; theApp.QueueDebugLogLine(false, error); } // clean up if (pUserSID != NULL) MHeapFree(pUserSID); if (szDomain != NULL) MHeapFree(szDomain); if (pNewACL != NULL) MHeapFree(pNewACL); if (pSD != NULL) LocalFree(pSD); // finished return fAPISuccess!=FALSE; }
/** * This function adjusts the specified WindowStation to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { ACCESS_ALLOWED_ACE *pace = NULL; ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the DACL for the window station. if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; // Create a new DACL. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Get the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize the ACL. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if the DACL is not NULL. if (pacl != NULL) { // get the file ACL size info if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD)); // Allocate memory for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new DACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add the first ACE to the window station. pace = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD) ); if (pace == NULL) throw; pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pace->Header.AceSize = (WORD)sizeof(ACCESS_ALLOWED_ACE) + (WORD)GetLengthSid(psid) - (WORD)sizeof(DWORD); pace->Mask = GENERIC_ALL; if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid)) throw; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Add an ACE to the window station. pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = GENERIC_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free the allocated buffers. if (pace != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pace); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse + (2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD)); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { LPVOID pTempAce; if (!GetAce(pacl, i, &pTempAce)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Add the first ACE to the window station. auto_buffer<ACCESS_ALLOWED_ACE*> ace(sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; ace->Header.AceSize = (WORD) (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Mask = GENERIC_ACCESS; if (!CopySid(GetLengthSid(psid), &ace->SidStart, psid)) { printf("CopySid() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Add the second ACE to the window station. ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; ace->Mask = WINSTA_ALL; if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
BOOL GetProcessIntegrityLevel( HANDLE hProcess, PDWORD pIntegrityLevel, PDWORD pPolicy, PDWORD pResourceIntegrityLevel, PDWORD pResourcePolicy) { HANDLE hToken = NULL; /* The OpenProcessToken function opens the access token associated with a process. * ProcessHandle [in] * A handle to the process whose access token is opened. * The process must have the PROCESS_QUERY_INFORMATION access permission. * DesiredAccess [in] * Specifies an access mask that specifies the requested types * of access to the access token. These requested access types * are compared with the discretionary access control list (DACL) * of the token to determine which accesses are granted or denied. */ if (!OpenProcessToken(hProcess, TOKEN_READ, &hToken)) { return(FALSE); } BOOL bReturn = FALSE; /* First, compute the size of the buffer to get the Integrity level */ DWORD dwNeededSize = 0; /* The GetTokenInformation function retrieves a specified type * of information about an access token. The calling process must have appropriate * access rights to obtain the information. */ if (!GetTokenInformation( hToken, TokenIntegrityLevel, NULL, 0, &dwNeededSize)) { PTOKEN_MANDATORY_LABEL pTokenInfo = NULL; if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { /* Second, allocate a memory block with the the required size */ pTokenInfo = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwNeededSize); if (pTokenInfo != NULL) { /* And finally, ask for the integrity level */ if (GetTokenInformation( hToken, TokenIntegrityLevel, pTokenInfo, dwNeededSize, &dwNeededSize)) { /* The GetSidSubAuthority function returns a pointer to a * specified subauthority in a security identifier (SID). * The subauthority value is a relative identifier (RID). * pSid [in] * A pointer to the SID structure from which a pointer * to a subauthority is to be returned. * This function does not handle SID structures that are not valid. * Call the IsValidSid function to verify that the SID structure * is valid before you call this function. * nSubAuthority [in] * Specifies an index value identifying the subauthority array * element whose address the function will return. * The function performs no validation tests on this value. * An application can call the GetSidSubAuthorityCount function * to discover the range of acceptable values. * Return value: * If the function succeeds, the return value is a pointer * to the specified SID subauthority. To get extended error information, * call GetLastError. */ /* Exaplanation for GetSidSubAuthorityCount function * The GetSidSubAuthorityCount function returns a pointer * to the member in a security identifier (SID) structure * that contains the subauthority count. * pSid [in] * A pointer to the SID structure from which a pointer * to the subauthority count is returned. * This function does not handle SID structures that are not valid. * Call the IsValidSid function to verify that the SID structure * is valid before you call this function. * */ *pIntegrityLevel = *GetSidSubAuthority( pTokenInfo->Label.Sid, (*GetSidSubAuthorityCount(pTokenInfo->Label.Sid)-1) ); bReturn = TRUE; } /* Don't forget to free the memory */ LocalFree(pTokenInfo); } } } /* Try to get the policy if the integrity level was available */ if (bReturn) { *pPolicy = TOKEN_MANDATORY_POLICY_OFF; dwNeededSize = sizeof(DWORD); GetTokenInformation( hToken, TokenMandatoryPolicy, pPolicy, dwNeededSize, &dwNeededSize); } /* Look for the resource policy */ *pResourceIntegrityLevel = 0; /* 0 means none explicitely set */ *pResourcePolicy = 0; PACL pSACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwResult = ERROR_SUCCESS; /* Look for the no-read-up/no-write-up policy in the SACL */ if (hToken != NULL) { /* The GetSecurityInfo function retrieves a copy of the * security descriptor for an object specified by a handle. * handle [in] * A handle to the object from which to retrieve security information. * ObjectType [in] * SE_OBJECT_TYPE enumeration value that indicates the type of object. * SecurityInfo [in] * A set of bit flags that indicate the type of security information to retrieve. * This parameter can be a combination of the SECURITY_INFORMATION bit flags. * ppsidOwner [out, optional] * A pointer to a variable that receives a pointer to the owner SID * in the security descriptor returned in ppSecurityDescriptor. * The returned pointer is valid only if you set the OWNER_SECURITY_INFORMATION flag. * This parameter can be NULL if you do not need the owner SID. * * */ dwResult = GetSecurityInfo( hProcess, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &pSACL, &pSD ); if (dwResult == ERROR_SUCCESS) { if (pSACL != NULL) { SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL; /* The GetAce function obtains a pointer to an access control entry (ACE) * in an access control list (ACL). * pAcl [in] * A pointer to an ACL that contains the ACE to be retrieved. * dwAceIndex [in] * The index of the ACE to be retrieved. * A value of zero corresponds to the first ACE in the ACL, * a value of one to the second ACE, and so on. * pAce [out] * A pointer to a pointer that the function sets to the address of the ACE. * */ if ((pSACL->AceCount > 0) && (GetAce(pSACL, 0, (PVOID*)&pACE))) { if (pACE != NULL) { SID* pSID = (SID*)(&pACE->SidStart); *pResourceIntegrityLevel = pSID->SubAuthority[0]; *pResourcePolicy = pACE->Mask; } } } } /* Cleanup memory allocated on our behalf */ if (pSD != NULL) LocalFree(pSD); } /* Don't forget to close the token handle. */ CloseHandle(hToken); return(bReturn); }
JNIEXPORT void JNICALL Java_com_microsoft_tfs_jni_internal_filesystem_NativeFileSystem_nativeRemoveExplicitAllowEntries( JNIEnv *env, jclass cls, jstring jPath, jstring jUserSIDString) { const WCHAR * path = NULL; const WCHAR * userSIDString = NULL; PSID userSID = NULL; DWORD result = 0; PACL dacl = NULL; PSECURITY_DESCRIPTOR securityDescriptor = NULL; ACL_SIZE_INFORMATION aclSizeInfo; ULONG aceCount = 0; BOOL modifiedDACL = FALSE; if (jPath == NULL) { throwRuntimeExceptionString(env, "path must not be null"); goto cleanup; } if (jUserSIDString == NULL) { throwRuntimeExceptionString(env, "user must not be null"); goto cleanup; } // Convert the SID string to a struct if ((userSIDString = javaStringToPlatformChars(env, jUserSIDString)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } if (ConvertStringSidToSidW(userSIDString, &userSID) == FALSE) { throwRuntimeExceptionCode(env, GetLastError(), "Error converting string sid %S to sid", userSIDString); goto cleanup; } if ((path = javaStringToPlatformChars(env, jPath)) == NULL) { // String allocation failed, exception already thrown goto cleanup; } // Get file's DACL result = GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, &securityDescriptor); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error getting file security info for %S", path); goto cleanup; } // Get the count of entries int the DACL if (GetAclInformation(dacl, &aclSizeInfo, sizeof(aclSizeInfo), AclSizeInformation) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error getting DACL"); goto cleanup; } // Loop over the DACL backwards, removing matching entries for (aceCount = aclSizeInfo.AceCount; aceCount > 0; aceCount--) { ULONG aceIndex = aceCount - 1; ACCESS_ALLOWED_ACE * ace = NULL; PSID sid = NULL; if (GetAce(dacl, aceIndex, (LPVOID *) &ace) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error getting ACE at index %d", aceIndex); goto cleanup; } // Skip inherited (non-explicit) entries if ((((ACE_HEADER *) ace)->AceFlags & INHERITED_ACE) == INHERITED_ACE) { continue; } // Extract the SID for "allow" types switch(((ACE_HEADER *) ace)->AceType) { case ACCESS_ALLOWED_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_CALLBACK_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE *) ace)->SidStart; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: sid = (PSID) &((ACCESS_ALLOWED_OBJECT_ACE *) ace)->SidStart; break; default: // These are "deny" or other entries break; } if (sid != NULL && EqualSid(sid, userSID)) { if (DeleteAce(dacl, aceIndex) == 0) { throwRuntimeExceptionCode(env, GetLastError(), "Error deleting ACE at index %d", aceIndex); goto cleanup; } modifiedDACL = TRUE; } // Nothing to free in the loop, all pointers are into dacl } if (modifiedDACL) { result = SetNamedSecurityInfo((WCHAR *) path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, dacl, NULL); if (result != ERROR_SUCCESS) { throwRuntimeExceptionCode(env, result, "Error setting security info for %S", path); goto cleanup; } } cleanup: if (path != NULL) { releasePlatformChars(env, jPath, path); } if (userSID != NULL) { LocalFree(userSID); } if (userSIDString != NULL) { releasePlatformChars(env, jUserSIDString, userSIDString); } // dacl points inside securityDescriptor if (securityDescriptor != NULL) { LocalFree(securityDescriptor); } }
/** * @brief * perm_granted_admin_and_name: returns 0 if permission mask in 'disallow' has * been granted to only admin-type of accounts and 'owner'. 'owner' can be * set to NULL. Otherwise, it will return the values EPERM or EACCESS with * error message returned in 'errmsg'. */ int perm_granted_admin_and_owner(char *path, int disallow, char *owner, char *errmsg) { int rc; DWORD i, j; SID *powner = NULL; char *powner_s = NULL; ACL *pdacl = NULL; SECURITY_DESCRIPTOR *psd = NULL; ACL_SIZE_INFORMATION sizeInfo; ACCESS_ALLOWED_ACE *pace; int violate = 0; struct accessinfo *allowed = NULL; struct accessinfo *denied = NULL; int mask; char *name; SID *esid = getusersid("Everyone"); if (GetNamedSecurityInfo(path, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, &powner, 0, &pdacl, 0, &psd) != ERROR_SUCCESS) { errno = GetLastError(); rc = errno; sprintf(errmsg, "GetNameSecurityInfo on file %s failed", path); goto chkerr; } /* is owner SID a privilege user? */ powner_s = getusername(powner); if (powner_s == NULL) powner_s = getgrpname(powner); if (powner_s != NULL) { if ( !sidIsAdminPrivilege(powner) || \ ( (owner != NULL) && strcmp(owner, powner_s) != 0 ) ) { rc = EPERM; sprintf(errmsg, "File %s not owned by user %s or an admin-type user!", path, owner); goto chkerr; } } /* make sure perm mask granted only to privilege groups or the special 'owner' */ GetAclInformation(pdacl, &sizeInfo, sizeof(sizeInfo), AclSizeInformation); allowed = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); denied = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); if (allowed == NULL || denied == NULL) { rc = errno; strcpy(errmsg, "malloc of allowed or denied struct failed!"); goto chkerr; } accessinfo_init(allowed, sizeInfo.AceCount); accessinfo_init(denied, sizeInfo.AceCount); for (i=0; i < sizeInfo.AceCount; i++) { GetAce(pdacl, i, (void **)&pace); name = getgrpname_full((SID *)&pace->SidStart); if (name == NULL) name = getusername((SID *)&pace->SidStart); /* later, we need to also check denied access which */ /* overrides allowed access. */ if ( pace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE &&\ (mask=(pace->Mask & disallow)) && \ ( EqualSid((SID *)&pace->SidStart, esid) || \ sid2rid((SID *)&pace->SidStart) != \ SECURITY_CREATOR_OWNER_RID ) && \ (!sidIsAdminPrivilege( (SID *)&pace->SidStart)) || \ ((owner != NULL) && strcmp(name, owner) != 0) ) { (void)accessinfo_add(allowed, sizeInfo.AceCount, name, (mask & 0xFFFF)); } else if (pace->Header.AceType == ACCESS_DENIED_ACE_TYPE) { (void)accessinfo_add(denied, sizeInfo.AceCount, name, (pace->Mask & 0xFFFF)); } else { if (name) { (void)free(name); } } } /* validate */ for (i=0; i < sizeInfo.AceCount; i++) { for (j=0; j < sizeInfo.AceCount; j++) { if( allowed[i].group == NULL || \ denied[j].group == NULL ) continue; if (strcmp(allowed[i].group, denied[j].group) == 0) allowed[i].mask &= ~denied[j].mask; /* unset the denied mask from allowed */ } } if (!accessinfo_mask_allzero(allowed, sizeInfo.AceCount)) { rc = EACCES; sprintf(errmsg, "File %s has following disallowed perm masks: ", path); strcat(errmsg, accessinfo_values(allowed, sizeInfo.AceCount)); goto chkerr; } rc = 0; chkerr: if (powner_s)(void)free(powner_s); /* NOTE: powner and pdacl hang off of psd, so a free of psd would */ /* automatically free them */ if (psd) LocalFree(psd); if (allowed) accessinfo_free(allowed, sizeInfo.AceCount); if (denied) accessinfo_free(denied, sizeInfo.AceCount); if (esid) LocalFree(esid); return (rc); }
static BOOL new_acl(SaveAclStruct *save_acl){ HANDLE tokenh; TOKEN_DEFAULT_DACL newdacl; DWORD required; PACL oldacl; PACL newacl; int i; ACL_SIZE_INFORMATION si; size_t newsize; PSID extra_sid; SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY; TOKEN_DEFAULT_DACL dummy; save_acl->initialized = FALSE; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_READ|TOKEN_WRITE,&tokenh)){ log_warning("Failed to open access token."); return FALSE; } save_acl->defdacl = &dummy; required = sizeof(TOKEN_DEFAULT_DACL); GetTokenInformation(tokenh, TokenDefaultDacl, &(save_acl->defdacl), sizeof(TOKEN_DEFAULT_DACL), &required); if(required == 0){ log_warning("Failed to get any ACL info from token."); CloseHandle(tokenh); return FALSE; } save_acl->defdacl = LocalAlloc(LPTR,required); if(!GetTokenInformation(tokenh, TokenDefaultDacl, save_acl->defdacl, required, &required)){ #ifdef HARDDEBUG { char *mes; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &mes, 0, NULL ); log_info(mes); LocalFree(mes); } #endif log_warning("Failed to get default ACL from token."); CloseHandle(tokenh); return FALSE; } oldacl = save_acl->defdacl->DefaultDacl; if(!GetAclInformation(oldacl, &si, sizeof(si), AclSizeInformation)){ log_warning("Failed to get size information for ACL"); CloseHandle(tokenh); return FALSE; } if(!AllocateAndInitializeSid(&nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &extra_sid)){ log_warning("Failed to initialize administrator SID."); CloseHandle(tokenh); return FALSE; } newsize = si.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(extra_sid); newacl = LocalAlloc(LPTR,newsize); if(!InitializeAcl(newacl, newsize, ACL_REVISION)){ log_warning("Failed to initialize new ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } for(i=0;i<((int)si.AceCount);++i){ ACE_HEADER *ace_header; if (!GetAce (oldacl, i, &ace_header)){ log_warning("Failed to get ACE from old ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } if(!AddAce(newacl,ACL_REVISION,0xffffffff,ace_header, ace_header->AceSize)){ log_warning("Failed to set ACE in new ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } } if(!AddAccessAllowedAce(newacl, ACL_REVISION2, PROCESS_ALL_ACCESS, extra_sid)){ log_warning("Failed to add system ACE to new ACL."); LocalFree(newacl); FreeSid(extra_sid); return FALSE; } newdacl.DefaultDacl = newacl; if(!SetTokenInformation(tokenh, TokenDefaultDacl, &newdacl, sizeof(newdacl))){ log_warning("Failed to set token information"); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } save_acl->initialized = TRUE; save_acl->newacl = newacl; save_acl->adminsid = extra_sid; CloseHandle(tokenh); return TRUE; }
// // get_permissions: 1 = yes, 0 = no, -1 = unknown/error // int perm::get_permissions( const char *file_name, ACCESS_MASK &AccessRights ) { DWORD retVal; PACL pacl; PSECURITY_DESCRIPTOR pSD; DWORD pSD_length = 0; DWORD pSD_length_needed = 0; BOOL acl_present = FALSE; BOOL acl_defaulted = FALSE; // Do the call first to find out how much space is needed. pSD = NULL; GetFileSecurity( file_name, // address of string for file name DACL_SECURITY_INFORMATION, // requested information pSD, // address of security descriptor pSD_length, // size of security descriptor buffer &pSD_length_needed // address of required size of buffer ); if( pSD_length_needed <= 0 ) { // Find out how much space is needed, if <=0 then error if ( (GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND) ) { // Here we have the tricky part of walking up the directory path // Typically it works like this: If the filename exists, great, we'll // get the permissions on that. If the filename does not exist, then // we pop the filename part off the file_name and look at the // directory. If that directory should be (for some odd reason) non- // existant, then we just pop that off, until either we find something // thats will give us a permissions bitmask, or we run out of places // to look (which shouldn't happen since c:\ should always give us // SOMETHING... int i = strlen( file_name ) - 1; while ( i >= 0 && ( file_name[i] != '\\' && file_name[i] != '/' ) ) { i--; } if ( i < 0 ) { // We've nowhere else to look, and this is bad. return -1; // Its not a no, its an unknown } char *new_file_name = new char[i+1]; strncpy(new_file_name, file_name, i); new_file_name[i]= '\0'; // Now that we've chopped off more of the filename, call get_permissions // again... retVal = get_permissions( new_file_name, AccessRights ); delete[] new_file_name; // ... and return what it returns. (after deleting the string that was // allocated. return retVal; } dprintf(D_ALWAYS, "perm::GetFileSecurity failed (err=%d)\n", GetLastError()); return -1; } pSD_length = pSD_length_needed + 2; // Add 2 for safety. pSD_length_needed = 0; pSD = new BYTE[pSD_length]; // Okay, now that we've found something, and know how large of an SD we need, // call the thing for real and lets get ON WITH IT ALREADY... if( !GetFileSecurity( file_name, // address of string for file name DACL_SECURITY_INFORMATION, // requested information pSD, // address of security descriptor pSD_length, // size of security descriptor buffer &pSD_length_needed // address of required size of buffer ) ) { dprintf(D_ALWAYS, "perm::GetFileSecurity(%s) failed (err=%d)\n", file_name, GetLastError()); delete[] pSD; return -1; } // Now, get the ACL from the security descriptor if( !GetSecurityDescriptorDacl( pSD, // address of security descriptor &acl_present, // address of flag for presence of disc. ACL &pacl, // address of pointer to ACL &acl_defaulted // address of flag for default disc. ACL ) ) { dprintf(D_ALWAYS, "perm::GetSecurityDescriptorDacl failed (file=%s err=%d)\n", file_name, GetLastError()); delete[] pSD; return -1; } // This is the workaround for the broken API GetEffectiveRightsFromAcl(). // It should be guaranteed to work on all versions of NT and 2000 but be aware // that nested global group permissions are not supported. // C. Stolley - June 2001 ACL_SIZE_INFORMATION acl_info; // Structure contains the following members: // DWORD AceCount; // DWORD AclBytesInUse; // DWORD AclBytesFree; // first get the number of ACEs in the ACL if (! GetAclInformation( pacl, // acl to get info from &acl_info, // buffer to receive info sizeof(acl_info), // size in bytes of buffer AclSizeInformation // class of info to retrieve ) ) { dprintf(D_ALWAYS, "Perm::GetAclInformation failed with error %d\n", GetLastError() ); return -1; } ACCESS_MASK allow = 0x0; ACCESS_MASK deny = 0x0; unsigned int aceCount = acl_info.AceCount; int result; // now look at each ACE in the ACL and see if it contains the user we're looking for for (unsigned int i=0; i < aceCount; i++) { LPVOID current_ace; if (! GetAce( pacl, // pointer to ACL i, // index of ACE we want ¤t_ace // pointer to ACE ) ) { dprintf(D_ALWAYS, "Perm::GetAce() failed! Error code %d\n", GetLastError() ); return -1; } dprintf(D_FULLDEBUG, "Calling Perm::userInAce() for %s\\%s\n", (Domain_name) ? Domain_name : "NULL", (Account_name) ? Account_name : "NULL" ); result = userInAce ( current_ace, Account_name, Domain_name ); if (result == 1) { switch ( ( (PACE_HEADER) current_ace)->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: allow |= ( (ACCESS_ALLOWED_ACE*) current_ace)->Mask; break; case ACCESS_DENIED_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: deny |= ( (ACCESS_DENIED_ACE*) current_ace)->Mask; break; } } } AccessRights = allow; AccessRights &= ~deny; // and now if we've made this far everything's happy so return true return 1; }
BOOL RemoveAceFromWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse - ((2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD))); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
/** * This function adjusts the specified Desktop to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToDesktop(HDESK hdesk, PSID psid) { ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the security descriptor for the desktop object. if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded ); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; } // Create a new security descriptor. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Obtain the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if NULL DACL. if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD); // Allocate buffer for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new ACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add ACE to the DACL. if (!AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL, psid) ) throw; // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free buffers. if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
BOOL RemoveAceFromDesktop(HDESK hdesk, PSID psid) { // Obtain the security descriptor for the desktop object. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_size = 0; if (!GetUserObjectSecurity(hdesk, &si, NULL, 0, &sd_size)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_size); if (!GetUserObjectSecurity(hdesk, &si, psd.get(), sd_size, &sd_size)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new security descriptor. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_size); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Obtain the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation(pacl, (LPVOID)&aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Allocate buffer for the new ACL. DWORD dwNewAclSize = aclSizeInfo.AclBytesInUse - (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); auto_buffer<PACL> new_acl(dwNewAclSize); // Initialize the new ACL. if (!InitializeAcl(new_acl.get(), dwNewAclSize, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { // Get an ACE. ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { // Add the ACE to the new ACL. if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
DWORD RemovePrincipalFromACL ( PACL Acl, LPTSTR Principal ) { ACL_SIZE_INFORMATION aclSizeInfo; ULONG i; LPVOID ace; ACCESS_ALLOWED_ACE *accessAllowedAce; ACCESS_DENIED_ACE *accessDeniedAce; SYSTEM_AUDIT_ACE *systemAuditAce; PSID principalSID; DWORD returnValue; ACE_HEADER *aceHeader; returnValue = GetPrincipalSID (Principal, &principalSID); if (returnValue != ERROR_SUCCESS) return returnValue; GetAclInformation (Acl, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation); for (i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce (Acl, i, &ace)) { free (principalSID); return GetLastError(); } aceHeader = (ACE_HEADER *) ace; if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace; if (EqualSid (principalSID, (PSID) &accessAllowedAce->SidStart)) { DeleteAce (Acl, i); free (principalSID); return ERROR_SUCCESS; } } else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { accessDeniedAce = (ACCESS_DENIED_ACE *) ace; if (EqualSid (principalSID, (PSID) &accessDeniedAce->SidStart)) { DeleteAce (Acl, i); free (principalSID); return ERROR_SUCCESS; } } else if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE) { systemAuditAce = (SYSTEM_AUDIT_ACE *) ace; if (EqualSid (principalSID, (PSID) &systemAuditAce->SidStart)) { DeleteAce (Acl, i); free (principalSID); return ERROR_SUCCESS; } } } free (principalSID); return ERROR_SUCCESS; }
int perm_granted(char *path, int perm_mask, char *user, char *realuser) { int rc; DWORD i, j; ACL *pdacl = NULL; SECURITY_DESCRIPTOR *psd = NULL; ACL_SIZE_INFORMATION sizeInfo; ACCESS_ALLOWED_ACE *pace; struct accessinfo *allowed = NULL; struct accessinfo *denied = NULL; int mask; char *name; SID *usid; if (GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, &pdacl, 0, &psd) != ERROR_SUCCESS) { errno = GetLastError(); rc = 1; goto perm_chkerr; } usid = getusersid2(user, realuser); if (usid == NULL) { rc = 2; goto perm_chkerr; } /* make sure perm mask granted only to privilege groups or the special 'owner' */ GetAclInformation(pdacl, &sizeInfo, sizeof(sizeInfo), AclSizeInformation); allowed = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); denied = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); if (allowed == NULL || denied == NULL) { rc = 3; goto perm_chkerr; } accessinfo_init(allowed, sizeInfo.AceCount); accessinfo_init(denied, sizeInfo.AceCount); for (i=0; i < sizeInfo.AceCount; i++) { GetAce(pdacl, i, (void **)&pace); name = getgrpname_full((SID *)&pace->SidStart); if (name == NULL) name = getusername((SID *)&pace->SidStart); /* later, we need to also check denied access which */ /* overrides allowed access. */ if ( (pace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) && \ (mask=(pace->Mask & perm_mask)) && \ EqualSid((SID *)&pace->SidStart, usid) ) { (void)accessinfo_add(allowed, sizeInfo.AceCount, name, (mask & 0xFFFF)); } else if (pace->Header.AceType == ACCESS_DENIED_ACE_TYPE) { (void)accessinfo_add(denied, sizeInfo.AceCount, name, (pace->Mask & 0xFFFF)); } else { if (name) { (void)free(name); } } } /* filter the allowed pool so that none appear in denied */ for (i=0; i < sizeInfo.AceCount; i++) { for (j=0; j < sizeInfo.AceCount; j++) { if( allowed[i].group == NULL || \ denied[j].group == NULL ) continue; if (strcmp(allowed[i].group, denied[j].group) == 0) allowed[i].mask &= ~denied[j].mask; /* unset the denied mask from allowed */ } } /* now filter perm_mask to those specified in allowed */ for (i=0; i < sizeInfo.AceCount; i++) { if (allowed[i].group == NULL) continue; /* unset the allowed mask from perm_mask */ perm_mask &= ~allowed[i].mask; } if (perm_mask != 0) { rc = 4; goto perm_chkerr; } rc = 0; perm_chkerr: if (pdacl) LocalFree(pdacl); if (psd) LocalFree(psd); if (allowed) accessinfo_free(allowed, sizeInfo.AceCount); if (denied) accessinfo_free(denied, sizeInfo.AceCount); if (usid) LocalFree(usid); return (rc); }
static int TestplatformChmod( const char *nativePath, int pmode) { static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | DELETE; /* * References to security functions (only available on NT and later). */ const BOOL set_readOnly = !(pmode & 0222); BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted; SID_IDENTIFIER_AUTHORITY userSidAuthority = { SECURITY_WORLD_SID_AUTHORITY }; BYTE *secDesc = 0; DWORD secDescLen, attr, newAclSize; ACL_SIZE_INFORMATION ACLSize; PACL curAcl, newAcl = 0; WORD j; SID *userSid = 0; char *userDomain = 0; int res = 0; /* * Process the chmod request. */ attr = GetFileAttributesA(nativePath); /* * nativePath not found */ if (attr == 0xffffffff) { res = -1; goto done; } /* * If nativePath is not a directory, there is no special handling. */ if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { goto done; } /* * Set the result to error, if the ACL change is successful it will be * reset to 0. */ res = -1; /* * Read the security descriptor for the directory. Note the first call * obtains the size of the security descriptor. */ if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) { DWORD secDescLen2 = 0; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto done; } secDesc = (BYTE *) ckalloc(secDescLen); if (!GetFileSecurityA(nativePath, infoBits, (PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2) || (secDescLen < secDescLen2)) { goto done; } } /* * Get the World SID. */ userSid = (SID *) ckalloc(GetSidLengthRequired((UCHAR) 1)); InitializeSid(userSid, &userSidAuthority, (BYTE) 1); *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID; /* * If curAclPresent == false then curAcl and curAclDefaulted not valid. */ if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc, &curAclPresent, &curAcl, &curAclDefaulted)) { goto done; } if (!curAclPresent || !curAcl) { ACLSize.AclBytesInUse = 0; ACLSize.AceCount = 0; } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize), AclSizeInformation)) { goto done; } /* * Allocate memory for the new ACL. */ newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(userSid) - sizeof(DWORD); newAcl = (ACL *) ckalloc(newAclSize); /* * Initialize the new ACL. */ if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) { goto done; } /* * Add denied to make readonly, this will be known as a "read-only tag". */ if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION, readOnlyMask, userSid)) { goto done; } acl_readOnly_found = FALSE; for (j = 0; j < ACLSize.AceCount; j++) { LPVOID pACE2; ACE_HEADER *phACE2; if (!GetAce(curAcl, j, &pACE2)) { goto done; } phACE2 = (ACE_HEADER *) pACE2; /* * Do NOT propagate inherited ACEs. */ if (phACE2->AceFlags & INHERITED_ACE) { continue; } /* * Skip the "read-only tag" restriction (either added above, or it is * being removed). */ if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) { ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2; if (pACEd->Mask == readOnlyMask && EqualSid(userSid, (PSID) &pACEd->SidStart)) { acl_readOnly_found = TRUE; continue; } } /* * Copy the current ACE from the old to the new ACL. */ if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2, ((PACE_HEADER) pACE2)->AceSize)) { goto done; } } /* * Apply the new ACL. */ if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA( (LPSTR) nativePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) { res = 0; } done: if (secDesc) { ckfree((char *) secDesc); } if (newAcl) { ckfree((char *) newAcl); } if (userSid) { ckfree((char *) userSid); } if (userDomain) { ckfree((char *) userDomain); } if (res != 0) { return res; } /* * Run normal chmod command. */ return chmod(nativePath, pmode); }