Class: Puppet::Util::Windows::ADSI::User

Inherits:
ADSIObject show all
Extended by:
FFI::Library
Defined in:
lib/puppet/util/windows.rb,
lib/puppet/util/windows/adsi.rb

Constant Summary collapse

MAX_USERNAME_LENGTH =

UNLEN from lmcons.h - stackoverflow.com/a/2155176

256

Instance Attribute Summary

Attributes inherited from ADSIObject

#name

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FFI::Library

attach_function_private

Methods inherited from ADSIObject

#[], #[]=, #commit, delete, each, exists?, get_sids, #initialize, localized_domains, name_sid_hash, #native_object, #object_class, parse_name, #sid, #uri, uri

Methods included from Enumerable

#uniq

Constructor Details

This class inherits a constructor from Puppet::Util::Windows::ADSI::ADSIObject

Class Method Details

.create(name) ⇒ Object

Raises:



281
282
283
284
285
# File 'lib/puppet/util/windows/adsi.rb', line 281

def create(name)
  # Windows error 1379: The specified local group already exists.
  raise Puppet::Error.new(_("Cannot create user if group '%{name}' exists.") % { name: name }) if Puppet::Util::Windows::ADSI::Group.exists? name
  new(name, Puppet::Util::Windows::ADSI.create(name, @object_class))
end

.current_user_nameObject



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/puppet/util/windows/adsi.rb', line 382

def self.current_user_name
  user_name = ''
  max_length = MAX_USERNAME_LENGTH + 1 # NULL terminated
  FFI::MemoryPointer.new(max_length * 2) do |buffer| # wide string
    FFI::MemoryPointer.new(:dword, 1) do |buffer_size|
      buffer_size.write_dword(max_length) # length in TCHARs

      if GetUserNameW(buffer, buffer_size) == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error.new(_("Failed to get user name"))
      end
      # buffer_size includes trailing NULL
      user_name = buffer.read_wide_string(buffer_size.read_dword - 1)
    end
  end

  user_name
end

.current_user_sidObject



400
401
402
# File 'lib/puppet/util/windows/adsi.rb', line 400

def self.current_user_sid
  Puppet::Util::Windows::SID.name_to_principal(current_user_name)
end

.list_allObject



273
274
275
# File 'lib/puppet/util/windows/adsi.rb', line 273

def list_all
  Puppet::Util::Windows::ADSI.execquery('select name from win32_useraccount where localaccount = "TRUE"')
end

.logon(name, password) ⇒ Object



277
278
279
# File 'lib/puppet/util/windows/adsi.rb', line 277

def logon(name, password)
  Puppet::Util::Windows::User.password_is?(name, password)
end

Instance Method Details

#add_flag(flag_name, value) ⇒ Object



292
293
294
295
296
297
298
# File 'lib/puppet/util/windows/adsi.rb', line 292

def add_flag(flag_name, value)
  flag = native_object.Get(flag_name) rescue 0

  native_object.Put(flag_name, flag | value)

  commit
end

#add_group_sids(*sids) ⇒ Object



334
335
336
337
# File 'lib/puppet/util/windows/adsi.rb', line 334

def add_group_sids(*sids)
  group_names = sids.map { |s| s. }
  add_to_groups(*group_names)
end

#add_to_groups(*group_names) ⇒ Object Also known as: add_to_group



319
320
321
322
323
# File 'lib/puppet/util/windows/adsi.rb', line 319

def add_to_groups(*group_names)
  group_names.each do |group_name|
    Puppet::Util::Windows::ADSI::Group.new(group_name).add_member_sids(sid)
  end
end

#group_sidsObject



344
345
346
# File 'lib/puppet/util/windows/adsi.rb', line 344

def group_sids
  self.class.get_sids(native_object.Groups)
end

#groupsObject



310
311
312
313
314
315
316
317
# File 'lib/puppet/util/windows/adsi.rb', line 310

def groups
  # https://msdn.microsoft.com/en-us/library/aa746342.aspx
  # WIN32OLE objects aren't enumerable, so no map
  groups = []
  # Setting WIN32OLE.codepage ensures values are returned as UTF-8
  native_object.Groups.each {|g| groups << g.Name} rescue nil
  groups
end

#password=(password) ⇒ Object



300
301
302
303
304
305
306
307
308
# File 'lib/puppet/util/windows/adsi.rb', line 300

def password=(password)
  if !password.nil?
    native_object.SetPassword(password)
    commit
  end

  fADS_UF_DONT_EXPIRE_PASSWD = 0x10000
  add_flag("UserFlags", fADS_UF_DONT_EXPIRE_PASSWD)
end

#password_is?(password) ⇒ Boolean

Returns:

  • (Boolean)


288
289
290
# File 'lib/puppet/util/windows/adsi.rb', line 288

def password_is?(password)
  self.class.logon(name, password)
end

#remove_from_groups(*group_names) ⇒ Object Also known as: remove_from_group



326
327
328
329
330
# File 'lib/puppet/util/windows/adsi.rb', line 326

def remove_from_groups(*group_names)
  group_names.each do |group_name|
    Puppet::Util::Windows::ADSI::Group.new(group_name).remove_member_sids(sid)
  end
end

#remove_group_sids(*sids) ⇒ Object



339
340
341
342
# File 'lib/puppet/util/windows/adsi.rb', line 339

def remove_group_sids(*sids)
  group_names = sids.map { |s| s. }
  remove_from_groups(*group_names)
end

#set_groups(desired_groups, minimum = true) ⇒ Object

TODO: This code’s pretty similar to set_members in the Group class. Would be nice to refactor them into the ADSIObject class at some point. This was not done originally because these use different methods to do stuff that are also aliased to other methods, so the shared code isn’t exactly a 1:1 mapping.



352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/puppet/util/windows/adsi.rb', line 352

def set_groups(desired_groups, minimum = true)
  return if desired_groups.nil?

  desired_groups = desired_groups.split(',').map(&:strip)

  current_hash = Hash[ self.group_sids.map { |sid| [sid.sid, sid] } ]
  desired_hash = self.class.name_sid_hash(desired_groups)

  # First we add the user to all the groups it should be in but isn't
  if !desired_groups.empty?
    groups_to_add = (desired_hash.keys - current_hash.keys).map { |sid| desired_hash[sid] }
    add_group_sids(*groups_to_add)
  end

  # Then we remove the user from all groups it is in but shouldn't be, if
  # that's been requested
  if !minimum
    if desired_hash.empty?
      groups_to_remove = current_hash.values
    else
      groups_to_remove = (current_hash.keys - desired_hash.keys).map { |sid| current_hash[sid] }
    end

    remove_group_sids(*groups_to_remove)
  end
end