]>
Commit | Line | Data |
---|---|---|
aff192e6 DM |
1 | package PVE::APLInfo; |
2 | ||
3 | use strict; | |
4 | use IO::File; | |
5 | use PVE::SafeSyslog; | |
6 | use PVE::I18N; | |
7 | use LWP::UserAgent; | |
8 | use PVE::Config; | |
9 | use POSIX qw(strftime); | |
10 | ||
11 | my $logfile = "/var/log/pveam.log"; | |
12 | ||
13 | # Default list of GPG keys allowed to sign aplinfo | |
14 | # | |
15 | #pub 1024D/5CAC72FE 2004-06-24 | |
16 | # Key fingerprint = 9ABD 7E02 AD24 3AD3 C2FB BCCC B0C1 CC22 5CAC 72FE | |
17 | #uid Proxmox Support Team <support@proxmox.com> | |
18 | ||
19 | my $valid_keys = { | |
20 | '9ABD7E02AD243AD3C2FBBCCCB0C1CC225CAC72FE' => 1, # fingerprint support@proxmox.com | |
21 | '25CAC72FE' => 1, # keyid support@proxmox.com | |
22 | }; | |
23 | ||
24 | sub import_gpg_keys { | |
25 | ||
26 | my $keyfile = '/usr/share/doc/pve-manager/support@proxmox.com.pubkey'; | |
27 | ||
28 | return system ("/usr/bin/gpg --batch --no-tty --status-fd=1 -q " . | |
29 | "--logger-fd=1 --import $keyfile >>$logfile"); | |
30 | } | |
31 | ||
32 | sub logmsg { | |
33 | my ($logfd, $msg) = @_; | |
34 | ||
35 | chomp $msg; | |
36 | ||
37 | my $tstr = strftime ("%b %d %H:%M:%S", localtime); | |
38 | ||
39 | foreach my $line (split (/\n/, $msg)) { | |
40 | print $logfd "$tstr $line\n"; | |
41 | } | |
42 | } | |
43 | ||
44 | sub url_get { | |
45 | my ($ua, $url, $file, $logfh) = @_; | |
46 | ||
47 | my $req = HTTP::Request->new(GET => $url); | |
48 | ||
49 | logmsg ($logfh, "start download $url"); | |
50 | my $res = $ua->request($req, $file); | |
51 | ||
52 | if ($res->is_success) { | |
53 | logmsg ($logfh, "download finished: " . $res->status_line); | |
54 | return 0; | |
55 | } | |
56 | ||
57 | logmsg ($logfh, "download failed: " . $res->status_line); | |
58 | ||
59 | return 1; | |
60 | } | |
61 | ||
62 | sub update { | |
63 | my ($proxy) = @_; | |
64 | ||
65 | my $aplurl = "http://download.proxmox.com/appliances"; | |
66 | my $aplsrcurl = "$aplurl/aplinfo.dat.gz"; | |
67 | my $aplsigurl = "$aplurl/aplinfo.dat.asc"; | |
68 | ||
69 | my $size; | |
70 | if (($size = (-s $logfile) || 0) > (1024*50)) { | |
71 | system ("mv $logfile $logfile.0"); | |
72 | } | |
73 | my $logfd = IO::File->new (">>$logfile"); | |
74 | logmsg ($logfd, "starting update"); | |
75 | ||
76 | import_gpg_keys(); | |
77 | ||
78 | my $tmp = "/tmp/pveam.tmp.$$"; | |
79 | my $tmpgz = "$tmp.gz"; | |
80 | my $sigfn = "$tmp.asc"; | |
81 | ||
82 | # this code works for ftp and http | |
83 | # always use passive ftp | |
84 | local $ENV{FTP_PASSIVE} = 1; | |
85 | my $ua = LWP::UserAgent->new; | |
86 | $ua->agent("PVE/1.0"); | |
87 | ||
88 | if ($proxy) { | |
89 | $ua->proxy(['http'], $proxy); | |
90 | } else { | |
91 | $ua->env_proxy; | |
92 | } | |
93 | ||
94 | eval { | |
95 | if (url_get ($ua, $aplsigurl, $sigfn, $logfd) != 0) { | |
96 | die "update failed - no signature\n"; | |
97 | } | |
98 | ||
99 | if (url_get ($ua, $aplsrcurl, $tmpgz, $logfd) != 0) { | |
100 | die "update failed - no data\n"; | |
101 | } | |
102 | ||
103 | if (system ("zcat -f $tmpgz >$tmp 2>/dev/null") != 0) { | |
104 | die "update failed: unable to unpack '$tmpgz'\n"; | |
105 | } | |
106 | ||
107 | # verify signature | |
108 | ||
109 | my $cmd = "/usr/bin/gpg --verify --batch --no-tty --status-fd=1 -q " . | |
110 | "--logger-fd=1 $sigfn $tmp"; | |
111 | ||
112 | open (CMD, "$cmd|") || | |
113 | die "unable to execute '$cmd': $!\n"; | |
114 | ||
115 | my $line; | |
116 | my $signer = ''; | |
117 | while (defined ($line = <CMD>)) { | |
118 | chomp $line; | |
119 | logmsg ($logfd, $line); | |
120 | ||
121 | # code borrowed from SA | |
122 | next if $line !~ /^\Q[GNUPG:]\E (?:VALID|GOOD)SIG (\S{8,40})/; | |
123 | my $key = $1; | |
124 | ||
125 | # we want either a keyid (8) or a fingerprint (40) | |
126 | if (length $key > 8 && length $key < 40) { | |
127 | substr($key, 8) = ''; | |
128 | } | |
129 | # use the longest match we can find | |
130 | $signer = $key if (length $key > length $signer) && $valid_keys->{$key}; | |
131 | } | |
132 | ||
133 | close (CMD); | |
134 | ||
135 | die "unable to verify signature\n" if !$signer; | |
136 | ||
137 | logmsg ($logfd, "signature valid: $signer"); | |
138 | ||
139 | # test syntax | |
140 | eval { | |
141 | my $fh = IO::File->new ("<$tmp") || | |
142 | die "unable to open file '$tmp' - $!\n"; | |
143 | PVE::Config::read_aplinfo ($tmp, $fh, 1); | |
144 | close ($fh); | |
145 | }; | |
146 | die "update failed: $@" if $@; | |
147 | ||
148 | if (system ("mv $tmp /var/lib/pve-manager/apl-available 2>/dev/null") != 0) { | |
149 | die "update failed: unable to store data\n"; | |
150 | } | |
151 | ||
152 | logmsg ($logfd, "update sucessful"); | |
153 | }; | |
154 | ||
155 | my $err = $@; | |
156 | ||
157 | unlink $tmp; | |
158 | unlink $tmpgz; | |
159 | unlink $sigfn; | |
160 | ||
161 | if ($err) { | |
162 | logmsg ($logfd, $err); | |
163 | close ($logfd); | |
164 | ||
165 | return 0; | |
166 | } | |
167 | ||
168 | close ($logfd); | |
169 | ||
170 | return 1; | |
171 | } | |
172 | ||
173 | sub load_data { | |
174 | ||
175 | my $filename = "/var/lib/pve-manager/apl-available"; | |
176 | ||
177 | if (! -f $filename) { | |
178 | system ("cp /usr/share/doc/pve-manager/aplinfo.dat /var/lib/pve-manager/apl-available"); | |
179 | } | |
180 | ||
181 | return PVE::Config::read_file ('aplinfo'); | |
182 | } | |
183 | ||
184 | sub display_name { | |
185 | my ($template) = @_; | |
186 | ||
187 | my $templates = load_data (); | |
188 | ||
189 | return $template if !$templates; | |
190 | ||
191 | my $d = $templates->{'all'}->{$template}; | |
192 | ||
193 | $template =~ s/\.tar\.gz$//; | |
194 | $template =~ s/_i386$//; | |
195 | ||
196 | return $template if !$d; | |
197 | ||
198 | return "$d->{package}_$d->{version}"; | |
199 | } | |
200 | ||
201 | sub pkginfo { | |
202 | my ($template) = @_; | |
203 | ||
204 | my $templates = load_data (); | |
205 | ||
206 | return undef if !$templates; | |
207 | ||
208 | my $d = $templates->{'all'}->{$template}; | |
209 | ||
210 | return $d; | |
211 | } | |
212 | ||
213 | sub webnews { | |
214 | my ($lang) = @_; | |
215 | ||
216 | my $templates = load_data (); | |
217 | ||
218 | my $html = ''; | |
219 | ||
220 | $html .= __("<b>Welcome</b> to the Proxmox Virtual Environment!"); | |
221 | $html .= "<br><br>"; | |
222 | $html .= __("For more information please visit our homepage at"); | |
223 | $html .= " <a href='http://www.proxmox.com' target='_blank'>www.proxmox.com</a>."; | |
224 | ||
225 | return $html if !$templates; | |
226 | ||
227 | # my $d = $templates->{'all'}->{"pve-web-news-$lang"} || | |
228 | my $d = $templates->{all}->{'pve-web-news'}; | |
229 | ||
230 | return $html if !$d; | |
231 | ||
232 | return $d->{description}; | |
233 | } | |
234 | ||
235 | 1; | |
236 |