mixlib-shellout 3.1.7 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82102f99cbf59a6ec48f6b7685e470ecd94bc629e27ae83b36a3eaa7e02ace33
|
4
|
+
data.tar.gz: 83d3a8aeb7bf139a209440bc8877b63f524b7d30c783b99af2c7406d237618ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 201ec59f8e4dd8f20443e9d78f880037cd65f91a890321647d95347d29bf478968554548efc311d2a1da82ae3a7c00220cb27021c13d21c8b2ecc28bdfbd20cc
|
7
|
+
data.tar.gz: 3c1caed9698c8820fb70b2245b134e303fcb55343323ea1c51350d625ceeee5f9c3ec8a68d5f81355aafad3c30d89a244316576b674a13eb922f7b0d8fb10948
|
data/lib/mixlib/shellout.rb
CHANGED
@@ -248,7 +248,7 @@ module Mixlib
|
|
248
248
|
# running or died without setting an exit status (e.g., terminated by
|
249
249
|
# `kill -9`).
|
250
250
|
def exitstatus
|
251
|
-
@status
|
251
|
+
@status && @status.exitstatus
|
252
252
|
end
|
253
253
|
|
254
254
|
# Run the command, writing the command's standard out and standard error
|
data/lib/mixlib/shellout/unix.rb
CHANGED
@@ -370,11 +370,11 @@ module Mixlib
|
|
370
370
|
return if attempt_reap
|
371
371
|
|
372
372
|
@terminate_reason = "Command exceeded allowed execution time, process terminated"
|
373
|
-
logger
|
373
|
+
logger.error("Command exceeded allowed execution time, sending TERM") if logger
|
374
374
|
Process.kill(:TERM, child_pgid)
|
375
375
|
sleep 3
|
376
376
|
attempt_reap
|
377
|
-
logger
|
377
|
+
logger.error("Command exceeded allowed execution time, sending KILL") if logger
|
378
378
|
Process.kill(:KILL, child_pgid)
|
379
379
|
reap
|
380
380
|
|
@@ -89,7 +89,7 @@ module Mixlib
|
|
89
89
|
# Start the process
|
90
90
|
#
|
91
91
|
process, profile, token = Process.create3(create_process_args)
|
92
|
-
logger
|
92
|
+
logger.debug(format_process(process, app_name, command_line, timeout)) if logger
|
93
93
|
begin
|
94
94
|
# Start pushing data into input
|
95
95
|
stdin_write << input if input
|
@@ -124,7 +124,7 @@ module Mixlib
|
|
124
124
|
kill_process_tree(process.process_id, wmi, logger)
|
125
125
|
Process.kill(:KILL, process.process_id)
|
126
126
|
rescue SystemCallError
|
127
|
-
logger
|
127
|
+
logger.warn("Failed to kill timed out process #{process.process_id}") if logger
|
128
128
|
end
|
129
129
|
|
130
130
|
raise Mixlib::ShellOut::CommandTimeout, [
|
@@ -398,16 +398,20 @@ module Mixlib
|
|
398
398
|
|
399
399
|
def kill_process(instance, logger)
|
400
400
|
child_pid = instance.wmi_ole_object.processid
|
401
|
-
logger
|
401
|
+
if logger
|
402
|
+
logger.debug([
|
402
403
|
"killing child process #{child_pid}::",
|
403
404
|
"#{instance.wmi_ole_object.Name} of parent #{pid}",
|
404
405
|
].join)
|
406
|
+
end
|
405
407
|
Process.kill(:KILL, instance.wmi_ole_object.processid)
|
406
408
|
rescue SystemCallError
|
407
|
-
logger
|
409
|
+
if logger
|
410
|
+
logger.debug([
|
408
411
|
"Failed to kill child process #{child_pid}::",
|
409
412
|
"#{instance.wmi_ole_object.Name} of parent #{pid}",
|
410
413
|
].join)
|
414
|
+
end
|
411
415
|
end
|
412
416
|
|
413
417
|
def format_process(process, app_name, command_line, timeout)
|
@@ -18,9 +18,11 @@
|
|
18
18
|
#
|
19
19
|
|
20
20
|
require "win32/process"
|
21
|
+
require "ffi/win32/extensions"
|
21
22
|
|
22
23
|
# Add new constants for Logon
|
23
24
|
module Process::Constants
|
25
|
+
private
|
24
26
|
|
25
27
|
LOGON32_LOGON_INTERACTIVE = 0x00000002
|
26
28
|
LOGON32_LOGON_BATCH = 0x00000004
|
@@ -44,6 +46,8 @@ module Process::Constants
|
|
44
46
|
WIN32_PROFILETYPE_PT_MANDATORY = 0x04
|
45
47
|
WIN32_PROFILETYPE_PT_ROAMING_PREEXISTING = 0x08
|
46
48
|
|
49
|
+
# The environment block list ends with two nulls (\0\0).
|
50
|
+
ENVIRONMENT_BLOCK_ENDS = "\0\0".freeze
|
47
51
|
end
|
48
52
|
|
49
53
|
# Structs required for data handling
|
@@ -77,6 +81,12 @@ module Process::Functions
|
|
77
81
|
attach_pfunc :UnloadUserProfile,
|
78
82
|
%i{handle handle}, :bool
|
79
83
|
|
84
|
+
attach_pfunc :CreateEnvironmentBlock,
|
85
|
+
%i{pointer ulong bool}, :bool
|
86
|
+
|
87
|
+
attach_pfunc :DestroyEnvironmentBlock,
|
88
|
+
%i{pointer}, :bool
|
89
|
+
|
80
90
|
ffi_lib :advapi32
|
81
91
|
|
82
92
|
attach_pfunc :LogonUserW,
|
@@ -147,13 +157,15 @@ module Process
|
|
147
157
|
si_hash = {}
|
148
158
|
|
149
159
|
# If the startup_info key is present, validate its subkeys
|
150
|
-
hash["startup_info"]
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
160
|
+
if hash["startup_info"]
|
161
|
+
hash["startup_info"].each do |key, val|
|
162
|
+
key = key.to_s.downcase
|
163
|
+
unless valid_si_keys.include?(key)
|
164
|
+
raise ArgumentError, "invalid startup_info key '#{key}'"
|
165
|
+
end
|
155
166
|
|
156
|
-
|
167
|
+
si_hash[key] = val
|
168
|
+
end
|
157
169
|
end
|
158
170
|
|
159
171
|
# The +command_line+ key is mandatory unless the +app_name+ key
|
@@ -169,9 +181,25 @@ module Process
|
|
169
181
|
|
170
182
|
env = nil
|
171
183
|
|
184
|
+
# Retrieve the environment variables for the specified user.
|
185
|
+
if hash["with_logon"]
|
186
|
+
logon, passwd, domain = format_creds_from_hash(hash)
|
187
|
+
logon_type = hash["elevated"] ? LOGON32_LOGON_BATCH : LOGON32_LOGON_INTERACTIVE
|
188
|
+
token = logon_user(logon, domain, passwd, logon_type)
|
189
|
+
logon_ptr = FFI::MemoryPointer.from_string(logon)
|
190
|
+
profile = PROFILEINFO.new.tap do |dat|
|
191
|
+
dat[:dwSize] = dat.size
|
192
|
+
dat[:dwFlags] = 1
|
193
|
+
dat[:lpUserName] = logon_ptr
|
194
|
+
end
|
195
|
+
|
196
|
+
load_user_profile(token, profile.pointer)
|
197
|
+
env_list = retrieve_environment_variables(token)
|
198
|
+
end
|
199
|
+
|
172
200
|
# The env string should be passed as a string of ';' separated paths.
|
173
201
|
if hash["environment"]
|
174
|
-
env = hash["environment"]
|
202
|
+
env = env_list.nil? ? hash["environment"] : merge_env_variables(env_list, hash["environment"])
|
175
203
|
|
176
204
|
unless env.respond_to?(:join)
|
177
205
|
env = hash["environment"].split(File::PATH_SEPARATOR)
|
@@ -393,6 +421,33 @@ module Process
|
|
393
421
|
true
|
394
422
|
end
|
395
423
|
|
424
|
+
# Retrieves the environment variables for the specified user.
|
425
|
+
#
|
426
|
+
# @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
|
427
|
+
# @param token [Integer] User token handle.
|
428
|
+
# @return [Boolean] true if successfully retrieves the environment variables for the specified user.
|
429
|
+
#
|
430
|
+
def create_environment_block(env_pointer, token)
|
431
|
+
unless CreateEnvironmentBlock(env_pointer, token, false)
|
432
|
+
raise SystemCallError.new("CreateEnvironmentBlock", FFI.errno)
|
433
|
+
end
|
434
|
+
|
435
|
+
true
|
436
|
+
end
|
437
|
+
|
438
|
+
# Frees environment variables created by the CreateEnvironmentBlock function.
|
439
|
+
#
|
440
|
+
# @param env_pointer [Pointer] The environment block is an array of null-terminated Unicode strings.
|
441
|
+
# @return [Boolean] true if successfully frees environment variables created by the CreateEnvironmentBlock function.
|
442
|
+
#
|
443
|
+
def destroy_environment_block(env_pointer)
|
444
|
+
unless DestroyEnvironmentBlock(env_pointer)
|
445
|
+
raise SystemCallError.new("DestroyEnvironmentBlock", FFI.errno)
|
446
|
+
end
|
447
|
+
|
448
|
+
true
|
449
|
+
end
|
450
|
+
|
396
451
|
def create_process_as_user(token, app, cmd, process_security,
|
397
452
|
thread_security, inherit, creation_flags, env, cwd, startinfo, procinfo)
|
398
453
|
|
@@ -527,5 +582,51 @@ module Process
|
|
527
582
|
[ logon, passwd, domain ]
|
528
583
|
end
|
529
584
|
|
585
|
+
# Retrieves the environment variables for the specified user.
|
586
|
+
#
|
587
|
+
# @param token [Integer] User token handle.
|
588
|
+
# @return env_list [Array<String>] Environment variables of specified user.
|
589
|
+
#
|
590
|
+
def retrieve_environment_variables(token)
|
591
|
+
env_list = []
|
592
|
+
env_pointer = FFI::MemoryPointer.new(:pointer)
|
593
|
+
create_environment_block(env_pointer, token)
|
594
|
+
str_ptr = env_pointer.read_pointer
|
595
|
+
offset = 0
|
596
|
+
loop do
|
597
|
+
new_str_pointer = str_ptr + offset
|
598
|
+
break if new_str_pointer.read_string(2) == ENVIRONMENT_BLOCK_ENDS
|
599
|
+
|
600
|
+
environment = new_str_pointer.read_wstring
|
601
|
+
env_list << environment
|
602
|
+
offset = offset + environment.length * 2 + 2
|
603
|
+
end
|
604
|
+
|
605
|
+
# To free the buffer when we have finished with the environment block
|
606
|
+
destroy_environment_block(str_ptr)
|
607
|
+
env_list
|
608
|
+
end
|
609
|
+
|
610
|
+
# Merge environment variables of specified user and current environment variables.
|
611
|
+
#
|
612
|
+
# @param fetched_env [Array<String>] environment variables of specified user.
|
613
|
+
# @param current_env [Array<String>] current environment variables.
|
614
|
+
# @return [Array<String>] Merged environment variables.
|
615
|
+
#
|
616
|
+
def merge_env_variables(fetched_env, current_env)
|
617
|
+
env_hash_1 = environment_list_to_hash(fetched_env)
|
618
|
+
env_hash_2 = environment_list_to_hash(current_env)
|
619
|
+
merged_env = env_hash_2.merge(env_hash_1)
|
620
|
+
merged_env.map { |k, v| "#{k}=#{v}" }
|
621
|
+
end
|
622
|
+
|
623
|
+
# Convert an array to a hash.
|
624
|
+
#
|
625
|
+
# @param env_var [Array<String>] Environment variables.
|
626
|
+
# @return [Hash] Converted an array to hash.
|
627
|
+
#
|
628
|
+
def environment_list_to_hash(env_var)
|
629
|
+
Hash[ env_var.map { |pair| pair.split("=", 2) } ]
|
630
|
+
end
|
530
631
|
end
|
531
632
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-shellout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-utils
|