#!/usr/bin/perl use strict; use warnings; use DBI; use Data::Dumper; $| = 1; my $SCIRE_CONFIG_FILE = '../etc/scireserver.conf'; #will be /etc/scire.conf when released. my %conf; my $LOGFILE; my $conf_file = (defined($conf{config})) ? $conf{config} : $SCIRE_CONFIG_FILE; read_config_file($conf_file); Dumper(\%conf); my $identified = 0; #Global variable to determine if already identified or not. my $client_id = 0; #Clobal variable for the client id. # Somehow this feels insecure. sub logger { my $line = shift; if(!defined $LOGFILE) { open(*LOGFILE, ">>$conf{logfile}") or die "Cannot open logfile $conf{logfile}"; } print LOGFILE localtime() . " " . $line . "\n"; } sub debug { my $line = shift; if ($conf{debug}) { if (defined($conf{logfile})) { logger("DEBUG: ${line}"); } else { print STDERR "DEBUG: ${line}\n"; } } } #Connect to the Database. my $connect_string = "DBI:$conf{db_type}:$conf{db_name};host=$conf{db_host}"; debug("Connecting to $connect_string"); #my $dbh = DBI->connect($connect_string, $conf{db_user}, $conf{db_passwd}, { RaiseError => 1 } ) # or die "Could not connect to database: $DBI::errstr"; while(<>) { my ($command, @args) = parse_command($_); # chomp( my $line = $_); # debug("DEBUG: line is: $line"); if($command eq "QUIT") { print "OK\n"; exit; } if($command eq "REGISTER") { my ($mac,$ip) = @args; register_client($mac, $ip); next; #End switch here. You can go no further. } if($command eq "IDENTIFY") { my $fingerprint = $args[0]; identify_client($fingerprint); next; #End switch here. You can go no further. } unless($identified == 1) { print "ERROR This client has not yet been authorized. Please identify!\n"; next; } if ($command eq "GET_JOBS") { get_jobs(); } elsif ($command eq "GET_JOB") { my $job = $args[0]; get_job($job); } elsif ($command eq "SET_JOB_STATUS") { my ($jobid,$status) = @args; set_job_status($jobid,$status); } else { print "ERROR The command $command is unknown. Please try again.\n"; } } sub read_config_file { my $conf_file = shift; open(FH, "< ${conf_file}") or die("Couldn't open the config file ${conf_file}: $!"); while () { chomp; next if /^\s*(?:#|$)/; if(/^\s*(.+?)\s*=\s*(.+?)\s*(?:#.*)?$/) { unless(defined($conf{lc($1)})) { #Don't overwrite anything specified in cmdline $conf{lc($1)} = $2; } } } close(FH) or die("Couldn't close the config file ${conf_file}: $!"); debug("Conf file $conf_file read."); } #New clients must be registered so they can be given a key to use (perhaps for job file transfers?) for authentication. This must be allowed before identifying. sub register_client { my ($mac,$ip) = @_; #Validate your inputs! $mac =~ /^[a-zA-Z0-9\:]+$/ or print "ERROR invalid mac $mac!\n"; $ip =~ /^[a-zA-Z0-9\.\:]+$/ or print "ERROR invalid ip $ip!\n"; my ($query, $status_id, $id, $sth); eval { $query = 'SELECT statusid FROM client_status WHERE statusname = "Pending"'; debug("Query is $query"); $status_id = "4"; #db.conn.GetRow($query) #$sth = $dbh->prepare($query); #$status_id = $sth->fetchrow_hashref->{'statusid'}; }; ($@) and print "ERROR Could not get status id: $DBI::errstr\n"; eval { $query = 'LOCK TABLES `gacl_axo_seq` WRITE'; debug("Query is $query"); #execute it #$dbh->do($query); $query = 'SELECT id FROM `gacl_axo_seq`'; debug("Query is $query"); $id = "56"; #execute $query #$sth = $dbh->prepare($query); #$id = $sth->fetchrow_hashref->{'id'}; $query = 'UPDATE `gacl_axo_seq` SET id=?'; debug("Query is $query"); #execute with $id #$sth = $dbh->prepare($query); #$sth->execute($id); $query = 'UNLOCK TABLES'; debug("Query is $query"); #$dbh->do($query); }; ($@) and print "ERROR during fetching of id sequence: $DBI::errstr\n"; eval { $query = 'INSERT INFO `gacl_axo` (id,section_value,value,order_value,name,hidden VALUES (?,"clients",?,1,?,0)'; debug("Query is $query"); #$sth = $dbh->prepare($query); #$sth->execute($id, $hostname, $hostname); #execute with $id, $hostname, $hostname #NOTE: not sure if this query is still valid. may be using id instead of hostname for one of those two now. $query = 'INSERT INTO clients (clientid,digest,cert,hostname,mac,ip,status) VALUES (?,?,?,?,?,?,?)'; debug("Query is $query"); #execute with $id, client_cert.digest("sha1"),crypto.dump_certificate(crypto.FILETYPE_PEM,client_cert),$hostname,$mac,$ip,$status_id)) #$sth = $dbh->prepare($query); #$sth->execute($id,$digest,$hostname,$mac,$ip,$status_id); }; ($@) and print "ERROR Could not insert client with $query: $DBI::errstr\n"; print "OK\n"; } #Identify the client by looking up the fingerprint in the database, and matching it up. sub identify_client { my $fingerprint = shift; #Validate your inputs! $fingerprint =~ s/"//g; #Clear the quotes. $fingerprint =~ /^[A-Za-z0-9]+$/ or print "ERROR invalid fingerprint!\n"; my $query = 'SELECT client_status.statusname, clients.clientid FROM clients JOIN client_status on (clients.status = client_status.statusid) WHERE clients.digest=?'; debug("Query is $query"); #$sth = $dbh->prepare($query); #$sth->execute($digest); #my $status_name = $sth->fetchrow_hashref->{'client_status.statusname'}; #$client_id = $sth->fetchrow_hashref->{'clients.clientid'}; $identified = 1; print "OK\n"; } sub get_jobs { my $query = <<' EndOfQuery' SELECT jobs.jobid FROM jobs NATURAL JOIN jobs_clients NATURAL JOIN job_conditions NATURAL JOIN job_history WHERE jobs_clients.clientid = ? AND jobs.jobid = jobs_clients.jobid AND (job_conditions.deploy_time < now()) AND (job_conditions.expiration_time > now()) AND job_history.statusid = '?' ORDER BY jobs.priority,jobs.created EndOfQuery debug("Query is $query"); #$sth = $dbh->prepare($query); #$sth->execute($client_id,$status_id); #my $jobs_ref = $sth->fetchall_arrayref(); #return $jobs_ref; } sub get_job { my $jobid = shift; #Validate your inputs! my $query = 'SELECT * FROM jobs LEFT JOIN job_conditions on (jobs.jobid) WHERE jobs.jobid = ?'; debug("Query is $query"); #my $sth = $dbh->prepare($query); #$sth->execute($jobid); #my $job = $sth->fetchrow_hashref(); #my $scriptid = $job{'script'}; $query = 'SELECT * FROM scripts WHERE scriptid=?'; debug("Query is $query"); #$sth = $dbh->prepare($query); #$sth->execute($scriptid); #$job{'script'} = $sth->fetchrow_hashref(); #Write the job w/ all data to a jobfile with the following path /JOBDIR/CLIENT_ID/queue/JOBID.job my $filename = "$conf{job_dir}/$client_id/queue/$jobid.job"; return "OK $filename\n"; } sub set_job_status { my ($jobid,$status) = @_; #Validate your inputs! } sub parse_command { my $line = shift; chomp $line; my @parts = split / (?!(?:[^" ]|[^"] [^"])+")/, $line; for(0..$#parts) { $parts[$_] =~ s/(^"|"$)//g; $parts[$_] =~ s/\\"/"/g; } return @parts; }