puppet 6.16.0-universal-darwin → 6.17.0-universal-darwin
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +4 -2
- data/Gemfile.lock +10 -10
- data/README.md +2 -2
- data/lib/puppet/agent.rb +2 -2
- data/lib/puppet/application/agent.rb +14 -3
- data/lib/puppet/configurer.rb +20 -12
- data/lib/puppet/confine.rb +1 -1
- data/lib/puppet/defaults.rb +25 -8
- data/lib/puppet/file_serving/http_metadata.rb +13 -1
- data/lib/puppet/file_serving/metadata.rb +4 -1
- data/lib/puppet/file_serving/terminus_selector.rb +7 -8
- data/lib/puppet/file_system/file_impl.rb +1 -1
- data/lib/puppet/file_system/uniquefile.rb +8 -16
- data/lib/puppet/forge.rb +1 -1
- data/lib/puppet/forge/cache.rb +1 -1
- data/lib/puppet/forge/repository.rb +3 -7
- data/lib/puppet/http/client.rb +5 -0
- data/lib/puppet/http/redirector.rb +9 -7
- data/lib/puppet/http/response.rb +19 -0
- data/lib/puppet/indirector.rb +1 -1
- data/lib/puppet/indirector/file_content/rest.rb +1 -1
- data/lib/puppet/indirector/file_metadata/http.rb +24 -5
- data/lib/puppet/indirector/file_metadata/rest.rb +2 -2
- data/lib/puppet/indirector/request.rb +1 -1
- data/lib/puppet/network/http/api/indirected_routes.rb +1 -1
- data/lib/puppet/network/http/api/master/v3/environment.rb +3 -0
- data/lib/puppet/network/http/connection_adapter.rb +6 -4
- data/lib/puppet/parser/ast/leaf.rb +5 -5
- data/lib/puppet/parser/ast/pops_bridge.rb +0 -4
- data/lib/puppet/parser/compiler.rb +1 -1
- data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +2 -0
- data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +2 -0
- data/lib/puppet/parser/environment_compiler.rb +4 -1
- data/lib/puppet/parser/resource.rb +3 -2
- data/lib/puppet/parser/resource/param.rb +6 -0
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -5
- data/lib/puppet/pops/issues.rb +5 -0
- data/lib/puppet/pops/resource/resource_type_impl.rb +2 -0
- data/lib/puppet/pops/validation/checker4_0.rb +10 -0
- data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
- data/lib/puppet/provider/package/aptitude.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/service/windows.rb +23 -7
- data/lib/puppet/provider/user/useradd.rb +11 -4
- data/lib/puppet/reports/http.rb +2 -0
- data/lib/puppet/resource.rb +2 -1
- data/lib/puppet/resource/type.rb +8 -0
- data/lib/puppet/ssl/ssl_context.rb +2 -2
- data/lib/puppet/ssl/ssl_provider.rb +20 -1
- data/lib/puppet/test/test_helper.rb +8 -10
- data/lib/puppet/trusted_external.rb +29 -1
- data/lib/puppet/type.rb +12 -5
- data/lib/puppet/type/file.rb +38 -13
- data/lib/puppet/type/file/checksum.rb +4 -4
- data/lib/puppet/type/file/source.rb +4 -4
- data/lib/puppet/type/service.rb +49 -0
- data/lib/puppet/util.rb +39 -15
- data/lib/puppet/util/checksums.rb +19 -4
- data/lib/puppet/util/fileparsing.rb +2 -2
- data/lib/puppet/util/provider_features.rb +1 -1
- data/lib/puppet/util/reference.rb +1 -1
- data/lib/puppet/util/windows/api_types.rb +45 -32
- data/lib/puppet/util/windows/eventlog.rb +1 -6
- data/lib/puppet/util/windows/principal.rb +8 -6
- data/lib/puppet/util/windows/registry.rb +11 -11
- data/lib/puppet/util/windows/service.rb +43 -26
- data/lib/puppet/util/windows/user.rb +23 -8
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +249 -221
- data/man/man5/puppet.conf.5 +19 -8
- data/man/man8/puppet-agent.8 +2 -2
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/agent_spec.rb +89 -0
- data/spec/integration/defaults_spec.rb +1 -2
- data/spec/integration/network/http_pool_spec.rb +26 -9
- data/spec/integration/parser/compiler_spec.rb +11 -0
- data/spec/integration/type/file_spec.rb +1 -1
- data/spec/integration/util/windows/registry_spec.rb +7 -7
- data/spec/integration/util/windows/user_spec.rb +40 -5
- data/spec/unit/configurer/fact_handler_spec.rb +4 -4
- data/spec/unit/context/trusted_information_spec.rb +10 -4
- data/spec/unit/file_serving/http_metadata_spec.rb +37 -14
- data/spec/unit/file_serving/terminus_selector_spec.rb +45 -26
- data/spec/unit/http/client_spec.rb +64 -8
- data/spec/unit/http/response_spec.rb +6 -0
- data/spec/unit/indirector/file_metadata/http_spec.rb +27 -0
- data/spec/unit/indirector/request_spec.rb +1 -1
- data/spec/unit/interface_spec.rb +3 -3
- data/spec/unit/network/http/api/indirected_routes_spec.rb +2 -1
- data/spec/unit/network/http/connection_spec.rb +42 -32
- data/spec/unit/parser/ast/block_expression_spec.rb +1 -1
- data/spec/unit/parser/environment_compiler_spec.rb +7 -0
- data/spec/unit/parser/scope_spec.rb +1 -1
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +15 -1
- data/spec/unit/pops/loaders/loaders_spec.rb +1 -1
- data/spec/unit/pops/types/type_calculator_spec.rb +1 -11
- data/spec/unit/provider/service/windows_spec.rb +22 -14
- data/spec/unit/provider/user/openbsd_spec.rb +1 -0
- data/spec/unit/provider/user/useradd_spec.rb +22 -16
- data/spec/unit/resource_spec.rb +3 -3
- data/spec/unit/ssl/ssl_provider_spec.rb +69 -43
- data/spec/unit/test/test_helper_spec.rb +17 -0
- data/spec/unit/transaction/report_spec.rb +1 -1
- data/spec/unit/type/file/source_spec.rb +3 -3
- data/spec/unit/type/file_spec.rb +122 -96
- data/spec/unit/type/service_spec.rb +176 -0
- data/spec/unit/type_spec.rb +50 -0
- data/spec/unit/util/checksums_spec.rb +16 -0
- data/spec/unit/util/windows/api_types_spec.rb +104 -40
- data/spec/unit/util/windows/service_spec.rb +4 -4
- data/spec/unit/util_spec.rb +3 -3
- data/spec/unit/x509/cert_provider_spec.rb +1 -1
- metadata +5 -5
- data/spec/integration/test/test_helper_spec.rb +0 -31
data/lib/puppet/util.rb
CHANGED
@@ -26,21 +26,20 @@ module Util
|
|
26
26
|
|
27
27
|
extend Puppet::Util::SymbolicFileMode
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
module_function :default_env
|
29
|
+
DEFAULT_ENV = if Puppet::Util::Platform.windows?
|
30
|
+
:windows
|
31
|
+
else
|
32
|
+
:posix
|
33
|
+
end.freeze
|
35
34
|
|
36
35
|
# @param name [String] The name of the environment variable to retrieve
|
37
36
|
# @param mode [Symbol] Which operating system mode to use e.g. :posix or :windows. Use nil to autodetect
|
38
37
|
# @return [String] Value of the specified environment variable. nil if it does not exist
|
39
38
|
# @api private
|
40
|
-
def get_env(name, mode =
|
39
|
+
def get_env(name, mode = DEFAULT_ENV)
|
41
40
|
if mode == :windows
|
42
|
-
Puppet::Util::Windows::Process.get_environment_strings.
|
43
|
-
if name.casecmp(key) == 0
|
41
|
+
Puppet::Util::Windows::Process.get_environment_strings.find do |key, value|
|
42
|
+
if name.casecmp(key) == 0
|
44
43
|
return value
|
45
44
|
end
|
46
45
|
end
|
@@ -54,7 +53,7 @@ module Util
|
|
54
53
|
# @param mode [Symbol] Which operating system mode to use e.g. :posix or :windows. Use nil to autodetect
|
55
54
|
# @return [Hash] A hashtable of all environment variables
|
56
55
|
# @api private
|
57
|
-
def get_environment(mode =
|
56
|
+
def get_environment(mode = DEFAULT_ENV)
|
58
57
|
case mode
|
59
58
|
when :posix
|
60
59
|
ENV.to_hash
|
@@ -69,7 +68,7 @@ module Util
|
|
69
68
|
# Removes all environment variables
|
70
69
|
# @param mode [Symbol] Which operating system mode to use e.g. :posix or :windows. Use nil to autodetect
|
71
70
|
# @api private
|
72
|
-
def clear_environment(mode =
|
71
|
+
def clear_environment(mode = DEFAULT_ENV)
|
73
72
|
case mode
|
74
73
|
when :posix
|
75
74
|
ENV.clear
|
@@ -87,7 +86,7 @@ module Util
|
|
87
86
|
# @param value [String] The value to set the variable to. nil deletes the environment variable
|
88
87
|
# @param mode [Symbol] Which operating system mode to use e.g. :posix or :windows. Use nil to autodetect
|
89
88
|
# @api private
|
90
|
-
def set_env(name, value = nil, mode =
|
89
|
+
def set_env(name, value = nil, mode = DEFAULT_ENV)
|
91
90
|
case mode
|
92
91
|
when :posix
|
93
92
|
ENV[name] = value
|
@@ -102,7 +101,7 @@ module Util
|
|
102
101
|
# @param name [Hash] Environment variables to merge into the existing environment. nil values will remove the variable
|
103
102
|
# @param mode [Symbol] Which operating system mode to use e.g. :posix or :windows. Use nil to autodetect
|
104
103
|
# @api private
|
105
|
-
def merge_environment(env_hash, mode =
|
104
|
+
def merge_environment(env_hash, mode = DEFAULT_ENV)
|
106
105
|
case mode
|
107
106
|
when :posix
|
108
107
|
env_hash.each { |name, val| ENV[name.to_s] = val }
|
@@ -296,6 +295,11 @@ module Util
|
|
296
295
|
AbsolutePathWindows = %r!^(?:(?:[A-Z]:#{slash})|(?:#{slash}#{slash}#{label}#{slash}#{label})|(?:#{slash}#{slash}\?#{slash}#{label}))!io
|
297
296
|
AbsolutePathPosix = %r!^/!
|
298
297
|
def absolute_path?(path, platform=nil)
|
298
|
+
unless path.is_a?(String)
|
299
|
+
Puppet.warning("Cannot check if #{path} is an absolute path because it is a '#{path.class}' and not a String'")
|
300
|
+
return false
|
301
|
+
end
|
302
|
+
|
299
303
|
# Ruby only sets File::ALT_SEPARATOR on Windows and the Ruby standard
|
300
304
|
# library uses that to test what platform it's on. Normally in Puppet we
|
301
305
|
# would use Puppet.features.microsoft_windows?, but this method needs to
|
@@ -356,7 +360,7 @@ module Util
|
|
356
360
|
|
357
361
|
# CGI.unescape doesn't handle space rules properly in uri paths
|
358
362
|
# URI.unescape does, but returns strings in their original encoding
|
359
|
-
path =
|
363
|
+
path = uri_unescape(uri.path.encode(Encoding::UTF_8))
|
360
364
|
|
361
365
|
if Puppet::Util::Platform.windows? && uri.scheme == 'file'
|
362
366
|
if uri.host && !uri.host.empty?
|
@@ -460,7 +464,18 @@ module Util
|
|
460
464
|
# + should be left unencoded
|
461
465
|
# URI::parse and URI::Generic.build don't like paths encoded with CGI.escape
|
462
466
|
# URI.escape does not change / to %2F and : to %3A like CGI.escape
|
463
|
-
|
467
|
+
#
|
468
|
+
# URI.escape is obsolete in Ruby 2.7. Ignore this error until we're able to
|
469
|
+
# switch to a different escape mechanism. If this is JRuby, we can't mask
|
470
|
+
# the error message, because this isn't thread safe. JRuby shouldn't be
|
471
|
+
# using Ruby 2.7 or raising the warning anyway.
|
472
|
+
orig_verbose = $VERBOSE
|
473
|
+
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
|
474
|
+
begin
|
475
|
+
encoded += URI.escape(parts[:path]) unless parts[:path].nil?
|
476
|
+
ensure
|
477
|
+
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
|
478
|
+
end
|
464
479
|
|
465
480
|
# each query parameter
|
466
481
|
if !parts[:query].nil?
|
@@ -479,6 +494,15 @@ module Util
|
|
479
494
|
end
|
480
495
|
module_function :uri_encode
|
481
496
|
|
497
|
+
def uri_unescape(path)
|
498
|
+
orig_verbose = $VERBOSE
|
499
|
+
$VERBOSE = nil unless Puppet::Util::Platform.jruby?
|
500
|
+
return URI.unescape(path)
|
501
|
+
ensure
|
502
|
+
$VERBOSE = orig_verbose unless Puppet::Util::Platform.jruby?
|
503
|
+
end
|
504
|
+
module_function :uri_unescape
|
505
|
+
|
482
506
|
def safe_posix_fork(stdin=$stdin, stdout=$stdout, stderr=$stderr, &block)
|
483
507
|
child_pid = Kernel.fork do
|
484
508
|
STDIN.reopen(stdin)
|
@@ -7,11 +7,26 @@ require 'time'
|
|
7
7
|
module Puppet::Util::Checksums
|
8
8
|
module_function
|
9
9
|
|
10
|
+
KNOWN_CHECKSUMS = [
|
11
|
+
:sha256, :sha256lite,
|
12
|
+
:md5, :md5lite,
|
13
|
+
:sha1, :sha1lite,
|
14
|
+
:sha512,
|
15
|
+
:sha384,
|
16
|
+
:sha224,
|
17
|
+
:mtime, :ctime, :none
|
18
|
+
].freeze
|
19
|
+
|
10
20
|
# It's not a good idea to use some of these in some contexts: for example, I
|
11
21
|
# wouldn't try bucketing a file using the :none checksum type.
|
12
22
|
def known_checksum_types
|
13
|
-
|
14
|
-
|
23
|
+
KNOWN_CHECKSUMS
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_checksum?(type, value)
|
27
|
+
!!send("#{type}?", value)
|
28
|
+
rescue NoMethodError
|
29
|
+
false
|
15
30
|
end
|
16
31
|
|
17
32
|
class FakeChecksum
|
@@ -223,7 +238,7 @@ module Puppet::Util::Checksums
|
|
223
238
|
|
224
239
|
# Return the :mtime timestamp of a file.
|
225
240
|
def mtime_file(filename)
|
226
|
-
Puppet::FileSystem.stat(filename).
|
241
|
+
Puppet::FileSystem.stat(filename).mtime
|
227
242
|
end
|
228
243
|
|
229
244
|
# by definition this doesn't exist
|
@@ -293,7 +308,7 @@ module Puppet::Util::Checksums
|
|
293
308
|
|
294
309
|
# Return the :ctime of a file.
|
295
310
|
def ctime_file(filename)
|
296
|
-
Puppet::FileSystem.stat(filename).
|
311
|
+
Puppet::FileSystem.stat(filename).ctime
|
297
312
|
end
|
298
313
|
|
299
314
|
def ctime_stream(&block)
|
@@ -300,7 +300,7 @@ module Puppet::Util::FileParsing
|
|
300
300
|
def record_line(name, options, &block)
|
301
301
|
raise ArgumentError, _("Must include a list of fields") unless options.include?(:fields)
|
302
302
|
|
303
|
-
record = FileRecord.new(:record, options, &block)
|
303
|
+
record = FileRecord.new(:record, **options, &block)
|
304
304
|
record.name = name.intern
|
305
305
|
|
306
306
|
new_line_type(record)
|
@@ -315,7 +315,7 @@ module Puppet::Util::FileParsing
|
|
315
315
|
def text_line(name, options, &block)
|
316
316
|
raise ArgumentError, _("You must provide a :match regex for text lines") unless options.include?(:match)
|
317
317
|
|
318
|
-
record = FileRecord.new(:text, options, &block)
|
318
|
+
record = FileRecord.new(:text, **options, &block)
|
319
319
|
record.name = name.intern
|
320
320
|
|
321
321
|
new_line_type(record)
|
@@ -62,7 +62,7 @@ module Puppet::Util::ProviderFeatures
|
|
62
62
|
@features ||= {}
|
63
63
|
raise Puppet::DevError, _("Feature %{name} is already defined") % { name: name } if @features.include?(name)
|
64
64
|
begin
|
65
|
-
obj = ProviderFeature.new(name, docs, hash)
|
65
|
+
obj = ProviderFeature.new(name, docs, **hash)
|
66
66
|
@features[obj.name] = obj
|
67
67
|
rescue ArgumentError => detail
|
68
68
|
error = ArgumentError.new(
|
@@ -19,15 +19,11 @@ module Puppet::Util::Windows::APITypes
|
|
19
19
|
|
20
20
|
class ::FFI::Pointer
|
21
21
|
NULL_HANDLE = 0
|
22
|
+
WCHAR_NULL = "\0\0".encode('UTF-16LE').freeze
|
22
23
|
|
23
24
|
def self.from_string_to_wide_string(str, &block)
|
24
25
|
str = Puppet::Util::Windows::String.wide_string(str)
|
25
|
-
FFI::MemoryPointer.
|
26
|
-
# uchar here is synonymous with byte
|
27
|
-
ptr.put_array_of_uchar(0, str.bytes.to_a)
|
28
|
-
|
29
|
-
yield ptr
|
30
|
-
end
|
26
|
+
FFI::MemoryPointer.from_wide_string(str, &block)
|
31
27
|
|
32
28
|
# ptr has already had free called, so nothing to return
|
33
29
|
nil
|
@@ -53,11 +49,17 @@ module Puppet::Util::Windows::APITypes
|
|
53
49
|
alias_method :read_word, :read_uint16
|
54
50
|
alias_method :read_array_of_wchar, :read_array_of_uint16
|
55
51
|
|
56
|
-
def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, encode_options = {})
|
52
|
+
def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, strip = false, encode_options = {})
|
57
53
|
# char_length is number of wide chars (typically excluding NULLs), *not* bytes
|
58
54
|
str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
|
55
|
+
|
56
|
+
if strip
|
57
|
+
i = str.index(WCHAR_NULL)
|
58
|
+
str = str[0, i] if i
|
59
|
+
end
|
60
|
+
|
59
61
|
str.encode(dst_encoding, str.encoding, encode_options)
|
60
|
-
rescue
|
62
|
+
rescue EncodingError => e
|
61
63
|
Puppet.debug "Unable to convert value #{str.nil? ? 'nil' : str.dump} to encoding #{dst_encoding} due to #{e.inspect}"
|
62
64
|
raise
|
63
65
|
end
|
@@ -68,32 +70,31 @@ module Puppet::Util::Windows::APITypes
|
|
68
70
|
# null_terminator = :double_null, then the terminating sequence is four bytes of zero. This is UNIT32 = 0
|
69
71
|
# @param encode_options [Hash] Accepts the same option hash that may be passed to String#encode in Ruby
|
70
72
|
def read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {})
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
idx = case null_terminator
|
74
|
+
when :single_null
|
75
|
+
# find index of wide null between 0 and max (exclusive)
|
76
|
+
(0...max_char_length).find do |i|
|
77
|
+
get_uint16(i * 2) == 0
|
78
|
+
end
|
79
|
+
when :double_null
|
80
|
+
# find index of double-wide null between 0 and max - 1 (exclusive)
|
81
|
+
(0...max_char_length - 1).find do |i|
|
82
|
+
get_uint32(i * 2) == 0
|
83
|
+
end
|
84
|
+
else
|
85
|
+
raise _("Unable to read wide strings with %{null_terminator} terminal nulls") % { null_terminator: null_terminator }
|
86
|
+
end
|
87
|
+
|
88
|
+
read_wide_string(idx || max_char_length, Encoding::UTF_8, false, encode_options)
|
85
89
|
end
|
86
90
|
|
87
91
|
def read_win32_local_pointer(&block)
|
88
|
-
ptr =
|
92
|
+
ptr = read_pointer
|
89
93
|
begin
|
90
|
-
ptr = read_pointer
|
91
94
|
yield ptr
|
92
95
|
ensure
|
93
|
-
if ptr &&
|
94
|
-
|
95
|
-
Puppet.debug "LocalFree memory leak"
|
96
|
-
end
|
96
|
+
if !ptr.null? && FFI::WIN32::LocalFree(ptr.address) != FFI::Pointer::NULL_HANDLE
|
97
|
+
Puppet.debug "LocalFree memory leak"
|
97
98
|
end
|
98
99
|
end
|
99
100
|
|
@@ -102,23 +103,35 @@ module Puppet::Util::Windows::APITypes
|
|
102
103
|
end
|
103
104
|
|
104
105
|
def read_com_memory_pointer(&block)
|
105
|
-
ptr =
|
106
|
+
ptr = read_pointer
|
106
107
|
begin
|
107
|
-
ptr = read_pointer
|
108
108
|
yield ptr
|
109
109
|
ensure
|
110
|
-
FFI::WIN32::CoTaskMemFree(ptr)
|
110
|
+
FFI::WIN32::CoTaskMemFree(ptr) unless ptr.null?
|
111
111
|
end
|
112
112
|
|
113
113
|
# ptr has already had CoTaskMemFree called, so nothing to return
|
114
114
|
nil
|
115
115
|
end
|
116
116
|
|
117
|
-
|
118
117
|
alias_method :write_dword, :write_uint32
|
119
118
|
alias_method :write_word, :write_uint16
|
120
119
|
end
|
121
120
|
|
121
|
+
class FFI::MemoryPointer
|
122
|
+
# Return a MemoryPointer that points to wide string. This is analogous to the
|
123
|
+
# FFI::MemoryPointer.from_string method.
|
124
|
+
def self.from_wide_string(wstr)
|
125
|
+
ptr = FFI::MemoryPointer.new(:uchar, wstr.bytesize + 2)
|
126
|
+
ptr.put_array_of_uchar(0, wstr.bytes.to_a)
|
127
|
+
ptr.put_uint16(wstr.bytesize, 0)
|
128
|
+
|
129
|
+
yield ptr if block_given?
|
130
|
+
|
131
|
+
ptr
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
122
135
|
# FFI Types
|
123
136
|
# https://github.com/ffi/ffi/wiki/Types
|
124
137
|
|
@@ -140,12 +140,7 @@ class Puppet::Util::Windows::EventLog
|
|
140
140
|
# @api private
|
141
141
|
def from_string_to_wide_string(str, &block)
|
142
142
|
str = wide_string(str)
|
143
|
-
FFI::MemoryPointer.
|
144
|
-
# uchar here is synonymous with byte
|
145
|
-
ptr.put_array_of_uchar(0, str.bytes.to_a)
|
146
|
-
|
147
|
-
yield ptr
|
148
|
-
end
|
143
|
+
FFI::MemoryPointer.from_wide_string(str) { |ptr| yield ptr }
|
149
144
|
|
150
145
|
# ptr has already had free called, so nothing to return
|
151
146
|
nil
|
@@ -41,6 +41,7 @@ module Puppet::Util::Windows::SID
|
|
41
41
|
# = 8 + max sub identifiers (15) * 4
|
42
42
|
MAXIMUM_SID_BYTE_LENGTH = 68
|
43
43
|
|
44
|
+
ERROR_INVALID_PARAMETER = 87
|
44
45
|
ERROR_INSUFFICIENT_BUFFER = 122
|
45
46
|
|
46
47
|
def self.lookup_account_name(system_name = nil, account_name)
|
@@ -48,9 +49,7 @@ module Puppet::Util::Windows::SID
|
|
48
49
|
begin
|
49
50
|
if system_name
|
50
51
|
system_name_wide = Puppet::Util::Windows::String.wide_string(system_name)
|
51
|
-
|
52
|
-
system_name_ptr = FFI::MemoryPointer.new(:byte, system_name_wide.bytesize)
|
53
|
-
system_name_ptr.put_array_of_uchar(0, system_name_wide.bytes.to_a)
|
52
|
+
system_name_ptr = FFI::MemoryPointer.from_wide_string(system_name_wide)
|
54
53
|
end
|
55
54
|
|
56
55
|
FFI::MemoryPointer.from_string_to_wide_string(account_name) do |account_name_ptr|
|
@@ -101,9 +100,7 @@ module Puppet::Util::Windows::SID
|
|
101
100
|
begin
|
102
101
|
if system_name
|
103
102
|
system_name_wide = Puppet::Util::Windows::String.wide_string(system_name)
|
104
|
-
|
105
|
-
system_name_ptr = FFI::MemoryPointer.new(:byte, system_name_wide.bytesize)
|
106
|
-
system_name_ptr.put_array_of_uchar(0, system_name_wide.bytes.to_a)
|
103
|
+
system_name_ptr = FFI::MemoryPointer.from_wide_string(system_name_wide)
|
107
104
|
end
|
108
105
|
|
109
106
|
FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr|
|
@@ -112,6 +109,11 @@ module Puppet::Util::Windows::SID
|
|
112
109
|
FFI::MemoryPointer.new(:uint32, 1) do |name_use_enum_ptr|
|
113
110
|
|
114
111
|
sid_ptr.write_array_of_uchar(sid_bytes)
|
112
|
+
|
113
|
+
if Puppet::Util::Windows::SID.IsValidSid(sid_ptr) == FFI::WIN32_FALSE
|
114
|
+
raise Puppet::Util::Windows::Error.new(_('Byte array for lookup_account_sid is invalid: %{sid_bytes}') % { sid_bytes: sid_bytes }, ERROR_INVALID_PARAMETER)
|
115
|
+
end
|
116
|
+
|
115
117
|
success = LookupAccountSidW(system_name_ptr, sid_ptr, FFI::Pointer::NULL, name_length_ptr,
|
116
118
|
FFI::Pointer::NULL, domain_length_ptr, name_use_enum_ptr)
|
117
119
|
last_error = FFI.errno
|
@@ -110,13 +110,16 @@ module Puppet::Util::Windows
|
|
110
110
|
|
111
111
|
private
|
112
112
|
|
113
|
-
|
113
|
+
# max number of wide characters including NULL terminator
|
114
|
+
MAX_KEY_CHAR_LENGTH = 255 + 1
|
115
|
+
|
116
|
+
def reg_enum_key(key, index, max_key_char_length = MAX_KEY_CHAR_LENGTH)
|
114
117
|
subkey, filetime = nil, nil
|
115
118
|
|
116
119
|
FFI::MemoryPointer.new(:dword) do |subkey_length_ptr|
|
117
120
|
FFI::MemoryPointer.new(FFI::WIN32::FILETIME.size) do |filetime_ptr|
|
118
|
-
FFI::MemoryPointer.new(:wchar,
|
119
|
-
subkey_length_ptr.write_dword(
|
121
|
+
FFI::MemoryPointer.new(:wchar, max_key_char_length) do |subkey_ptr|
|
122
|
+
subkey_length_ptr.write_dword(max_key_char_length)
|
120
123
|
|
121
124
|
# RegEnumKeyEx cannot be called twice to properly size the buffer
|
122
125
|
result = RegEnumKeyExW(key.hkey, index,
|
@@ -141,7 +144,10 @@ module Puppet::Util::Windows
|
|
141
144
|
[subkey, filetime]
|
142
145
|
end
|
143
146
|
|
144
|
-
|
147
|
+
# max number of wide characters including NULL terminator
|
148
|
+
MAX_VALUE_CHAR_LENGTH = 16383 + 1
|
149
|
+
|
150
|
+
def reg_enum_value(key, index, max_value_length = MAX_VALUE_CHAR_LENGTH)
|
145
151
|
subkey, type, data = nil, nil, nil
|
146
152
|
|
147
153
|
FFI::MemoryPointer.new(:dword) do |subkey_length_ptr|
|
@@ -234,7 +240,7 @@ module Puppet::Util::Windows
|
|
234
240
|
begin
|
235
241
|
case type
|
236
242
|
when Win32::Registry::REG_SZ, Win32::Registry::REG_EXPAND_SZ
|
237
|
-
result = [ type,
|
243
|
+
result = [ type, data_ptr.read_wide_string(string_length, Encoding::UTF_8, true) ]
|
238
244
|
when Win32::Registry::REG_MULTI_SZ
|
239
245
|
result = [ type, data_ptr.read_wide_string(string_length).split(/\0/) ]
|
240
246
|
when Win32::Registry::REG_BINARY
|
@@ -314,12 +320,6 @@ module Puppet::Util::Windows
|
|
314
320
|
result
|
315
321
|
end
|
316
322
|
|
317
|
-
def sanitize(value)
|
318
|
-
# Replace null bytes with a space
|
319
|
-
value.tr!("\x00", ' ')
|
320
|
-
value
|
321
|
-
end
|
322
|
-
|
323
323
|
ffi_convention :stdcall
|
324
324
|
|
325
325
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms724862(v=vs.85).aspx
|
@@ -440,43 +440,60 @@ module Puppet::Util::Windows
|
|
440
440
|
end
|
441
441
|
module_function :service_start_type
|
442
442
|
|
443
|
-
#
|
443
|
+
# Query the configuration of a service using QueryServiceConfigW
|
444
|
+
# to find its current logon account
|
444
445
|
#
|
445
|
-
# @
|
446
|
-
#
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
if startup_code.nil?
|
453
|
-
raise Puppet::Error.new(_("Unknown start type %{start_type}") % {startup_type: startup_type.to_s})
|
446
|
+
# @return [String] logon_account account currently set for the service's logon
|
447
|
+
# in the format "DOMAIN\Account" or ".\Account" if it's a local account
|
448
|
+
def logon_account(service_name)
|
449
|
+
open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_CONFIG) do |service|
|
450
|
+
query_config(service) do |config|
|
451
|
+
return config[:lpServiceStartName].read_arbitrary_wide_string_up_to(Puppet::Util::Windows::ADSI::User::MAX_USERNAME_LENGTH)
|
452
|
+
end
|
454
453
|
end
|
454
|
+
end
|
455
|
+
module_function :logon_account
|
456
|
+
|
457
|
+
# Set the startup configuration of a windows service
|
458
|
+
#
|
459
|
+
# @param [String] service_name the name of the service to modify
|
460
|
+
# @param [Hash] options the configuration to be applied. Expected option keys:
|
461
|
+
# - [Integer] startup_type a code corresponding to a start type for
|
462
|
+
# windows service, see the "Service start type codes" section in the
|
463
|
+
# Puppet::Util::Windows::Service file for the list of available codes
|
464
|
+
# - [String] logon_account the account to be used by the service for logon
|
465
|
+
# - [String] logon_password the provided logon_account's password to be used by the service for logon
|
466
|
+
# - [Bool] delayed whether the service should be started with a delay
|
467
|
+
def set_startup_configuration(service_name, options: {})
|
468
|
+
options[:startup_type] = SERVICE_START_TYPES.key(options[:startup_type]) || SERVICE_NO_CHANGE
|
469
|
+
options[:logon_account] = wide_string(options[:logon_account]) || FFI::Pointer::NULL
|
470
|
+
options[:logon_password] = wide_string(options[:logon_password]) || FFI::Pointer::NULL
|
471
|
+
|
455
472
|
open_service(service_name, SC_MANAGER_CONNECT, SERVICE_CHANGE_CONFIG) do |service|
|
456
|
-
# Currently the only thing puppet's API can really manage
|
457
|
-
# in this list is dwStartType (the third param). Thus no
|
458
|
-
# generic function was written to make use of all the params
|
459
|
-
# since the API as-is couldn't use them anyway
|
460
473
|
success = ChangeServiceConfigW(
|
461
474
|
service,
|
462
|
-
SERVICE_NO_CHANGE,
|
463
|
-
|
464
|
-
SERVICE_NO_CHANGE,
|
465
|
-
FFI::Pointer::NULL,
|
466
|
-
FFI::Pointer::NULL,
|
467
|
-
FFI::Pointer::NULL,
|
468
|
-
FFI::Pointer::NULL,
|
469
|
-
|
470
|
-
|
471
|
-
FFI::Pointer::NULL
|
475
|
+
SERVICE_NO_CHANGE, # dwServiceType
|
476
|
+
options[:startup_type], # dwStartType
|
477
|
+
SERVICE_NO_CHANGE, # dwErrorControl
|
478
|
+
FFI::Pointer::NULL, # lpBinaryPathName
|
479
|
+
FFI::Pointer::NULL, # lpLoadOrderGroup
|
480
|
+
FFI::Pointer::NULL, # lpdwTagId
|
481
|
+
FFI::Pointer::NULL, # lpDependencies
|
482
|
+
options[:logon_account], # lpServiceStartName
|
483
|
+
options[:logon_password], # lpPassword
|
484
|
+
FFI::Pointer::NULL # lpDisplayName
|
472
485
|
)
|
473
486
|
if success == FFI::WIN32_FALSE
|
474
487
|
raise Puppet::Util::Windows::Error.new(_("Failed to update service configuration"))
|
475
488
|
end
|
476
489
|
end
|
477
|
-
|
490
|
+
|
491
|
+
if options[:startup_type]
|
492
|
+
options[:delayed] ||= false
|
493
|
+
set_startup_mode_delayed(service_name, options[:delayed])
|
494
|
+
end
|
478
495
|
end
|
479
|
-
module_function :
|
496
|
+
module_function :set_startup_configuration
|
480
497
|
|
481
498
|
# enumerate over all services in all states and return them as a hash
|
482
499
|
#
|