[Bro] Running external command line programs

Chris Crawford christopher.p.crawford at gmail.com
Fri Feb 22 08:59:09 PST 2013


Cool -- that did the trick.  This is really good stuff.

I decided to try using this against other bro events, besides just
bro_init():

$ cat exec-test.bro
@load ./exec

event dns_message(c: connection, is_orig: bool, msg: dns_msg, len: count)
        {
        Exec::run("./hello", function(r: Exec::Result)
                {
                if ( ! r?$stdout )
                        {
                        print "nothing?!?";
                        return;
                        }

                for ( i in r$stdout )
                        {
                        print r$stdout[i];
                        }
                });
        }

./hello is just a hello world program.

So, when I test that, I see the following.

$ bro -r test.pcap exec-test.bro
Hello World
Hello World
Hello World
nothing?!?
ERROR: 1361476370.202590 no such index (Exec::results[Exec::name])
(././exec.bro, line 25)
[...]


This got me wondering -- why would exec-test.bro ever have a case where (!
r?$stdout) is true, when I have a program that absolutely returns output
every time it's run? (And then print out "nothing?!?")

For convenience:
# exec.bro
 21 event Exec::stdout_line(description: Input::EventDescription, tpe:
Input::Event, s: string)
 22         {
 23         local name = sub(description$name, /_[^_]*$/, "");
 24
 25         if ( ! results[name]?$stdout )
 26                 results[name]$stdout = vector(s);
 27         else
 28                 results[name]$stdout[|results[name]$stdout|] = s;
 29         }


It's also worth noting that exec.bro really trashes the /tmp directory at
this point.

# exec.bro
 94 function run(cmd: string, cb: function(r: Result))
 95         {
 96         local tmpfile = "/tmp/bro-exec-" + unique_id("");
 97         system(fmt("touch %s_done", tmpfile));
 98         system(fmt("touch %s_stdout", tmpfile));
 99         system(fmt("touch %s_stderr", tmpfile));
100         # Sleep for 1 sec before writing to the done file to avoid race
conditions
101         # This makes sure that all of the data is read from
102         system(fmt("%s 2>>%s_stderr 1>> %s_stdout; echo
\"exit_code:${?}\" > %s_done; sleep 1; echo \"done\" >> %s_done", cmd, tmpf
103
104         results[tmpfile] = [];
105         callbacks[tmpfile] = cb;
106
107         schedule 1msec { start_watching_files(tmpfile) };
108         }

That chunk of code probably needs something like this:

system(fmt("rm %s_done", tmpfile));
system(fmt("rm %s_stdout", tmpfile));
system(fmt("rm %s_stderr", tmpfile));

I'm just not sure where it should go.

-Chris

On Thu, Feb 21, 2013 at 4:54 PM, Seth Hall <seth at icir.org> wrote:

>
> On Feb 21, 2013, at 4:47 PM, Chris Crawford <
> christopher.p.crawford at gmail.com> wrote:
>
> > Is there another way to load the listen script?
>
> Oh, I think it's because you're reading a packet capture.  When reading
> packets from a file you can't enable the communication framework.
>
> Just try taking out the -r argument.  You should be able to just put
> frameworks/communication/listen on the command line too instead of the full
> file path.  Also, Bro won't terminate until you kill it.
>
>   .Seth
>
> --
> Seth Hall
> International Computer Science Institute
> (Bro) because everyone has a network
> http://www.bro-ids.org/
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.ICSI.Berkeley.EDU/pipermail/bro/attachments/20130222/9a226230/attachment.html 


More information about the Bro mailing list