diff options
author | Bryan McLellan <btm@loftninjas.org> | 2017-07-19 15:26:26 -0400 |
---|---|---|
committer | Bryan McLellan <btm@loftninjas.org> | 2017-07-19 15:57:48 -0400 |
commit | d4c860f87fc8ef9fa14d2b9c8ad1183fb6f75535 (patch) | |
tree | 45e91338a692951ecf1708290cdace93719a7fa2 | |
parent | cb07cc92ec9f5bc5f390bbb2553105525cf18869 (diff) | |
download | mixlib-shellout-btm/elevated.tar.gz |
Update error messages to indicate user who lacks privilege on Windowsbtm/elevated
In some cases the user running mixlib-shellout needs additional privileges, in
other cases the user we're trying to run the process as needs them.
Signed-off-by: Bryan McLellan <btm@loftninjas.org>
-rw-r--r-- | lib/mixlib/shellout/windows/core_ext.rb | 145 |
1 files changed, 54 insertions, 91 deletions
diff --git a/lib/mixlib/shellout/windows/core_ext.rb b/lib/mixlib/shellout/windows/core_ext.rb index 5f78353..f3de488 100644 --- a/lib/mixlib/shellout/windows/core_ext.rb +++ b/lib/mixlib/shellout/windows/core_ext.rb @@ -35,7 +35,7 @@ module Process::Constants WAIT_FAILED = 0xFFFFFFFF ERROR_PRIVILEGE_NOT_HELD = 1314 - ERROR_LOGON_TYPE_NOT_GRANTED = 0X569 + ERROR_LOGON_TYPE_NOT_GRANTED = 0x569 end # Define the functions needed to check with Service windows station @@ -276,100 +276,14 @@ module Process # interactive windows station to attach to, which is created with the # LogonUser cann with the LOGON32_LOGON_INTERACTIVE flag. if winsta_name =~ /^Service-0x0-.*$/i - token = FFI::MemoryPointer.new(:ulong) - - bool = LogonUserW( - logon, # User - domain, # Domain - passwd, # Password - LOGON32_LOGON_INTERACTIVE, # Logon Type - LOGON32_PROVIDER_DEFAULT, # Logon Provider - token # User token handle - ) - - unless bool - if FFI.errno == ERROR_LOGON_TYPE_NOT_GRANTED - raise SystemCallError.new("LogonUserW (You must hold `Log on as a service` and `Log on as a batch job` permissions.)", FFI.errno) - else - raise SystemCallError.new("LogonUserW", FFI.errno) - end - end + token = logon_user(logon, domain, passwd, LOGON32_LOGON_INTERACTIVE) - token = token.read_ulong - - begin - bool = CreateProcessAsUserW( - token, # User token handle - app, # App name - cmd, # Command line - process_security, # Process attributes - thread_security, # Thread attributes - inherit, # Inherit handles - hash["creation_flags"], # Creation Flags - env, # Environment - cwd, # Working directory - startinfo, # Startup Info - procinfo # Process Info - ) - - unless bool - if FFI.errno == ERROR_PRIVILEGE_NOT_HELD - raise SystemCallError.new("CreateProcessAsUserW (You must hold the 'Replace a process level token' permission. Refresh the logon context after adding this right to make it effective.)", FFI.errno) - else - raise SystemCallError.new("CreateProcessAsUserW failed.", FFI.errno) - end - end - ensure - CloseHandle(token) - end + create_process_as_user(token, app, cmd, process_security, thread_security, hash["creation_flags"], env, cwd, startinfo, procinfo) else if hash["elevated"] - token = FFI::MemoryPointer.new(:ulong) - - bool = LogonUserW( - logon, # User - domain, # Domain - passwd, # Password - LOGON32_LOGON_BATCH, # Logon Type - LOGON32_PROVIDER_DEFAULT, # Logon Provider - token # User token handle - ) - - unless bool - if FFI.errno == ERROR_LOGON_TYPE_NOT_GRANTED - raise SystemCallError.new("LogonUserW (You must hold `Log on as a service` and `Log on as a batch job` permissions.)", FFI.errno) - else - raise SystemCallError.new("LogonUserW", FFI.errno) - end - end + token = logon_user(logon, domain, passwd, LOGON32_LOGON_BATCH) - token = token.read_ulong - - begin - bool = CreateProcessAsUserW( - token, # User token handle - app, # App name - cmd, # Command line - process_security, # Process attributes - thread_security, # Thread attributes - inherit, # Inherit handles - hash["creation_flags"], # Creation Flags - env, # Environment - cwd, # Working directory - startinfo, # Startup Info - procinfo # Process Info - ) - - unless bool - if FFI.errno == ERROR_PRIVILEGE_NOT_HELD - raise SystemCallError.new("CreateProcessAsUserW (You must hold the 'Replace a process level token' permission. Refresh the logon context after adding this right to make it effective.)", FFI.errno) - else - raise SystemCallError.new("CreateProcessAsUserW failed.", FFI.errno) - end - end - ensure - CloseHandle(token) - end + create_process_as_user(token, app, cmd, process_security, thread_security, hash["creation_flags"], env, cwd, startinfo, procinfo) else bool = CreateProcessWithLogonW( logon, # User @@ -428,5 +342,54 @@ module Process procinfo[:dwThreadId] ) end + + def logon_user(user, domain, passwd, type, provider = LOGON32_PROVIDER_DEFAULT) + token = FFI::MemoryPointer.new(:ulong) + + bool = LogonUserW( + user, # User + domain, # Domain + passwd, # Password + type, # Logon Type + provider, # Logon Provider + token # User token handle + ) + + unless bool + if (FFI.errno == ERROR_LOGON_TYPE_NOT_GRANTED) && (type == LOGON32_LOGON_BATCH) + raise SystemCallError.new("LogonUserW (User '#{user}' must hold 'Log on as a batch job' permissions.)", FFI.errno) + else + raise SystemCallError.new("LogonUserW", FFI.errno) + end + end + + token.read_ulong + end + + def create_process_as_user(token, app, cmd, process_security, thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo) + bool = CreateProcessAsUserW( + token, # User token handle + app, # App name + cmd, # Command line + process_security, # Process attributes + thread_security, # Thread attributes + inherit, # Inherit handles + creation_flags, # Creation Flags + env, # Environment + cwd, # Working directory + startinfo, # Startup Info + procinfo # Process Info + ) + + unless bool + if FFI.errno == ERROR_PRIVILEGE_NOT_HELD + raise SystemCallError.new("CreateProcessAsUserW (User '#{::ENV['USERNAME']}' must hold the 'Replace a process level token' and 'Adjust Memory Quotas for a process' permissions. Logoff the user after adding this right to make it effective.)", FFI.errno) + else + raise SystemCallError.new("CreateProcessAsUserW failed.", FFI.errno) + end + end + ensure + CloseHandle(token) + end end end |