package PVE::APLInfo;
use strict;
+use warnings;
+
use IO::File;
-use PVE::SafeSyslog;
use LWP::UserAgent;
use POSIX qw(strftime);
+use PVE::SafeSyslog;
+use PVE::Storage;
+use PVE::Tools qw(run_command);
+use PVE::pvecfg;
+
my $logfile = "/var/log/pveam.log";
my $aplinfodir = "/var/lib/pve-manager/apl-info";
-# Default list of GPG keys allowed to sign aplinfo
-#
-#pub 1024D/5CAC72FE 2004-06-24
-# Key fingerprint = 9ABD 7E02 AD24 3AD3 C2FB BCCC B0C1 CC22 5CAC 72FE
-#uid Proxmox Support Team <support@proxmox.com>
-#pub 2048R/A16EB94D 2008-08-15 [expires: 2023-08-12]
-# Key fingerprint = 694C FF26 795A 29BA E07B 4EB5 85C2 5E95 A16E B94D
-#uid Turnkey Linux Release Key <release@turnkeylinux.com>
-
-my $valid_keys = {
- '9ABD7E02AD243AD3C2FBBCCCB0C1CC225CAC72FE' => 1, # fingerprint support@proxmox.com
- '25CAC72FE' => 1, # keyid support@proxmox.com
- '694CFF26795A29BAE07B4EB585C25E95A16EB94D' => 1, # fingerprint release@turnkeylinux.com
- 'A16EB94D' => 1, # keyid release@turnkeylinux.com
-};
-
-sub import_gpg_keys {
-
- my @keyfiles = ('support@proxmox.com.pubkey', 'release@turnkeylinux.com.pubkey');
-
- foreach my $key (@keyfiles) {
- my $fn = "/usr/share/doc/pve-manager/$key";
- system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " .
- "--logger-fd=1 --import $fn >>$logfile");
- }
-}
-
sub logmsg {
my ($logfd, $msg) = @_;
chomp $msg;
- my $tstr = strftime ("%b %d %H:%M:%S", localtime);
+ my $tstr = strftime ("%F %H:%M:%S", localtime);
foreach my $line (split (/\n/, $msg)) {
print $logfd "$tstr $line\n";
while (my $rec = <$fh>) {
chomp $rec;
-
+
my $res = {};
while ($rec) {
$res->{lc $1} = $2;
} else {
my $msg = "unable to parse appliance record: $rec\n";
- $update ? die $msg : warn $msg;
+ $update ? die $msg : warn $msg;
$res = {};
last;
}
}
-
+
if ($res->{'package'} eq 'pve-web-news' && $res->{description}) {
- $list->{'all'}->{$res->{'package'}} = $res;
+ $list->{'all'}->{$res->{'package'}} = $res;
next;
}
$res->{section} = 'unknown' if !$res->{section};
-
+
if ($res->{'package'} && $res->{type} && $res->{os} && $res->{version} &&
$res->{infopage}) {
my $template;
if ($res->{location}) {
$template = $res->{location};
- $template =~ s|.*/([^/]+.tar.[gx]z)$|$1|;
+ $template =~ s|.*/([^/]+$PVE::Storage::vztmpl_extension_re)$|$1|;
if ($res->{location} !~ m|^([a-zA-Z]+)\://|) {
# relative localtion (no http:// prefix)
$res->{location} = "$source/$res->{location}";
$list->{'all'}->{$template} = $res;
} else {
my $msg = "found incomplete appliance records\n";
- $update ? die $msg : warn $msg;
+ $update ? die $msg : warn $msg;
}
}
}
close($fh);
die $err if $err;
-
+
return $list;
}
}
sub download_aplinfo {
- my ($ua, $aplurl, $host, $logfd) = @_;
+ my ($ua, $aplinfo, $logfd) = @_;
- my $aplsrcurl = "$aplurl/aplinfo.dat.gz";
- my $aplsigurl = "$aplurl/aplinfo.dat.asc";
+ my $aplsrcurl = "$aplinfo->{url}/$aplinfo->{file}.gz";
+ my $aplsigurl = "$aplinfo->{url}/$aplinfo->{file}.asc";
+ my $host = $aplinfo->{host};
my $tmp = "$aplinfodir/pveam-${host}.tmp.$$";
my $tmpgz = "$tmp.gz";
if (url_get($ua, $aplsrcurl, $tmpgz, $logfd) != 0) {
die "update failed - no data file '$aplsrcurl'\n";
}
-
- if (system("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) {
- die "update failed: unable to unpack '$tmpgz'\n";
- }
-
- # verify signature
-
- my $cmd = "/usr/bin/gpg --verify --trust-model always --batch --no-tty --status-fd=1 -q " .
- "--logger-fd=1 $sigfn $tmp";
-
- open(CMD, "$cmd|") ||
- die "unable to execute '$cmd': $!\n";
-
- my $line;
- my $signer = '';
- while (defined($line = <CMD>)) {
- chomp $line;
- logmsg($logfd, $line);
-
- # code borrowed from SA
- next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/;
- my $key = $1;
-
- # we want either a keyid (8) or a fingerprint (40)
- if (length $key > 8 && length $key < 40) {
- substr($key, 8) = '';
- }
- # use the longest match we can find
- $signer = $key if (length $key > length $signer) && $valid_keys->{$key};
- }
- close(CMD);
+ eval { run_command(["gunzip", "-f", $tmpgz]) };
+ die "update failed: unable to unpack '$tmpgz'\n" if $@;
- die "unable to verify signature\n" if !$signer;
+ # verify signature
+ my $trustedkeyring = "/usr/share/doc/pve-manager/trustedkeys.gpg";
+ my $cmd = "/usr/bin/gpgv -q --keyring $trustedkeyring $sigfn $tmp";
- logmsg($logfd, "signature valid: $signer");
+ my $logfunc = sub { logmsg($logfd, "signature verification: $_[0]"); };
+ eval {
+ run_command($cmd, outfunc => $logfunc, errfunc => $logfunc);
+ };
+ die "unable to verify signature - $@\n" if $@;
# test syntax
- eval {
- my $fh = IO::File->new("<$tmp") ||
- die "unable to open file '$tmp' - $!\n";
- read_aplinfo($tmp, {}, $aplurl, 1);
- close($fh);
- };
+ eval { read_aplinfo($tmp, {}, $aplinfo->{url}, 1) };
die "update failed: $@" if $@;
- if (system("mv $tmp $aplinfodir/$host 2>/dev/null") != 0) {
- die "update failed: unable to store data\n";
- }
+ rename($tmp, "$aplinfodir/$host") or
+ die "update failed: unable to store data: $!\n";
- logmsg($logfd, "update sucessful");
+ logmsg($logfd, "update successful");
};
my $err = $@;
}
sub get_apl_sources {
-
- my $urls = [];
- push @$urls, "http://download.proxmox.com/images";
- push @$urls, "http://releases.turnkeylinux.org/pve";
-
- return $urls;
+ my $sources = [
+ {
+ host => "download.proxmox.com",
+ url => "http://download.proxmox.com/images",
+ file => 'aplinfo-pve-8.dat',
+ },
+ {
+ host => "releases.turnkeylinux.org",
+ url => "https://releases.turnkeylinux.org/pve",
+ file => 'aplinfo.dat',
+ },
+ ];
+
+ return $sources;
}
sub update {
my ($proxy) = @_;
- my $size;
- if (($size = (-s $logfile) || 0) > (1024*50)) {
- system ("mv $logfile $logfile.0");
+ my $logfile_size = -s $logfile || 0;
+ if ($logfile_size > 1024 * 256) {
+ rename($logfile, "$logfile.0") or warn "failed to rotate log file $logfile - $!\n";
}
my $logfd = IO::File->new (">>$logfile");
logmsg($logfd, "starting update");
- import_gpg_keys();
-
my $ua = LWP::UserAgent->new;
- $ua->agent("PVE/1.0");
+ my $release = PVE::pvecfg::release();
+ $ua->agent("PVE/$release");
if ($proxy) {
$ua->proxy(['http', 'https'], $proxy);
$ua->env_proxy;
}
- my $urls = get_apl_sources();
+ my $sources = get_apl_sources();
mkdir $aplinfodir;
my @dlerr = ();
- foreach my $aplurl (@$urls) {
- eval {
- my $uri = URI->new($aplurl);
- my $host = $uri->host();
- download_aplinfo($ua, $aplurl, $host, $logfd);
+ foreach my $info (@$sources) {
+ eval {
+ download_aplinfo($ua, $info, $logfd);
};
if (my $err = $@) {
logmsg ($logfd, $err);
- push @dlerr, $aplurl;
+ push @dlerr, $info->{url};
}
- }
+ }
close($logfd);
sub load_data {
- my $urls = get_apl_sources();
+ my $sources = get_apl_sources();
my $list = {};
-
- foreach my $aplurl (@$urls) {
-
- eval {
-
- my $uri = URI->new($aplurl);
- my $host = $uri->host();
- read_aplinfo("$aplinfodir/$host", $list, $aplurl);
+ foreach my $info (@$sources) {
+ eval {
+ my $host = $info->{host};
+ read_aplinfo("$aplinfodir/$host", $list, $info->{url});
};
warn $@ if $@;
}