puppet 5.5.14-universal-darwin → 5.5.16-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 +2 -0
- data/Gemfile.lock +18 -17
- data/ext/solaris/smf/puppet.xml +2 -0
- data/lib/hiera/scope.rb +7 -0
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/device.rb +22 -10
- data/lib/puppet/configurer.rb +23 -38
- data/lib/puppet/network/http/connection.rb +2 -0
- data/lib/puppet/pops/types/types.rb +5 -3
- data/lib/puppet/provider.rb +1 -2
- data/lib/puppet/provider/cron/crontab.rb +1 -1
- data/lib/puppet/provider/package.rb +2 -0
- data/lib/puppet/provider/package/dpkg.rb +15 -2
- data/lib/puppet/provider/package/gem.rb +65 -29
- data/lib/puppet/provider/package/pip.rb +136 -111
- data/lib/puppet/provider/package/pip3.rb +1 -1
- data/lib/puppet/provider/package/puppet_gem.rb +1 -1
- data/lib/puppet/provider/package/rpm.rb +27 -16
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/package_targetable.rb +68 -0
- data/lib/puppet/provider/service/upstart.rb +8 -8
- data/lib/puppet/provider/user/useradd.rb +16 -13
- data/lib/puppet/settings/server_list_setting.rb +9 -0
- data/lib/puppet/ssl/validator/default_validator.rb +30 -0
- data/lib/puppet/type/package.rb +46 -9
- data/lib/puppet/util/pidlock.rb +15 -1
- data/lib/puppet/util/windows/process.rb +70 -0
- data/lib/puppet/util/windows/registry.rb +7 -1
- data/lib/puppet/util/windows/user.rb +14 -4
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +81 -78
- data/man/man5/puppet.conf.5 +2 -2
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-ca.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-cert.8 +1 -1
- data/man/man8/puppet-certificate.8 +1 -1
- data/man/man8/puppet-certificate_request.8 +1 -1
- data/man/man8/puppet-certificate_revocation_list.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-master.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-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/network/http_pool_spec.rb +120 -0
- data/spec/integration/type/package_spec.rb +1 -1
- data/spec/integration/util/windows/registry_spec.rb +52 -0
- data/spec/integration/util/windows/user_spec.rb +19 -0
- data/spec/lib/puppet_spec/https.rb +166 -0
- data/spec/unit/configurer_spec.rb +49 -13
- data/spec/unit/functions/new_spec.rb +15 -0
- data/spec/unit/hiera/scope_spec.rb +7 -0
- data/spec/unit/network/http/connection_spec.rb +0 -130
- data/spec/unit/provider/package/dpkg_spec.rb +18 -1
- data/spec/unit/provider/package/gem_spec.rb +101 -48
- data/spec/unit/provider/package/pip3_spec.rb +17 -0
- data/spec/unit/provider/package/pip_spec.rb +59 -68
- data/spec/unit/provider/package/puppet_gem_spec.rb +22 -6
- data/spec/unit/provider/package/rpm_spec.rb +116 -27
- data/spec/unit/provider/service/upstart_spec.rb +3 -19
- data/spec/unit/settings/server_list_setting_spec.rb +21 -0
- data/spec/unit/ssl/validator_spec.rb +2 -0
- data/spec/unit/util/pidlock_spec.rb +46 -0
- metadata +9 -2
@@ -27,14 +27,14 @@ Puppet::Type.type(:service).provide :upstart, :parent => :debian do
|
|
27
27
|
# We only want to use upstart as our provider if the upstart daemon is running.
|
28
28
|
# This can be checked by running `initctl version --quiet` on a machine that has
|
29
29
|
# upstart installed.
|
30
|
-
confine :true => lambda {
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
confine :true => lambda { has_initctl? }
|
31
|
+
|
32
|
+
def self.has_initctl?
|
33
|
+
initctl('version', '--quiet')
|
34
|
+
true
|
35
|
+
rescue
|
36
|
+
false
|
37
|
+
end
|
38
38
|
|
39
39
|
# upstart developer haven't implemented initctl enable/disable yet:
|
40
40
|
# http://www.linuxplanet.com/linuxplanet/tutorials/7033/2/
|
@@ -105,11 +105,11 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
105
105
|
# because by default duplicates are allowed. This check is
|
106
106
|
# to ensure consistent behaviour of the useradd provider when
|
107
107
|
# using both useradd and luseradd
|
108
|
-
if
|
109
|
-
if @resource.should(:uid)
|
108
|
+
if (!@resource.allowdupe?) && @resource.forcelocal?
|
109
|
+
if @resource.should(:uid) && finduser('uid', @resource.should(:uid).to_s)
|
110
110
|
raise(Puppet::Error, "UID #{@resource.should(:uid).to_s} already exists, use allowdupe to force user creation")
|
111
111
|
end
|
112
|
-
elsif @resource.allowdupe?
|
112
|
+
elsif @resource.allowdupe? && (!@resource.forcelocal?)
|
113
113
|
return ["-o"]
|
114
114
|
end
|
115
115
|
[]
|
@@ -126,16 +126,16 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
126
126
|
|
127
127
|
def check_manage_home
|
128
128
|
cmd = []
|
129
|
-
if @resource.managehome?
|
129
|
+
if @resource.managehome? && (!@resource.forcelocal?)
|
130
130
|
cmd << "-m"
|
131
|
-
elsif
|
131
|
+
elsif (!@resource.managehome?) && Facter.value(:osfamily) == 'RedHat'
|
132
132
|
cmd << "-M"
|
133
133
|
end
|
134
134
|
cmd
|
135
135
|
end
|
136
136
|
|
137
137
|
def check_system_users
|
138
|
-
if self.class.system_users?
|
138
|
+
if self.class.system_users? && resource.system?
|
139
139
|
["-r"]
|
140
140
|
else
|
141
141
|
[]
|
@@ -149,11 +149,11 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
149
149
|
Puppet::Type.type(:user).validproperties.sort.each do |property|
|
150
150
|
next if property == :ensure
|
151
151
|
next if property_manages_password_age?(property)
|
152
|
-
next if property == :groups
|
153
|
-
next if property == :expiry
|
152
|
+
next if (property == :groups) && @resource.forcelocal?
|
153
|
+
next if (property == :expiry) && @resource.forcelocal?
|
154
154
|
# the value needs to be quoted, mostly because -c might
|
155
155
|
# have spaces in it
|
156
|
-
if value = @resource.should(property)
|
156
|
+
if (value = @resource.should(property)) && (value != "")
|
157
157
|
cmd << flag(property) << munge(property, value)
|
158
158
|
end
|
159
159
|
end
|
@@ -167,7 +167,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
167
167
|
else
|
168
168
|
cmd = [command(:add)]
|
169
169
|
end
|
170
|
-
if
|
170
|
+
if (!@resource.should(:gid)) && Puppet::Util.gid(@resource[:name])
|
171
171
|
cmd += ["-g", @resource[:name]]
|
172
172
|
end
|
173
173
|
cmd += add_properties
|
@@ -203,7 +203,10 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
203
203
|
else
|
204
204
|
cmd = [command(:delete)]
|
205
205
|
end
|
206
|
-
|
206
|
+
# Solaris `userdel -r` will fail if the homedir does not exist.
|
207
|
+
if @resource.managehome? && (('Solaris' != Facter.value(:operatingsystem)) || Dir.exist?(Dir.home(@resource[:name])))
|
208
|
+
cmd << '-r'
|
209
|
+
end
|
207
210
|
cmd << @resource[:name]
|
208
211
|
end
|
209
212
|
|
@@ -239,10 +242,10 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
239
242
|
check_valid_shell
|
240
243
|
end
|
241
244
|
super
|
242
|
-
if @resource.forcelocal?
|
245
|
+
if @resource.forcelocal? && self.groups?
|
243
246
|
set(:groups, @resource[:groups])
|
244
247
|
end
|
245
|
-
if @resource.forcelocal?
|
248
|
+
if @resource.forcelocal? && @resource[:expiry]
|
246
249
|
set(:expiry, @resource[:expiry])
|
247
250
|
end
|
248
251
|
end
|
@@ -4,6 +4,15 @@ class Puppet::Settings::ServerListSetting < Puppet::Settings::ArraySetting
|
|
4
4
|
:server_list
|
5
5
|
end
|
6
6
|
|
7
|
+
def print(value)
|
8
|
+
if value.is_a?(Array)
|
9
|
+
#turn into a string
|
10
|
+
value.map {|item| item.join(":") }.join(",")
|
11
|
+
else
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
def munge(value)
|
8
17
|
servers = super
|
9
18
|
servers.map! { |server|
|
@@ -10,6 +10,7 @@ class Puppet::SSL::Validator::DefaultValidator #< class Puppet::SSL::Validator
|
|
10
10
|
attr_reader :peer_certs
|
11
11
|
attr_reader :verify_errors
|
12
12
|
attr_reader :ssl_configuration
|
13
|
+
attr_reader :last_error
|
13
14
|
|
14
15
|
FIVE_MINUTES_AS_SECONDS = 5 * 60
|
15
16
|
|
@@ -40,6 +41,8 @@ class Puppet::SSL::Validator::DefaultValidator #< class Puppet::SSL::Validator
|
|
40
41
|
def reset!
|
41
42
|
@peer_certs = []
|
42
43
|
@verify_errors = []
|
44
|
+
@hostname = nil
|
45
|
+
@last_error = nil
|
43
46
|
end
|
44
47
|
|
45
48
|
# Performs verification of the SSL connection and collection of the
|
@@ -85,6 +88,31 @@ class Puppet::SSL::Validator::DefaultValidator #< class Puppet::SSL::Validator
|
|
85
88
|
error_string = store_context.error_string || "OpenSSL error #{error}"
|
86
89
|
|
87
90
|
case error
|
91
|
+
when OpenSSL::X509::V_OK
|
92
|
+
if @hostname
|
93
|
+
# chain is from leaf to root, opposite of the order that `call` is invoked
|
94
|
+
chain_cert = store_context.chain.first
|
95
|
+
peer_cert = @peer_certs.last
|
96
|
+
|
97
|
+
# ruby 2.4 doesn't compare certs based on value, so force to DER byte array
|
98
|
+
if peer_cert && chain_cert && peer_cert.content.to_der == chain_cert.to_der && !OpenSSL::SSL.verify_certificate_identity(peer_cert.content, @hostname)
|
99
|
+
valid_certnames = [peer_cert.name, *peer_cert.subject_alt_names].uniq
|
100
|
+
if valid_certnames.size > 1
|
101
|
+
expected_certnames = _("expected one of %{certnames}") % { certnames: valid_certnames.join(', ') }
|
102
|
+
else
|
103
|
+
expected_certnames = _("expected %{certname}") % { certname: valid_certnames.first }
|
104
|
+
end
|
105
|
+
|
106
|
+
msg = _("Server hostname '%{host}' did not match server certificate; %{expected_certnames}") % { host: @hostname, expected_certnames: expected_certnames }
|
107
|
+
@last_error = Puppet::Error.new(msg)
|
108
|
+
return false
|
109
|
+
else
|
110
|
+
@verify_errors << "#{error_string} for #{current_cert.subject}"
|
111
|
+
end
|
112
|
+
else
|
113
|
+
@verify_errors << "#{error_string} for #{current_cert.subject}"
|
114
|
+
end
|
115
|
+
|
88
116
|
when OpenSSL::X509::V_ERR_CRL_NOT_YET_VALID
|
89
117
|
# current_crl can be nil
|
90
118
|
# https://github.com/ruby/ruby/blob/ruby_1_9_3/ext/openssl/ossl_x509store.c#L501-L510
|
@@ -118,6 +146,8 @@ class Puppet::SSL::Validator::DefaultValidator #< class Puppet::SSL::Validator
|
|
118
146
|
# @api private
|
119
147
|
#
|
120
148
|
def setup_connection(connection)
|
149
|
+
@hostname = connection.address
|
150
|
+
|
121
151
|
if ssl_certificates_are_present?
|
122
152
|
connection.cert_store = @ssl_host.ssl_store
|
123
153
|
connection.ca_file = @ssl_configuration.ca_auth_file
|
data/lib/puppet/type/package.rb
CHANGED
@@ -20,8 +20,8 @@ module Puppet
|
|
20
20
|
requires in order to function, and you must meet those requirements
|
21
21
|
to use a given provider.
|
22
22
|
|
23
|
-
You can declare multiple package resources with the same `name
|
24
|
-
as they specify different providers and
|
23
|
+
You can declare multiple package resources with the same `name` as long
|
24
|
+
as they have unique titles, and specify different providers and commands.
|
25
25
|
|
26
26
|
Note that you must use the _title_ to make a reference to a package
|
27
27
|
resource; `Package[<NAME>]` is not a synonym for `Package[<TITLE>]` like
|
@@ -66,6 +66,8 @@ module Puppet
|
|
66
66
|
:methods => [:package_settings_insync?, :package_settings, :package_settings=]
|
67
67
|
feature :virtual_packages, "The provider accepts virtual package names for install and uninstall."
|
68
68
|
|
69
|
+
feature :targetable, "The provider accepts a targeted package management command."
|
70
|
+
|
69
71
|
ensurable do
|
70
72
|
desc <<-EOT
|
71
73
|
What state the package should be in. On packaging systems that can
|
@@ -271,20 +273,55 @@ module Puppet
|
|
271
273
|
providify
|
272
274
|
paramclass(:provider).isnamevar
|
273
275
|
|
274
|
-
#
|
275
|
-
|
276
|
-
|
277
|
-
|
276
|
+
# Specify a targeted package management command.
|
277
|
+
newparam(:command, :required_features => :targetable) do
|
278
|
+
desc <<-EOT
|
279
|
+
The targeted command to use when managing a package:
|
280
|
+
|
281
|
+
package { 'mysql':
|
282
|
+
provider => gem,
|
283
|
+
}
|
284
|
+
|
285
|
+
package { 'mysql-opt':
|
286
|
+
name => 'mysql',
|
287
|
+
provider => gem,
|
288
|
+
command => '/opt/ruby/bin/gem',
|
289
|
+
}
|
290
|
+
|
291
|
+
Each provider defines a package management command; and uses the first
|
292
|
+
instance of the command found in the PATH.
|
293
|
+
|
294
|
+
Providers supporting the targetable feature allow you to specify the
|
295
|
+
absolute path of the package management command; useful when multiple
|
296
|
+
instances of the command are installed, or the command is not in the PATH.
|
297
|
+
EOT
|
298
|
+
|
299
|
+
isnamevar
|
300
|
+
defaultto :default
|
301
|
+
end
|
302
|
+
|
303
|
+
# We have more than one namevar, so we need title_patterns.
|
304
|
+
# However, we cheat and set the patterns to map to name only
|
305
|
+
# and completely ignore provider (and command, for targetable providers).
|
306
|
+
# So far, the logic that determines uniqueness appears to just
|
307
|
+
# "Do The Right Thing™" when provider (and command) are explicitly set.
|
278
308
|
#
|
279
309
|
# The following resources will be seen as unique by puppet:
|
280
310
|
#
|
281
311
|
# # Uniqueness Key: ['mysql', nil]
|
282
|
-
# package{'mysql': }
|
312
|
+
# package {'mysql': }
|
313
|
+
#
|
314
|
+
# # Uniqueness Key: ['mysql', 'gem', nil]
|
315
|
+
# package {'gem-mysql':
|
316
|
+
# name => 'mysql,
|
317
|
+
# provider => gem,
|
318
|
+
# }
|
283
319
|
#
|
284
|
-
# # Uniqueness Key: ['mysql', 'gem']
|
285
|
-
# package{'gem-mysql':
|
320
|
+
# # Uniqueness Key: ['mysql', 'gem', '/opt/ruby/bin/gem']
|
321
|
+
# package {'gem-mysql-opt':
|
286
322
|
# name => 'mysql,
|
287
323
|
# provider => gem
|
324
|
+
# command => '/opt/ruby/bin/gem',
|
288
325
|
# }
|
289
326
|
#
|
290
327
|
# This does not handle the case where providers like 'yum' and 'rpm' should
|
data/lib/puppet/util/pidlock.rb
CHANGED
@@ -54,7 +54,21 @@ class Puppet::Util::Pidlock
|
|
54
54
|
begin
|
55
55
|
Process.kill(0, lock_pid)
|
56
56
|
rescue *errors
|
57
|
-
@lockfile.unlock
|
57
|
+
return @lockfile.unlock
|
58
|
+
end
|
59
|
+
|
60
|
+
# Ensure the process associated with this pid is our process. If
|
61
|
+
# not, we can unlock the lockfile. For now this is only done on
|
62
|
+
# POSIX and Windows platforms (PUP-9247).
|
63
|
+
if Puppet.features.posix?
|
64
|
+
procname = Puppet::Util::Execution.execute(["ps", "-p", lock_pid, "-o", "comm="]).strip
|
65
|
+
args = Puppet::Util::Execution.execute(["ps", "-p", lock_pid, "-o", "args="]).strip
|
66
|
+
@lockfile.unlock unless procname =~ /ruby/ && args =~ /puppet/ || procname =~ /puppet(-.*)?$/
|
67
|
+
elsif Puppet.features.microsoft_windows?
|
68
|
+
# On Windows, we're checking if the filesystem path name of the running
|
69
|
+
# process is our vendored ruby:
|
70
|
+
exe_path = Puppet::Util::Windows::Process::get_process_image_name_by_pid(lock_pid)
|
71
|
+
@lockfile.unlock unless exe_path =~ /\\bin\\ruby.exe$/
|
58
72
|
end
|
59
73
|
end
|
60
74
|
private :clear_if_stale
|
@@ -10,6 +10,10 @@ module Puppet::Util::Windows::Process
|
|
10
10
|
WAIT_INTERVAL = 200
|
11
11
|
# https://docs.microsoft.com/en-us/windows/desktop/ProcThread/process-creation-flags
|
12
12
|
CREATE_NO_WINDOW = 0x08000000
|
13
|
+
#https://docs.microsoft.com/en-us/windows/desktop/ProcThread/process-security-and-access-rights
|
14
|
+
PROCESS_QUERY_INFORMATION = 0x0400
|
15
|
+
# https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
|
16
|
+
MAX_PATH_LENGTH = 32767
|
13
17
|
|
14
18
|
def execute(command, arguments, stdin, stdout, stderr)
|
15
19
|
create_args = {
|
@@ -62,6 +66,26 @@ module Puppet::Util::Windows::Process
|
|
62
66
|
end
|
63
67
|
module_function :get_current_process
|
64
68
|
|
69
|
+
def open_process(desired_access, inherit_handle, process_id, &block)
|
70
|
+
phandle = nil
|
71
|
+
inherit = inherit_handle ? FFI::WIN32_TRUE : FFI::WIN32_FALSE
|
72
|
+
begin
|
73
|
+
phandle = OpenProcess(desired_access, inherit, process_id)
|
74
|
+
if phandle == FFI::Pointer::NULL_HANDLE
|
75
|
+
raise Puppet::Util::Windows::Error.new(
|
76
|
+
"OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id})")
|
77
|
+
end
|
78
|
+
|
79
|
+
yield phandle
|
80
|
+
ensure
|
81
|
+
FFI::WIN32.CloseHandle(phandle) if phandle
|
82
|
+
end
|
83
|
+
|
84
|
+
# phandle has had CloseHandle called against it, so nothing to return
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
module_function :open_process
|
88
|
+
|
65
89
|
def open_process_token(handle, desired_access, &block)
|
66
90
|
token_handle = nil
|
67
91
|
begin
|
@@ -97,6 +121,32 @@ module Puppet::Util::Windows::Process
|
|
97
121
|
end
|
98
122
|
module_function :with_process_token
|
99
123
|
|
124
|
+
def get_process_image_name_by_pid(pid)
|
125
|
+
image_name = ""
|
126
|
+
|
127
|
+
open_process(PROCESS_QUERY_INFORMATION, false, pid) do |phandle|
|
128
|
+
|
129
|
+
FFI::MemoryPointer.new(:dword, 1) do |exe_name_length_ptr|
|
130
|
+
# UTF is 2 bytes/char:
|
131
|
+
max_chars = MAX_PATH_LENGTH + 1
|
132
|
+
exe_name_length_ptr.write_dword(max_chars)
|
133
|
+
FFI::MemoryPointer.new(:wchar, max_chars) do |exe_name_ptr|
|
134
|
+
use_win32_path_format = 0
|
135
|
+
result = QueryFullProcessImageNameW(phandle, use_win32_path_format, exe_name_ptr, exe_name_length_ptr)
|
136
|
+
if result == FFI::WIN32_FALSE
|
137
|
+
raise Puppet::Util::Windows::Error.new(
|
138
|
+
"QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, " +
|
139
|
+
"exe_name_ptr, #{max_chars}")
|
140
|
+
end
|
141
|
+
image_name = exe_name_ptr.read_wide_string(exe_name_length_ptr.read_dword)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
image_name
|
147
|
+
end
|
148
|
+
module_function :get_process_image_name_by_pid
|
149
|
+
|
100
150
|
def lookup_privilege_value(name, system_name = '', &block)
|
101
151
|
FFI::MemoryPointer.new(LUID.size) do |luid_ptr|
|
102
152
|
result = LookupPrivilegeValueW(
|
@@ -366,6 +416,16 @@ module Puppet::Util::Windows::Process
|
|
366
416
|
attach_function_private :SetEnvironmentVariableW,
|
367
417
|
[:lpcwstr, :lpcwstr], :win32_bool
|
368
418
|
|
419
|
+
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx
|
420
|
+
# HANDLE WINAPI OpenProcess(
|
421
|
+
# _In_ DWORD DesiredAccess,
|
422
|
+
# _In_ BOOL InheritHandle,
|
423
|
+
# _In_ DWORD ProcessId
|
424
|
+
# );
|
425
|
+
ffi_lib :kernel32
|
426
|
+
attach_function_private :OpenProcess,
|
427
|
+
[:dword, :win32_bool, :dword], :handle
|
428
|
+
|
369
429
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379295(v=vs.85).aspx
|
370
430
|
# BOOL WINAPI OpenProcessToken(
|
371
431
|
# _In_ HANDLE ProcessHandle,
|
@@ -376,6 +436,16 @@ module Puppet::Util::Windows::Process
|
|
376
436
|
attach_function_private :OpenProcessToken,
|
377
437
|
[:handle, :dword, :phandle], :win32_bool
|
378
438
|
|
439
|
+
# https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-queryfullprocessimagenamew
|
440
|
+
# BOOL WINAPI QueryFullProcessImageName(
|
441
|
+
# _In_ HANDLE hProcess,
|
442
|
+
# _In_ DWORD dwFlags,
|
443
|
+
# _Out_ LPWSTR lpExeName,
|
444
|
+
# _In_ PDWORD lpdwSize,
|
445
|
+
# );
|
446
|
+
ffi_lib :kernel32
|
447
|
+
attach_function_private :QueryFullProcessImageNameW,
|
448
|
+
[:handle, :dword, :lpwstr, :pdword], :win32_bool
|
379
449
|
|
380
450
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379261(v=vs.85).aspx
|
381
451
|
# typedef struct _LUID {
|
@@ -232,7 +232,7 @@ module Puppet::Util::Windows
|
|
232
232
|
begin
|
233
233
|
case type
|
234
234
|
when Win32::Registry::REG_SZ, Win32::Registry::REG_EXPAND_SZ
|
235
|
-
result = [ type, data_ptr.read_wide_string(string_length) ]
|
235
|
+
result = [ type, sanitize(data_ptr.read_wide_string(string_length)) ]
|
236
236
|
when Win32::Registry::REG_MULTI_SZ
|
237
237
|
result = [ type, data_ptr.read_wide_string(string_length).split(/\0/) ]
|
238
238
|
when Win32::Registry::REG_BINARY
|
@@ -312,6 +312,12 @@ module Puppet::Util::Windows
|
|
312
312
|
result
|
313
313
|
end
|
314
314
|
|
315
|
+
def sanitize(value)
|
316
|
+
# Replace null bytes with a space
|
317
|
+
value.gsub!("\x00", ' ')
|
318
|
+
value
|
319
|
+
end
|
320
|
+
|
315
321
|
ffi_convention :stdcall
|
316
322
|
|
317
323
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms724862(v=vs.85).aspx
|
@@ -75,15 +75,18 @@ module Puppet::Util::Windows::User
|
|
75
75
|
module_function :password_is?
|
76
76
|
|
77
77
|
def logon_user(name, password, &block)
|
78
|
-
fLOGON32_LOGON_NETWORK = 3
|
79
78
|
fLOGON32_PROVIDER_DEFAULT = 0
|
79
|
+
fLOGON32_LOGON_INTERACTIVE = 2
|
80
|
+
fLOGON32_LOGON_NETWORK = 3
|
80
81
|
|
81
82
|
token = nil
|
82
83
|
begin
|
83
84
|
FFI::MemoryPointer.new(:handle, 1) do |token_pointer|
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
#try logon using network else try logon using interactive mode
|
86
|
+
if logon_user_by_logon_type(name, password, fLOGON32_LOGON_NETWORK, fLOGON32_PROVIDER_DEFAULT, token_pointer) == FFI::WIN32_FALSE
|
87
|
+
if logon_user_by_logon_type(name, password, fLOGON32_LOGON_INTERACTIVE, fLOGON32_PROVIDER_DEFAULT, token_pointer) == FFI::WIN32_FALSE
|
88
|
+
raise Puppet::Util::Windows::Error.new(_("Failed to logon user %{name}") % {name: name.inspect})
|
89
|
+
end
|
87
90
|
end
|
88
91
|
|
89
92
|
yield token = token_pointer.read_handle
|
@@ -95,8 +98,15 @@ module Puppet::Util::Windows::User
|
|
95
98
|
# token has been closed by this point
|
96
99
|
true
|
97
100
|
end
|
101
|
+
|
98
102
|
module_function :logon_user
|
99
103
|
|
104
|
+
def self.logon_user_by_logon_type(name, password, logon_type, logon_provider, token)
|
105
|
+
LogonUserW(wide_string(name), wide_string('.'), password.nil? ? FFI::Pointer::NULL : wide_string(password), logon_type, logon_provider, token)
|
106
|
+
end
|
107
|
+
|
108
|
+
private_class_method :logon_user_by_logon_type
|
109
|
+
|
100
110
|
def load_profile(user, password)
|
101
111
|
logon_user(user, password) do |token|
|
102
112
|
FFI::MemoryPointer.from_string_to_wide_string(user) do |lpUserName|
|