diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-19 23:50:49 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-19 23:50:49 +0000 |
commit | 3b4ba5f786bf16531f601e9205308454cd7390b5 (patch) | |
tree | 81861aef7476cdc18c11968af787888378145082 /chrome/installer | |
parent | 446295a3cf435144ae54e6116068e0da6220b81e (diff) | |
download | chromium_src-3b4ba5f786bf16531f601e9205308454cd7390b5.zip chromium_src-3b4ba5f786bf16531f601e9205308454cd7390b5.tar.gz chromium_src-3b4ba5f786bf16531f601e9205308454cd7390b5.tar.bz2 |
Twiddle the DACLs in setup.exe before re-launch at user level
In Vista and above the c:\windows\temp directory does not seem to allow RX for other accounts.
So we add RX for the authenticated_users group before doing the user-level relaunch.
BUG=41699
TEST= see bug
Review URL: http://codereview.chromium.org/1585044
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/util/google_chrome_distribution.cc | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc index 7029fef0..6171066 100644 --- a/chrome/installer/util/google_chrome_distribution.cc +++ b/chrome/installer/util/google_chrome_distribution.cc @@ -10,6 +10,7 @@ #include <windows.h> #include <wtsapi32.h> #include <msi.h> +#include <sddl.h> #include "base/file_path.h" #include "base/path_service.h" @@ -17,6 +18,7 @@ #include "base/registry.h" #include "base/scoped_ptr.h" #include "base/string_util.h" +#include "base/win_util.h" #include "base/wmi_util.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/json_value_serializer.h" @@ -133,6 +135,52 @@ bool RelaunchSetup(const std::wstring& flag, int value, return base::LaunchApp(cmd_line, false, false, NULL); } +// For System level installs, setup.exe lives in the system temp, which +// is normally c:\windows\temp. In many cases files inside this folder +// are not accessible for execution by regular user accounts. +// This function changes the permisions so that any authenticated user +// can launch |exe| later on. This function should only be called if the +// code is running at the system level. +bool FixDACLsForExecute(const wchar_t* exe) { + // The general strategy to is to add an ACE to the exe DACL the quick + // and dirty way: a) read the DACL b) convert it to sddl string c) add the + // new ACE to the string d) convert sddl string back to DACL and finally + // e) write new dacl. + char buff[1024]; + DWORD len = sizeof(buff); + PSECURITY_DESCRIPTOR sd = reinterpret_cast<PSECURITY_DESCRIPTOR>(buff); + if (!::GetFileSecurityW(exe, DACL_SECURITY_INFORMATION, sd, len, &len)) + return false; + wchar_t* sddl = 0; + if (!::ConvertSecurityDescriptorToStringSecurityDescriptorW(sd, + SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &sddl, NULL)) + return false; + std::wstring new_sddl(sddl); + ::LocalFree(sddl); + sd = NULL; + // See MSDN for the security descriptor definition language (SDDL) syntax, + // in our case we add "A;" generic read 'GR' and generic execute 'GX' for + // the nt\authenticated_users 'AU' group, that becomes: + const wchar_t kAllowACE[] = L"(A;;GRGX;;;AU)"; + // We should check that there are no special ACES for the group we + // are interested, which is nt\authenticated_users. + if (std::wstring::npos != new_sddl.find(L";AU)")) + return false; + // Specific ACEs (not inherited) need to go to the front. It is ok if we + // are the very first one. + size_t pos_insert = new_sddl.find(L"("); + if (std::wstring::npos == pos_insert) + return false; + // All good, time to change the dacl. + new_sddl.insert(pos_insert, kAllowACE); + if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(new_sddl.c_str(), + SDDL_REVISION_1, &sd, NULL)) + return false; + bool rv = ::SetFileSecurityW(exe, DACL_SECURITY_INFORMATION, sd) == TRUE; + ::LocalFree(sd); + return rv; +} + // This function launches setup as the currently logged-in interactive // user that is the user whose logon session is attached to winsta0\default. // It assumes that currently we are running as SYSTEM in a non-interactive @@ -142,9 +190,18 @@ bool RelaunchSetup(const std::wstring& flag, int value, // Remote Desktop sessions do not count as interactive sessions; running this // method as a user logged in via remote desktop will do nothing. bool RelaunchSetupAsConsoleUser(const std::wstring& flag) { - CommandLine cmd_line(CommandLine::ForCurrentProcess()->GetProgram()); + FilePath setup_exe = CommandLine::ForCurrentProcess()->GetProgram(); + CommandLine cmd_line(setup_exe); cmd_line.AppendSwitch(WideToASCII(flag)); + if (win_util::GetWinVersion() > win_util::WINVERSION_XP) { + // Make sure that in Vista and Above we have the proper DACLs so + // the interactive user can launch it. + if (!FixDACLsForExecute(setup_exe.ToWStringHack().c_str())) { + NOTREACHED(); + } + } + DWORD console_id = ::WTSGetActiveConsoleSessionId(); if (console_id == 0xFFFFFFFF) return false; |