module Puppet::Util::Windows::SID
Constants
- AccountOperators
- AllAppPackages
- Anonymous
- AuthenticatedUsers
- BackupOperators
- Batch
- BuiltinAdministrators
- BuiltinUsers
- Creator
- CreatorGroup
- CreatorGroupServer
- CreatorOwner
- CreatorOwnerServer
- Dialup
- ERROR_INVALID_SID_STRUCTURE
- ERROR_NONE_MAPPED
missing from
Windows::Error- EnterpriseDomainControllers
- Everyone
- Guests
- Interactive
- Local
- LocalSystem
- MAXIMUM_SID_STRING_LENGTH
stackoverflow.com/a/1792930 - 68 bytes, 184 characters in a string
- Network
- Nobody
- NonUnique
- Nt
- NtLocal
- NtNetwork
- Null
Well Known SIDs
- PowerUsers
- PrincipalSelf
- PrintOperators
- Proxy
- Replicators
- RestrictedCode
- ServerOperators
- Service
- TerminalServerUsers
- World
Public Class Methods
Converts a COM instance of IAdsUser or IAdsGroup to a SID::Principal object, Raises an Error for nil or an object without an objectSID / Name property. This method returns a SID::Principal with the account, domain, SID, etc This method will return instances even when the SID is unresolvable, as may be the case when domain users have been added to local groups, but removed from the domain
# File lib/puppet/util/windows/sid.rb 113 def ads_to_principal(ads_object) 114 if !ads_object || !ads_object.respond_to?(:ole_respond_to?) || 115 !ads_object.ole_respond_to?(:objectSID) || !ads_object.ole_respond_to?(:Name) 116 raise Puppet::Error.new("ads_object must be an IAdsUser or IAdsGroup instance") 117 end 118 octet_string_to_principal(ads_object.objectSID) 119 rescue Puppet::Util::Windows::Error => e 120 # if the error is not a lookup / mapping problem, immediately re-raise 121 raise if e.code != ERROR_NONE_MAPPED 122 123 # if the Name property isn't formatted like a SID, OR 124 if !valid_sid?(ads_object.Name) || 125 # if the objectSID doesn't match the Name property, also raise 126 ((converted = octet_string_to_sid_string(ads_object.objectSID)) != ads_object.Name) 127 raise Puppet::Error.new("ads_object Name: #{ads_object.Name} invalid or does not match objectSID: #{ads_object.objectSID} (#{converted})", e) 128 end 129 130 unresolved_principal(ads_object.Name, ads_object.objectSID) 131 end
# File lib/puppet/util/windows/sid.rb 219 def get_length_sid(sid_ptr) 220 # MSDN states IsValidSid should be called on pointer first 221 if ! sid_ptr.kind_of?(FFI::Pointer) || IsValidSid(sid_ptr) == FFI::WIN32_FALSE 222 raise Puppet::Util::Windows::Error.new(_("Invalid SID")) 223 end 224 225 GetLengthSid(sid_ptr) 226 end
Convert an account name, e.g. 'Administrators' into a Principal::SID object, e.g. 'S-1-5-32-544'. The name can be specified as 'Administrators', 'BUILTINAdministrators', or 'S-1-5-32-544', and will return the SID object. Returns nil if the account doesn't exist. This method returns a SID::Principal with the account, domain, SID, etc
# File lib/puppet/util/windows/sid.rb 68 def name_to_principal(name, allow_unresolved = false) 69 # Apparently, we accept a symbol.. 70 name = name.to_s.strip if name 71 72 # if name is a SID string, convert it to raw bytes for use with lookup_account_sid 73 raw_sid_bytes = nil 74 begin 75 string_to_sid_ptr(name) do |sid_ptr| 76 raw_sid_bytes = sid_ptr.read_array_of_uchar(get_length_sid(sid_ptr)) 77 end 78 rescue => e 79 # Avoid debug logs pollution with valid account names 80 # https://docs.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertstringsidtosidw#return-value 81 Puppet.debug("Could not retrieve raw SID bytes from '#{name}': #{e.message}") unless e.code == ERROR_INVALID_SID_STRUCTURE 82 end 83 84 raw_sid_bytes ? Principal.lookup_account_sid(raw_sid_bytes) : Principal.lookup_account_name(name) 85 rescue => e 86 Puppet.debug("#{e.message}") 87 (allow_unresolved && raw_sid_bytes) ? unresolved_principal(name, raw_sid_bytes) : nil 88 end
Convert an account name, e.g. 'Administrators' into a SID string, e.g. 'S-1-5-32-544'. The name can be specified as 'Administrators', 'BUILTINAdministrators', or 'S-1-5-32-544', and will return the SID. Returns nil if the account doesn't exist.
# File lib/puppet/util/windows/sid.rb 56 def name_to_sid(name) 57 sid = name_to_principal(name) 58 59 sid ? sid.sid : nil 60 end
Converts an octet string array of bytes to a SID::Principal object, e.g. [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0] is the representation for S-1-5-18, the local 'SYSTEM' account. Raises an Error for nil or non-array input. This method returns a SID::Principal with the account, domain, SID, etc
# File lib/puppet/util/windows/sid.rb 97 def octet_string_to_principal(bytes) 98 if !bytes || !bytes.respond_to?('pack') || bytes.empty? 99 raise Puppet::Util::Windows::Error.new(_("Octet string must be an array of bytes")) 100 end 101 102 Principal.lookup_account_sid(bytes) 103 end
# File lib/puppet/util/windows/sid.rb 229 def octet_string_to_sid_string(sid_bytes) 230 sid_string = nil 231 232 FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr| 233 sid_ptr.write_array_of_uchar(sid_bytes) 234 sid_string = Puppet::Util::Windows::SID.sid_ptr_to_string(sid_ptr) 235 end 236 237 sid_string 238 end
Convert a SID pointer to a SID string, e.g. “S-1-5-32-544”.
# File lib/puppet/util/windows/sid.rb 158 def sid_ptr_to_string(psid) 159 if ! psid.kind_of?(FFI::Pointer) || IsValidSid(psid) == FFI::WIN32_FALSE 160 raise Puppet::Util::Windows::Error.new(_("Invalid SID")) 161 end 162 163 sid_string = nil 164 FFI::MemoryPointer.new(:pointer, 1) do |buffer_ptr| 165 if ConvertSidToStringSidW(psid, buffer_ptr) == FFI::WIN32_FALSE 166 raise Puppet::Util::Windows::Error.new(_("Failed to convert binary SID")) 167 end 168 169 buffer_ptr.read_win32_local_pointer do |wide_string_ptr| 170 if wide_string_ptr.null? 171 raise Puppet::Error.new(_("ConvertSidToStringSidW failed to allocate buffer for sid")) 172 end 173 174 sid_string = wide_string_ptr.read_arbitrary_wide_string_up_to(MAXIMUM_SID_STRING_LENGTH) 175 end 176 end 177 178 sid_string 179 end
Convert a SID string, e.g. “S-1-5-32-544” to a name, e.g. 'BUILTINAdministrators'. Returns nil if an account for that SID does not exist.
# File lib/puppet/util/windows/sid.rb 137 def sid_to_name(value) 138 139 sid_bytes = [] 140 begin 141 string_to_sid_ptr(value) do |ptr| 142 sid_bytes = ptr.read_array_of_uchar(get_length_sid(ptr)) 143 end 144 rescue Puppet::Util::Windows::Error => e 145 raise if e.code != ERROR_INVALID_SID_STRUCTURE 146 end 147 148 Principal.lookup_account_sid(sid_bytes).domain_account 149 rescue 150 nil 151 end
Convert a SID string, e.g. “S-1-5-32-544” to a pointer (containing the address of the binary SID structure). The returned value can be used in Win32 APIs that expect a PSID, e.g. IsValidSid. The account for this SID may or may not exist.
# File lib/puppet/util/windows/sid.rb 186 def string_to_sid_ptr(string_sid, &block) 187 FFI::MemoryPointer.from_string_to_wide_string(string_sid) do |lpcwstr| 188 FFI::MemoryPointer.new(:pointer, 1) do |sid_ptr_ptr| 189 190 if ConvertStringSidToSidW(lpcwstr, sid_ptr_ptr) == FFI::WIN32_FALSE 191 raise Puppet::Util::Windows::Error.new(_("Failed to convert string SID: %{string_sid}") % { string_sid: string_sid }) 192 end 193 194 sid_ptr_ptr.read_win32_local_pointer do |sid_ptr| 195 yield sid_ptr 196 end 197 end 198 end 199 200 # yielded sid_ptr has already had LocalFree called, nothing to return 201 nil 202 end
@api private
# File lib/puppet/util/windows/sid.rb 242 def self.unresolved_principal(name, sid_bytes) 243 Principal.new( 244 name, # account 245 sid_bytes, # sid_bytes 246 name, # sid string 247 nil, #domain 248 # https://msdn.microsoft.com/en-us/library/cc245534.aspx?f=255&MSPPError=-2147217396 249 # Indicates that the type of object could not be determined. For example, no object with that SID exists. 250 :SidTypeUnknown) 251 end
Return true if the string is a valid SID, e.g. “S-1-5-32-544”, false otherwise.
# File lib/puppet/util/windows/sid.rb 206 def valid_sid?(string_sid) 207 valid = false 208 209 begin 210 string_to_sid_ptr(string_sid) { |ptr| valid = ! ptr.nil? && ! ptr.null? } 211 rescue Puppet::Util::Windows::Error => e 212 raise if e.code != ERROR_INVALID_SID_STRUCTURE 213 end 214 215 valid 216 end
Private Instance Methods
Converts a COM instance of IAdsUser or IAdsGroup to a SID::Principal object, Raises an Error for nil or an object without an objectSID / Name property. This method returns a SID::Principal with the account, domain, SID, etc This method will return instances even when the SID is unresolvable, as may be the case when domain users have been added to local groups, but removed from the domain
# File lib/puppet/util/windows/sid.rb 113 def ads_to_principal(ads_object) 114 if !ads_object || !ads_object.respond_to?(:ole_respond_to?) || 115 !ads_object.ole_respond_to?(:objectSID) || !ads_object.ole_respond_to?(:Name) 116 raise Puppet::Error.new("ads_object must be an IAdsUser or IAdsGroup instance") 117 end 118 octet_string_to_principal(ads_object.objectSID) 119 rescue Puppet::Util::Windows::Error => e 120 # if the error is not a lookup / mapping problem, immediately re-raise 121 raise if e.code != ERROR_NONE_MAPPED 122 123 # if the Name property isn't formatted like a SID, OR 124 if !valid_sid?(ads_object.Name) || 125 # if the objectSID doesn't match the Name property, also raise 126 ((converted = octet_string_to_sid_string(ads_object.objectSID)) != ads_object.Name) 127 raise Puppet::Error.new("ads_object Name: #{ads_object.Name} invalid or does not match objectSID: #{ads_object.objectSID} (#{converted})", e) 128 end 129 130 unresolved_principal(ads_object.Name, ads_object.objectSID) 131 end
# File lib/puppet/util/windows/sid.rb 219 def get_length_sid(sid_ptr) 220 # MSDN states IsValidSid should be called on pointer first 221 if ! sid_ptr.kind_of?(FFI::Pointer) || IsValidSid(sid_ptr) == FFI::WIN32_FALSE 222 raise Puppet::Util::Windows::Error.new(_("Invalid SID")) 223 end 224 225 GetLengthSid(sid_ptr) 226 end
Convert an account name, e.g. 'Administrators' into a Principal::SID object, e.g. 'S-1-5-32-544'. The name can be specified as 'Administrators', 'BUILTINAdministrators', or 'S-1-5-32-544', and will return the SID object. Returns nil if the account doesn't exist. This method returns a SID::Principal with the account, domain, SID, etc
# File lib/puppet/util/windows/sid.rb 68 def name_to_principal(name, allow_unresolved = false) 69 # Apparently, we accept a symbol.. 70 name = name.to_s.strip if name 71 72 # if name is a SID string, convert it to raw bytes for use with lookup_account_sid 73 raw_sid_bytes = nil 74 begin 75 string_to_sid_ptr(name) do |sid_ptr| 76 raw_sid_bytes = sid_ptr.read_array_of_uchar(get_length_sid(sid_ptr)) 77 end 78 rescue => e 79 # Avoid debug logs pollution with valid account names 80 # https://docs.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertstringsidtosidw#return-value 81 Puppet.debug("Could not retrieve raw SID bytes from '#{name}': #{e.message}") unless e.code == ERROR_INVALID_SID_STRUCTURE 82 end 83 84 raw_sid_bytes ? Principal.lookup_account_sid(raw_sid_bytes) : Principal.lookup_account_name(name) 85 rescue => e 86 Puppet.debug("#{e.message}") 87 (allow_unresolved && raw_sid_bytes) ? unresolved_principal(name, raw_sid_bytes) : nil 88 end
Convert an account name, e.g. 'Administrators' into a SID string, e.g. 'S-1-5-32-544'. The name can be specified as 'Administrators', 'BUILTINAdministrators', or 'S-1-5-32-544', and will return the SID. Returns nil if the account doesn't exist.
# File lib/puppet/util/windows/sid.rb 56 def name_to_sid(name) 57 sid = name_to_principal(name) 58 59 sid ? sid.sid : nil 60 end
Converts an octet string array of bytes to a SID::Principal object, e.g. [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0] is the representation for S-1-5-18, the local 'SYSTEM' account. Raises an Error for nil or non-array input. This method returns a SID::Principal with the account, domain, SID, etc
# File lib/puppet/util/windows/sid.rb 97 def octet_string_to_principal(bytes) 98 if !bytes || !bytes.respond_to?('pack') || bytes.empty? 99 raise Puppet::Util::Windows::Error.new(_("Octet string must be an array of bytes")) 100 end 101 102 Principal.lookup_account_sid(bytes) 103 end
# File lib/puppet/util/windows/sid.rb 229 def octet_string_to_sid_string(sid_bytes) 230 sid_string = nil 231 232 FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr| 233 sid_ptr.write_array_of_uchar(sid_bytes) 234 sid_string = Puppet::Util::Windows::SID.sid_ptr_to_string(sid_ptr) 235 end 236 237 sid_string 238 end
Convert a SID pointer to a SID string, e.g. “S-1-5-32-544”.
# File lib/puppet/util/windows/sid.rb 158 def sid_ptr_to_string(psid) 159 if ! psid.kind_of?(FFI::Pointer) || IsValidSid(psid) == FFI::WIN32_FALSE 160 raise Puppet::Util::Windows::Error.new(_("Invalid SID")) 161 end 162 163 sid_string = nil 164 FFI::MemoryPointer.new(:pointer, 1) do |buffer_ptr| 165 if ConvertSidToStringSidW(psid, buffer_ptr) == FFI::WIN32_FALSE 166 raise Puppet::Util::Windows::Error.new(_("Failed to convert binary SID")) 167 end 168 169 buffer_ptr.read_win32_local_pointer do |wide_string_ptr| 170 if wide_string_ptr.null? 171 raise Puppet::Error.new(_("ConvertSidToStringSidW failed to allocate buffer for sid")) 172 end 173 174 sid_string = wide_string_ptr.read_arbitrary_wide_string_up_to(MAXIMUM_SID_STRING_LENGTH) 175 end 176 end 177 178 sid_string 179 end
Convert a SID string, e.g. “S-1-5-32-544” to a name, e.g. 'BUILTINAdministrators'. Returns nil if an account for that SID does not exist.
# File lib/puppet/util/windows/sid.rb 137 def sid_to_name(value) 138 139 sid_bytes = [] 140 begin 141 string_to_sid_ptr(value) do |ptr| 142 sid_bytes = ptr.read_array_of_uchar(get_length_sid(ptr)) 143 end 144 rescue Puppet::Util::Windows::Error => e 145 raise if e.code != ERROR_INVALID_SID_STRUCTURE 146 end 147 148 Principal.lookup_account_sid(sid_bytes).domain_account 149 rescue 150 nil 151 end
Convert a SID string, e.g. “S-1-5-32-544” to a pointer (containing the address of the binary SID structure). The returned value can be used in Win32 APIs that expect a PSID, e.g. IsValidSid. The account for this SID may or may not exist.
# File lib/puppet/util/windows/sid.rb 186 def string_to_sid_ptr(string_sid, &block) 187 FFI::MemoryPointer.from_string_to_wide_string(string_sid) do |lpcwstr| 188 FFI::MemoryPointer.new(:pointer, 1) do |sid_ptr_ptr| 189 190 if ConvertStringSidToSidW(lpcwstr, sid_ptr_ptr) == FFI::WIN32_FALSE 191 raise Puppet::Util::Windows::Error.new(_("Failed to convert string SID: %{string_sid}") % { string_sid: string_sid }) 192 end 193 194 sid_ptr_ptr.read_win32_local_pointer do |sid_ptr| 195 yield sid_ptr 196 end 197 end 198 end 199 200 # yielded sid_ptr has already had LocalFree called, nothing to return 201 nil 202 end
Return true if the string is a valid SID, e.g. “S-1-5-32-544”, false otherwise.
# File lib/puppet/util/windows/sid.rb 206 def valid_sid?(string_sid) 207 valid = false 208 209 begin 210 string_to_sid_ptr(string_sid) { |ptr| valid = ! ptr.nil? && ! ptr.null? } 211 rescue Puppet::Util::Windows::Error => e 212 raise if e.code != ERROR_INVALID_SID_STRUCTURE 213 end 214 215 valid 216 end