Hi folks, I''ve got most everything done for the pure Ruby version of win32-file. The last thing left (since I''ll be moving the IO methods to a different package eventually) is the file security stuff. Here''s what I''ve got so far for the get_permissions method. However, I''m stuck at GetAce(). If someone could help me finish up this method, I would be most appreciative. Also, should we consider dumping this approach in favor of a OLE + WMI solution, using Win32_LogicalFileSecuritySetting ? Dan def self.get_permissions(file) current_length = 0 length_needed = [1].pack(''L'') sec_buf = '''' loop do bool = @@GetFileSecurity.call( file, DACL_SECURITY_INFORMATION, sec_buf, sec_buf.length, length_needed ) if bool == 0 && @@GetLastError.call != ERROR_INSUFFICIENT_BUFFER raise ArgumentError, get_last_error end break if sec_buf.length >= length_needed.unpack(''L'').first sec_buf += '' '' * length_needed.unpack("L").first end control = [0].pack(''L'') revision = [0].pack(''L'') if @@GetSecurityDescriptorControl.call(sec_buf, control, revision) == 0 raise ArgumentError, get_last_error end # No DACL exists if (control.unpack(''L'').first & SE_DACL_PRESENT) == 0 raise ArgumentError, ''No DACL present: explicit deny all'' end dacl_present = [0].pack(''L'') dacl_defaulted = [0].pack(''L'') acl_ptr = [0].pack(''L'') val = @@GetSecurityDescriptorDacl.call( sec_buf, dacl_present, acl_ptr, dacl_defaulted ) if val == 0 raise ArgumentError, get_last_error end acl_buf = 0.chr * 8 @@memcpy.call(acl_buf, acl_ptr.unpack(''L'').first, 8) if acl_buf.unpack(''CCSSS'').first == 0 raise ArgumentError, ''DACL is NULL: implicit access grant'' end ace_count = acl_buf.unpack(''CCSSS'')[3] ace_ptr = [0].pack(''L'') # stuck here 0.upto(ace_count - 1){ |i| if @@GetAce.call(acl_buf, i, ace_ptr) == 0 next end ace_buf = 0.chr * 4 @@memcpy.call(ace_buf, ace_ptr.unpack(''L'').first, 4) p ace_buf.unpack(''CCS'') # Not what I expect } end
Hi,> >Hi folks, > >I''ve got most everything done for the pure Ruby version of >win32-file. >The last thing left (since I''ll be moving the IO methods to a >different >package eventually) is the file security stuff. Here''s what I''ve >got so >far for the get_permissions method. However, I''m stuck at GetAce(). > If >someone could help me finish up this method, I would be most >appreciative. > >Also, should we consider dumping this approach in favor of a OLE + >WMI >solution, using Win32_LogicalFileSecuritySetting ? >Yes. I think we can do more things with this than WMI.>Dan > >def self.get_permissions(file) > current_length = 0 > length_needed = [1].pack(''L'') > sec_buf = '''' > > loop do > bool = @@GetFileSecurity.call( > file, > DACL_SECURITY_INFORMATION, > sec_buf, > sec_buf.length, > length_needed > ) > > if bool == 0 && @@GetLastError.call != >ERROR_INSUFFICIENT_BUFFER > raise ArgumentError, get_last_error > end > > break if sec_buf.length >= length_needed.unpack(''L'').first > sec_buf += '' '' * length_needed.unpack("L").first > end > > control = [0].pack(''L'') > revision = [0].pack(''L'') > > if @@GetSecurityDescriptorControl.call(sec_buf, control, >revision) >== 0 > raise ArgumentError, get_last_error > end > > # No DACL exists > if (control.unpack(''L'').first & SE_DACL_PRESENT) == 0 > raise ArgumentError, ''No DACL present: explicit deny all'' > end > > dacl_present = [0].pack(''L'') > dacl_defaulted = [0].pack(''L'') > acl_ptr = [0].pack(''L'') > > val = @@GetSecurityDescriptorDacl.call( > sec_buf, > dacl_present, > acl_ptr, > dacl_defaulted > ) > > if val == 0 > raise ArgumentError, get_last_error > end > > acl_buf = 0.chr * 8 > @@memcpy.call(acl_buf, acl_ptr.unpack(''L'').first, 8) > > if acl_buf.unpack(''CCSSS'').first == 0 > raise ArgumentError, ''DACL is NULL: implicit access grant'' > end > > ace_count = acl_buf.unpack(''CCSSS'')[3] > ace_ptr = [0].pack(''L'') > > # stuck here > 0.upto(ace_count - 1){ |i| > if @@GetAce.call(acl_buf, i, ace_ptr) == 0 > next > end > > ace_buf = 0.chr * 4 > @@memcpy.call(ace_buf, ace_ptr.unpack(''L'').first, 4) > > p ace_buf.unpack(''CCS'') # Not what I expect > } > > end > >Refer to ruby-talk:184780 define GetAce like this: GetAce = Win32API.new(''advapi32'', ''GetAce'', ''LLP'', ''I'') and call like this: GetAce.call(acl_ptr.unpack(''L'')[0], i, ace_ptr) Regards, Park Heesob
> -----Original Message----- > From: win32utils-devel-bounces at rubyforge.org > [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of > Park Heesob > Sent: Monday, March 20, 2006 7:37 PM > To: win32utils-devel at rubyforge.org > Subject: Re: [Win32utils-devel] Need some ACL help for win32-file<snip>> > > >Also, should we consider dumping this approach in favor of a OLE + > >WMI > >solution, using Win32_LogicalFileSecuritySetting ? > > > Yes. I think we can do more things with this than WMI.Wait - you think we should use WMI or we shouldn''t? <snip>> Refer to ruby-talk:184780 > > define GetAce like this: > GetAce = Win32API.new(''advapi32'', ''GetAce'', ''LLP'', ''I'') > > and call like this: > GetAce.call(acl_ptr.unpack(''L'')[0], i, ace_ptr)Ah, thanks. Feel like taking on LookupAccountSid? :) Regards, Dan
Well, I''ve given up trying to figure out the rest of the file permissions stuff (LookupAccountSid, etc). I''m just not getting it. I''ve committed what I''ve done so far (now in the toplevel win32-file project in the CVS repo) in file.rb. Any help appreciated. Regards, Dan
Hi,> Well, I''ve given up trying to figure out the rest of the file > permissions stuff (LookupAccountSid, etc). I''m just not getting it. >Well, Don''t give up :) Here is the LookupAccountSid stuff: 0.upto(ace_count - 1){ |i| if @@GetAce.call(dacl_ptr.unpack(''L'').first, i, ace_ptr) == 0 next end ace_buf = 0.chr * 12 # Header:4,Mask:4,SidStart:4 (struct ACCESS_ALLOWD_ACE) @@memcpy.call(ace_buf, ace_ptr.unpack(''L'').first, ace_buf.size) if ace_buf.unpack(''CCS'').first == ACCESS_ALLOWED_ACE_TYPE name = 0.chr * 256 name_len_ptr = [name.size].pack(''L'') domain = 0.chr * 256 domain_len_ptr = [domain.size].pack(''L'') snu_ptr = 0.chr * 4 val = @@LookupAccountSid.call( nil, # local computer ace_ptr.unpack(''L'').first + 8, # address of ace_ptr->SidStart name, name_len_ptr, domain, domain_len_ptr, snu_ptr ) if val == 0 raise ArgumentError, get_last_error end name = name[0...name_len_ptr.unpack(''L'').first] domain = domain[0...domain_len_ptr.unpack(''L'').first] mask = ace_buf.unpack(''LLL'')[1] puts "\n\nUser:#{name},Domain:#{domain}" puts "FILE_APPEND_DATA" if (mask & FILE_APPEND_DATA).nonzero? puts "FILE_EXECUTE" if (mask & FILE_EXECUTE).nonzero? puts "FILE_READ_ATTRIBUTES" if (mask & FILE_READ_ATTRIBUTES).nonzero? puts "FILE_READ_DATA" if (mask & FILE_READ_DATA).nonzero? puts "FILE_READ_EA" if (mask & FILE_READ_EA).nonzero? puts "FILE_WRITE_ATTRIBUTES" if (mask & FILE_WRITE_ATTRIBUTES).nonzero? puts "FILE_WRITE_DATA" if (mask & FILE_WRITE_DATA).nonzero? puts "FILE_WRITE_EA" if (mask & FILE_WRITE_EA).nonzero? puts "DELETE" if (mask & DELETE).nonzero? puts "READ_CONTROL" if (mask & READ_CONTROL).nonzero? puts "WRITE_DAC" if (mask & WRITE_DAC).nonzero? puts "WRITE_OWNER" if (mask & WRITE_OWNER).nonzero? puts "SYNCHRONIZE" if (mask & SYNCHRONIZE).nonzero? puts "ACCESS_SYSTEM_SECURITY" if (mask & ACCESS_SYSTEM_SECURITY).nonzero? puts "MAXIMUM_ALLOWED" if (mask & MAXIMUM_ALLOWED).nonzero? end And define LookupAccountSid like this: @@LookupAccountSid Win32API.new(''advapi32'', ''LookupAccountSid'', ''PLPPPPP'', ''I'')> I''ve committed what I''ve done so far (now in the toplevel win32-file > project in the CVS repo) in file.rb. Any help appreciated. > > Regards, > > DanRegards, Park Heesob
> -----Original Message----- > From: win32utils-devel-bounces at rubyforge.org > [mailto:win32utils-devel-bounces at rubyforge.org] On Behalf Of > Park Heesob > Sent: Wednesday, March 22, 2006 5:58 AM > To: win32utils-devel at rubyforge.org > Subject: Re: [Win32utils-devel] Need some ACL help for win32-file > > > Hi, > > Well, I''ve given up trying to figure out the rest of the file > > permissions stuff (LookupAccountSid, etc). I''m just not > getting it. > > > Well, Don''t give up :) > > Here is the LookupAccountSid stuff:<snip> Excellent, thanks! I was pretty close. Mainly I was stuck on the second argument (SidStart) and how to handle that. Dan