From 1dfc8d63a8438e42544b06cfdf225f222107eed2 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Wed, 6 Jul 2022 07:41:18 +0200 Subject: [PATCH] Add new option --chown-admin If specified and the process token owner is the local administrator, the owner is preserved and the primary group is set to the local administrator group. --- main.cc | 3 ++- win32.cc | 41 ++++++++++++++++++++++++++++++----------- win32.h | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/main.cc b/main.cc index 3a8c5ea..81c4a65 100644 --- a/main.cc +++ b/main.cc @@ -99,6 +99,7 @@ static StringOption Arch ("", 'a', "arch", IDS_HELPTEXT_ARCH, false); static BoolOption UnattendedOption (false, 'q', "quiet-mode", IDS_HELPTEXT_QUIET_MODE); static BoolOption PackageManagerOption (false, 'M', "package-manager", IDS_HELPTEXT_PACKAGE_MANAGER); static BoolOption NoAdminOption (false, 'B', "no-admin", IDS_HELPTEXT_NO_ADMIN); +static BoolOption ChownAdminOption (false, '\0', "chown-admin" /*, TODO: IDS_HELPTEXT_... */); static BoolOption WaitOption (false, 'W', "wait", IDS_HELPTEXT_WAIT); static BoolOption HelpOption (false, 'h', "help", IDS_HELPTEXT_HELP); static BoolOption VersionOption (false, 'V', "version", IDS_HELPTEXT_VERSION); @@ -359,7 +360,7 @@ WinMain (HINSTANCE h, } /* Set default DACL and Group. */ - nt_sec.setDefaultSecurity ((root_scope == IDC_ROOT_SYSTEM)); + nt_sec.setDefaultSecurity ((root_scope == IDC_ROOT_SYSTEM), ChownAdminOption); /* If --symlink-type option isn't given, look for winsymlinks in CYGWIN diff --git a/win32.cc b/win32.cc index 55072a9..5dc9616 100644 --- a/win32.cc +++ b/win32.cc @@ -308,7 +308,7 @@ NTSecurity::setAdminGroup () } void -NTSecurity::setDefaultSecurity (bool isAdmin) +NTSecurity::setDefaultSecurity (bool isAdmin, bool keepAdmin) { /* Get the processes access token. */ if (!OpenProcessToken (GetCurrentProcess (), @@ -335,21 +335,40 @@ NTSecurity::setDefaultSecurity (bool isAdmin) /* Set the default DACL to all permissions for everyone as a fallback. */ setDefaultDACL (); - /* Get the user */ - if (!GetTokenInformation (token.theHANDLE (), TokenUser, &ownerSID, + /* Get the owner */ + if (!GetTokenInformation (token.theHANDLE (), TokenOwner, &ownerSID, sizeof ownerSID, &size)) { - NoteFailedAPI ("GetTokenInformation(user)"); + NoteFailedAPI ("GetTokenInformation(owner)"); return; } - /* Make it the owner */ - TOKEN_OWNER owner = { ownerSID.user.User.Sid }; - if (!SetTokenInformation (token.theHANDLE (), TokenOwner, &owner, - sizeof owner)) + + bool ownerIsAdmin = !!EqualSid (ownerSID.user.User.Sid, administratorsSID.theSID ()); + + if (keepAdmin && ownerIsAdmin) + Log (LOG_TIMESTAMP) << "Default owner is Administrator" << endLog; + else { - NoteFailedAPI ("SetTokenInformation(owner)"); - return; + /* Get the user */ + if (!GetTokenInformation (token.theHANDLE (), TokenUser, &ownerSID, + sizeof ownerSID, &size)) + { + NoteFailedAPI ("GetTokenInformation(user)"); + return; + } + /* Make it the owner */ + TOKEN_OWNER owner = { ownerSID.user.User.Sid }; + if (!SetTokenInformation (token.theHANDLE (), TokenOwner, &owner, + sizeof owner)) + { + NoteFailedAPI ("SetTokenInformation(owner)"); + return; + } + Log (LOG_TIMESTAMP) << "Default owner changed " + << (ownerIsAdmin ? "from Administrator " : "") + << "to current user" << endLog; } + /* Get original primary group. The token's primary group will be reset to the original group right before we call the postinstall scripts. This is necessary, otherwise, if the installing user is a domain user, @@ -365,7 +384,7 @@ NTSecurity::setDefaultSecurity (bool isAdmin) /* Try to set the primary group to the Administrators group, but only if "Install for all users" has been chosen. If it doesn't work, we're no admin and that's all there's to say about it. */ - if (isAdmin) + if (isAdmin || (keepAdmin && ownerIsAdmin)) setAdminGroup (); } diff --git a/win32.h b/win32.h index 02c1d06..560512b 100644 --- a/win32.h +++ b/win32.h @@ -130,7 +130,7 @@ public: void resetPrimaryGroup(); void setAdminGroup (); void initialiseWellKnownSIDs (); - void setDefaultSecurity(bool isAdmin); + void setDefaultSecurity(bool isAdmin, bool keepAdmin); bool isRunAsAdmin (); bool hasSymlinkCreationRights (); private: -- 2.36.1