module Win32::TaskScheduler::SID

Constants

BUILT_IN_GROUPS
ERROR_INSUFFICIENT_BUFFER
SERVICE_ACCOUNT_USERS

Public Class Methods

BuiltinAdministrators() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 50
def self.BuiltinAdministrators
  from_string_sid("S-1-5-32-544")
end
BuiltinUsers() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 54
def self.BuiltinUsers
  from_string_sid("S-1-5-32-545")
end
Guests() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 58
def self.Guests
  from_string_sid("S-1-5-32-546")
end
LocalSystem() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 38
def self.LocalSystem
  from_string_sid("S-1-5-18")
end
NtLocal() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 42
def self.NtLocal
  from_string_sid("S-1-5-19")
end
NtNetwork() click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 46
def self.NtNetwork
  from_string_sid("S-1-5-20")
end
account(sid) click to toggle source

Accepts a security identifier (SID) as input. It retrieves the name of the account for this SID and the name of the first domain on which this SID is found @see docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-lookupaccountsidw

# File lib/win32/taskscheduler/sid.rb, line 94
def self.account(sid)
  sid = sid.pointer if sid.respond_to?(:pointer)
  name_size = FFI::Buffer.new(:long).write_long(0)
  referenced_domain_name_size = FFI::Buffer.new(:long).write_long(0)

  if LookupAccountSidW(nil, sid, nil, name_size, nil, referenced_domain_name_size, nil)
    raise "Expected ERROR_INSUFFICIENT_BUFFER from LookupAccountSid, and got no error!"
  elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER
    raise FFI::LastError.error
  end

  name = FFI::MemoryPointer.new :char, (name_size.read_long * 2)
  referenced_domain_name = FFI::MemoryPointer.new :char, (referenced_domain_name_size.read_long * 2)
  use = FFI::Buffer.new(:long).write_long(0)
  unless LookupAccountSidW(nil, sid, name, name_size, referenced_domain_name, referenced_domain_name_size, use)
    raise FFI::LastError.error
  end
  [referenced_domain_name.read_wstring(referenced_domain_name_size.read_long), name.read_wstring(name_size.read_long), use.read_long]
end
account_names(domain, name, _use) click to toggle source

Formats domain, name and returns a hash with account_name and account_simple_name

# File lib/win32/taskscheduler/sid.rb, line 117
def self.account_names(domain, name, _use)
  account_name = !domain.to_s.empty? ? "#{domain}\\#{name}" : name
  account_simple_name = name
  { account_name: account_name, account_simple_name: account_simple_name }
end
from_string_sid(string_sid) click to toggle source

Converts a string-format security identifier (SID) into a valid, functional SID and returns a hash with account_name and account_simple_name @see docs.microsoft.com/en-us/windows/desktop/api/sddl/nf-sddl-convertstringsidtosidw

# File lib/win32/taskscheduler/sid.rb, line 66
def self.from_string_sid(string_sid)
  result = FFI::MemoryPointer.new :pointer
  unless ConvertStringSidToSidW(utf8_to_wide(string_sid), result)
    raise FFI::LastError.error
  end
  result_pointer = result.read_pointer
  domain, name, use = account(result_pointer)
  LocalFree(result_pointer)
  account_names(domain, name, use)
end
utf8_to_wide(ustring) click to toggle source
# File lib/win32/taskscheduler/sid.rb, line 77
def self.utf8_to_wide(ustring)
  # ensure it is actually UTF-8
  # Ruby likes to mark binary data as ASCII-8BIT
  ustring = (ustring + "").force_encoding("UTF-8")

  # ensure we have the double-null termination Windows Wide likes
  ustring += "\000\000" if ustring.empty? || ustring[-1].chr != "\000"

  # encode it all as UTF-16LE AKA Windows Wide Character AKA Windows Unicode
  ustring.encode("UTF-16LE")
end