class Puppet::Util::Windows::SID::Principal
Constants
- ERROR_INSUFFICIENT_BUFFER
- ERROR_INVALID_PARAMETER
- MAXIMUM_SID_BYTE_LENGTH
8 + max sub identifiers (15) * 4¶ ↑
- SID_NAME_USE
msdn.microsoft.com/en-us/library/windows/desktop/aa379601(v=vs.85).aspx
Attributes
account[R]
account_type[R]
domain[R]
domain_account[R]
sid[R]
sid_bytes[R]
Public Class Methods
lookup_account_name(system_name = nil, sanitize = true, account_name)
click to toggle source
# File lib/puppet/util/windows/principal.rb 47 def self.lookup_account_name(system_name = nil, sanitize = true, account_name) 48 account_name = sanitize_account_name(account_name) if sanitize 49 system_name_ptr = FFI::Pointer::NULL 50 begin 51 if system_name 52 system_name_wide = Puppet::Util::Windows::String.wide_string(system_name) 53 system_name_ptr = FFI::MemoryPointer.from_wide_string(system_name_wide) 54 end 55 56 FFI::MemoryPointer.from_string_to_wide_string(account_name) do |account_name_ptr| 57 FFI::MemoryPointer.new(:byte, MAXIMUM_SID_BYTE_LENGTH) do |sid_ptr| 58 FFI::MemoryPointer.new(:dword, 1) do |sid_length_ptr| 59 FFI::MemoryPointer.new(:dword, 1) do |domain_length_ptr| 60 FFI::MemoryPointer.new(:uint32, 1) do |name_use_enum_ptr| 61 62 sid_length_ptr.write_dword(MAXIMUM_SID_BYTE_LENGTH) 63 success = LookupAccountNameW(system_name_ptr, account_name_ptr, sid_ptr, sid_length_ptr, 64 FFI::Pointer::NULL, domain_length_ptr, name_use_enum_ptr) 65 last_error = FFI.errno 66 67 if (success == FFI::WIN32_FALSE && last_error != ERROR_INSUFFICIENT_BUFFER) 68 raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountNameW with account: %{account_name}') % { account_name: account_name}, last_error) 69 end 70 71 FFI::MemoryPointer.new(:lpwstr, domain_length_ptr.read_dword) do |domain_ptr| 72 if LookupAccountNameW(system_name_ptr, account_name_ptr, 73 sid_ptr, sid_length_ptr, 74 domain_ptr, domain_length_ptr, name_use_enum_ptr) == FFI::WIN32_FALSE 75 raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountNameW with account: %{account_name}') % { account_name: account_name} ) 76 end 77 78 # with a SID returned, loop back through lookup_account_sid to retrieve official name 79 # necessary when accounts like . or '' are passed in 80 return lookup_account_sid( 81 system_name, 82 sid_ptr.read_bytes(sid_length_ptr.read_dword).unpack('C*')) 83 end 84 end 85 end 86 end 87 end 88 end 89 ensure 90 system_name_ptr.free if system_name_ptr != FFI::Pointer::NULL 91 end 92 end
lookup_account_sid(system_name = nil, sid_bytes)
click to toggle source
# File lib/puppet/util/windows/principal.rb 94 def self.lookup_account_sid(system_name = nil, sid_bytes) 95 system_name_ptr = FFI::Pointer::NULL 96 if (sid_bytes.nil? || (!sid_bytes.is_a? Array) || (sid_bytes.length == 0)) 97 #TRANSLATORS `lookup_account_sid` is a variable name and should not be translated 98 raise Puppet::Util::Windows::Error.new(_('Byte array for lookup_account_sid must not be nil and must be at least 1 byte long')) 99 end 100 101 begin 102 if system_name 103 system_name_wide = Puppet::Util::Windows::String.wide_string(system_name) 104 system_name_ptr = FFI::MemoryPointer.from_wide_string(system_name_wide) 105 end 106 107 FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr| 108 FFI::MemoryPointer.new(:dword, 1) do |name_length_ptr| 109 FFI::MemoryPointer.new(:dword, 1) do |domain_length_ptr| 110 FFI::MemoryPointer.new(:uint32, 1) do |name_use_enum_ptr| 111 112 sid_ptr.write_array_of_uchar(sid_bytes) 113 114 if Puppet::Util::Windows::SID.IsValidSid(sid_ptr) == FFI::WIN32_FALSE 115 raise Puppet::Util::Windows::Error.new(_('Byte array for lookup_account_sid is invalid: %{sid_bytes}') % { sid_bytes: sid_bytes }, ERROR_INVALID_PARAMETER) 116 end 117 118 success = LookupAccountSidW(system_name_ptr, sid_ptr, FFI::Pointer::NULL, name_length_ptr, 119 FFI::Pointer::NULL, domain_length_ptr, name_use_enum_ptr) 120 last_error = FFI.errno 121 122 if (success == FFI::WIN32_FALSE && last_error != ERROR_INSUFFICIENT_BUFFER) 123 raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW with bytes: %{sid_bytes}') % { sid_bytes: sid_bytes}, last_error) 124 end 125 126 FFI::MemoryPointer.new(:lpwstr, name_length_ptr.read_dword) do |name_ptr| 127 FFI::MemoryPointer.new(:lpwstr, domain_length_ptr.read_dword) do |domain_ptr| 128 if LookupAccountSidW(system_name_ptr, sid_ptr, name_ptr, name_length_ptr, 129 domain_ptr, domain_length_ptr, name_use_enum_ptr) == FFI::WIN32_FALSE 130 raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW with bytes: %{sid_bytes}') % { sid_bytes: sid_bytes} ) 131 end 132 133 return new( 134 name_ptr.read_wide_string(name_length_ptr.read_dword), 135 sid_bytes, 136 Puppet::Util::Windows::SID.sid_ptr_to_string(sid_ptr), 137 domain_ptr.read_wide_string(domain_length_ptr.read_dword), 138 SID_NAME_USE[name_use_enum_ptr.read_uint32]) 139 end 140 end 141 end 142 end 143 end 144 end 145 ensure 146 system_name_ptr.free if system_name_ptr != FFI::Pointer::NULL 147 end 148 end
new(account, sid_bytes, sid, domain, account_type)
click to toggle source
# File lib/puppet/util/windows/principal.rb 8 def initialize(account, sid_bytes, sid, domain, account_type) 9 # This is only ever called from lookup_account_sid which has already 10 # removed the potential for passing in an account like host\user 11 @account = account 12 @sid_bytes = sid_bytes 13 @sid = sid 14 @domain = domain 15 @account_type = account_type 16 # When domain is available and it is a Domain principal, use domain only 17 # otherwise if domain is available then combine it with parsed account 18 # otherwise when the domain is not available, use the account value directly 19 # WinNT naming standard https://msdn.microsoft.com/en-us/library/windows/desktop/aa746534(v=vs.85).aspx 20 if (domain && !domain.empty? && @account_type == :SidTypeDomain) 21 @domain_account = @domain 22 elsif (domain && !domain.empty?) 23 @domain_account = "#{domain}\\#{@account}" 24 else 25 @domain_account = account 26 end 27 end
Private Class Methods
sanitize_account_name(account_name)
click to toggle source
Sanitize the given account name for lookup to avoid known issues
# File lib/puppet/util/windows/principal.rb 151 def self.sanitize_account_name(account_name) 152 return account_name unless account_name.start_with?('APPLICATION PACKAGE AUTHORITY\\') 153 account_name.split('\\').last 154 end
Public Instance Methods
==(compare)
click to toggle source
added for backward compatibility
# File lib/puppet/util/windows/principal.rb 30 def ==(compare) 31 compare.is_a?(Puppet::Util::Windows::SID::Principal) && 32 @sid_bytes == compare.sid_bytes 33 end