Hi all,
How does this look?
require ''win32/security''
include Win32
s = Security::SID.new(''djberge'')
#<Win32::Security::SID:0x2c6c56c
@domain="mydomain",
@host="myhost",
@sid="\001\005\000...",
@account_type="user",
@account="djberge">
s.length => 28
s.account => ''djberge''
s.domain => ''mydomain''
s.sid => ''\001...''
s.account_type => ''user''
s.to_s => S-1-5-21-55555-444444-88-118888-999999
s.valid? => true
s == s => true
Here''s the implementation so far (more comments at end):
# win32/security/sid.rb
require ''windows/security''
require ''windows/error''
require ''windows/msvcrt/string''
require ''windows/msvcrt/buffer''
require ''socket''
module Win32
module Security
class SID
include Windows::Security
include Windows::Error
include Windows::MSVCRT::String
include Windows::MSVCRT::Buffer
extend Windows::Security
extend Windows::Error
extend Windows::MSVCRT::String
class Error < StandardError; end
# The binary SID object itself.
attr_reader :sid
# The account name passed to the constructor.
attr_reader :account
# The SID account type, e.g. ''user, ''group'',
etc.
attr_reader :account_type
# The domain the SID is on.
attr_reader :domain
# The host passed to the constructor, or the localhost if none
# was specified.
attr_reader :host
# Converts a binary SID to a string in S-R-I-S-S... format.
#
def self.convert_sid_to_string_sid(sid)
sid_addr =
[sid].pack(''p*'').unpack(''L'')[0]
sid_buf = 0.chr * 80
sid_ptr = 0.chr * 4
unless ConvertSidToStringSid(sid_addr, sid_ptr)
raise Error, get_last_error
end
strcpy(sid_buf, sid_ptr.unpack(''L'')[0])
sid_buf.strip
end
# Converts a string in S-R-I-S-S... format back to a binary
SID.
#
def self.convert_string_sid_to_sid(string)
sid_buf = 0.chr * 80
string_addr =
[string].pack(''p*'').unpack(''L'')[0]
unless ConvertStringSidToSid(string_addr, sid_buf)
raise Error, get_last_error
end
sid_buf.strip
end
# Creates and returns a new Win32::Security::SID object, based
on
# the account name. If a host is provided, then the information
is
# retrieved from that host. Otherwise, the local host is used.
#
# Note that this does NOT create a new SID, but merely
retrieves
# information for an existing SID. To create a new SID, use the
# SID.create method.
#--
# TODO: Add the SID.create method.
#
def initialize(account, host=Socket.gethostname)
sid = 0.chr * 28
sid_cb = [sid.size].pack(''L'')
domain_buf = 0.chr * 80
domain_cch = [domain_buf.size].pack(''L'')
sid_name_use = 0.chr * 4
bool = LookupAccountName(
host,
account,
sid,
sid_cb,
domain_buf,
domain_cch,
sid_name_use
)
unless bool
raise Error, get_last_error
end
@sid = sid.strip
@host = host
@domain = domain_buf.strip
@account = account
@account_type
get_account_type(sid_name_use.unpack(''L'')[0])
sid
end
# Returns the binary SID in string format suitable for display,
# storage or transmission.
#
def to_s
sid_addr =
[@sid].pack(''p*'').unpack(''L'').first
sid_buf = 0.chr * 80
sid_ptr = 0.chr * 4
unless ConvertSidToStringSid(sid_addr, sid_ptr)
raise Error, get_last_error
end
strcpy(sid_buf, sid_ptr.unpack(''L'').first)
sid_buf.strip
end
alias to_str to_s
# Returns whether or not the SID object is equal to +other+.
#
def ==(other)
EqualSid(@sid, other.sid)
end
# Returns whether or not the SID is a valid sid.
#
def valid?
IsValidSid(@sid)
end
# Returns the length of the SID object, in bytes.
#
def length
GetLengthSid(@sid)
end
private
# Converts a numeric account type into a human readable string.
#
def get_account_type(value)
case value
when SidTypeUser
''user''
when SidTypeGroup
''group''
when SidTypeDomain
''domain''
when SidTypeAlias
''alias''
when SidTypeWellKnownGroup
''well known group''
when SidTypeDeletedAccount
''deleted account''
when SidTypeInvalid
''invalid''
when SidTypeUnknown
''unknown''
when SidComputer
''computer''
end
end
end
end
end
# end sid.rb
I wasn''t sure if SID.new should refer to an existing account, or
actually create a new SID via InitializeSid() or something. My current
idea is to setup a SID.create method for actually creating a new SID.
Does that seem reasonable? Or does that seem counterintuitive?
Anyway, there you go. Please let me know what you think.
Regards,
Dan
This communication is the property of Qwest and may contain confidential or
privileged information. Unauthorized use of this communication is strictly
prohibited and may be unlawful. If you have received this communication
in error, please immediately notify the sender by reply e-mail and destroy
all copies of the communication and any attachments.