#!/usr/bin/env ruby # == SYNOPSIS # example.rb [options] [include ...] # # == DESCRIPTION # # Dazuko is a means to hook into a machine's file system and can be used # to monitor (log for diagnostic purposes) or intercept (filter based on # scan results) access to data (files and directories). Dazuko is mostly # used by antivirus scanners to achieve on access scan capabilites. # # The example.rb script demonstrates how to use the Dazuko extension in # ruby style (in an object oriented manner), with and without threads. # # == OPTIONS # # Any path specification following the options is taken as an include path # (just like the "--incl" option had been specified). # # === --help # # Print out a help screen # # === --mask number # # Set the access mask to this value. The numeric parameter # is determined by adding the appropriate bits for the # operations as defined in the +DAZUKO_ON_OPEN+ etc constants. # # === --incl path # # Adds the specified path to the list of include paths. # # This option can be specified multiple times. Multiple arguments # can be specified when separated with colons. # # === --excl path # # Adds the specified path to the list of exclude paths. # # This option can be specified multiple times. Multiple arguments # can be specified when separated with colons. # # === --want type # # This options specifies how event details should be passed to the # access handler. Valid types are "Array" and "Hash". # # === --deny # # This option toggles the behaviour of the access handler. When # it is active, all files with the pattern "deny" in their path name # are denied. # # Use this option with care! See the README and the Perl binding's # README for details. # # === --thrd number # # Without this option the script runs a single instance of the # Dazuko class. When this option is given, this many threads # with one Dazuko instance for each are started. # # == AUTHOR # # Gerhard Sittig # # == SEE ALSO # # Dazuko(3) # # http://www.dazuko.org/ # ----- license (BSD style) ------------------------------------- # { $license = < #{ val }\n" end # block access when (enabled and) certain checks apply deny_rc = false if ($deny) then if ((acc['filename'] != nil) && (acc['filename'] =~ /deny/)) then print "filename matches /deny/\n" deny_rc = true end end # work around the lack of data release code in Dazuko.c: # free as much of the access data as we can do here acc = nil # return the deny status return(deny_rc) end # the main logic: setup a Dazuko instance, get accesses def main(nr) print "main(#{ nr })\n" if (nr != 0) ok = true # preparation d = Dazuko.new ver = d.ioversion? print "IO version #{ ver['text'] }\n" ok = false if ((ok) and (! d.register("example:ruby", ($deny) ? "rw" : "r"))) if (ok) then ver = d.version? print "module version #{ ver['text'] }\n" end ok = false if ((ok) and (! d.set_mask($mask))) ok = false if ((ok) and (! d.add_include($incl))) ok = false if ((ok) and (! d.add_exclude($excl))) ok = false if ((ok) and (! d.access_want($want))) # get accesses (until error or interrupt) trap('INT') do ok = false end loop do break if (! ok) rc = d.get_access() do |acc| deny_rc = false if (acc.class == Array) then deny_rc = handle_access_array(acc, nr) elsif (acc.class == Hash) then deny_rc = handle_access_hash(acc, nr) else print "unknown type of access data \"#{ acc.class }\"\n" end print "will #{ (deny_rc) ? 'deny' : 'grant' } access\n" deny_rc end break if (! rc) end # cleanup d.unregister() if (d.group != nil) d = nil end # preparation steps (scan options, check parameters) def prep() # scan cmdline options opts = GetoptLong.new( [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--mask", "-m", GetoptLong::REQUIRED_ARGUMENT ], [ "--incl", "-i", GetoptLong::REQUIRED_ARGUMENT ], [ "--excl", "-e", GetoptLong::REQUIRED_ARGUMENT ], [ "--want", "-w", GetoptLong::REQUIRED_ARGUMENT ], [ "--deny", "-d", GetoptLong::NO_ARGUMENT ], [ "--thrd", "-t", GetoptLong::REQUIRED_ARGUMENT ] ) opts.each do |opt, arg| if (opt == "--help") then synopsis() exit(0) elsif (opt == "--mask") then $mask = arg.to_i elsif (opt == "--incl") then $incl << arg.to_s elsif (opt == "--excl") then $excl << arg.to_s elsif (opt == "--want") then $want = arg.to_s elsif (opt == "--deny") then $deny = ! $deny elsif (opt == "--thrd") then $thrd = arg.to_i else synopsis() exit(1) end end # remaining arguments are includes $ARGV.each do |arg| $incl << arg.to_s end # split arrays (makes "--incl 1:2 --incl 3" work) $incl = $incl.join(':').split(':') $excl = $excl.join(':').split(':') # make all path names absolute / unified $incl.map! do |fn| File.expand_path(fn) end $excl.map! do |fn| File.expand_path(fn) end # print out parameters print "parameter dump:\n" print "\taccess mask #{ $mask }\n" print "\tincludes #{ $incl.join(':') }\n" print "\texcludes #{ $excl.join(':') }\n" print "\taccess wanted as #{ $want }\n" print "\tdeny access\n" if ($deny) print "\tnumber of threads #{ $thrd }\n" if ($thrd > 0) # check parameters ok = true ok = false if ($mask == 0) ok = false if ($incl[0] == nil) if (! ok) then print "parameters not acceptable\n" exit(1) end end # the entry point of the example script prep() if ($thrd == 0) then main(0) else threads = [] 1.upto($thrd) do |count| print "starting thread #{ count }\n" threads[count - 1] = Thread.new do main(count) end end print "waiting for #{ $thrd } threads to end\n" threads.each do |t| t.join end end # } # ----- E O F ---------------------------------------------------