puppet 4.5.2-universal-darwin → 4.5.3-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.

@@ -45,7 +45,7 @@ module Puppet::Util::Plist
45
45
  {:failonfail => true, :combine => true})
46
46
  return parse_plist(plist)
47
47
  rescue Puppet::ExecutionFailure => detail
48
- Puppet.warning("Cannot read file #{path}; Puppet is skipping it.\n" + "Details: #{detail}")
48
+ Puppet.warning("Cannot read file #{file_path}; Puppet is skipping it.\n" + "Details: #{detail}")
49
49
  end
50
50
  end
51
51
  end
@@ -158,6 +158,20 @@ module Win32
158
158
 
159
159
  MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
160
160
 
161
+ # unfortunately MSTask.h does not specify the limits for any settings
162
+ # so these were determined with some experimentation
163
+ # if values too large are written, its suspected there may be internal
164
+ # limits may be exceeded, corrupting the job
165
+ # used for max application name and path values
166
+ MAX_PATH = 260
167
+ # UNLEN from lmcons.h is 256
168
+ # https://technet.microsoft.com/it-it/library/bb726984(en-us).aspx specifies 104
169
+ MAX_ACCOUNT_LENGTH = 256
170
+ # command line max length is limited to 8191, choose something high but still enough that we don't blow out CLI
171
+ MAX_PARAMETERS_LENGTH = 4096
172
+ # in testing, this value could be set to a length of 99999, but saving / loading the task failed
173
+ MAX_COMMENT_LENGTH = 8192
174
+
161
175
  # Returns a new TaskScheduler object. If a work_item (and possibly the
162
176
  # the trigger) are passed as arguments then a new work item is created and
163
177
  # associated with that trigger, although you can still activate other tasks
@@ -212,7 +226,7 @@ module Win32
212
226
  name_ptr_ptr = FFI::Pointer.new(:pointer, names_array_ptr)
213
227
  for i in 0 ... count
214
228
  name_ptr_ptr[i].read_com_memory_pointer do |name_ptr|
215
- array << name_ptr.read_arbitrary_wide_string_up_to(256)
229
+ array << name_ptr.read_arbitrary_wide_string_up_to(MAX_PATH)
216
230
  end
217
231
  end
218
232
  end
@@ -269,12 +283,15 @@ module Win32
269
283
  #
270
284
  def save(file = nil)
271
285
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
286
+ raise Error.new('Account information must be set on the current task to save it properly.') if !@account_information_set
272
287
 
273
288
  reset = true
274
289
 
275
290
  begin
276
291
  @pITask.QueryInstance(COM::PersistFile) do |pIPersistFile|
277
- pIPersistFile.Save(wide_string(file), 1)
292
+ wide_file = wide_string(file)
293
+ pIPersistFile.Save(wide_file, 1)
294
+ pIPersistFile.SaveCompleted(wide_file)
278
295
  end
279
296
  rescue
280
297
  reset = false
@@ -311,6 +328,15 @@ module Win32
311
328
  # bad. In this case the task is created but a warning is generated and
312
329
  # false is returned.
313
330
  #
331
+ # Note that if intending to use SYSTEM, specify an empty user and nil password
332
+ #
333
+ # Calling task.set_account_information('SYSTEM', nil) will generally not
334
+ # work, except for one special case where flags are also set like:
335
+ # task.flags = Win32::TaskScheduler::TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
336
+ #
337
+ # This must be done prior to the 1st save() call for the task to be
338
+ # properly registered and visible through the MMC snap-in / schtasks.exe
339
+ #
314
340
  def set_account_information(user, password)
315
341
  raise Error.new('No current task scheduler. ITaskScheduler is NULL.') if @pITS.nil?
316
342
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
@@ -321,11 +347,15 @@ module Win32
321
347
  if (user.nil? || user=="") && (password.nil? || password=="")
322
348
  @pITask.SetAccountInformation(wide_string(""), FFI::Pointer::NULL)
323
349
  else
350
+ if user.length > MAX_ACCOUNT_LENGTH
351
+ raise Error.new("User has exceeded maximum allowed length #{MAX_ACCOUNT_LENGTH}")
352
+ end
324
353
  user = wide_string(user)
325
354
  password = wide_string(password)
326
355
  @pITask.SetAccountInformation(user, password)
327
356
  end
328
357
 
358
+ @account_information_set = true
329
359
  bool = true
330
360
  rescue Puppet::Util::Windows::Error => e
331
361
  raise e unless e.code == SCHED_E_ACCOUNT_INFORMATION_NOT_SET
@@ -350,7 +380,7 @@ module Win32
350
380
  FFI::MemoryPointer.new(:pointer) do |ptr|
351
381
  @pITask.GetAccountInformation(ptr)
352
382
  ptr.read_com_memory_pointer do |str_ptr|
353
- user = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
383
+ user = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
354
384
  end
355
385
  end
356
386
  rescue Puppet::Util::Windows::Error => e
@@ -374,7 +404,7 @@ module Win32
374
404
  @pITask.GetApplicationName(ptr)
375
405
 
376
406
  ptr.read_com_memory_pointer do |str_ptr|
377
- app = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
407
+ app = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
378
408
  end
379
409
  end
380
410
 
@@ -388,6 +418,10 @@ module Win32
388
418
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
389
419
  raise TypeError unless app.is_a?(String)
390
420
 
421
+ # the application name is written to a .job file on disk, so is subject to path limitations
422
+ if app.length > MAX_PATH
423
+ raise Error.new("Application name has exceeded maximum allowed length #{MAX_PATH}")
424
+ end
391
425
  @pITask.SetApplicationName(wide_string(app))
392
426
 
393
427
  app
@@ -405,7 +439,7 @@ module Win32
405
439
  @pITask.GetParameters(ptr)
406
440
 
407
441
  ptr.read_com_memory_pointer do |str_ptr|
408
- param = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
442
+ param = str_ptr.read_arbitrary_wide_string_up_to(MAX_PARAMETERS_LENGTH) if ! str_ptr.null?
409
443
  end
410
444
  end
411
445
 
@@ -421,6 +455,10 @@ module Win32
421
455
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
422
456
  raise TypeError unless param.is_a?(String)
423
457
 
458
+ if param.length > MAX_PARAMETERS_LENGTH
459
+ raise Error.new("Parameters has exceeded maximum allowed length #{MAX_PARAMETERS_LENGTH}")
460
+ end
461
+
424
462
  @pITask.SetParameters(wide_string(param))
425
463
 
426
464
  param
@@ -438,7 +476,7 @@ module Win32
438
476
  @pITask.GetWorkingDirectory(ptr)
439
477
 
440
478
  ptr.read_com_memory_pointer do |str_ptr|
441
- dir = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
479
+ dir = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
442
480
  end
443
481
  end
444
482
 
@@ -452,6 +490,10 @@ module Win32
452
490
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
453
491
  raise TypeError unless dir.is_a?(String)
454
492
 
493
+ if dir.length > MAX_PATH
494
+ raise Error.new("Working directory has exceeded maximum allowed length #{MAX_PATH}")
495
+ end
496
+
455
497
  @pITask.SetWorkingDirectory(wide_string(dir))
456
498
 
457
499
  dir
@@ -465,28 +507,30 @@ module Win32
465
507
  raise Error.new('No current task scheduler. ITaskScheduler is NULL.') if @pITS.nil?
466
508
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
467
509
 
510
+ priority_name = ''
511
+
468
512
  FFI::MemoryPointer.new(:dword, 1) do |ptr|
469
513
  @pITask.GetPriority(ptr)
470
514
 
471
515
  pri = ptr.read_dword
472
516
  if (pri & IDLE) != 0
473
- priority = 'idle'
517
+ priority_name = 'idle'
474
518
  elsif (pri & NORMAL) != 0
475
- priority = 'normal'
519
+ priority_name = 'normal'
476
520
  elsif (pri & HIGH) != 0
477
- priority = 'high'
521
+ priority_name = 'high'
478
522
  elsif (pri & REALTIME) != 0
479
- priority = 'realtime'
523
+ priority_name = 'realtime'
480
524
  elsif (pri & BELOW_NORMAL) != 0
481
- priority = 'below_normal'
525
+ priority_name = 'below_normal'
482
526
  elsif (pri & ABOVE_NORMAL) != 0
483
- priority = 'above_normal'
527
+ priority_name = 'above_normal'
484
528
  else
485
- priority = 'unknown'
529
+ priority_name = 'unknown'
486
530
  end
487
531
  end
488
532
 
489
- priority
533
+ priority_name
490
534
  end
491
535
 
492
536
  # Sets the priority of the task. The +priority+ should be a numeric
@@ -534,6 +578,13 @@ module Win32
534
578
  end
535
579
  end
536
580
 
581
+ # preload task with the SYSTEM account
582
+ # empty string '' means 'SYSTEM' per MSDN, so default it
583
+ # given an account is necessary for creation of a task
584
+ # note that a user may set SYSTEM explicitly, but that has problems
585
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381276(v=vs.85).aspx
586
+ set_account_information('', nil)
587
+
537
588
  @pITask
538
589
  end
539
590
 
@@ -699,7 +750,7 @@ module Win32
699
750
  @pITask.GetComment(ptr)
700
751
 
701
752
  ptr.read_com_memory_pointer do |str_ptr|
702
- comment = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
753
+ comment = str_ptr.read_arbitrary_wide_string_up_to(MAX_COMMENT_LENGTH) if ! str_ptr.null?
703
754
  end
704
755
  end
705
756
 
@@ -712,6 +763,10 @@ module Win32
712
763
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
713
764
  raise TypeError unless comment.is_a?(String)
714
765
 
766
+ if comment.length > MAX_COMMENT_LENGTH
767
+ raise Error.new("Comment has exceeded maximum allowed length #{MAX_COMMENT_LENGTH}")
768
+ end
769
+
715
770
  @pITask.SetComment(wide_string(comment))
716
771
  comment
717
772
  end
@@ -727,7 +782,7 @@ module Win32
727
782
  @pITask.GetCreator(ptr)
728
783
 
729
784
  ptr.read_com_memory_pointer do |str_ptr|
730
- creator = str_ptr.read_arbitrary_wide_string_up_to(256) if ! str_ptr.null?
785
+ creator = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
731
786
  end
732
787
  end
733
788
 
@@ -740,6 +795,11 @@ module Win32
740
795
  raise Error.new('No currently active task. ITask is NULL.') if @pITask.nil?
741
796
  raise TypeError unless creator.is_a?(String)
742
797
 
798
+ if creator.length > MAX_ACCOUNT_LENGTH
799
+ raise Error.new("Creator has exceeded maximum allowed length #{MAX_ACCOUNT_LENGTH}")
800
+ end
801
+
802
+
743
803
  @pITask.SetCreator(wide_string(creator))
744
804
  creator
745
805
  end
@@ -808,14 +868,8 @@ module Win32
808
868
 
809
869
  # Returns whether or not the scheduled task exists.
810
870
  def exists?(job_name)
811
- bool = false
812
- Dir.foreach("#{ENV['SystemRoot']}/Tasks"){ |file|
813
- if File.basename(file, '.job') == job_name
814
- bool = true
815
- break
816
- end
817
- }
818
- bool
871
+ # task name comparison is case insensitive
872
+ tasks.any? { |name| name.casecmp(job_name + '.job') == 0 }
819
873
  end
820
874
 
821
875
  private
@@ -887,6 +941,7 @@ module Win32
887
941
  # Ensure that COM reference is decremented properly
888
942
  @pITask.Release if @pITask && ! @pITask.null?
889
943
  @pITask = nil
944
+ @account_information_set = false
890
945
  end
891
946
 
892
947
  def populate_trigger(task_trigger, trigger)
@@ -927,9 +982,10 @@ module Win32
927
982
 
928
983
  trigger_struct = COM::TASK_TRIGGER.new(trigger_ptr)
929
984
  trigger_struct[:cbTriggerSize] = COM::TASK_TRIGGER.size
930
- trigger_struct[:wBeginYear] = trigger['start_year'] || 0
931
- trigger_struct[:wBeginMonth] = trigger['start_month'] || 0
932
- trigger_struct[:wBeginDay] = trigger['start_day'] || 0
985
+ now = Time.now
986
+ trigger_struct[:wBeginYear] = trigger['start_year'] || now.year
987
+ trigger_struct[:wBeginMonth] = trigger['start_month'] || now.month
988
+ trigger_struct[:wBeginDay] = trigger['start_day'] || now.day
933
989
  trigger_struct[:wEndYear] = trigger['end_year'] || 0
934
990
  trigger_struct[:wEndMonth] = trigger['end_month'] || 0
935
991
  trigger_struct[:wEndDay] = trigger['end_day'] || 0
@@ -940,7 +996,7 @@ module Win32
940
996
  trigger_struct[:rgFlags] = trigger['flags'] || 0
941
997
  trigger_struct[:TriggerType] = trigger['trigger_type'] || :TASK_TIME_TRIGGER_ONCE
942
998
  trigger_struct[:Type] = trigger_type_union
943
- trigger_struct[:wRandomMinutesInterval] = trigger['random_minutes_interval']
999
+ trigger_struct[:wRandomMinutesInterval] = trigger['random_minutes_interval'] || 0
944
1000
 
945
1001
  task_trigger.SetTrigger(trigger_struct)
946
1002
  end
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  module Puppet
10
- PUPPETVERSION = '4.5.2'
10
+ PUPPETVERSION = '4.5.3'
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -120,7 +120,7 @@ require 'puppet_spec/language'
120
120
  end
121
121
 
122
122
  it 'fails when no value is provided for required first parameter', :if => call_type == 'EPP' do
123
- expect_fail(params, [], /default expression for \$b tries to illegally access not yet evaluated \$a/)
123
+ expect_fail(params, [], /expects a value for parameter \$a/)
124
124
  end
125
125
 
126
126
  it "will use the referenced parameter's given value" do
@@ -476,6 +476,7 @@ describe "Puppet::Util::Windows::Security", :if => Puppet.features.microsoft_win
476
476
  it "should retrieve the user sid" do
477
477
  sid = nil
478
478
  user = Puppet::Util::Windows::ADSI::User.create("puppet#{rand(10000)}")
479
+ user.password = 'PUPPET_RULeZ_123!'
479
480
  user.commit
480
481
  begin
481
482
  sid = Puppet::Util::Windows::ADSI::User.new(user.name).sid.sid
@@ -90,6 +90,26 @@ describe 'the new function' do
90
90
  )).to have_resource('Notify[Integer, 1]')
91
91
  end
92
92
 
93
+ context 'when prefixed by a sign' do
94
+ { '+1' => 1,
95
+ '-1' => -1,
96
+ '+ 1' => 1,
97
+ '- 1' => -1,
98
+ '+0x10' => 16,
99
+ '+ 0x10' => 16,
100
+ '-0x10' => -16,
101
+ '- 0x10' => -16
102
+ }.each do |str, result|
103
+ it "produces #{result} from the string '#{str}'" do
104
+ expect(compile_to_catalog(<<-"MANIFEST"
105
+ $x = Integer.new("#{str}")
106
+ notify { "${type($x, generalized)}, $x": }
107
+ MANIFEST
108
+ )).to have_resource("Notify[Integer, #{result}]")
109
+ end
110
+ end
111
+ end
112
+
93
113
  context "when radix is not set it uses default and" do
94
114
  { "10" => 10,
95
115
  "010" => 8,
@@ -131,7 +151,11 @@ describe 'the new function' do
131
151
  "010" => 2,
132
152
  "00010" => 2,
133
153
  '0B111' => 7,
134
- '0b111' => 7
154
+ '0b111' => 7,
155
+ '+0B111' => 7,
156
+ '-0b111' => -7,
157
+ '+ 0B111'=> 7,
158
+ '- 0b111'=> -7
135
159
  }.each do |str, result|
136
160
  it "produces #{result} from the string '#{str}'" do
137
161
  expect(compile_to_catalog(<<-"MANIFEST"
@@ -142,8 +166,12 @@ describe 'the new function' do
142
166
  end
143
167
  end
144
168
 
145
- { "0x10" => :error,
146
- '0X10' => :error
169
+ { '0x10' => :error,
170
+ '0X10' => :error,
171
+ '+0X10' => :error,
172
+ '-0X10' => :error,
173
+ '+ 0X10'=> :error,
174
+ '- 0X10'=> :error
147
175
  }.each do |str, result|
148
176
  it "errors when given the non binary value compliant string '#{str}'" do
149
177
  expect{compile_to_catalog(<<-"MANIFEST"
@@ -158,6 +186,10 @@ describe 'the new function' do
158
186
  { "10" => 8,
159
187
  "010" => 8,
160
188
  "00010" => 8,
189
+ '+00010' => 8,
190
+ '-00010' => -8,
191
+ '+ 00010'=> 8,
192
+ '- 00010'=> -8,
161
193
  }.each do |str, result|
162
194
  it "produces #{result} from the string '#{str}'" do
163
195
  expect(compile_to_catalog(<<-"MANIFEST"
@@ -172,6 +204,10 @@ describe 'the new function' do
172
204
  '0X10' => :error,
173
205
  '0B10' => :error,
174
206
  '0b10' => :error,
207
+ '+0b10' => :error,
208
+ '-0b10' => :error,
209
+ '+ 0b10'=> :error,
210
+ '- 0b10'=> :error,
175
211
  }.each do |str, result|
176
212
  it "errors when given the non octal value compliant string '#{str}'" do
177
213
  expect{compile_to_catalog(<<-"MANIFEST"
@@ -190,6 +226,10 @@ describe 'the new function' do
190
226
  "0X10" => 16,
191
227
  "0b1" => 16*11+1,
192
228
  "0B1" => 16*11+1,
229
+ '+0B1' => 16*11+1,
230
+ '-0B1' => -16*11-1,
231
+ '+ 0B1' => 16*11+1,
232
+ '- 0B1' => -16*11-1,
193
233
  }.each do |str, result|
194
234
  it "produces #{result} from the string '#{str}'" do
195
235
  expect(compile_to_catalog(<<-"MANIFEST"
@@ -201,6 +241,10 @@ describe 'the new function' do
201
241
  end
202
242
 
203
243
  { '0XGG' => :error,
244
+ '+0XGG' => :error,
245
+ '-0XGG' => :error,
246
+ '+ 0XGG'=> :error,
247
+ '- 0XGG'=> :error,
204
248
  }.each do |str, result|
205
249
  it "errors when given the non octal value compliant string '#{str}'" do
206
250
  expect{compile_to_catalog(<<-"MANIFEST"
@@ -226,7 +270,6 @@ describe 'the new function' do
226
270
  end
227
271
 
228
272
  { '0X10' => :error,
229
- '0X10' => :error,
230
273
  '0b10' => :error,
231
274
  '0B10' => :error,
232
275
  }.each do |str, result|
@@ -291,6 +334,10 @@ describe 'the new function' do
291
334
  { 42 => "Notify[Integer, 42]",
292
335
  42.3 => "Notify[Float, 42.3]",
293
336
  "42.0" => "Notify[Float, 42.0]",
337
+ "+42.0" => "Notify[Float, 42.0]",
338
+ "-42.0" => "Notify[Float, -42.0]",
339
+ "+ 42.0" => "Notify[Float, 42.0]",
340
+ "- 42.0" => "Notify[Float, -42.0]",
294
341
  "42.3" => "Notify[Float, 42.3]",
295
342
  "0x10" => "Notify[Integer, 16]",
296
343
  "010" => "Notify[Integer, 8]",
@@ -321,6 +368,10 @@ describe 'the new function' do
321
368
  { 42 => "Notify[Float, 42.0]",
322
369
  42.3 => "Notify[Float, 42.3]",
323
370
  "42.0" => "Notify[Float, 42.0]",
371
+ "+42.0" => "Notify[Float, 42.0]",
372
+ "-42.0" => "Notify[Float, -42.0]",
373
+ "+ 42.0" => "Notify[Float, 42.0]",
374
+ "- 42.0" => "Notify[Float, -42.0]",
324
375
  "42.3" => "Notify[Float, 42.3]",
325
376
  "0x10" => "Notify[Float, 16.0]",
326
377
  "010" => "Notify[Float, 10.0]",
@@ -514,7 +565,7 @@ describe 'the new function' do
514
565
  context 'when invoked on String' do
515
566
  { {} => 'Notify[String, {}]',
516
567
  [] => 'Notify[String, []]',
517
- {'a'=>true} => 'Notify[String, {"a" => true}]',
568
+ {'a'=>true} => "Notify[String, {'a' => true}]",
518
569
  [1,2,3,4] => 'Notify[String, [1, 2, 3, 4]]',
519
570
  [[1,2],[3,4]] => 'Notify[String, [[1, 2], [3, 4]]]',
520
571
  'abcd' => 'Notify[String, abcd]',