#! /usr/local/bin/perl -w # The Emergency Client - send commands to the emergency daemon # David A. Madore - Public Domain # This is a stupid client which just sends a command verbatim to the # emergency daemon. All it takes care of is to put a valid timestamp # and MAC. # Options recognized: # # -K specifies the key to use; or -k specifies a # keyfile (the client will use the first line as key). # # -h and -p specifies the host and port to connect # to. # # -t specifies an explicit timestamp to use. # # The command follows the options. use strict; use warnings; use Digest::SHA qw(hmac_sha256_hex); use Socket; use Socket6; use Getopt::Std; use constant { DEFAULT_PORT => 911 }; my %opts; getopts("K:k:h:p:t:", \%opts); my $key; if ( defined($opts{K}) ) { $key = $opts{K}; } elsif ( defined($opts{k}) ) { open my $keyfile, "<", $opts{k} or die "Cannot open key file $opts{k}: $!"; $key = <$keyfile>; chomp $key; close $keyfile; } die "No key specified (use -K or -k option)" unless defined($key); my $host; if ( defined($opts{h}) ) { $host = $opts{h}; } else { $host = "localhost"; } my $port; if ( defined($opts{p}) ) { $port = $opts{p}; } else { $port = DEFAULT_PORT; } my @res = getaddrinfo($host, $port, AF_UNSPEC, SOCK_DGRAM) or die "Cannot resolve host $host port $port"; my ($family, $socktype, $proto, $haddr) = @res; my $socket; socket $socket, $family, $socktype, $proto or die "Can't create socket: $!"; bind $socket, sockaddr_in6(0, in6addr_any); sub curtime { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time); return sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ",$year+1900,$mon+1,$mday,$hour,$min,$sec); } my $command = $ARGV[0]; $command = "PING" unless defined($command); my $timestamp = $opts{t}; $timestamp = curtime unless defined($timestamp); my $validate = "$command|$timestamp"; my $maccheck = hmac_sha256_hex($validate, $key); send $socket, "$command|$timestamp|$maccheck", 0, $haddr; my $buf; my $sender; eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 5; do { $sender = recv($socket, $buf, 16384, 0); } while ( $sender ne $haddr ); }; if ( $@ ) { printf "timeout\n"; } else { printf "%s", $buf; }