I''m working on the win32-file-security lib (the security functions split out from win32-file), but I''m stuck on the get_permissions method conversion to FFI. Specifically, the ACL struct doesn''t seem to get filled with correct values on the call to GetSecurityDescriptorDacl. They''re junk. I''ve tried creating a new ACL from the pointer, but that didn''t seem to work. Any ideas? Dan # file.rb require ''ffi'' class String # Convenience method for converting strings to UTF-16LE for wide character # functions that require it. def wincode (self.tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode(''UTF-16LE'') end end class File extend FFI::Library ffi_lib ''advapi32'' SE_DACL_PRESENT = 4 DACL_SECURITY_INFORMATION = 4 ACCESS_ALLOWED_ACE_TYPE = 0 ERROR_INSUFFICIENT_BUFFER = 122 class ACL < FFI::Struct layout( :AclRevision, :uchar, :Sbz1, :uchar, :AclSize, :ushort, :AceCount, :ushort, :Sbz2, :ushort ) end attach_function :GetFileSecurityW, [:buffer_in, :ulong, :pointer, :ulong, :pointer], :bool attach_function :GetSecurityDescriptorControl, [:pointer, :pointer, :pointer], :bool attach_function :GetSecurityDescriptorDacl, [:pointer, :pointer, ACL, :pointer], :ulong def self.get_permissions(file, host=nil) size_needed_ptr = FFI::MemoryPointer.new(:ulong) security_ptr = FFI::MemoryPointer.new(:ulong) wide_file = file.wincode # First pass, get the size needed bool = GetFileSecurityW( wide_file, DACL_SECURITY_INFORMATION, security_ptr, security_ptr.size, size_needed_ptr ) errno = FFI.errno if !bool && errno != ERROR_INSUFFICIENT_BUFFER raise SystemCallError.new("GetFileSecurity", errno) end size_needed = size_needed_ptr.read_ulong security_ptr = FFI::MemoryPointer.new(size_needed) # Second pass, this time with the appropriately sized security pointer bool = GetFileSecurityW( wide_file, DACL_SECURITY_INFORMATION, security_ptr, security_ptr.size, size_needed_ptr ) unless bool raise SystemCallError.new("GetFileSecurity", FFI.errno) end control_ptr = FFI::MemoryPointer.new(:ulong) revision_ptr = FFI::MemoryPointer.new(:ulong) unless GetSecurityDescriptorControl(security_ptr, control_ptr, revision_ptr) raise SystemCallError.new("GetSecurityDescriptorControl", FFI.errno) end control = control_ptr.read_ulong if control & SE_DACL_PRESENT == 0 raise ArgumentError, "No DACL present: explicit deny all" end acl = ACL.new dacl_present_ptr = FFI::MemoryPointer.new(:bool) dacl_defaulted_ptr = FFI::MemoryPointer.new(:ulong) # TODO: ACL struct is not getting filled with expected values. Fix. val = GetSecurityDescriptorDacl( security_ptr, dacl_present_ptr, acl, dacl_defaulted_ptr ) if val == 0 raise SystemCallError.new("GetSecurityDescriptorDacl", FFI.errno) end if acl[:AclRevision] == 0 raise ArgumentError, "DACL is NULL: implicit access grant" end p acl[:AclRevision] p acl[:AclSize] p acl[:AceCount] end end File.get_permissions(''test.txt'')
Hi, 2012/11/30 Daniel Berger <djberg96 at gmail.com>:> I''m working on the win32-file-security lib (the security functions > split out from win32-file), but I''m stuck on the get_permissions > method conversion to FFI. Specifically, the ACL struct doesn''t seem to > get filled with correct values on the call to > GetSecurityDescriptorDacl. They''re junk. > > I''ve tried creating a new ACL from the pointer, but that didn''t seem > to work. Any ideas? >I guess you have some trouble for the pointer of pointer. Here is a working code: require ''ffi'' class String # Convenience method for converting strings to UTF-16LE for wide character # functions that require it. def wincode (self.tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode(''UTF-16LE'') end end class File extend FFI::Library ffi_lib ''advapi32'' SE_DACL_PRESENT = 4 DACL_SECURITY_INFORMATION = 4 ACCESS_ALLOWED_ACE_TYPE = 0 ERROR_INSUFFICIENT_BUFFER = 122 class ACL < FFI::Struct layout( :AclRevision, :uchar, :Sbz1, :uchar, :AclSize, :ushort, :AceCount, :ushort, :Sbz2, :ushort ) end attach_function :GetFileSecurityW, [:buffer_in, :ulong, :pointer, :ulong, :pointer], :bool attach_function :GetSecurityDescriptorControl, [:pointer, :pointer, :pointer], :bool attach_function :GetSecurityDescriptorDacl, [:pointer, :pointer, ACL, :pointer], :ulong def self.get_permissions(file, host=nil) size_needed_ptr = FFI::MemoryPointer.new(:ulong) security_ptr = FFI::MemoryPointer.new(:ulong) wide_file = file.wincode # First pass, get the size needed bool = GetFileSecurityW( wide_file, DACL_SECURITY_INFORMATION, security_ptr, security_ptr.size, size_needed_ptr ) errno = FFI.errno if !bool && errno != ERROR_INSUFFICIENT_BUFFER raise SystemCallError.new("GetFileSecurity", errno) end size_needed = size_needed_ptr.read_ulong security_ptr = FFI::MemoryPointer.new(size_needed) # Second pass, this time with the appropriately sized security pointer bool = GetFileSecurityW( wide_file, DACL_SECURITY_INFORMATION, security_ptr, security_ptr.size, size_needed_ptr ) unless bool raise SystemCallError.new("GetFileSecurity", FFI.errno) end control_ptr = FFI::MemoryPointer.new(:ulong) revision_ptr = FFI::MemoryPointer.new(:ulong) unless GetSecurityDescriptorControl(security_ptr, control_ptr, revision_ptr) raise SystemCallError.new("GetSecurityDescriptorControl", FFI.errno) end control = control_ptr.read_ulong if control & SE_DACL_PRESENT == 0 raise ArgumentError, "No DACL present: explicit deny all" end acl_pptr = FFI::MemoryPointer.new(:pointer) dacl_present_ptr = FFI::MemoryPointer.new(:bool) dacl_defaulted_ptr = FFI::MemoryPointer.new(:ulong) val = GetSecurityDescriptorDacl( security_ptr, dacl_present_ptr, acl_pptr, dacl_defaulted_ptr ) if val == 0 raise SystemCallError.new("GetSecurityDescriptorDacl", FFI.errno) end acl = ACL.new(acl_pptr.read_pointer) if acl[:AclRevision] == 0 raise ArgumentError, "DACL is NULL: implicit access grant" end p acl[:AclRevision] p acl[:AclSize] p acl[:AceCount] end end File.get_permissions(''test.txt'') Regards, Park Heesob
On Thu, Nov 29, 2012 at 8:23 PM, Heesob Park <phasis at gmail.com> wrote:> Hi, > > 2012/11/30 Daniel Berger <djberg96 at gmail.com>: >> I''m working on the win32-file-security lib (the security functions >> split out from win32-file), but I''m stuck on the get_permissions >> method conversion to FFI. Specifically, the ACL struct doesn''t seem to >> get filled with correct values on the call to >> GetSecurityDescriptorDacl. They''re junk. >> >> I''ve tried creating a new ACL from the pointer, but that didn''t seem >> to work. Any ideas? >> > I guess you have some trouble for the pointer of pointer. > > Here is a working code: > > require ''ffi'' > > class String > # Convenience method for converting strings to UTF-16LE for wide character > # functions that require it. > def wincode > (self.tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode(''UTF-16LE'') > end > end > > class File > extend FFI::Library > ffi_lib ''advapi32'' > > SE_DACL_PRESENT = 4 > DACL_SECURITY_INFORMATION = 4 > ACCESS_ALLOWED_ACE_TYPE = 0 > ERROR_INSUFFICIENT_BUFFER = 122 > > class ACL < FFI::Struct > layout( > :AclRevision, :uchar, > :Sbz1, :uchar, > :AclSize, :ushort, > :AceCount, :ushort, > :Sbz2, :ushort > ) > end > > attach_function :GetFileSecurityW, [:buffer_in, :ulong, :pointer, > :ulong, :pointer], :bool > attach_function :GetSecurityDescriptorControl, [:pointer, :pointer, > :pointer], :bool > attach_function :GetSecurityDescriptorDacl, [:pointer, :pointer, > ACL, :pointer], :ulong > > def self.get_permissions(file, host=nil) > size_needed_ptr = FFI::MemoryPointer.new(:ulong) > security_ptr = FFI::MemoryPointer.new(:ulong) > > wide_file = file.wincode > > # First pass, get the size needed > bool = GetFileSecurityW( > wide_file, > DACL_SECURITY_INFORMATION, > security_ptr, > security_ptr.size, > size_needed_ptr > ) > > errno = FFI.errno > > if !bool && errno != ERROR_INSUFFICIENT_BUFFER > raise SystemCallError.new("GetFileSecurity", errno) > end > > size_needed = size_needed_ptr.read_ulong > > security_ptr = FFI::MemoryPointer.new(size_needed) > > # Second pass, this time with the appropriately sized security pointer > bool = GetFileSecurityW( > wide_file, > DACL_SECURITY_INFORMATION, > security_ptr, > security_ptr.size, > size_needed_ptr > ) > > unless bool > raise SystemCallError.new("GetFileSecurity", FFI.errno) > end > > control_ptr = FFI::MemoryPointer.new(:ulong) > revision_ptr = FFI::MemoryPointer.new(:ulong) > > unless GetSecurityDescriptorControl(security_ptr, control_ptr, revision_ptr) > raise SystemCallError.new("GetSecurityDescriptorControl", FFI.errno) > end > > control = control_ptr.read_ulong > > if control & SE_DACL_PRESENT == 0 > raise ArgumentError, "No DACL present: explicit deny all" > end > > acl_pptr = FFI::MemoryPointer.new(:pointer) > dacl_present_ptr = FFI::MemoryPointer.new(:bool) > dacl_defaulted_ptr = FFI::MemoryPointer.new(:ulong) > > val = GetSecurityDescriptorDacl( > security_ptr, > dacl_present_ptr, > acl_pptr, > dacl_defaulted_ptr > ) > if val == 0 > raise SystemCallError.new("GetSecurityDescriptorDacl", FFI.errno) > end > acl = ACL.new(acl_pptr.read_pointer) > if acl[:AclRevision] == 0 > raise ArgumentError, "DACL is NULL: implicit access grant" > end > > p acl[:AclRevision] > p acl[:AclSize] > p acl[:AceCount] > end > end > > File.get_permissions(''test.txt'')Thanks! I think I''m stuck again, this time the SidStart member of the ACCESS_ALLOWED_ACE struct isn''t valid. Can you please take a look? git clone https://github.com/djberg96/win32-file-security.git Thanks, Dan
Hi, 2012/12/1 Daniel Berger <djberg96 at gmail.com>> On Thu, Nov 29, 2012 at 8:23 PM, Heesob Park <phasis at gmail.com> wrote: > > Hi, > > > > 2012/11/30 Daniel Berger <djberg96 at gmail.com>: > >> I''m working on the win32-file-security lib (the security functions > >> split out from win32-file), but I''m stuck on the get_permissions > >> method conversion to FFI. Specifically, the ACL struct doesn''t seem to > >> get filled with correct values on the call to > >> GetSecurityDescriptorDacl. They''re junk. > >> > >> I''ve tried creating a new ACL from the pointer, but that didn''t seem > >> to work. Any ideas? > >> > > I guess you have some trouble for the pointer of pointer. > > > > Here is a working code: > > > ... > Thanks! > > I think I''m stuck again, this time the SidStart member of the > ACCESS_ALLOWED_ACE struct isn''t valid. Can you please take a look? > > git clone https://github.com/djberg96/win32-file-security.git > > > The LookupAccountSidW call should beval = LookupAccountSidW( wide_host, ace_pptr.read_pointer+8, name, name_size, domain, domain_size, use_ptr ) Regards, Park Heesob -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/win32utils-devel/attachments/20121201/80684ece/attachment.html>
On Fri, Nov 30, 2012 at 3:48 PM, Heesob Park <phasis at gmail.com> wrote:> Hi, > > 2012/12/1 Daniel Berger <djberg96 at gmail.com> >> >> On Thu, Nov 29, 2012 at 8:23 PM, Heesob Park <phasis at gmail.com> wrote: >> > Hi, >> > >> > 2012/11/30 Daniel Berger <djberg96 at gmail.com>: >> >> I''m working on the win32-file-security lib (the security functions >> >> split out from win32-file), but I''m stuck on the get_permissions >> >> method conversion to FFI. Specifically, the ACL struct doesn''t seem to >> >> get filled with correct values on the call to >> >> GetSecurityDescriptorDacl. They''re junk. >> >> >> >> I''ve tried creating a new ACL from the pointer, but that didn''t seem >> >> to work. Any ideas? >> >> >> > I guess you have some trouble for the pointer of pointer. >> > >> > Here is a working code: >> > >> ... >> Thanks! >> >> I think I''m stuck again, this time the SidStart member of the >> ACCESS_ALLOWED_ACE struct isn''t valid. Can you please take a look? >> >> git clone https://github.com/djberg96/win32-file-security.git >> >> > The LookupAccountSidW call should be > > val = LookupAccountSidW( > wide_host, > ace_pptr.read_pointer+8, > name, > name_size, > domain, > domain_size, > use_ptr > )I thought the :SidStart member was the same thing. Guess not. Anyway, that worked, thanks! Thanks, Dan