2020-05-29 13:41:58 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Model\Table;
|
|
|
|
|
|
|
|
use App\Model\Table\AppTable;
|
|
|
|
use Cake\ORM\Table;
|
|
|
|
use Cake\Validation\Validator;
|
2020-06-23 14:42:53 +02:00
|
|
|
use Cake\Event\EventInterface;
|
|
|
|
use ArrayObject;
|
2020-05-29 13:41:58 +02:00
|
|
|
|
|
|
|
class EncryptionKeysTable extends AppTable
|
|
|
|
{
|
2022-10-21 15:25:52 +02:00
|
|
|
|
|
|
|
public $gpg = null;
|
|
|
|
|
2020-05-29 13:41:58 +02:00
|
|
|
public function initialize(array $config): void
|
|
|
|
{
|
|
|
|
parent::initialize($config);
|
2020-06-19 00:40:58 +02:00
|
|
|
$this->addBehavior('UUID');
|
2021-11-17 15:43:52 +01:00
|
|
|
$this->addBehavior('AuditLog');
|
2021-09-28 13:32:51 +02:00
|
|
|
$this->addBehavior('Timestamp');
|
2020-05-29 13:41:58 +02:00
|
|
|
$this->belongsTo(
|
|
|
|
'Individuals',
|
|
|
|
[
|
|
|
|
'foreignKey' => 'owner_id',
|
2021-03-15 22:47:13 +01:00
|
|
|
'conditions' => ['owner_model' => 'individual']
|
2020-05-29 13:41:58 +02:00
|
|
|
]
|
|
|
|
);
|
|
|
|
$this->belongsTo(
|
|
|
|
'Organisations',
|
|
|
|
[
|
|
|
|
'foreignKey' => 'owner_id',
|
2021-03-15 22:47:13 +01:00
|
|
|
'conditions' => ['owner_model' => 'organisation']
|
2020-05-29 13:41:58 +02:00
|
|
|
]
|
|
|
|
);
|
2020-06-04 10:05:45 +02:00
|
|
|
$this->setDisplayField('encryption_key');
|
2020-05-29 13:41:58 +02:00
|
|
|
}
|
|
|
|
|
2020-06-19 00:40:58 +02:00
|
|
|
public function beforeMarshal(EventInterface $event, ArrayObject $data, ArrayObject $options)
|
|
|
|
{
|
2020-06-23 14:42:53 +02:00
|
|
|
if (empty($data['owner_id'])) {
|
2021-03-15 22:47:13 +01:00
|
|
|
if (empty($data['owner_model'])) {
|
2020-06-19 00:40:58 +02:00
|
|
|
return false;
|
|
|
|
}
|
2021-03-15 22:47:13 +01:00
|
|
|
if (empty($data[$data['owner_model'] . '_id'])) {
|
2020-06-23 14:42:53 +02:00
|
|
|
return false;
|
|
|
|
}
|
2021-03-15 22:47:13 +01:00
|
|
|
$data['owner_id'] = $data[$data['owner_model'] . '_id'];
|
2020-06-19 00:40:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-29 13:41:58 +02:00
|
|
|
public function validationDefault(Validator $validator): Validator
|
|
|
|
{
|
|
|
|
$validator
|
|
|
|
->notEmptyString('type')
|
|
|
|
->notEmptyString('encryption_key')
|
|
|
|
->notEmptyString('owner_id')
|
2021-03-15 22:47:13 +01:00
|
|
|
->notEmptyString('owner_model')
|
|
|
|
->requirePresence(['type', 'encryption_key', 'owner_id', 'owner_model'], 'create');
|
2020-05-29 13:41:58 +02:00
|
|
|
return $validator;
|
|
|
|
}
|
2022-10-21 15:25:52 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 0 - true if key is valid
|
|
|
|
* 1 - User e-mail
|
|
|
|
* 2 - Error message
|
|
|
|
* 3 - Not used
|
|
|
|
* 4 - Key fingerprint
|
|
|
|
* 5 - Key fingerprint
|
|
|
|
* @param \App\Model\Entity\EncryptionKey $encryptionKey
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function verifySingleGPG(\App\Model\Entity\EncryptionKey $encryptionKey): array
|
|
|
|
{
|
|
|
|
$result = [0 => false, 1 => null];
|
|
|
|
|
|
|
|
$gpg = $this->initializeGpg();
|
|
|
|
if (!$gpg) {
|
|
|
|
$result[2] = 'GnuPG is not configured on this system.';
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$currentTimestamp = time();
|
|
|
|
$keys = $gpg->keyInfo($encryptionKey['encryption_key']);
|
|
|
|
if (count($keys) !== 1) {
|
|
|
|
$result[2] = 'Multiple or no key found';
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
$key = $keys[0];
|
|
|
|
$result[4] = $key->getPrimaryKey()->getFingerprint();
|
|
|
|
$result[5] = $result[4];
|
|
|
|
|
|
|
|
$sortedKeys = ['valid' => 0, 'expired' => 0, 'noEncrypt' => 0];
|
|
|
|
foreach ($key->getSubKeys() as $subKey) {
|
|
|
|
$expiration = $subKey->getExpirationDate();
|
|
|
|
if ($expiration != 0 && $currentTimestamp > $expiration) {
|
|
|
|
$sortedKeys['expired']++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!$subKey->canEncrypt()) {
|
|
|
|
$sortedKeys['noEncrypt']++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$sortedKeys['valid']++;
|
|
|
|
}
|
|
|
|
if (!$sortedKeys['valid']) {
|
|
|
|
$result[2] = 'The user\'s PGP key does not include a valid subkey that could be used for encryption.';
|
|
|
|
if ($sortedKeys['expired']) {
|
|
|
|
$result[2] .= ' ' . __n('Found %s subkey that have expired.', 'Found %s subkeys that have expired.', $sortedKeys['expired'], $sortedKeys['expired']);
|
|
|
|
}
|
|
|
|
if ($sortedKeys['noEncrypt']) {
|
|
|
|
$result[2] .= ' ' . __n('Found %s subkey that is sign only.', 'Found %s subkeys that are sign only.', $sortedKeys['noEncrypt'], $sortedKeys['noEncrypt']);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$result[0] = true;
|
|
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$result[2] = $e->getMessage();
|
|
|
|
}
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize GPG. Returns `null` if initialization failed.
|
|
|
|
*
|
|
|
|
* @return null|CryptGpgExtended
|
|
|
|
*/
|
|
|
|
public function initializeGpg()
|
|
|
|
{
|
|
|
|
require_once(ROOT . '/src/Lib/Tools/GpgTool.php');
|
|
|
|
if ($this->gpg !== null) {
|
|
|
|
if ($this->gpg === false) { // initialization failed
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return $this->gpg;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$this->gpg = \App\Lib\Tools\GpgTool::initializeGpg();
|
|
|
|
return $this->gpg;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
//$this->logException("GPG couldn't be initialized, GPG encryption and signing will be not available.", $e, LOG_NOTICE);
|
|
|
|
$this->gpg = false;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2020-05-29 13:41:58 +02:00
|
|
|
}
|