metasploit-framework/lib/rex/post/file_stat.rb

221 lines
4.3 KiB
Ruby

#!/usr/bin/env ruby
#
# This is just a container class basically, that acts like File::Struct
#
# You must supply an initialize method that somehow populates the stathash..
#
module Rex
module Post
###
#
# This class emulates the ruby FileStat class against a remote entity in a
# generic fashion. Refer to the ruby documentation for expected behavior.
#
###
class FileStat
#
# Basic file types.
#
@@ftypes = [
'fifo', 'characterSpecial', 'directory',
'blockSpecial', 'file', 'link', 'socket'
]
attr_accessor :stathash
def initialize(buf='')
self.stathash = {}
update(buf) if (buf and not buf.empty?)
end
def dev
self.stathash['st_dev']
end
def ino
self.stathash['st_ino']
end
def mode
self.stathash['st_mode']
end
def nlink
self.stathash['st_nlink']
end
def uid
self.stathash['st_uid']
end
def gid
self.stathash['st_gid']
end
def rdev
self.stathash['st_rdev']
end
def size
self.stathash['st_size']
end
def blksize
self.stathash['st_blksize']
end
def blocks
self.stathash['st_blocks']
end
def atime
Time.at(self.stathash['st_atime'])
end
def mtime
Time.at(self.stathash['st_mtime'])
end
def ctime
Time.at(self.stathash['st_ctime'])
end
def update(buf)
# XXX: This needs to understand more than just 'stat' structures
# Windows can also return _stat32, _stat32i64, _stat64i32, and _stat64 structures
skeys = %W{st_dev st_ino st_mode st_wtf st_nlink st_uid st_gid st_rdev st_size st_ctime st_atime st_mtime}
svals = buf.unpack("VvvvvvvVVVVV")
skeys.each_index do |i|
self.stathash[ skeys[i] ] = svals[i]
end
end
#
# S_IFMT 0170000 bitmask for the file type bitfields
# S_IFSOCK 0140000 socket
# S_IFLNK 0120000 symbolic link
# S_IFREG 0100000 regular file
# S_IFBLK 0060000 block device
# S_IFDIR 0040000 directory
# S_IFCHR 0020000 character device
# S_IFIFO 0010000 fifo
#
# this is my own, just a helper...
def filetype?(mask)
return true if mode & 0170000 == mask
return false
end
def blockdev?
filetype?(060000)
end
def chardev?
filetype?(020000)
end
def directory?
filetype?(040000)
end
def file?
filetype?(0100000)
end
def pipe?
filetype?(010000) # ??? fifo?
end
def socket?
filetype(0140000)
end
def symlink?
filetype(0120000)
end
def ftype
return @@ftypes[(mode & 0170000) >> 13].dup
end
#
# S_ISUID 0004000 set UID bit
# S_ISGID 0002000 set GID bit (see below)
# S_ISVTX 0001000 sticky bit (see below)
# S_IRWXU 00700 mask for file owner permissions
# S_IRUSR 00400 owner has read permission
# S_IWUSR 00200 owner has write permission
# S_IXUSR 00100 owner has execute permission
# S_IRWXG 00070 mask for group permissions
# S_IRGRP 00040 group has read permission
# S_IWGRP 00020 group has write permission
# S_IXGRP 00010 group has execute permission
# S_IRWXO 00007 mask for permissions for others (not in group)
# S_IROTH 00004 others have read permission
# S_IWOTH 00002 others have write permisson
# S_IXOTH 00001 others have execute permission
#
def perm?(mask)
return true if mode & mask == mask
return false
end
def setgid?
perm?(02000)
end
def setuid?
perm?(04000)
end
def sticky?
perm?(01000)
end
def executable?
raise NotImplementedError
end
def executable_real?
raise NotImplementedError
end
def grpowned?
raise NotImplementedError
end
def owned?
raise NotImplementedError
end
def readable?
raise NotImplementedError
end
def readable_real?
raise NotImplementedError
end
def writeable?
raise NotImplementedError
end
def writeable_real?
raise NotImplementedError
end
#
# Return pretty information about a file's permissions.
#
def prettymode
m = mode
om = '%04o' % m
perms = ''
3.times {
perms = ((m & 01) == 01 ? 'x' : '-') + perms
perms = ((m & 02) == 02 ? 'w' : '-') + perms
perms = ((m & 04) == 04 ? 'r' : '-') + perms
m >>= 3
}
return "#{om}/#{perms}"
end
#
# Return pretty information about a file.
#
def pretty
" Size: #{size} Blocks: #{blocks} IO Block: #{blksize} Type: #{rdev}\n"\
"Device: #{dev} Inode: #{ino} Links: #{nlink}\n"\
" Mode: #{prettymode}\n"\
" Uid: #{uid} Gid: #{gid}\n"\
"Access: #{atime}\n"\
"Modify: #{mtime}\n"\
"Change: #{ctime}\n"
end
end
end; end # Post/Rex