mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Fix issues with win_runas
modules/file.py: Pass the right parameters to `check_perms` on Windows platform/win.py: Return actual error on runas failure platform/win.py: Setup environment for CreateProcessWithLogonW states/file.py: Pass the right parameters to `file.check_perms` on Windows states/zfs.py: Fix __virtual__ so it doesn't stacktrace in Windows logs states/zpool.py: Fix __virtual__ so it doesn't stacktrace in Windows logs utils/win_runas.py: Cleanup the handles a little better by using some try/finally blocks. states/test_file.py: Just use os.mkdir on Windows as the mode is ignored
This commit is contained in:
parent
bceffa1d92
commit
4a9c020787
7 changed files with 114 additions and 95 deletions
|
@ -2759,11 +2759,16 @@ def blockreplace(path,
|
|||
backup_path = '{0}{1}'.format(path, backup)
|
||||
shutil.copy2(path, backup_path)
|
||||
# copy2 does not preserve ownership
|
||||
check_perms(backup_path,
|
||||
None,
|
||||
perms['user'],
|
||||
perms['group'],
|
||||
perms['mode'])
|
||||
if salt.utils.platform.is_windows():
|
||||
check_perms(path=backup_path,
|
||||
ret=None,
|
||||
owner=perms['user'])
|
||||
else:
|
||||
check_perms(name=backup_path,
|
||||
ret=None,
|
||||
user=perms['user'],
|
||||
group=perms['group'],
|
||||
mode=perms['mode'])
|
||||
|
||||
# write new content in the file while avoiding partial reads
|
||||
try:
|
||||
|
@ -2774,11 +2779,16 @@ def blockreplace(path,
|
|||
fh_.close()
|
||||
|
||||
# this may have overwritten file attrs
|
||||
check_perms(path,
|
||||
None,
|
||||
perms['user'],
|
||||
perms['group'],
|
||||
perms['mode'])
|
||||
if salt.utils.platform.is_windows():
|
||||
check_perms(path=path,
|
||||
ret=None,
|
||||
owner=perms['user'])
|
||||
else:
|
||||
check_perms(path,
|
||||
ret=None,
|
||||
user=perms['user'],
|
||||
group=perms['group'],
|
||||
mode=perms['mode'])
|
||||
|
||||
if show_changes:
|
||||
return diff
|
||||
|
@ -5397,7 +5407,7 @@ def manage_file(name,
|
|||
# on Windows. The local function will be overridden
|
||||
# pylint: disable=E1120,E1121,E1123
|
||||
ret = check_perms(
|
||||
path=name,
|
||||
path=name,
|
||||
ret=ret,
|
||||
owner=kwargs.get('win_owner'),
|
||||
grant_perms=kwargs.get('win_perms'),
|
||||
|
|
|
@ -10,9 +10,9 @@ Much of what is here was adapted from the following:
|
|||
http://stackoverflow.com/questions/29566330
|
||||
'''
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
import os
|
||||
import collections
|
||||
import logging
|
||||
import os
|
||||
import psutil
|
||||
|
||||
import ctypes
|
||||
|
@ -21,7 +21,6 @@ from ctypes import wintypes
|
|||
from salt.ext.six.moves import range
|
||||
from salt.ext.six.moves import zip
|
||||
|
||||
import win32con
|
||||
import win32con
|
||||
import win32api
|
||||
import win32process
|
||||
|
@ -598,7 +597,7 @@ class HANDLE_IHV(wintypes.HANDLE):
|
|||
|
||||
def errcheck_ihv(result, func, args):
|
||||
if result.value == INVALID_HANDLE_VALUE:
|
||||
raise ctypes.WinError()
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
return result.value
|
||||
|
||||
|
||||
|
@ -608,13 +607,13 @@ class DWORD_IDV(wintypes.DWORD):
|
|||
|
||||
def errcheck_idv(result, func, args):
|
||||
if result.value == INVALID_DWORD_VALUE:
|
||||
raise ctypes.WinError()
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
return result.value
|
||||
|
||||
|
||||
def errcheck_bool(result, func, args):
|
||||
if not result:
|
||||
raise ctypes.WinError()
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
return args
|
||||
|
||||
|
||||
|
@ -1035,10 +1034,8 @@ def CreateProcessWithTokenW(token,
|
|||
startupinfo = STARTUPINFO()
|
||||
if currentdirectory is not None:
|
||||
currentdirectory = ctypes.create_unicode_buffer(currentdirectory)
|
||||
if environment:
|
||||
environment = ctypes.pointer(
|
||||
environment_string(environment)
|
||||
)
|
||||
if environment is not None:
|
||||
environment = ctypes.pointer(environment_string(environment))
|
||||
process_info = PROCESS_INFORMATION()
|
||||
ret = advapi32.CreateProcessWithTokenW(
|
||||
token,
|
||||
|
@ -1174,14 +1171,23 @@ def make_inheritable(token):
|
|||
)
|
||||
|
||||
|
||||
def CreateProcessWithLogonW(username=None, domain=None, password=None,
|
||||
logonflags=0, applicationname=None, commandline=None, creationflags=0,
|
||||
environment=None, currentdirectory=None, startupinfo=None):
|
||||
def CreateProcessWithLogonW(username=None,
|
||||
domain=None,
|
||||
password=None,
|
||||
logonflags=0,
|
||||
applicationname=None,
|
||||
commandline=None,
|
||||
creationflags=0,
|
||||
environment=None,
|
||||
currentdirectory=None,
|
||||
startupinfo=None):
|
||||
creationflags |= win32con.CREATE_UNICODE_ENVIRONMENT
|
||||
if commandline is not None:
|
||||
commandline = ctypes.create_unicode_buffer(commandline)
|
||||
if startupinfo is None:
|
||||
startupinfo = STARTUPINFO()
|
||||
if environment is not None:
|
||||
environment = ctypes.pointer(environment_string(environment))
|
||||
process_info = PROCESS_INFORMATION()
|
||||
advapi32.CreateProcessWithLogonW(
|
||||
username,
|
||||
|
|
|
@ -6343,7 +6343,14 @@ def copy_(name,
|
|||
# the filesystem we're copying to is squashed or doesn't support chown
|
||||
# then we shouldn't be checking anything.
|
||||
if not preserve:
|
||||
__salt__['file.check_perms'](name, ret, user, group, mode)
|
||||
if salt.utils.platform.is_windows():
|
||||
# TODO: Add the other win_* parameters to this function
|
||||
ret = __salt__['file.check_perms'](
|
||||
path=name,
|
||||
ret=ret,
|
||||
owner=user)
|
||||
else:
|
||||
__salt__['file.check_perms'](name, ret, user, group, mode)
|
||||
except (IOError, OSError):
|
||||
return _error(
|
||||
ret, 'Failed to copy "{0}" to "{1}"'.format(source, name))
|
||||
|
|
|
@ -68,10 +68,9 @@ def __virtual__():
|
|||
'''
|
||||
Provides zfs state
|
||||
'''
|
||||
if __grains__['zfs_support']:
|
||||
return __virtualname__
|
||||
else:
|
||||
return (False, "The zfs state cannot be loaded: zfs not supported")
|
||||
if not __grains__.get('zfs_support'):
|
||||
return False, 'The zfs state cannot be loaded: zfs not supported'
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _absent(name, dataset_type, force=False, recursive=False):
|
||||
|
|
|
@ -88,10 +88,9 @@ def __virtual__():
|
|||
'''
|
||||
Provides zpool state
|
||||
'''
|
||||
if __grains__['zfs_support']:
|
||||
return __virtualname__
|
||||
else:
|
||||
if not __grains__.get('zfs_support'):
|
||||
return False, 'The zpool state cannot be loaded: zfs not supported'
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _layout_to_vdev(layout, device_dir=None):
|
||||
|
|
|
@ -95,6 +95,7 @@ def runas(cmdLine, username, password=None, cwd=None):
|
|||
except WindowsError: # pylint: disable=undefined-variable
|
||||
log.debug("Unable to impersonate SYSTEM user")
|
||||
impersonation_token = None
|
||||
win32api.CloseHandle(th)
|
||||
|
||||
# Impersonation of the SYSTEM user failed. Fallback to an un-privileged
|
||||
# runas.
|
||||
|
@ -105,7 +106,6 @@ def runas(cmdLine, username, password=None, cwd=None):
|
|||
if domain == 'NT AUTHORITY':
|
||||
# Logon as a system level account, SYSTEM, LOCAL SERVICE, or NETWORK
|
||||
# SERVICE.
|
||||
logonType = win32con.LOGON32_LOGON_SERVICE
|
||||
user_token = win32security.LogonUser(
|
||||
username,
|
||||
domain,
|
||||
|
@ -172,53 +172,56 @@ def runas(cmdLine, username, password=None, cwd=None):
|
|||
# Create the environment for the user
|
||||
env = win32profile.CreateEnvironmentBlock(user_token, False)
|
||||
|
||||
# Start the process in a suspended state.
|
||||
process_info = salt.platform.win.CreateProcessWithTokenW(
|
||||
int(user_token),
|
||||
logonflags=1,
|
||||
applicationname=None,
|
||||
commandline=cmdLine,
|
||||
currentdirectory=cwd,
|
||||
creationflags=creationflags,
|
||||
startupinfo=startup_info,
|
||||
environment=env,
|
||||
)
|
||||
try:
|
||||
# Start the process in a suspended state.
|
||||
process_info = salt.platform.win.CreateProcessWithTokenW(
|
||||
int(user_token),
|
||||
logonflags=1,
|
||||
applicationname=None,
|
||||
commandline=cmdLine,
|
||||
currentdirectory=cwd,
|
||||
creationflags=creationflags,
|
||||
startupinfo=startup_info,
|
||||
environment=env,
|
||||
)
|
||||
|
||||
hProcess = process_info.hProcess
|
||||
hThread = process_info.hThread
|
||||
dwProcessId = process_info.dwProcessId
|
||||
dwThreadId = process_info.dwThreadId
|
||||
hProcess = process_info.hProcess
|
||||
hThread = process_info.hThread
|
||||
dwProcessId = process_info.dwProcessId
|
||||
dwThreadId = process_info.dwThreadId
|
||||
|
||||
salt.platform.win.kernel32.CloseHandle(stdin_write.handle)
|
||||
salt.platform.win.kernel32.CloseHandle(stdout_write.handle)
|
||||
salt.platform.win.kernel32.CloseHandle(stderr_write.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)
|
||||
|
||||
ret = {'pid': dwProcessId}
|
||||
# Resume the process
|
||||
psutil.Process(dwProcessId).resume()
|
||||
ret = {'pid': dwProcessId}
|
||||
# Resume the process
|
||||
psutil.Process(dwProcessId).resume()
|
||||
|
||||
# Wait for the process to exit and get it's return code.
|
||||
if win32event.WaitForSingleObject(hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0:
|
||||
exitcode = win32process.GetExitCodeProcess(hProcess)
|
||||
ret['retcode'] = exitcode
|
||||
# Wait for the process to exit and get it's return code.
|
||||
if win32event.WaitForSingleObject(hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0:
|
||||
exitcode = win32process.GetExitCodeProcess(hProcess)
|
||||
ret['retcode'] = exitcode
|
||||
|
||||
# Read standard out
|
||||
fd_out = msvcrt.open_osfhandle(stdout_read.handle, os.O_RDONLY | os.O_TEXT)
|
||||
with os.fdopen(fd_out, 'r') as f_out:
|
||||
stdout = f_out.read()
|
||||
ret['stdout'] = stdout
|
||||
# Read standard out
|
||||
fd_out = msvcrt.open_osfhandle(stdout_read.handle, os.O_RDONLY | os.O_TEXT)
|
||||
with os.fdopen(fd_out, 'r') as f_out:
|
||||
stdout = f_out.read()
|
||||
ret['stdout'] = stdout
|
||||
|
||||
# Read standard error
|
||||
fd_err = msvcrt.open_osfhandle(stderr_read.handle, os.O_RDONLY | os.O_TEXT)
|
||||
with os.fdopen(fd_err, 'r') as f_err:
|
||||
stderr = f_err.read()
|
||||
ret['stderr'] = stderr
|
||||
|
||||
salt.platform.win.kernel32.CloseHandle(hProcess)
|
||||
win32api.CloseHandle(user_token)
|
||||
if impersonation_token:
|
||||
win32security.RevertToSelf()
|
||||
win32api.CloseHandle(impersonation_token)
|
||||
# Read standard error
|
||||
fd_err = msvcrt.open_osfhandle(stderr_read.handle, os.O_RDONLY | os.O_TEXT)
|
||||
with os.fdopen(fd_err, 'r') as f_err:
|
||||
stderr = f_err.read()
|
||||
ret['stderr'] = stderr
|
||||
finally:
|
||||
salt.platform.win.kernel32.CloseHandle(hProcess)
|
||||
win32api.CloseHandle(th)
|
||||
win32api.CloseHandle(user_token)
|
||||
if impersonation_token:
|
||||
win32security.RevertToSelf()
|
||||
win32api.CloseHandle(impersonation_token)
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -258,20 +261,21 @@ def runas_unpriv(cmd, username, password, cwd=None):
|
|||
hStdError=errwrite,
|
||||
)
|
||||
|
||||
# Run command and return process info structure
|
||||
process_info = salt.platform.win.CreateProcessWithLogonW(
|
||||
username=username,
|
||||
domain=domain,
|
||||
password=password,
|
||||
logonflags=salt.platform.win.LOGON_WITH_PROFILE,
|
||||
commandline=cmd,
|
||||
startupinfo=startup_info,
|
||||
currentdirectory=cwd)
|
||||
|
||||
salt.platform.win.kernel32.CloseHandle(dupin)
|
||||
salt.platform.win.kernel32.CloseHandle(c2pwrite)
|
||||
salt.platform.win.kernel32.CloseHandle(errwrite)
|
||||
salt.platform.win.kernel32.CloseHandle(process_info.hThread)
|
||||
try:
|
||||
# Run command and return process info structure
|
||||
process_info = salt.platform.win.CreateProcessWithLogonW(
|
||||
username=username,
|
||||
domain=domain,
|
||||
password=password,
|
||||
logonflags=salt.platform.win.LOGON_WITH_PROFILE,
|
||||
commandline=cmd,
|
||||
startupinfo=startup_info,
|
||||
currentdirectory=cwd)
|
||||
salt.platform.win.kernel32.CloseHandle(process_info.hThread)
|
||||
finally:
|
||||
salt.platform.win.kernel32.CloseHandle(dupin)
|
||||
salt.platform.win.kernel32.CloseHandle(c2pwrite)
|
||||
salt.platform.win.kernel32.CloseHandle(errwrite)
|
||||
|
||||
# Initialize ret and set first element
|
||||
ret = {'pid': process_info.dwProcessId}
|
||||
|
|
|
@ -915,10 +915,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
tmp_dir = os.path.join(TMP, 'pgdata')
|
||||
sym_dir = os.path.join(TMP, 'pg_data')
|
||||
|
||||
if IS_WINDOWS:
|
||||
self.run_function('file.mkdir', [tmp_dir, 'Administrators'])
|
||||
else:
|
||||
os.mkdir(tmp_dir, 0o700)
|
||||
os.mkdir(tmp_dir, 0o700)
|
||||
|
||||
self.run_function('file.symlink', [tmp_dir, sym_dir])
|
||||
|
||||
|
@ -1254,10 +1251,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
null_file = '{0}/null'.format(tmp_dir)
|
||||
broken_link = '{0}/broken'.format(tmp_dir)
|
||||
|
||||
if IS_WINDOWS:
|
||||
self.run_function('file.mkdir', [tmp_dir, 'Administrators'])
|
||||
else:
|
||||
os.mkdir(tmp_dir, 0o700)
|
||||
os.mkdir(tmp_dir, 0o700)
|
||||
|
||||
self.run_function('file.symlink', [null_file, broken_link])
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue