Module: Win32::TaskScheduler::SID

Extended by:
Helper
Included in:
Win32::TaskScheduler
Defined in:
lib/win32/taskscheduler/sid.rb

Constant Summary collapse

ERROR_INSUFFICIENT_BUFFER =
122
SERVICE_ACCOUNT_USERS =
[self.LocalSystem, self.NtLocal, self.NtNetwork].map do |user|
  [user[:account_simple_name].upcase, user[:account_name].upcase]
end.flatten.freeze
BUILT_IN_GROUPS =
[self.BuiltinAdministrators, self.BuiltinUsers, self.Guests].map do |user|
  [user[:account_simple_name].upcase, user[:account_name].upcase]
end.flatten.freeze

Constants included from Helper

Helper::FORMAT_MESSAGE_FROM_SYSTEM, Helper::FORMAT_MESSAGE_IGNORE_INSERTS, Helper::FORMAT_MESSAGE_MAX_WIDTH_MASK

Class Method Summary collapse

Methods included from Helper

ole_error, win_error

Class Method Details

.account(sid) ⇒ Object

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



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/win32/taskscheduler/sid.rb', line 94

def self.(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) ⇒ Object

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



117
118
119
120
121
# File 'lib/win32/taskscheduler/sid.rb', line 117

def self.(domain, name, _use)
   = !domain.to_s.empty? ? "#{domain}\\#{name}" : name
   = name
  { account_name: , account_simple_name:  }
end

.BuiltinAdministratorsObject



50
51
52
# File 'lib/win32/taskscheduler/sid.rb', line 50

def self.BuiltinAdministrators
  from_string_sid("S-1-5-32-544")
end

.BuiltinUsersObject



54
55
56
# File 'lib/win32/taskscheduler/sid.rb', line 54

def self.BuiltinUsers
  from_string_sid("S-1-5-32-545")
end

.from_string_sid(string_sid) ⇒ Object

Converts a string-format security identifier (SID) into a valid, functional SID and returns a hash with account_name and account_simple_name



66
67
68
69
70
71
72
73
74
75
# 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 = (result_pointer)
  LocalFree(result_pointer)
  (domain, name, use)
end

.GuestsObject



58
59
60
# File 'lib/win32/taskscheduler/sid.rb', line 58

def self.Guests
  from_string_sid("S-1-5-32-546")
end

.LocalSystemObject



38
39
40
# File 'lib/win32/taskscheduler/sid.rb', line 38

def self.LocalSystem
  from_string_sid("S-1-5-18")
end

.NtLocalObject



42
43
44
# File 'lib/win32/taskscheduler/sid.rb', line 42

def self.NtLocal
  from_string_sid("S-1-5-19")
end

.NtNetworkObject



46
47
48
# File 'lib/win32/taskscheduler/sid.rb', line 46

def self.NtNetwork
  from_string_sid("S-1-5-20")
end

.utf8_to_wide(ustring) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
# 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