[Win32utils-devel] Help needed for get_permissions

Heesob Park phasis at gmail.com
Fri Nov 30 03:23:02 UTC 2012


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


More information about the win32utils-devel mailing list