summaryrefslogtreecommitdiff
path: root/lib/chef/win32/security/sid.rb
diff options
context:
space:
mode:
authorsersut <serdar@opscode.com>2014-07-09 16:05:27 -0700
committersersut <serdar@opscode.com>2014-07-14 13:18:31 -0700
commit04612158ac256ce46faad599e141ff7d1161fd66 (patch)
tree5d6ff018c0173c2ec0282bf9e68357964a06e578 /lib/chef/win32/security/sid.rb
parent3ec42a522a5b40d1ef217f23831b7417bda65761 (diff)
downloadchef-04612158ac256ce46faad599e141ff7d1161fd66.tar.gz
Automatically find out the sid for Administrators so that the specs can run on boxes for which the administrators account is renamed.
Diffstat (limited to 'lib/chef/win32/security/sid.rb')
-rw-r--r--lib/chef/win32/security/sid.rb56
1 files changed, 53 insertions, 3 deletions
diff --git a/lib/chef/win32/security/sid.rb b/lib/chef/win32/security/sid.rb
index e1b20224bb..8e9407dc80 100644
--- a/lib/chef/win32/security/sid.rb
+++ b/lib/chef/win32/security/sid.rb
@@ -17,11 +17,22 @@
#
require 'chef/win32/security'
+require 'chef/win32/api/net'
+require 'chef/win32/api/error'
+
+require 'wmi-lite/wmi'
class Chef
module ReservedNames::Win32
class Security
class SID
+ include Chef::ReservedNames::Win32::API::Net
+ include Chef::ReservedNames::Win32::API::Error
+
+ class << self
+ include Chef::ReservedNames::Win32::API::Net
+ include Chef::ReservedNames::Win32::API::Error
+ end
def initialize(pointer, owner = nil)
@pointer = pointer
@@ -178,13 +189,11 @@ class Chef
SID.from_string_sid('S-1-5-32-544')
end
- # Machine-specific, well-known SIDs
- # TODO: don't use strings, dummy
def self.None
SID.from_account("#{::ENV['COMPUTERNAME']}\\None")
end
def self.Administrator
- SID.from_account("#{::ENV['COMPUTERNAME']}\\Administrator")
+ SID.from_account("#{::ENV['COMPUTERNAME']}\\#{SID.admin_account_name}")
end
def self.Guest
SID.from_account("#{::ENV['COMPUTERNAME']}\\Guest")
@@ -193,6 +202,47 @@ class Chef
def self.current_user
SID.from_account("#{::ENV['USERDOMAIN']}\\#{::ENV['USERNAME']}")
end
+
+ def self.admin_account_name
+ @admin_account_name ||= begin
+ admin_account_name = nil
+
+ # Call NetUserEnum to enumerate the users without hitting network
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/aa370652(v=vs.85).aspx
+ servername = nil # We are querying the local server
+ level = 3 # We want USER_INFO_3 structure which contains the SID
+ filter = FILTER_NORMAL_ACCOUNT # Only query the user accounts
+ bufptr = FFI::MemoryPointer.new(:pointer) # Buffer which will receive the data
+ prefmaxlen = MAX_PREFERRED_LENGTH # Let the system allocate the needed amount of memory
+ entriesread = FFI::Buffer.new(:long).write_long(0)
+ totalentries = FFI::Buffer.new(:long).write_long(0)
+ resume_handle = FFI::Buffer.new(:long).write_long(0)
+
+ status = ERROR_MORE_DATA
+
+ while(status == ERROR_MORE_DATA) do
+ status = NetUserEnum(servername, level, filter, bufptr, prefmaxlen, entriesread, totalentries, resume_handle)
+
+ if (status == NERR_Success || status == ERROR_MORE_DATA)
+ entriesread.read_long.times.collect do |i|
+ user_info = USER_INFO_3.new(bufptr.read_pointer + i * USER_INFO_3.size)
+ # Check if the account is the Administrator account
+ # RID for the Administrator account is always 500 and it's privilage is set to USER_PRIV_ADMIN
+ if user_info[:usri3_user_id] == 500 && user_info[:usri3_priv] == 2 # USER_PRIV_ADMIN (2) - Administrator
+ admin_account_name = user_info[:usri3_name].read_wstring
+ break
+ end
+ end
+
+ # Free the memory allocated by the system
+ NetApiBufferFree(bufptr.read_pointer)
+ end
+ end
+
+ raise "Can not determine the administrator account name." if admin_account_name.nil?
+ admin_account_name
+ end
+ end
end
end
end