Runtime.cpp (4518B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include "TestHooks.h" 6 #include <AppInstallerRuntime.h> 7 #include <winget/Filesystem.h> 8 9 using namespace AppInstaller; 10 using namespace AppInstaller::Filesystem; 11 using namespace AppInstaller::Runtime; 12 using namespace TestCommon; 13 14 bool CanWriteToPath(const std::filesystem::path& directory, const std::filesystem::path& file = "test.txt") 15 { 16 std::ofstream out{ directory / file }; 17 out << "Test"; 18 return out.good(); 19 } 20 21 void RequireAdminOwner(const std::filesystem::path& directory) 22 { 23 wil::unique_hlocal_security_descriptor securityDescriptor; 24 PSID ownerSID = nullptr; 25 THROW_IF_WIN32_ERROR(GetNamedSecurityInfoW(directory.c_str(), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &ownerSID, nullptr, nullptr, nullptr, &securityDescriptor)); 26 27 auto adminSID = wil::make_static_sid(SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS); 28 REQUIRE(EqualSid(adminSID.get(), ownerSID)); 29 } 30 31 TEST_CASE("ApplyACL_CurrentUserOwner", "[runtime]") 32 { 33 TempDirectory directory("CurrentUserOwner"); 34 PathDetails details; 35 details.Path = directory; 36 details.SetOwner(ACEPrincipal::CurrentUser); 37 38 details.ApplyACL(); 39 40 REQUIRE(CanWriteToPath(directory)); 41 } 42 43 TEST_CASE("ApplyACL_RemoveWriteForUser", "[runtime]") 44 { 45 TempDirectory directory("CurrentUserCantWrite"); 46 PathDetails details; 47 details.Path = directory; 48 details.ACL[ACEPrincipal::CurrentUser] = ACEPermissions::ReadExecute; 49 50 details.ApplyACL(); 51 52 REQUIRE(!CanWriteToPath(directory)); 53 } 54 55 TEST_CASE("ApplyACL_AdminOwner", "[runtime]") 56 { 57 TempDirectory directory("AdminOwner"); 58 PathDetails details; 59 details.Path = directory; 60 details.SetOwner(ACEPrincipal::Admins); 61 62 if (IsRunningAsAdmin()) 63 { 64 details.ApplyACL(); 65 RequireAdminOwner(directory); 66 REQUIRE(CanWriteToPath(directory)); 67 } 68 else 69 { 70 // A non-admin token cannot set the owner to be the Admins group 71 REQUIRE_THROWS_HR(details.ApplyACL(), HRESULT_FROM_WIN32(ERROR_INVALID_OWNER)); 72 } 73 } 74 75 TEST_CASE("ApplyACL_BothOwners", "[runtime]") 76 { 77 TempDirectory directory("AdminOwner"); 78 PathDetails details; 79 details.Path = directory; 80 details.ACL[ACEPrincipal::CurrentUser] = ACEPermissions::ReadExecute; 81 details.ACL[ACEPrincipal::System] = ACEPermissions::All; 82 83 if (IsRunningAsSystem()) 84 { 85 // Both cannot be owners 86 REQUIRE_THROWS_HR(details.ApplyACL(), HRESULT_FROM_WIN32(ERROR_INVALID_STATE)); 87 } 88 else 89 { 90 REQUIRE_NOTHROW(details.ApplyACL()); 91 } 92 } 93 94 TEST_CASE("ApplyACL_CurrentUserOwner_SystemAll", "[runtime]") 95 { 96 TempDirectory directory("UserAndSystem"); 97 PathDetails details; 98 details.Path = directory; 99 details.SetOwner(ACEPrincipal::CurrentUser); 100 details.ACL[ACEPrincipal::System] = ACEPermissions::All; 101 102 details.ApplyACL(); 103 104 REQUIRE(CanWriteToPath(directory)); 105 } 106 107 TEST_CASE("VerifyDevModeEnabledCheck", "[runtime]") 108 { 109 if (!Runtime::IsRunningAsAdmin()) 110 { 111 WARN("Test requires admin privilege. Skipped."); 112 return; 113 } 114 115 bool initialState = IsDevModeEnabled(); 116 117 EnableDevMode(!initialState); 118 bool modifiedState = IsDevModeEnabled(); 119 120 // Revert to original state. 121 EnableDevMode(initialState); 122 bool revertedState = IsDevModeEnabled(); 123 124 REQUIRE(modifiedState != initialState); 125 REQUIRE(revertedState == initialState); 126 } 127 128 TEST_CASE("EnsureUserProfileNotPresentInDisplayPaths", "[runtime]") 129 { 130 // Clear the overrides that we use when testing as they don't consider display purposes 131 Runtime::TestHook_ClearPathOverrides(); 132 auto restorePaths = wil::scope_exit([]() { TestCommon::SetTestPathOverrides(); }); 133 134 std::filesystem::path userProfilePath = Filesystem::GetKnownFolderPath(FOLDERID_Profile); 135 std::string userProfileString = userProfilePath.u8string(); 136 137 for (auto i = ToIntegral(ToEnum<Runtime::PathName>(0)); i < ToIntegral(Runtime::PathName::Max); ++i) 138 { 139 std::filesystem::path displayPath = GetPathTo(ToEnum<Runtime::PathName>(i), true); 140 std::string displayPathString = displayPath.u8string(); 141 INFO(i << " = " << displayPathString); 142 REQUIRE(displayPathString.find(userProfileString) == std::string::npos); 143 } 144 }