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