security.txt + bugfixes

This commit is contained in:
2023-03-05 15:30:06 +01:00
parent 5acd13b945
commit c8965e209b
32 changed files with 336 additions and 46 deletions

View File

@@ -0,0 +1,16 @@
<?php
namespace Core\Objects\DatabaseEntity\Attribute;
#[\Attribute(\Attribute::TARGET_CLASS)] class UsePropertiesOf {
private string $class;
public function __construct(string $class) {
$this->class = $class;
}
public function getClass(): string {
return $this->class;
}
}

View File

@@ -38,6 +38,7 @@ use Core\Objects\DatabaseEntity\Attribute\MultipleReference;
use Core\Objects\DatabaseEntity\Attribute\NoFetch;
use Core\Objects\DatabaseEntity\Attribute\Transient;
use Core\Objects\DatabaseEntity\Attribute\Unique;
use Core\Objects\DatabaseEntity\Attribute\UsePropertiesOf;
class DatabaseEntityHandler implements Persistable {
@@ -75,14 +76,17 @@ class DatabaseEntityHandler implements Persistable {
public function init() {
$className = $this->entityClass->getName();
$entityClass = $this->entityClass;
while ($usePropsOf = self::getAttribute($entityClass, UsePropertiesOf::class)) {
$entityClass = new \ReflectionClass($usePropsOf->getClass());
}
$uniqueColumns = self::getAttribute($this->entityClass, Unique::class);
$uniqueColumns = self::getAttribute($entityClass, Unique::class);
if ($uniqueColumns) {
$this->constraints[] = new \Core\Driver\SQL\Constraint\Unique($uniqueColumns->getColumns());
}
foreach ($this->entityClass->getProperties() as $property) {
foreach ($entityClass->getProperties() as $property) {
$propertyName = $property->getName();
if ($propertyName === "id") {
$this->properties[$propertyName] = $property;
@@ -123,8 +127,8 @@ class DatabaseEntityHandler implements Persistable {
try {
$requestedClass = new \ReflectionClass($extendingClass);
if (!$requestedClass->isSubclassOf($this->entityClass)) {
$this->raiseError("Class '$extendingClass' must be an inheriting from '" . $this->entityClass->getName() . "' for an extending enum");
if (!$requestedClass->isSubclassOf($entityClass)) {
$this->raiseError("Class '$extendingClass' must be an inheriting from '" . $entityClass->getName() . "' for an extending enum");
} else {
$this->extendingClasses[$key] = $requestedClass;
}

View File

@@ -27,6 +27,10 @@ class GpgKey extends DatabaseEntity {
$this->added = new \DateTime();
}
public function _encrypt(string $body): array {
return self::encrypt($body, $this->fingerprint);
}
public static function encrypt(string $body, string $gpgFingerprint): array {
$gpgFingerprint = escapeshellarg($gpgFingerprint);
$cmd = self::GPG2 . " --encrypt --output - --recipient $gpgFingerprint --trust-model always --batch --armor";
@@ -40,6 +44,23 @@ class GpgKey extends DatabaseEntity {
}
}
public function _sign(string $body): array {
return self::sign($body, $this->fingerprint);
}
public static function sign(string $body, string $gpgFingerprint): array {
$gpgFingerprint = escapeshellarg($gpgFingerprint);
$cmd = self::GPG2 . " --clearsign --output - --local-user $gpgFingerprint --batch --armor";
list($out, $err) = self::proc_exec($cmd, $body, true);
if ($out === null) {
return createError("Error while communicating with GPG agent");
} else if ($err) {
return createError($err);
} else {
return ["success" => true, "data" => $out];
}
}
private static function proc_exec(string $cmd, ?string $stdin = null, bool $raw = false): ?array {
$descriptorSpec = array(0 => ["pipe", "r"], 1 => ["pipe", "w"], 2 => ["pipe", "w"]);
$process = proc_open($cmd, $descriptorSpec, $pipes);
@@ -101,7 +122,11 @@ class GpgKey extends DatabaseEntity {
return createError($err);
}
public static function export($gpgFingerprint, bool $armored): array {
public function _export(bool $armored = true): array {
return self::export($this->fingerprint, $armored);
}
public static function export(string $gpgFingerprint, bool $armored): array {
$cmd = self::GPG2 . " --export ";
if ($armored) {
$cmd .= "--armor ";

View File

@@ -2,7 +2,6 @@
namespace Core\Objects\DatabaseEntity {
use Core\Driver\SQL\SQL;
use Core\Objects\DatabaseEntity\Attribute\MaxLength;
use Core\Objects\DatabaseEntity\Attribute\Transient;
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;

View File

@@ -249,6 +249,8 @@ abstract class Route extends DatabaseEntity {
new DocumentRoute("/login", true, \Core\Documents\Account::class, "account/login.twig"),
new DocumentRoute("/resendConfirmEmail", true, \Core\Documents\Account::class, "account/resend_confirm_email.twig"),
new DocumentRoute("/debug", true, \Core\Documents\Info::class),
new DocumentRoute("/.well-known/security.txt", true, \Core\Documents\Security::class),
new DocumentRoute("/.well-known/gpg-key.txt", true, \Core\Documents\Security::class),
new StaticFileRoute("/", true, "/static/welcome.html"),
];
}

View File

@@ -44,6 +44,16 @@ class Session extends DatabaseEntity {
return null;
}
if (is_array($session->data)) {
foreach ($session->data as $key => $value) {
$_SESSION[$key] = $value;
if ($key === "2faAuthenticated" && $value === true) {
$tfaToken = $session->getUser()->getTwoFactorToken();
$tfaToken?->authenticate();
}
}
}
$session->context = $context;
return $session;
}
@@ -66,6 +76,7 @@ class Session extends DatabaseEntity {
}
public function setData(array $data) {
$this->data = $data;
foreach ($data as $key => $value) {
$_SESSION[$key] = $value;
}
@@ -107,7 +118,7 @@ class Session extends DatabaseEntity {
$sql = $this->context->getSQL();
return $this->user->update($sql) &&
$this->save($sql, ["expires", "data"]);
$this->save($sql, ["expires", "data", "os", "browser"]);
}
public function getCsrfToken(): string {