[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