Hi, I''ve added what I think is a working File.owned? method to the win32-file-security gem. However, I''m not 100% sure that my method of comparison is correct - I''m comparing sid strings (where I sort of artifically chop the size of one of them) instead of using EqualSid with pointers. Can someone please validate? Just pull the latest git master. Suggestions welcome. Thanks, Dan PS - Heesob, I thought maybe you implemented this already at some point, but I couldn''t find it. If you did and I missed it then I''m sorry!
Hi, 2012/12/25 Daniel Berger <djberg96 at gmail.com>:> Hi, > > I''ve added what I think is a working File.owned? method to the > win32-file-security gem. However, I''m not 100% sure that my method of > comparison is correct - I''m comparing sid strings (where I sort of > artifically chop the size of one of them) instead of using EqualSid > with pointers. > > Can someone please validate? Just pull the latest git master. > > Suggestions welcome. > > Thanks, > > Dan > > PS - Heesob, I thought maybe you implemented this already at some > point, but I couldn''t find it. If you did and I missed it then I''m > sorry!The File.owned? method works fine on some tests. I can''t remember I have implemented this method. But I found some related messages. http://rubyforge.org/pipermail/win32utils-devel/2008-June/thread.html#1163 Regards, Park Heesob
On Mon, Dec 24, 2012 at 6:42 PM, Heesob Park <phasis at gmail.com> wrote:> Hi, > > 2012/12/25 Daniel Berger <djberg96 at gmail.com>: >> Hi, >> >> I''ve added what I think is a working File.owned? method to the >> win32-file-security gem. However, I''m not 100% sure that my method of >> comparison is correct - I''m comparing sid strings (where I sort of >> artifically chop the size of one of them) instead of using EqualSid >> with pointers. >> >> Can someone please validate? Just pull the latest git master. >> >> Suggestions welcome. >> >> Thanks, >> >> Dan >> >> PS - Heesob, I thought maybe you implemented this already at some >> point, but I couldn''t find it. If you did and I missed it then I''m >> sorry! > The File.owned? method works fine on some tests. > > I can''t remember I have implemented this method. > But I found some related messages. > http://rubyforge.org/pipermail/win32utils-devel/2008-June/thread.html#1163Ok, I just wanted to make sure bit of code wasn''t problematic: if string_sid == sid.read_string(string_sid.size) return_value = true end I''m not sure how to implement File.chown. The links from those 2008 messages seem to be dead. I found this: http://www.perlmonks.org/?node_id=70562 Would that work? Regards, Dan
Hi, 2012/12/25 Daniel Berger <djberg96 at gmail.com>> > On Mon, Dec 24, 2012 at 6:42 PM, Heesob Park <phasis at gmail.com> wrote: > > Hi, > > > > 2012/12/25 Daniel Berger <djberg96 at gmail.com>: > >> Hi, > >> > >> I''ve added what I think is a working File.owned? method to the > >> win32-file-security gem. However, I''m not 100% sure that my method of > >> comparison is correct - I''m comparing sid strings (where I sort of > >> artifically chop the size of one of them) instead of using EqualSid > >> with pointers. > >> > >> Can someone please validate? Just pull the latest git master. > >> > >> Suggestions welcome. > >> > >> Thanks, > >> > >> Dan > >> > >> PS - Heesob, I thought maybe you implemented this already at some > >> point, but I couldn''t find it. If you did and I missed it then I''m > >> sorry! > > The File.owned? method works fine on some tests. > > > > I can''t remember I have implemented this method. > > But I found some related messages. > > > > http://rubyforge.org/pipermail/win32utils-devel/2008-June/thread.html#1163 > > Ok, I just wanted to make sure bit of code wasn''t problematic: > > if string_sid == sid.read_string(string_sid.size) > return_value = true > end > > I''m not sure how to implement File.chown. The links from those 2008 > messages seem to be dead. I found this: > > http://www.perlmonks.org/?node_id=70562 > > Would that work? >Did you mean you cannot reach the link? http://rubyforge.org/pipermail/win32utils-devel/2008-June/001170.html Following is the content of the message: ========================================================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. >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
On Tue, Dec 25, 2012 at 8:02 AM, Heesob Park <phasis at gmail.com> wrote:> Hi, > > 2012/12/25 Daniel Berger <djberg96 at gmail.com> >> >> On Mon, Dec 24, 2012 at 6:42 PM, Heesob Park <phasis at gmail.com> wrote: >> > Hi, >> > >> > 2012/12/25 Daniel Berger <djberg96 at gmail.com>: >> >> Hi, >> >> >> >> I''ve added what I think is a working File.owned? method to the >> >> win32-file-security gem. However, I''m not 100% sure that my method of >> >> comparison is correct - I''m comparing sid strings (where I sort of >> >> artifically chop the size of one of them) instead of using EqualSid >> >> with pointers. >> >> >> >> Can someone please validate? Just pull the latest git master. >> >> >> >> Suggestions welcome. >> >> >> >> Thanks, >> >> >> >> Dan >> >> >> >> PS - Heesob, I thought maybe you implemented this already at some >> >> point, but I couldn''t find it. If you did and I missed it then I''m >> >> sorry! >> > The File.owned? method works fine on some tests. >> > >> > I can''t remember I have implemented this method. >> > But I found some related messages. >> > >> > http://rubyforge.org/pipermail/win32utils-devel/2008-June/thread.html#1163 >> >> Ok, I just wanted to make sure bit of code wasn''t problematic: >> >> if string_sid == sid.read_string(string_sid.size) >> return_value = true >> end >> >> I''m not sure how to implement File.chown. The links from those 2008 >> messages seem to be dead. I found this: >> >> http://www.perlmonks.org/?node_id=70562 >> >> Would that work? >> > Did you mean you cannot reach the link? > http://rubyforge.org/pipermail/win32utils-devel/2008-June/001170.html > > Following is the content of the message: > ========================================================> 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. >> > 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'') > =============================================================Thanks for this. It''s similar in many ways to what I was already working on, so I was definitely using your code as a reference point, so that helped. I think I have a working File.owner and File.chown implementation now in github. The only odd thing is that the explorer pop-up properties window doesn''t seem to reflect the ownership change (in the "details" tab), but a "dir /q" on the command line does show it, as does the File.owner method. Perhaps I did something wrong? Also, I''m not sure what to do with the "group" parameter for the File.chown method (to match the Ruby API spec). For now I''m just ignoring it. Technically it''s not in line with the spec anyway, since we''re accepting a userid (string) instead of a numeric id for the owner. I suppose we could alter that, but I kinda like it that way. Anyway, please feel free to take a look and see what you think. Regards, Dan
Hi, 2012/12/29 Daniel Berger <djberg96 at gmail.com>> > On Tue, Dec 25, 2012 at 8:02 AM, Heesob Park <phasis at gmail.com> wrote: > > Hi, > > > > 2012/12/25 Daniel Berger <djberg96 at gmail.com> > >> > >> On Mon, Dec 24, 2012 at 6:42 PM, Heesob Park <phasis at gmail.com> wrote: > >> > Hi, > >> > > >> > 2012/12/25 Daniel Berger <djberg96 at gmail.com>: > >> >> Hi, > >> >> > >> >> I''ve added what I think is a working File.owned? method to the > >> >> win32-file-security gem. However, I''m not 100% sure that my method of > >> >> comparison is correct - I''m comparing sid strings (where I sort of > >> >> artifically chop the size of one of them) instead of using EqualSid > >> >> with pointers. > >> >> > >> >> Can someone please validate? Just pull the latest git master. > >> >> > >> >> Suggestions welcome. > >> >> > >> >> Thanks, > >> >> > >> >> Dan > >> >> > >> >> PS - Heesob, I thought maybe you implemented this already at some > >> >> point, but I couldn''t find it. If you did and I missed it then I''m > >> >> sorry! > >> > The File.owned? method works fine on some tests. > >> > > >> > I can''t remember I have implemented this method. > >> > But I found some related messages. > >> > > >> > http://rubyforge.org/pipermail/win32utils-devel/2008-June/thread.html#1163 > >> > >> Ok, I just wanted to make sure bit of code wasn''t problematic: > >> > >> if string_sid == sid.read_string(string_sid.size) > >> return_value = true > >> end > >> > >> I''m not sure how to implement File.chown. The links from those 2008 > >> messages seem to be dead. I found this: > >> > >> http://www.perlmonks.org/?node_id=70562 > >> > >> Would that work? > >> > > Did you mean you cannot reach the link? > > http://rubyforge.org/pipermail/win32utils-devel/2008-June/001170.html > > > > > Thanks for this. It''s similar in many ways to what I was already > working on, so I was definitely using your code as a reference point, > so that helped. > > I think I have a working File.owner and File.chown implementation now > in github. The only odd thing is that the explorer pop-up properties > window doesn''t seem to reflect the ownership change (in the "details" > tab), but a "dir /q" on the command line does show it, as does the > File.owner method. Perhaps I did something wrong? >I added SE_CHANGE_NOTIFY_NAME privilege to notify to the explorer.> Also, I''m not sure what to do with the "group" parameter for the > File.chown method (to match the Ruby API spec). For now I''m just > ignoring it. Technically it''s not in line with the spec anyway, since > we''re accepting a userid (string) instead of a numeric id for the > owner. I suppose we could alter that, but I kinda like it that way. >I think that "group" parameter should be ignored on Windows.> Anyway, please feel free to take a look and see what you think. >Regards, Park Heesob
Hi,>> I think I have a working File.owner and File.chown implementation now >> in github. The only odd thing is that the explorer pop-up properties >> window doesn''t seem to reflect the ownership change (in the "details" >> tab), but a "dir /q" on the command line does show it, as does the >> File.owner method. Perhaps I did something wrong? >> > I added SE_CHANGE_NOTIFY_NAME privilege to notify to the explorer.I tried with your patch, but it still doesn''t seem to show the change. Windows 7, BTW. Regards, Dan
Hi, 2012/12/31 Daniel Berger <djberg96 at gmail.com>:> Hi, > >>> I think I have a working File.owner and File.chown implementation now >>> in github. The only odd thing is that the explorer pop-up properties >>> window doesn''t seem to reflect the ownership change (in the "details" >>> tab), but a "dir /q" on the command line does show it, as does the >>> File.owner method. Perhaps I did something wrong? >>> >> I added SE_CHANGE_NOTIFY_NAME privilege to notify to the explorer. > > I tried with your patch, but it still doesn''t seem to show the change. > Windows 7, BTW. >I confirmed the ownership change on Windows 7 explore. You must reopen properties window. Refer to this help message: "If you have just taken ownership of this object, you will need to close and reopen this object?s properties before you can view or change permissions." Regards, Park Heesob