MISP/app/Model/SystemSetting.php

143 lines
3.8 KiB
PHP
Raw Normal View History

2021-11-04 16:28:41 +01:00
<?php
App::uses('AppModel', 'Model');
App::uses('JsonTool', 'Tools');
2021-11-05 16:50:19 +01:00
App::uses('BetterSecurity', 'Tools');
2021-11-04 16:28:41 +01:00
/**
* Class for ondemand encryption of JSON serialized value
*/
class EncryptedValue implements JsonSerializable
{
const ENCRYPTED_MAGIC = "\x1F\x1D";
/** @var string */
private $value;
public function __construct($value)
{
$this->value = $value;
}
/**
* @return mixed
* @throws JsonException
* @throws Exception
*/
public function decrypt()
{
2021-11-05 16:50:19 +01:00
$decrypt = BetterSecurity::decrypt($this->value, Configure::read('Security.encryption_key'));
return JsonTool::decode($decrypt);
}
public function __toString()
{
return $this->decrypt();
}
public function jsonSerialize()
{
return $this->decrypt();
}
}
2021-11-04 16:28:41 +01:00
class SystemSetting extends AppModel
{
public $actsAs = [
'SysLogLogable.SysLogLogable' => [
'userModel' => 'User',
'userKey' => 'user_id',
'change' => 'full'
],
'AuditLog'
];
public $primaryKey = 'setting';
/**
* @return array
*/
2021-11-04 16:28:41 +01:00
public function getSettings()
{
$settings = $this->find('list', [
'fields' => ['SystemSetting.setting', 'SystemSetting.value'],
]);
return array_map([$this, 'decode'], $settings);
2021-11-04 16:28:41 +01:00
}
/**
* @param string $setting Setting name
2021-11-04 16:28:41 +01:00
* @param mixed $value
* @throws Exception
*/
public function setSetting($setting, $value)
{
$value = JsonTool::encode($value);
// If encryption is enabled and setting name contains `password` or `apikey` string, encrypt value to protect it
$key = Configure::read('Security.encryption_key');
if ($key && self::isSensitive($setting)) {
2021-11-05 16:50:19 +01:00
$value = EncryptedValue::ENCRYPTED_MAGIC . BetterSecurity::encrypt($value, $key);
}
2021-11-04 16:28:41 +01:00
$valid = $this->save(['SystemSetting' => [
'setting' => $setting,
'value' => $value,
2021-11-04 16:28:41 +01:00
]]);
if (!$valid) {
throw new Exception("Could not save system setting `$setting` because of validation errors: " . JsonTool::encode($this->validationErrors));
}
}
2021-11-05 21:51:31 +01:00
/**
* @param string|null $old Old (or current) encryption key.
* @param string|null $new New encryption key. If empty, encrypted values will be decrypted.
* @throws JsonException
*/
public function reencrypt($old, $new)
{
$settings = $this->find('list', [
'fields' => ['SystemSetting.setting', 'SystemSetting.value'],
]);
$toSave = [];
foreach ($settings as $setting => $value) {
if (!self::isSensitive($setting)) {
continue;
}
if (substr($value, 0, 2) === EncryptedValue::ENCRYPTED_MAGIC) {
$value = BetterSecurity::decrypt(substr($value, 2), $old);
}
if (!empty($new)) {
$value = EncryptedValue::ENCRYPTED_MAGIC . BetterSecurity::encrypt($value, $new);
}
$toSave[] = ['SystemSetting' => [
'setting' => $setting,
'value' => $value,
]];
}
return $this->saveMany($toSave);
}
/**
* @param string $value
* @return EncryptedValue|mixed
* @throws JsonException
*/
private function decode($value)
{
if (substr($value, 0, 2) === EncryptedValue::ENCRYPTED_MAGIC) {
return new EncryptedValue(substr($value, 2));
} else {
return JsonTool::decode($value);
}
}
/**
* @param $setting
* @return bool
*/
public static function isSensitive($setting)
{
return strpos($setting, 'password') !== false || strpos($setting, 'apikey') !== false;
}
2021-11-04 16:28:41 +01:00
}