Module: Puppet::Util::Windows::SID
- Extended by:
- FFI::Library
- Included in:
- AccessControlEntry, SecurityDescriptor
- Defined in:
- lib/puppet/util/windows.rb,
lib/puppet/util/windows/sid.rb,
lib/puppet/util/windows/principal.rb
Defined Under Namespace
Classes: Principal
Constant Summary collapse
- ERROR_NONE_MAPPED =
missing from Windows::Error
1332
- ERROR_INVALID_SID_STRUCTURE =
1337
- Null =
Well Known SIDs
'S-1-0'
- Nobody =
'S-1-0-0'
- World =
'S-1-1'
- Everyone =
'S-1-1-0'
- Local =
'S-1-2'
- Creator =
'S-1-3'
- CreatorOwner =
'S-1-3-0'
- CreatorGroup =
'S-1-3-1'
- CreatorOwnerServer =
'S-1-3-2'
- CreatorGroupServer =
'S-1-3-3'
- NonUnique =
'S-1-4'
- Nt =
'S-1-5'
- Dialup =
'S-1-5-1'
- Network =
'S-1-5-2'
- Batch =
'S-1-5-3'
- Interactive =
'S-1-5-4'
- Service =
'S-1-5-6'
- Anonymous =
'S-1-5-7'
- Proxy =
'S-1-5-8'
- EnterpriseDomainControllers =
'S-1-5-9'
- PrincipalSelf =
'S-1-5-10'
- AuthenticatedUsers =
'S-1-5-11'
- RestrictedCode =
'S-1-5-12'
- TerminalServerUsers =
'S-1-5-13'
- LocalSystem =
'S-1-5-18'
- NtLocal =
'S-1-5-19'
- NtNetwork =
'S-1-5-20'
- BuiltinAdministrators =
'S-1-5-32-544'
- BuiltinUsers =
'S-1-5-32-545'
- Guests =
'S-1-5-32-546'
- PowerUsers =
'S-1-5-32-547'
- AccountOperators =
'S-1-5-32-548'
- ServerOperators =
'S-1-5-32-549'
- PrintOperators =
'S-1-5-32-550'
- BackupOperators =
'S-1-5-32-551'
- Replicators =
'S-1-5-32-552'
- MAXIMUM_SID_STRING_LENGTH =
stackoverflow.com/a/1792930 - 68 bytes, 184 characters in a string
184
Class Method Summary collapse
-
.ads_to_principal(ads_object) ⇒ Object
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.
- .get_length_sid(sid_ptr) ⇒ Object
-
.name_to_principal(name) ⇒ Object
(also: name_to_sid_object)
Convert an account name, e.g.
-
.name_to_sid(name) ⇒ Object
Convert an account name, e.g.
-
.octet_string_to_principal(bytes) ⇒ Object
(also: octet_string_to_sid_object)
Converts an octet string array of bytes to a SID::Principal object, e.g.
- .octet_string_to_sid_string(sid_bytes) ⇒ Object
-
.sid_ptr_to_string(psid) ⇒ Object
Convert a SID pointer to a SID string, e.g.
-
.sid_to_name(value) ⇒ Object
Convert a SID string, e.g.
-
.string_to_sid_ptr(string_sid, &block) ⇒ Object
Convert a SID string, e.g.
- .unresolved_principal(name, sid_bytes) ⇒ Object private
-
.valid_sid?(string_sid) ⇒ Boolean
Return true if the string is a valid SID, e.g.
Methods included from FFI::Library
Class Method Details
.ads_to_principal(ads_object) ⇒ Object
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
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/puppet/util/windows/sid.rb', line 107 def ads_to_principal(ads_object) if !ads_object || !ads_object.respond_to?(:ole_respond_to?) || !ads_object.ole_respond_to?(:objectSID) || !ads_object.ole_respond_to?(:Name) raise Puppet::Error.new("ads_object must be an IAdsUser or IAdsGroup instance") end octet_string_to_principal(ads_object.objectSID) rescue Puppet::Util::Windows::Error => e # if the error is not a lookup / mapping problem, immediately re-raise raise if e.code != ERROR_NONE_MAPPED # if the Name property isn't formatted like a SID, OR if !valid_sid?(ads_object.Name) || # if the objectSID doesn't match the Name property, also raise ((converted = octet_string_to_sid_string(ads_object.objectSID)) != ads_object.Name) raise Puppet::Error.new("ads_object Name: #{ads_object.Name} invalid or does not match objectSID: #{ads_object.objectSID} (#{converted})", e) end unresolved_principal(ads_object.Name, ads_object.objectSID) end |
.get_length_sid(sid_ptr) ⇒ Object
213 214 215 216 217 218 219 220 |
# File 'lib/puppet/util/windows/sid.rb', line 213 def get_length_sid(sid_ptr) # MSDN states IsValidSid should be called on pointer first if ! sid_ptr.kind_of?(FFI::Pointer) || IsValidSid(sid_ptr) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Invalid SID")) end GetLengthSid(sid_ptr) end |
.name_to_principal(name) ⇒ Object Also known as: name_to_sid_object
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
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/puppet/util/windows/sid.rb', line 66 def name_to_principal(name) # Apparently, we accept a symbol.. name = name.to_s.strip if name # if name is a SID string, convert it to raw bytes for use with lookup_account_sid raw_sid_bytes = nil begin string_to_sid_ptr(name) do |sid_ptr| raw_sid_bytes = sid_ptr.read_array_of_uchar(get_length_sid(sid_ptr)) end rescue end raw_sid_bytes ? Principal.lookup_account_sid(raw_sid_bytes) : Principal.lookup_account_name(name) rescue nil end |
.name_to_sid(name) ⇒ Object
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.
54 55 56 57 58 |
# File 'lib/puppet/util/windows/sid.rb', line 54 def name_to_sid(name) sid = name_to_principal(name) sid ? sid.sid : nil end |
.octet_string_to_principal(bytes) ⇒ Object Also known as: octet_string_to_sid_object
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
91 92 93 94 95 96 97 |
# File 'lib/puppet/util/windows/sid.rb', line 91 def octet_string_to_principal(bytes) if !bytes || !bytes.respond_to?('pack') || bytes.empty? raise Puppet::Util::Windows::Error.new(_("Octet string must be an array of bytes")) end Principal.lookup_account_sid(bytes) end |
.octet_string_to_sid_string(sid_bytes) ⇒ Object
223 224 225 226 227 228 229 230 231 232 |
# File 'lib/puppet/util/windows/sid.rb', line 223 def octet_string_to_sid_string(sid_bytes) sid_string = nil FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr| sid_ptr.write_array_of_uchar(sid_bytes) sid_string = Puppet::Util::Windows::SID.sid_ptr_to_string(sid_ptr) end sid_string end |
.sid_ptr_to_string(psid) ⇒ Object
Convert a SID pointer to a SID string, e.g. “S-1-5-32-544”.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/puppet/util/windows/sid.rb', line 152 def sid_ptr_to_string(psid) if ! psid.kind_of?(FFI::Pointer) || IsValidSid(psid) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Invalid SID")) end sid_string = nil FFI::MemoryPointer.new(:pointer, 1) do |buffer_ptr| if ConvertSidToStringSidW(psid, buffer_ptr) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Failed to convert binary SID")) end buffer_ptr.read_win32_local_pointer do |wide_string_ptr| if wide_string_ptr.null? raise Puppet::Error.new(_("ConvertSidToStringSidW failed to allocate buffer for sid")) end sid_string = wide_string_ptr.read_arbitrary_wide_string_up_to(MAXIMUM_SID_STRING_LENGTH) end end sid_string end |
.sid_to_name(value) ⇒ Object
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.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/puppet/util/windows/sid.rb', line 131 def sid_to_name(value) sid_bytes = [] begin string_to_sid_ptr(value) do |ptr| sid_bytes = ptr.read_array_of_uchar(get_length_sid(ptr)) end rescue Puppet::Util::Windows::Error => e raise if e.code != ERROR_INVALID_SID_STRUCTURE end Principal.lookup_account_sid(sid_bytes).domain_account rescue nil end |
.string_to_sid_ptr(string_sid, &block) ⇒ Object
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.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/puppet/util/windows/sid.rb', line 180 def string_to_sid_ptr(string_sid, &block) FFI::MemoryPointer.from_string_to_wide_string(string_sid) do |lpcwstr| FFI::MemoryPointer.new(:pointer, 1) do |sid_ptr_ptr| if ConvertStringSidToSidW(lpcwstr, sid_ptr_ptr) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Failed to convert string SID: %{string_sid}") % { string_sid: string_sid }) end sid_ptr_ptr.read_win32_local_pointer do |sid_ptr| yield sid_ptr end end end # yielded sid_ptr has already had LocalFree called, nothing to return nil end |
.unresolved_principal(name, sid_bytes) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/puppet/util/windows/sid.rb', line 236 def self.unresolved_principal(name, sid_bytes) Principal.new( name + " (unresolvable)", # account sid_bytes, # sid_bytes name, # sid string nil, #domain # https://msdn.microsoft.com/en-us/library/cc245534.aspx?f=255&MSPPError=-2147217396 # Indicates that the type of object could not be determined. For example, no object with that SID exists. :SidTypeUnknown) end |
.valid_sid?(string_sid) ⇒ Boolean
Return true if the string is a valid SID, e.g. “S-1-5-32-544”, false otherwise.
200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/puppet/util/windows/sid.rb', line 200 def valid_sid?(string_sid) valid = false begin string_to_sid_ptr(string_sid) { |ptr| valid = ! ptr.nil? && ! ptr.null? } rescue Puppet::Util::Windows::Error => e raise if e.code != ERROR_INVALID_SID_STRUCTURE end valid end |