in reply to RPC

oh yeah, and be careful.. make sure your script has an array of commands its allowed to run, that way no one can cat /etc/passwd through your script or something like that. if you're going to need to cehck files on the system.. it might pay to setup an array of those files, that way no one can access anything you don't want them to see via your script. ie:
my @CMDS = ("ps", "top", "df", "vmstat", "blah"); my @FILES = ( "/etc/running.cfg", "/home/me/lastchecked.txt", "/var/l +og/httpd/error_log"); my ($cmd, @ARGS) = split(/\s/, $input); my $ok; for(@CMDS) { if($cmd eq $_) { $ok=1; } } if(!$ok) { die "tried to do something that wasn't cool: $input\n"; } # then check for files in args my $ok=0; my $arg; foreach $arg (@ARGS) if(-e $arg) { # we have a file $file=true; for(@FILES) { if($arg eq $_) { $ok=1; } } } } if($file && !$ok) { die "tried to access a bad thing: $input\n"; } # We're pretty much safe to continue

untested, but you get the idea.. make sure that only what you anticipate being input is actually input, that way you can pretty much secure the script.. also run it as a user with as little privileges as possible..

-brad

Replies are listed 'Best First'.
(jeffa) RE: Re: RPC
by jeffa (Bishop) on Nov 08, 2000 at 19:30 UTC
    Done and done!

    I went overboard on this issue. The server has a config file that it reads the actual *nix commands from, along with a pneumonic name (i.e. inodes='df -i') and stores the key-value pairs in a hash. When a client connects to the server, the server sends the pneumonics, so the client never sees the actual command.

    # from server sub get_commands() { open CONF, 'query.conf' or die "No config file found: $!\n"; while (<CONF>) { next if /^#/; chomp; my ($command, $query) = split(/\t/, $_); $commands{$command} = $query; } close CONF; } sub send_commands { my $rhost = shift; my @commands = sort keys %commands; &log_msg("Request for command list from $rhost"); return join(":", @commands); } # and from the client sub get_commands { my $answer; my $i = 'a'; eval { $answer = $conn->rpc('send_commands', $host) }; die "Server $rhost not responding\n" if $@; map { $commands{$i++} = $_ } split(":", $answer); } sub print_menu { print '#' x 30, "\n"; map { print "# $_) $commands{$_}\n" } sort keys %commands; print "# q) quit\n"; print '#' x 30, "\n"; print "Enter choice: "; } # the main processing loop for the client $SIG{ALRM} = sub { die "TIMEOUT" }; &print_menu; while (my $arg = <>) { last if $arg =~ /q/; chomp $arg; my $answer; eval { alarm(10); $answer = $conn->rpc('run', $commands{$arg}, $host) }; alarm(0); }; warn "$queries{$arg} timed out - $host could be down\n" if $@ =~ / +TIMEOUT/; print $answer; &print_menu; }
    Of course the major limitation at this point is only 'a' thru 'p' commands will be available.