Created
April 2, 2017 18:25
-
-
Save dspreitz/0474624f2771405dbf425f278368cc74 to your computer and use it in GitHub Desktop.
bla
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# This script is for use with the Open Glider Network FLARM Detection System only | |
# Any other uses are NOT authorised | |
# | |
# Code has been sponsored by Temeletry Limited (http://www.temeletry.co.uk) | |
# | |
# Copyright (c) 2014, Melissa Jenkins, Temeletry Limited (melissa-ogn@temeletry.co.uk) | |
# | |
use strict; | |
use File::Copy; | |
use File::stat; | |
use Cwd; | |
# to make sure the file was downloaded properly | |
# md5sum 57b80f87891f936b9dcd3f38edee7722 RmeupofZYXEIBjkLLbQuxblRB91JL4szA6tTylb4gkggYUJ3YDt1uazxHK7/HmAYlBjcZq+wgrFvqifD9TFB1nl3JBacSmvE5hpp9M+Csbd9kWrYx4xxOBcGO3cns53bG2nHKiD9nkFfhbQ5O71gujXZ4KhCxmydT/zrOK0zrgNYkhQWgBvID78vwl+WRPRg+2w2vyjTr0iOFCgDJCnhxXzoCkC57o3R7mfXc0P22nRhm2P3FOGdo//mzdX6GGaiE5YKq+ufhKn6rimCVqfkn8uc5zY6L4J26/sZDoIAfSQuC6E1zd+uzHFsrtZNg+0YUvnL6DTA8W5Zzof5M7KOrA== | |
my $version='2.1a'; | |
my $old_handle = select (STDOUT); | |
$| = 1; # perform flush after each write to STDOUT | |
select ($old_handle); | |
my $scriptname = $0; | |
if( ! ($scriptname =~ m|^/| )) { | |
$scriptname = cwd() . "/".$0; | |
$scriptname =~ s|/./|/|; | |
} | |
# do they want help? | |
if( $ARGV[0] =~ '[-]+h' ) { | |
print "$scriptname - OGN Updater v$version\n\n". | |
" -r reboot after running. If installing this will tell the crontab to issue a reboot \n". | |
" after it has checked for updates. Service will not be restarted till after it boots.\n". | |
" -i Do not start the service when done.\n". | |
" -t Test, print what path, user and configuration file is being worked on.\n"; | |
exit 1; | |
} | |
if( $> != 0 ) { | |
die "You need to run this as root, or use sudo"; | |
} | |
# The image version was not good and would sit waiting for a LONG time, use the one from 1.3 | |
my $startupepoch = 1429006250; # on linux date -d '10/25/2014' '+%s', on bsd date -f '%m/%d/%Y' -j '+%s' '1/1/2000' | |
# old style tokens | |
if( -e '/home/pi/sitetoken.txt' ) { | |
move( '/home/pi/sitetoken.txt', '/etc/sitetoken.txt' ); | |
} | |
# keep the same site id for the whole thing | |
my $token; my $aprscall = '*early'; | |
if( ! -e "/etc/sitetoken.txt" ) { | |
my $code = qx( /bin/dd if=/dev/urandom bs=1 count=8 status=noxfer 2>/dev/null ); | |
($token) = join('-',unpack('H4 H4 H4', $code )); | |
qx( echo $token > /etc/sitetoken.txt ); | |
} | |
else { | |
$token = qx( cat /etc/sitetoken.txt ); | |
chomp $token; | |
} | |
## exit when a script update is found | |
print "Checking for updates to update script ($scriptname, existing version $version)... "; | |
if( ! -e $scriptname ) { | |
status( "scriptnamewrong,$scriptname" ); | |
die "Unable to identify script name ($scriptname)" ; | |
} | |
{ | |
my $lasttime = stat($scriptname)->mtime; | |
my $currenttime; | |
my $tempname = '/tmp/update.temporary'; | |
unlink( $tempname ); | |
system( "/usr/bin/curl -s -R https://ognconfig.onglide.com/files/v2.1/update -# -o $tempname" ); | |
if( -e "$tempname" ) { | |
$currenttime = stat($tempname)->mtime; | |
} | |
else { | |
status("error,no_temp_file"); | |
} | |
if( defined( $currenttime ) && $lasttime != $currenttime ) { | |
my ($md5sum_calculated,$md5sum_expected,$signature); | |
if( qx( /bin/grep -v '^# md5sum' $tempname | /usr/bin/md5sum ) =~ /^([0-9a-f]+) / ) { | |
$md5sum_calculated = $1; | |
} | |
if( qx( /bin/grep -e '^# md5sum' $tempname ) =~ /md5sum ([0-9a-f]+) (.*)/ ) { | |
$md5sum_expected = $1; | |
$signature = $2; | |
} | |
# if they are defined and the same | |
if( defined( $md5sum_expected ) && $md5sum_expected eq $md5sum_calculated ) { | |
# we need to check to make sure we have our public key saved away, without this | |
# we can't validate the identify | |
{ | |
if( ! open( OUT, '>', '/etc/ognupdatekey.pem' ) ) { | |
status("error,write,/etc/ognupdatekey.pem,$!"); | |
if( ! -e '/etc/ognupdatekey.pem' ) { | |
status("error,nokey"); | |
} | |
} | |
print OUT "-----BEGIN PUBLIC KEY-----\n". | |
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArG/od7cdIuhSvKXNbO80\n". | |
"tFncaCfwuKUrBGxGE6uxzXRfwcCIn8UukGTnzdMEErh441K+itC69KhgkEhY809K\n". | |
"sxKMJqZ2FL6lXdin7eIMpOKLIXKmwwRYyTYdChXbnrd3Y5e9BXOWEUJVsg2PYrDt\n". | |
"xQnm20PiUgQXVCoW0xuxCnltj69nWGdXWPwhvFYT2ulhIXfVivJmUvHESK2GbYTo\n". | |
"h2Fv7aIQACv4EK7UpPb9zPqBrV4MmwqAKP2LzycIdmlH9D1ebB9T2hK31MIegKuV\n". | |
"VWQFQyqzxnFou3n1WYN3RBe5VdPuabQGXe4VQGmJVR1/1GQ+rPLRaQYU2zDYdLi1\n". | |
"EQIDAQAB\n". | |
"-----END PUBLIC KEY-----\n"; | |
close( OUT ); | |
} | |
# execute openssl to | |
my $md5sum_signed = qx( echo "$signature" | /usr/bin/base64 -d | /usr/bin/openssl rsautl -verify -inkey /etc/ognupdatekey.pem -keyform PEM -pubin ); | |
chomp( $md5sum_signed ); | |
if( ! -e '/etc/ognupdatekey.pem' ) { | |
$md5sum_signed = $md5sum_calculated; | |
status("not_checking_signature"); | |
print "*** Not Checking signature as no pem file exists ***\n"; | |
} | |
# make sure it matches | |
if( defined( $md5sum_signed ) && $md5sum_signed eq $md5sum_calculated ) { | |
# and that it isn't the same as the one we are running (datetime issue locally) | |
my $current_md5sum = ''; | |
if( qx( /bin/grep -e '^# md5sum' $scriptname ) =~ /md5sum ([0-9a-f]+) (.*)/ ) { | |
$current_md5sum = $1; | |
} | |
if( $current_md5sum ne $md5sum_calculated ) { | |
copy( $tempname, $scriptname ); | |
unlink( $tempname ); | |
qx( /bin/chmod +x $scriptname ); | |
status( "scriptupdate" ); | |
print "an update has been found, restarting script.\n"; | |
exec $scriptname, @ARGV ; | |
} | |
else { | |
print "already up to date\n"; | |
status( "uptodate,$current_md5sum" ); | |
} | |
} | |
else { | |
print "invalid signature, not signed by correct key? ($md5sum_signed != $md5sum_calculated), not updating script.\n"; | |
status( "sig_problem,".($md5sum_signed||'?').','.($md5sum_expected||'?') ); | |
} | |
} | |
else { | |
print "invalid checksum ($md5sum_expected != $md5sum_calculated), not updating script.\n"; | |
status( "checksum_problem,".($md5sum_calculated||'?').','.($md5sum_expected||'?') ); | |
} | |
} | |
else { | |
print "up to date.\n"; | |
status("uptodate,".($currenttime||'-').",$lasttime"); | |
} | |
if( -e "$tempname" ) { | |
unlink( $tempname ); | |
} | |
} | |
## Make sure we have the correct procServer configuration file before we do anything as it | |
# won't work without it! | |
if( ! -e '/etc/rtlsdr-ogn.conf' ) { | |
status( 'noconfig' ); | |
die "Unable to find /etc/rtlsdr-ogn.conf\n"; | |
} | |
if( $ARGV[0] eq '-t' ) { | |
status( "testing" ); | |
} | |
print "Checking automatic updater is installed..."; | |
my $check = qx( /usr/bin/crontab -u root -l ); | |
if( $check =~ /update/ ) { | |
print "yes.\n"; | |
} | |
elsif( $ARGV[0] eq '-t' ) { | |
print "no. testing only\n"; | |
} | |
else { | |
# if we are installing and have been asked to do a reboot after running | |
# then we will add the -r flag to the crontab | |
my $reboot = ''; | |
if( $ARGV[0] eq '-r' ) { | |
$reboot = '-r'; | |
} | |
my $when = sprintf( "%d %d", int(rand(59)), (int(rand(7))+23)%24 ); | |
if( ! open( OUT, "| /usr/bin/crontab -u root -" )) { | |
status("error,write,crontab,$!"); | |
die "unable to write to crontab to install"; | |
} | |
print OUT $check; | |
print OUT "$when * * * $scriptname $reboot\n"; | |
close( OUT ); | |
$when =~ s/ /:/; | |
status( "crontab/$when" ); | |
print "installed.\n"; | |
} | |
# what we read from the configuration file | |
my %config; | |
my @config_order; | |
my %config_description; | |
# next check for daemon startup script and extra details from that | |
my $installdirectory; | |
my $username; | |
my $configfile;# if you need to copy it from /tmp/rtlsdr-ogn.site.conf after the upgrade | |
my $os; my $processor; | |
{ | |
my $fh; | |
if( ! open( $fh, '<', "/etc/rtlsdr-ogn.conf" )) { | |
status("error,open,/etc/rtlsdr-ogn.conf,$!"); | |
die "Unable to read /etc/rtlsdr-ogn.conf"; | |
} | |
while( <$fh> ) { | |
my $line = $_; | |
chomp $line; | |
if( $line =~ m|^50000\s+([a-z0-9_-]+)\s+([a-z0-9/._-]+)\s+([a-z0-9/._-]+)\s+([a-z0-9/._-]+)|i ) { | |
$installdirectory = $2; | |
$username = $1; | |
$configfile = $4; | |
} | |
} | |
# sanity check | |
if( ! ($installdirectory =~ m|/rtlsdr-ogn$|) ) { | |
status('failed/idir'); | |
die "Please change your /etc/rtlsdr-ogn.conf to point to the rtlsdr-ogn directory rather than a version specific directory."; | |
} | |
# remove the rtlsdr as this is included in the original distributions | |
my $installeddirectory = $installdirectory; | |
$installdirectory =~ s/rtlsdr-ogn$//; | |
$installdirectory =~ s|/$||; | |
# exactly where is the config file, find it the same way the ogn process would - change into the directory | |
# and then convert to an absolute path | |
chdir $installeddirectory; | |
my $expandedconfigfile = Cwd::abs_path( $configfile ); | |
copy( $expandedconfigfile, "/tmp/rtlsdr-ogn.site.conf" ); | |
chdir $installdirectory; | |
read_config(); | |
$aprscall = $config{APRS_Call}||'unknown'; | |
$aprscall =~ s/"//g; | |
# make sure the device has been configured, if not then don't do anything | |
if( $aprscall eq 'Example' || $aprscall eq 'unknown' ) { | |
status( "failed/unconfigured" ); | |
die "This device has not yet been configured.\nPlease edit $expandedconfigfile\n". | |
"If you are using an image from https://ognconfig.onglide.com or the bootstrap you should complete configuration before running this.\n". | |
"If the update script has been installed then it will automatically retry the update every night.\n"; | |
} | |
# next step is to check which install it is | |
$processor = qx( /bin/uname -p ); | |
my $hardware = qx( cat /proc/cpuinfo | grep Hardware ); | |
$os = qx( /bin/uname -a ); | |
my $download; | |
my $md5download = 'http://download.glidernet.org/md5.txt'; | |
my $filename; | |
my $dist; | |
my $osv = undef; | |
if( -e '/etc/init.d/flarm-update' ) { | |
print "Disabling old updater..."; | |
if( $ARGV[0] ne '-t' ) { | |
status("old_disabled"); | |
qx( /usr/sbin/update-rc.d flarm-update remove 2>/dev/null); | |
unlink "/etc/init.d/flarm-update"; | |
print "done.\n"; | |
} | |
else { | |
print "skipped... testing\n"; | |
} | |
} | |
if( $hardware =~ /BCM2708/ || ( $os =~ /arm/ && -e "$installdirectory/rtlsdr-ogn/gpu_dev") ) { | |
$filename = "rtlsdr-ogn-bin-RPI-GPU-latest.tgz"; | |
$download = "http://download.glidernet.org/rpi-gpu/$filename"; | |
$dist = 'RPI-GPU'; | |
$os = 'raspberry'; | |
$osv=qx( /bin/uname -r ); | |
} | |
elsif( $processor =~ /arm/ || $os =~ /arm/ ) { | |
$filename = "rtlsdr-ogn-bin-ARM-latest.tgz"; | |
$download = "http://download.glidernet.org/arm/$filename"; | |
$dist = 'ARM'; | |
} | |
elsif( $processor =~ /32/ || $processor =~ /i[0-9]86/ || $os =~ /[0-9]86-pae/ ) { | |
$filename = "rtlsdr-ogn-bin-x86-latest.tgz"; | |
$download = "http://download.glidernet.org/x86/$filename"; | |
$dist = 'x86'; | |
} | |
elsif( $processor =~ /64/ ) { | |
$filename = "rtlsdr-ogn-bin-x64-latest.tgz"; | |
$download = "http://download.glidernet.org/x64/$filename"; | |
$dist = 'x64'; | |
} | |
else { | |
my $sstring = "unidentified,$os,$processor,$hardware,".qx( uname -a ).",".qx( uname -m ); | |
$sstring =~ s/[^A-Za-z0-9_.]/_/g; | |
status( $sstring ); | |
die "Unable to identify installation type :(\n". | |
"os: $os\n". | |
"processor: $processor\n". | |
"uname -m: ". qx( uname -m ). "\n". | |
"Please email melissa-ognconfig\@littlebluecar with the above output for help!\n"; | |
} | |
# identify the existing version | |
my $existingversion = readlink( $installdirectory."/rtlsdr-ogn" ); | |
status( $installdirectory.','.($existingversion||'?').','.$dist ); | |
status( "iedd,".$installeddirectory ); | |
print "Source: $download\n". | |
"Installation Directory: $installdirectory\n"; | |
print "Configuration file: $configfile ($expandedconfigfile)\n"; | |
print "Callsign: $aprscall\n"; | |
print "\nExisting version: $existingversion\n"; | |
if( $ARGV[0] eq '-t' ) { | |
print "\n Testing only - no changes made\n"; | |
exit; | |
} | |
# this is a work around as the OGN official startup script will hang on NTP for a LONG time | |
# use the 1_3 version as it is less prone to this problem | |
{ | |
my $startuptime = stat("/etc/init.d/rtlsdr-ogn")->mtime; | |
if( $startuptime < $startupepoch ) { | |
system( "/usr/bin/curl 'https://ognconfig.onglide.com/files/v2.1/rtlsdr-ogn' -R -# -o /etc/init.d/rtlsdr-ogn" ); | |
qx( /bin/chmod +x /etc/init.d/rtlsdr-ogn ); | |
qx( /usr/bin/sudo /usr/sbin/update-rc.d -f rtlsdr-ogn defaults 2>/dev/null); | |
status( "upgrading/rtlsdr-ogn" ); | |
} | |
} | |
# First we need to check the MD5 status and see if we have a different checksum as this will | |
# trump the file date check we used to use | |
my $expectedchecksum = 'expected'; | |
{ | |
my $f = "$installdirectory/md5.txt"; | |
my $lasttime = -e $f ? stat($f)->mtime : 0; | |
qx( /usr/bin/curl -s -z $f $md5download -o $f ); | |
my $currenttime = stat($f)->mtime; | |
if( qx( cat $f | /bin/grep $filename ) =~ /^([0-9a-f]+) / ) { | |
$expectedchecksum = $1; | |
} | |
# if the file has changed then we need to check to see if the checksum has changed | |
if ( $lasttime != $currenttime ) { | |
print "Fetched new checksum file\n"; | |
my $currentchecksum = 'current'; | |
if( qx( /usr/bin/md5sum $installdirectory/$filename ) =~ /^([0-9a-f]+) / ) { | |
$currentchecksum = $1; | |
} | |
if( $currentchecksum ne $expectedchecksum ) { | |
status( "md5sumdiff,$download,$currentchecksum,$expectedchecksum"); | |
system( "touch -d 2000-01-01T00:00:00 $installdirectory/$filename" ); | |
print "md5: checksum incorrect ($currentchecksum != $expectedchecksum), marking current download as old\n" | |
} | |
} | |
else { | |
status("md5sum,file_date_unchanged"); | |
} | |
} | |
# check for a new download and that the dates are different from before | |
my $lasttime = -e "$installdirectory/$filename" ? stat("$installdirectory/$filename")->mtime : 0; | |
qx( /usr/bin/curl -s -z $installdirectory/$filename $download -o $installdirectory/$filename ); | |
my $currenttime = stat("$installdirectory/$filename")->mtime; | |
# check what version is in the archive | |
my $symlinkdetails = qx( /bin/tar tf $installdirectory/$filename | grep -e 'rtlsdr-ogn-' | head -1 ); | |
my $archiveversion; | |
chomp( $symlinkdetails ); | |
if( $symlinkdetails =~ /^(rtlsdr-ogn-[0-9.]+)/ ) { | |
$archiveversion = $1; | |
print "Archive version: $archiveversion\n"; | |
} | |
else { | |
# error on invalid files and abort | |
status("invalid,$download,$!,$symlinkdetails,$?"); | |
print "Unable to identify archive version or archive missing symlink for rtlsdr-ogn\n"; | |
exit; | |
} | |
# make sure that the downloaded version has the correct checksum, if it doesn't then don't | |
# do anything with it | |
if( qx( /usr/bin/md5sum $installdirectory/$filename ) =~ /^([0-9a-f]+) / ) { | |
my $currentchecksum = $1; | |
if( $currentchecksum ne $expectedchecksum ) { | |
status("invalidcsum,$download,$currentchecksum,$expectedchecksum"); | |
print "Downloaded file does not match the published checksum, aborting\n"; | |
exit; | |
} | |
} | |
print "\n"; | |
# if they are then we are upgrading | |
if( $lasttime != $currenttime || $archiveversion ne ($existingversion||'') ) { | |
print "Upgrade from ".($existingversion||'no symlink found')." to $archiveversion found. installing\n"; | |
print "$lasttime != $currenttime\n"; | |
status( "upgrading/$archiveversion" ); | |
} | |
else { | |
status( "up2date$ARGV[0]" ); | |
print "Up to date. (version $existingversion)\n"; | |
# if we have been asked to reboot then do it upon completion | |
if( $ARGV[0] eq '-r' ) { | |
qx( /sbin/reboot ); | |
} | |
exit; | |
} | |
# perform the upgrade, first stop the service so we don't get any conflicts | |
print "Stopping ogn service: "; | |
qx( /usr/sbin/service rtlsdr-ogn stop ); | |
print "done.\n"; | |
# then uncompress it | |
qx( cd $installdirectory ; /bin/tar xzf $filename ); | |
qx( cd $installdirectory ; /bin/rm rtlsdr-ogn; /bin/ln -fs $archiveversion rtlsdr-ogn ); | |
# then make sure it is executable and can run as root | |
qx( cd $installdirectory/rtlsdr-ogn ; /bin/chown ogn:ogn *; /bin/chown root gsm_scan ogn-rf; /bin/chmod a+s gsm_scan ogn-rf; /usr/bin/mkfifo ogn-rf.fifo; /bin/chown ogn:ogn ogn-rf.fifo ); | |
# if it is a pi then make the gpu_dev | |
if( $dist eq 'RPI-GPU' ) { | |
if( ($osv+0) >= 4.1 ) { | |
qx( cd $installdirectory/rtlsdr-ogn; /bin/mknod gpu_dev c 249 0; /bin/chown ogn:ogn gpu_dev ); | |
} | |
else { | |
qx( cd $installdirectory/rtlsdr-ogn; /bin/mknod gpu_dev c 100 0; /bin/chown ogn:ogn gpu_dev ); | |
} | |
} | |
################### | |
# make sure we have the configuration file in the right directory | |
chdir( $installeddirectory ); | |
my $newexpandedconfigfile = Cwd::abs_path( $configfile ); | |
# check if anything has changed... if it has then we need to copy the file | |
if( $newexpandedconfigfile ne $expandedconfigfile ) { | |
if( ! copy( '/tmp/rtlsdr-ogn.site.conf', "$newexpandedconfigfile" ) ) { | |
print "unable to copy $!\n"; | |
} | |
status("mvconfig,f,$expandedconfigfile" ); | |
status("mvconfig,t,$newexpandedconfigfile" ); | |
print "Copied configuration file to $configfile ($newexpandedconfigfile)\n"; | |
} | |
else { | |
status("config,$expandedconfigfile"); | |
print "Configuration file path has not changed, not copying. Backup in /tmp/rtlsdr-ogn.site.conf if needed\n"; | |
} | |
# and if we are allowed to start the ogn service | |
if( $ARGV[0] ne '-i' && $ARGV[0] ne '-r' ) { | |
print "Restarting ogn service: "; | |
qx( /usr/sbin/service rtlsdr-ogn start ); | |
print "done.\n"; | |
} | |
$existingversion = readlink( $installdirectory."/rtlsdr-ogn" ); | |
status( "done/$existingversion/$ARGV[0]" ); | |
print "Upgrade completed ($existingversion)\n"; | |
# if we have been asked to reboot then do it upon completion | |
if( $ARGV[0] eq '-r' ) { | |
qx( /sbin/reboot ); | |
} | |
} | |
sub read_config { | |
my @sections; | |
# read it into the hash | |
open( my $fh, '<', "/tmp/rtlsdr-ogn.site.conf" ) || return; | |
while( <$fh> ) { | |
my $line = $_; | |
chomp $line; | |
if( $line =~ /^\s*([A-Za-z]+):/ ) { | |
push @sections, $1; | |
push @config_order, "+$1"; | |
} | |
if( $line =~ /^\s*}/ ) { | |
pop @sections; | |
push @config_order, "-$1"; | |
} | |
if( $line =~ /([A-Za-z]+)\s*=\s*([^;]+)(.*)/ ) { | |
my $key = join('_',@sections,$1); | |
$config{$key} = $2; | |
$config_description{$key} = $3; | |
push @config_order, "=$key,$1"; # so we know what order to write in | |
} | |
} | |
close ($fh); | |
} | |
sub status { | |
my ($status) = @_; | |
print $status."\n"; | |
qx( /usr/bin/curl -s https://ognconfig.onglide.com/perl/startupgrade.pl?token=$token/v$version\\&status=$status\\&call=$aprscall ); | |
} | |
sub date { | |
my @t = gmtime($_[0]); | |
return sprintf( "%04d-%02d-%02dT%02d-%02d-%02d", ($t[5]+1900),($t[4]+1),$t[3],$t[2],$t[1],$t[0]); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment