[Win32utils-devel] User sid
Park Heesob
phasis at gmail.com
Sun Jun 29 05:38:12 EDT 2008
Hi,
----- Original Message -----
From: "Berger, Daniel" <Daniel.Berger at qwest.com>
To: "Development and ideas for win32utils projects"
<win32utils-devel at rubyforge.org>
Sent: Saturday, June 28, 2008 12:27 AM
Subject: Re: [Win32utils-devel] User sid
> Hi,
>
> <snip>
>
>> > What do you think about the idea of having Process.uid
>> return a SID, and
>> > a Process.uid= method that would take a SID? I think this
>> is possible
>> > with SetSecurityInfo, but I haven't tried yet.
>> >
>> > Possible enhancement for win32-process 0.6.0?
>> >
>> I'm not sure it is possible. but it is worthwhile.
>
> Here's one possible solution I came across.
>
> http://hockeythoughts.net/forums/printthread.php?t=1210
>
> There might be better ones, though.
>
>> In relation to the SID,
>> Finding the Owner of a File Object
>> (http://msdn.microsoft.com/en-us/library/aa446629(VS.85).aspx)
>> and Taking Object Ownership
>> (http://msdn.microsoft.com/en-us/library/aa379620(VS.85).aspx)
>> is also possible enhancement for win32-file, right?
>
> That looks like a good idea. With that we could implement a working
> File.chown (and File.owned?, too, I think), correct?
>
> Please go ahead and implement this if you have the desire and the time,
> as I will be out next week on vacation.
>
I have implemented it as you expected :)
After adding following two lines to the security.rb:
API.new('GetSecurityInfo', 'LLLPPPPP', 'L', 'advapi32')
API.new('SetSecurityInfo', 'LLLPPPP', 'L', 'advapi32')
Here is a working code for change_owner and get_owner :
require 'windows/process'
require 'windows/handle'
require 'windows/file'
require 'windows/error'
require 'windows/security'
require 'windows/msvcrt/string'
require 'windows/msvcrt/buffer'
include Windows::Process
include Windows::Handle
include Windows::File
include Windows::Error
include Windows::Security
include Windows::MSVCRT::String
include Windows::MSVCRT::Buffer
SE_KERNEL_OBJECT = 6
SE_FILE_OBJECT = 1
OWNER_SECURITY_INFORMATION = 1
SECURITY_DESCRIPTOR_REVISION = 1
def get_sid(account)
sid = 0.chr * 28
sid_cb = [sid.size].pack('L')
name_buf = 0.chr * 80
name_cch = [name_buf.size].pack('L')
domain_buf = 0.chr * 80
domain_cch = [domain_buf.size].pack('L')
sid_name_use = 0.chr * 4
bool = LookupAccountName(
nil,
account,
sid,
sid_cb,
domain_buf,
domain_cch,
sid_name_use
)
unless bool
raise get_last_error
end
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 get_last_error
end
strcpy(sid_buf,sid_ptr.unpack('L').first)
sid
end
def enable_privilege(privilege)
modify_state(privilege, true)
end
def disable_privilege(privilege)
modify_state(privilege, false)
end
def modify_state(privilege,enable)
token_handle = [0].pack('L')
unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY |
TOKEN_ADJUST_PRIVILEGES, token_handle)
raise get_last_error
end
token_handle = token_handle.unpack('L')[0]
return_length = [0].pack('L')
luid = 0.chr * 8
LookupPrivilegeValue("", privilege, luid)
unless LookupPrivilegeValue("", privilege, luid)
raise get_last_error
end
luid = luid.unpack('LL')
if enable
tkp1 = [ 1, luid[0], luid[1], 2 ].pack('LLLL')
else
tkp1 = [ 1, luid[0], luid[1], 0 ].pack('LLLL')
end
unless AdjustTokenPrivileges(token_handle, 0, tkp1, tkp1.size, nil, nil)
raise get_last_error
end
CloseHandle(token_handle)
true
end
def get_owner(file)
handle = CreateFile(
file,
GENERIC_READ ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0
)
if handle == INVALID_HANDLE_VALUE
raise ArgumentError, get_last_error
end
sid = 0.chr * 28
sid_ptr = [0].pack('L')
ret = GetSecurityInfo(
handle,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
sid_ptr,nil,nil,nil,nil)
if(ret!=0)
raise get_last_error
end
name_buf = 0.chr * 80
name_cch = [name_buf.size].pack('L')
domain_buf = 0.chr * 80
domain_cch = [domain_buf.size].pack('L')
sid_name_use = 0.chr * 4
bool = LookupAccountSid(
nil,
sid_ptr.unpack('L').first,
name_buf,
name_cch,
domain_buf,
domain_cch,
sid_name_use
)
unless bool
raise get_last_error
end
name_buf.strip
end
def change_owner(file,account)
enable_privilege("SeRestorePrivilege")
sid = get_sid(account)
sec_desc = 0.chr * SECURITY_DESCRIPTOR_MIN_LENGTH
unless InitializeSecurityDescriptor(sec_desc, 1)
raise get_last_error
end
unless SetSecurityDescriptorOwner(sec_desc, sid, 0)
raise get_last_error
end
unless SetFileSecurity(file, OWNER_SECURITY_INFORMATION, sec_desc)
raise get_last_error
end
disable_privilege ("SeRestorePrivilege")
end
You can test it with
change_owner('c:/test.txt','user')
or
get_owner('c:/test.txt')
Regards,
Park Heesob
More information about the win32utils-devel
mailing list