Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions salt/modules/cmdmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,12 +726,7 @@ def _run(
f"Specified cwd '{cwd}' either not absolute or does not exist"
)

if (
python_shell is not True
and shell is not None
# and not salt.utils.platform.is_windows()
and not isinstance(cmd, list)
):
if python_shell is not True and shell is not None and not isinstance(cmd, list):
cmd = salt.utils.args.shlex_split(cmd)

if success_retcodes is None:
Expand Down
11 changes: 6 additions & 5 deletions salt/platform/win.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ def grant_winsta_and_desktop(th):
"""
current_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0]
# Add permissions for the sid to the current windows station and thread id.
# This prevents windows error 0xC0000142.
# This prevents Windows error 0xC0000142.
winsta = win32process.GetProcessWindowStation()
set_user_perm(winsta, WINSTA_ALL, current_sid)
desktop = win32service.GetThreadDesktop(win32api.GetCurrentThreadId())
Expand Down Expand Up @@ -1341,11 +1341,12 @@ def CreateProcessWithLogonW(

def prepend_cmd(win_shell, cmd):
"""
Prep cmd when shell is cmd.exe. Always use a command string instead of a list to satisfy
both CreateProcess and CreateProcessWithToken.
Prep cmd when shell is cmd.exe. Always use a command string instead of a
list to satisfy both CreateProcess and CreateProcessWithToken.

cmd must be double-quoted to ensure proper handling of space characters. The first opening
quote and the closing quote are stripped automatically by the Win32 API.
cmd must be double-quoted to ensure proper handling of space characters.
The first opening quote and the closing quote are stripped automatically by
the Win32 API.
"""
if isinstance(cmd, (list, tuple)):
args = subprocess.list2cmdline(cmd)
Expand Down
57 changes: 41 additions & 16 deletions salt/utils/win_runas.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import subprocess
import time

import salt.utils.path
from salt.exceptions import CommandExecutionError

try:
Expand Down Expand Up @@ -68,7 +69,7 @@ def split_username(username):
return str(user_name), str(domain)


def create_env(user_token, inherit, timeout=1):
def create_env(username, user_token, inherit=False, timeout=1):
"""
CreateEnvironmentBlock might fail when we close a login session and then
try to re-open one very quickly. Run the method multiple times to work
Expand All @@ -77,15 +78,30 @@ def create_env(user_token, inherit, timeout=1):
start = time.time()
env = None
exc = None
while True:
try:
env = win32profile.CreateEnvironmentBlock(user_token, False)
except pywintypes.error as exc:
pass
else:
break
if time.time() - start > timeout:
break
profile_info_dict = {"UserName": username}
try:
profile_handle = win32profile.LoadUserProfile(user_token, profile_info_dict)
while True:
try:
env = win32profile.CreateEnvironmentBlock(user_token, inherit)
if env is not None:
break
except pywintypes.error as exc:
pass
else:
break
if time.time() - start > timeout:
break
except (win32api.error, pywintypes.error) as e:
msg = f"Failed to load user profile: {e}"
raise CommandExecutionError(msg)

try:
win32profile.UnloadUserProfile(user_token, profile_handle)
except (win32api.error, pywintypes.error) as e:
msg = f"Failed to unload user profile: {e}"
raise CommandExecutionError(msg)

if env is not None:
return env
if exc is not None:
Expand All @@ -95,8 +111,8 @@ def create_env(user_token, inherit, timeout=1):
def runas(cmd, username, password=None, cwd=None):
"""
Run a command as another user. If the process is running as an admin or
system account this method does not require a password. Other non
privileged accounts need to provide a password for the user to runas.
system account, this method does not require a password. Other
non-privileged accounts need to provide a password for the user to "runas".
Commands are run in with the highest level privileges possible for the
account provided.
"""
Expand All @@ -115,10 +131,12 @@ def runas(cmd, username, password=None, cwd=None):
# Elevate the token from the current process
access = win32security.TOKEN_QUERY | win32security.TOKEN_ADJUST_PRIVILEGES
th = win32security.OpenProcessToken(win32api.GetCurrentProcess(), access)
import salt.platform.win

salt.platform.win.elevate_token(th)

# Try to impersonate the SYSTEM user. This process needs to be running as a
# user who as been granted the SeImpersonatePrivilege, Administrator
# user who has been granted the SeImpersonatePrivilege, Administrator
# accounts have this permission by default.
try:
impersonation_token = salt.platform.win.impersonate_sid(
Expand Down Expand Up @@ -211,15 +229,22 @@ def runas(cmd, username, password=None, cwd=None):
)

# Create the environment for the user
env = create_env(user_token, False)
env = create_env(username, user_token, inherit=False)
application_name = None
# TODO: Maybe it has something to do with applicationname
# application_name = salt.utils.path.which("cmd.exe")
# application_name = cmd
# import salt.utils.args
# if salt.utils.args.shlex_split(cmd)[0].endswith((".bat", "cmd", "cmd.exe")):
# application_name = salt.utils.path.which("cmd.exe")

hProcess = None
try:
# Start the process in a suspended state.
process_info = salt.platform.win.CreateProcessWithTokenW(
int(user_token),
logonflags=1,
applicationname=None,
applicationname=application_name,
commandline=cmd,
currentdirectory=cwd,
creationflags=creationflags,
Expand All @@ -232,7 +257,7 @@ def runas(cmd, username, password=None, cwd=None):
dwProcessId = process_info.dwProcessId
dwThreadId = process_info.dwThreadId

# We don't use these so let's close the handle
# We don't use these, so let's close the handle
salt.platform.win.kernel32.CloseHandle(stdin_write.handle)
salt.platform.win.kernel32.CloseHandle(stdout_write.handle)
salt.platform.win.kernel32.CloseHandle(stderr_write.handle)
Expand Down
Loading
Loading