Skip to content

Commit 48fe323

Browse files
committed
Player software: verify chromeos package on upload.
xibosignageltd/xibo-private#926
1 parent 8577ed8 commit 48fe323

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

lib/Entity/PlayerVersion.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22
/*
3-
* Copyright (C) 2024 Xibo Signage Ltd
3+
* Copyright (C) 2025 Xibo Signage Ltd
44
*
55
* Xibo - Digital Signage - https://xibosignage.com
66
*
@@ -32,7 +32,9 @@
3232
use Xibo\Service\LogServiceInterface;
3333
use Xibo\Storage\StorageServiceInterface;
3434
use Xibo\Support\Exception\DuplicateEntityException;
35+
use Xibo\Support\Exception\GeneralException;
3536
use Xibo\Support\Exception\InvalidArgumentException;
37+
use Xibo\Support\Exception\NotFoundException;
3638

3739
/**
3840
* Class PlayerVersion
@@ -223,10 +225,53 @@ public function unpack(string $libraryFolder): static
223225
if ($this->type === 'chromeOS') {
224226
$this->getLog()->debug('add: handling chromeOS upload');
225227

226-
// TODO: check the signature of the file to make sure it comes from a verified source.
228+
$fullFileName = $libraryFolder . 'playersoftware/' . $this->fileName;
229+
230+
// Check the signature of the file to make sure it comes from a verified source.
231+
try {
232+
$this->getLog()->debug('unpack: loading gnupg to verify the signature');
233+
234+
$gpg = new \gnupg();
235+
$gpg->seterrormode(\gnupg::ERROR_EXCEPTION);
236+
$info = $gpg->verify(
237+
file_get_contents($fullFileName),
238+
false,
239+
);
240+
241+
if ($info === false
242+
|| $info[0]['fingerprint'] !== '10415C506BE63E70BAF1D58BC1EF165A0F880F75'
243+
|| $info[0]['status'] !== 0
244+
|| $info[0]['summary'] !== 0
245+
) {
246+
$this->getLog()->error('unpack: unable to verify GPG. file = ' . $this->fileName);
247+
throw new GeneralException();
248+
}
249+
250+
$this->getLog()->debug('unpack: signature verified');
251+
252+
// Signature verified, move the file, so we can decrypt it.
253+
rename($fullFileName, $libraryFolder . 'playersoftware/' . $this->versionId . '.gpg');
254+
255+
$this->getLog()->debug('unpack: using the shell to decrypt the file');
256+
257+
// Go to the shell to decrypt it.
258+
shell_exec('gpg --decrypt --output ' . $libraryFolder . 'playersoftware/' . $this->versionId
259+
. ' ' . $libraryFolder . 'playersoftware/' . $this->versionId . '.gpg');
260+
261+
// Was this successful?
262+
if (!file_exists($libraryFolder . 'playersoftware/' . $this->versionId)) {
263+
throw new NotFoundException('Not found after decryption');
264+
}
265+
266+
// Rename the GPG file back to its original name.
267+
rename($libraryFolder . 'playersoftware/' . $this->versionId . '.gpg', $fullFileName);
268+
} catch (\Exception $e) {
269+
$this->getLog()->error('unpack: ' . $e->getMessage());
270+
throw new InvalidArgumentException(__('Package file unsupported or invalid'));
271+
}
227272

228273
$zip = new \ZipArchive();
229-
if (!$zip->open($libraryFolder . 'playersoftware/' . $this->fileName)) {
274+
if (!$zip->open($libraryFolder . 'playersoftware/' . $this->versionId)) {
230275
throw new InvalidArgumentException(__('Unable to open ZIP'));
231276
}
232277

@@ -273,6 +318,9 @@ public function unpack(string $libraryFolder): static
273318
$manifest = Str::replace('assets/icons/192x192.png', $this->config->uri('img/192x192.png'), $manifest);
274319

275320
file_put_contents($folder . '/manifest.json', $manifest);
321+
322+
// Unlink our decrypted file
323+
unlink($libraryFolder . 'playersoftware/' . $this->versionId);
276324
}
277325

278326
return $this;

0 commit comments

Comments
 (0)