Module: Puppet::Util::Windows::SID

Extended by:
FFI::Library
Included in:
AccessControlEntry, SecurityDescriptor
Defined in:
lib/puppet/util/windows/sid.rb

Constant Summary collapse

ERROR_NONE_MAPPED =

missing from Windows::Error

1332
ERROR_INVALID_SID_STRUCTURE =
1337
MAXIMUM_SID_STRING_LENGTH =

stackoverflow.com/a/1792930 - 68 bytes, 184 characters in a string

184

Class Method Summary collapse

Methods included from FFI::Library

attach_function_private

Class Method Details

.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.



16
17
18
19
20
# File 'lib/puppet/util/windows/sid.rb', line 16

def name_to_sid(name)
  sid = name_to_sid_object(name)

  sid ? sid.to_s : nil
end

.name_to_sid_object(name) ⇒ Object

Convert an account name, e.g. ‘Administrators’ into a 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.



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/puppet/util/windows/sid.rb', line 27

def name_to_sid_object(name)
  # Apparently, we accept a symbol..
  name = name.to_s.strip if name

  # if it's in SID string form, convert to user
  parsed_sid = Win32::Security::SID.string_to_sid(name) rescue nil

  parsed_sid ? Win32::Security::SID.new(parsed_sid) : Win32::Security::SID.new(name)
rescue
  nil
end

.octet_string_to_sid_object(bytes) ⇒ Object

Converts an octet string array of bytes to a SID 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.



44
45
46
47
48
49
50
# File 'lib/puppet/util/windows/sid.rb', line 44

def octet_string_to_sid_object(bytes)
  if !bytes || !bytes.respond_to?('pack') || bytes.empty?
    raise Puppet::Util::Windows::Error.new("Octet string must be an array of bytes")
  end

  Win32::Security::SID.new(bytes.pack('C*'))
end

.sid_ptr_to_string(psid) ⇒ Object

Convert a SID pointer to a SID string, e.g. “S-1-5-32-544”.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/puppet/util/windows/sid.rb', line 73

def sid_ptr_to_string(psid)
  if ! psid.instance_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.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/puppet/util/windows/sid.rb', line 56

def sid_to_name(value)
  sid = Win32::Security::SID.new(Win32::Security::SID.string_to_sid(value))

  if sid.domain and sid.domain.length > 0
    "#{sid.domain}\\#{sid.}"
  else
    sid.
  end
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.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/puppet/util/windows/sid.rb', line 101

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}")
      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

.valid_sid?(string_sid) ⇒ Boolean

Return true if the string is a valid SID, e.g. “S-1-5-32-544”, false otherwise.



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/puppet/util/windows/sid.rb', line 121

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