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; }
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; }
HRESULT IPCShared::CreateWinNTDescriptor(DWORD pid, BOOL bRestrictiveACL, SECURITY_ATTRIBUTES **ppSA, KernelObject whatObject, EDescriptorType descType) { WRAPPER_NO_CONTRACT; HRESULT hr = NO_ERROR; // Gotta have a place to stick the new SA... if (ppSA == NULL) { _ASSERTE(!"Caller must supply ppSA"); return E_INVALIDARG; } *ppSA = NULL; ACL *pACL = NULL; SECURITY_DESCRIPTOR *pSD = NULL; SECURITY_ATTRIBUTES *pSA = NULL; // Allocate a SD. _ASSERTE (SECURITY_DESCRIPTOR_MIN_LENGTH == sizeof(SECURITY_DESCRIPTOR)); pSD = new (nothrow) SECURITY_DESCRIPTOR; if (pSD == NULL) { hr = E_OUTOFMEMORY; goto errExit; } // Do basic SD initialization if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { hr = HRESULT_FROM_GetLastError(); goto errExit; } // Grab the ACL for the IPC block for the given process if (!InitializeGenericIPCAcl(pid, bRestrictiveACL, &pACL, whatObject, descType)) { hr = E_FAIL; goto errExit; } // Add the ACL as the DACL for the SD. if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) { hr = HRESULT_FROM_GetLastError(); goto errExit; } // Allocate a SA. pSA = new (nothrow) SECURITY_ATTRIBUTES; if (pSA == NULL) { hr = E_OUTOFMEMORY; goto errExit; } // Pass out the new SA. *ppSA = pSA; pSA->nLength = sizeof(SECURITY_ATTRIBUTES); pSA->lpSecurityDescriptor = pSD; pSA->bInheritHandle = FALSE; // uncomment this line if you want to see the DACL being generated. //DumpSD(pSD); errExit: if (FAILED(hr)) { if (pACL != NULL) { for(int i = 0; i < pACL->AceCount; i++) DeleteAce(pACL, i); delete [] pACL; } if (pSD != NULL) delete pSD; } return hr; }
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); } }
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; }
// This function will remove the noninherited ACEs from // ppDestAcl that don't show up in 'acl'. This is needed for // SetSecurity - inherited ACEs need to stay, and any ACEs that // are being set need to stay, but all others need to go. HRESULT RemoveExplicitUniqueAces(PACL acl, PACL *ppDestAcl) { BOOL bResult = 0; DWORD errorCode = S_OK; HRESULT hr = S_OK; ACL_SIZE_INFORMATION aclInformation; DWORD totalCount; DWORD aceIndex = 0; LPVOID ace; BYTE aceFlags; BOOL alreadyExists = FALSE; if ( !ARGUMENT_PRESENT(acl) || !ARGUMENT_PRESENT(*ppDestAcl) ) { return E_INVALIDARG; } bResult = GetAclInformation( *ppDestAcl, &aclInformation, sizeof(aclInformation), AclSizeInformation ); FailGracefullyGLE(bResult, L"GetAclInformation"); totalCount = aclInformation.AceCount; while ( aceIndex < totalCount ) { bResult = GetAce( *ppDestAcl, aceIndex, &ace ); FailGracefullyGLE(bResult, L"GetAce"); aceFlags = ((PACE_HEADER)ace)->AceFlags; // We only care about explcit (i.e. non-inherited) ACEs if ( IS_FLAG_SET(aceFlags, INHERITED_ACE) ) { aceIndex++; continue; } hr = ACEAlreadyInACL( acl, ace, &alreadyExists, false ); FailGracefully(hr, L"ACEAlreadyInACL"); // If it's not in 'acl', then it's unique if ( alreadyExists == FALSE ) { bResult = DeleteAce(*ppDestAcl, aceIndex); FailGracefullyGLE(bResult, L"DeleteAce"); totalCount--; } else { aceIndex++; } } exit_gracefully: return hr; }