[Win32utils-devel] Help needed for get_permissions
Daniel Berger
djberg96 at gmail.com
Thu Nov 29 17:46:49 UTC 2012
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')
More information about the win32utils-devel
mailing list