/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test for NTFS File Permissions being correctly changed to match the new * directory upon moving a file. (Bug 224692.) */ #include "../TestHarness.h" #include "nsEmbedString.h" #include "nsIFile.h" #include #include #define BUFFSIZE 512 nsresult TestPermissions() { nsresult rv; // Return value // File variables HANDLE tempFileHandle; nsCOMPtr tempFile; nsCOMPtr tempDirectory1; nsCOMPtr tempDirectory2; WCHAR filePath[MAX_PATH]; WCHAR dir1Path[MAX_PATH]; WCHAR dir2Path[MAX_PATH]; // Security variables DWORD result; PSID everyoneSID = nullptr, adminSID = nullptr; PACL dirACL = nullptr, fileACL = nullptr; PSECURITY_DESCRIPTOR dirSD = nullptr, fileSD = nullptr; EXPLICIT_ACCESS ea[2]; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; SECURITY_ATTRIBUTES sa; TRUSTEE everyoneTrustee; ACCESS_MASK everyoneRights; // Create a well-known SID for the Everyone group. if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSID)) { fail("NTFS Permissions: AllocateAndInitializeSid Error"); return NS_ERROR_FAILURE; } // Create a SID for the Administrators group. if(! AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminSID)) { fail("NTFS Permissions: AllocateAndInitializeSid Error"); return NS_ERROR_FAILURE; } // Initialize an EXPLICIT_ACCESS structure for an ACE. // The ACE will allow Everyone read access to the directory. ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); ea[0].grfAccessPermissions = GENERIC_READ; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) everyoneSID; // Initialize an EXPLICIT_ACCESS structure for an ACE. // The ACE will allow the Administrators group full access ea[1].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) adminSID; // Create a new ACL that contains the new ACEs. result = SetEntriesInAcl(2, ea, nullptr, &dirACL); if (ERROR_SUCCESS != result) { fail("NTFS Permissions: SetEntriesInAcl Error"); return NS_ERROR_FAILURE; } // Initialize a security descriptor. dirSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (nullptr == dirSD) { fail("NTFS Permissions: LocalAlloc Error"); return NS_ERROR_FAILURE; } if (!InitializeSecurityDescriptor(dirSD, SECURITY_DESCRIPTOR_REVISION)) { fail("NTFS Permissions: InitializeSecurityDescriptor Error"); return NS_ERROR_FAILURE; } // Add the ACL to the security descriptor. if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) { fail("NTFS Permissions: SetSecurityDescriptorDacl Error"); return NS_ERROR_FAILURE; } // Initialize a security attributes structure. sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = dirSD; sa.bInheritHandle = false; // Create and open first temporary directory if(!CreateDirectoryW(L".\\NTFSPERMTEMP1", &sa)) { fail("NTFS Permissions: Creating Temporary Directory"); return NS_ERROR_FAILURE; } GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1", MAX_PATH, dir1Path, nullptr); rv = NS_NewLocalFile(nsEmbedString(dir1Path), false, getter_AddRefs(tempDirectory1)); if (NS_FAILED(rv)) { fail("NTFS Permissions: Opening Temporary Directory 1"); return rv; } // Create and open temporary file tempFileHandle = CreateFileW(L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", GENERIC_READ | GENERIC_WRITE, 0, nullptr, //default security CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if(tempFileHandle == INVALID_HANDLE_VALUE) { fail("NTFS Permissions: Creating Temporary File"); return NS_ERROR_FAILURE; } CloseHandle(tempFileHandle); GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", MAX_PATH, filePath, nullptr); rv = NS_NewLocalFile(nsEmbedString(filePath), false, getter_AddRefs(tempFile)); if (NS_FAILED(rv)) { fail("NTFS Permissions: Opening Temporary File"); return rv; } // Update Everyone Explict_Acess to full access. ea[0].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; // Update the ACL to contain the new ACEs. result = SetEntriesInAcl(2, ea, nullptr, &dirACL); if (ERROR_SUCCESS != result) { fail("NTFS Permissions: SetEntriesInAcl 2 Error"); return NS_ERROR_FAILURE; } // Add the new ACL to the security descriptor. if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) { fail("NTFS Permissions: SetSecurityDescriptorDacl 2 Error"); return NS_ERROR_FAILURE; } // Create and open second temporary directory if(!CreateDirectoryW(L".\\NTFSPERMTEMP2", &sa)) { fail("NTFS Permissions: Creating Temporary Directory 2"); return NS_ERROR_FAILURE; } GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP2", MAX_PATH, dir2Path, nullptr); rv = NS_NewLocalFile(nsEmbedString(dir2Path), false, getter_AddRefs(tempDirectory2)); if (NS_FAILED(rv)) { fail("NTFS Permissions: Opening Temporary Directory 2"); return rv; } // Move the file. rv = tempFile->MoveTo(tempDirectory2, EmptyString()); if (NS_FAILED(rv)) { fail("NTFS Permissions: Moving"); return rv; } // Access the ACL of the file result = GetNamedSecurityInfoW(L".\\NTFSPERMTEMP2\\NTFSPerm.tmp", SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION, nullptr, nullptr, &fileACL, nullptr, &fileSD); if (ERROR_SUCCESS != result) { fail("NTFS Permissions: GetNamedSecurityDescriptor Error"); return NS_ERROR_FAILURE; } // Build a trustee representing "Everyone" BuildTrusteeWithSid(&everyoneTrustee, everyoneSID); // Get Everyone's effective rights. result = GetEffectiveRightsFromAcl(fileACL, &everyoneTrustee, &everyoneRights); if (ERROR_SUCCESS != result) { fail("NTFS Permissions: GetEffectiveRightsFromAcl Error"); return NS_ERROR_FAILURE; } // Check for delete access, which we won't have unless permissions have // updated if((everyoneRights & DELETE) == (DELETE)) { passed("NTFS Permissions Test"); rv = NS_OK; } else { fail("NTFS Permissions: Access check."); rv = NS_ERROR_FAILURE; } // Cleanup if (everyoneSID) FreeSid(everyoneSID); if (adminSID) FreeSid(adminSID); if (dirACL) LocalFree(dirACL); if (dirSD) LocalFree(dirSD); if(fileACL) LocalFree(fileACL); tempDirectory1->Remove(true); tempDirectory2->Remove(true); return rv; } int main(int argc, char** argv) { ScopedXPCOM xpcom("NTFSPermissionsTests"); // name for tests being run if (xpcom.failed()) return 1; int rv = 0; if(NS_FAILED(TestPermissions())) rv = 1; return rv; }