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