diff options
Diffstat (limited to 'lib/private/Security')
23 files changed, 155 insertions, 414 deletions
diff --git a/lib/private/Security/Bruteforce/Capabilities.php b/lib/private/Security/Bruteforce/Capabilities.php index b50eea0b7af..add2bb8d8b5 100644 --- a/lib/private/Security/Bruteforce/Capabilities.php +++ b/lib/private/Security/Bruteforce/Capabilities.php @@ -29,8 +29,8 @@ declare(strict_types=1); */ namespace OC\Security\Bruteforce; -use OCP\Capabilities\IPublicCapability; use OCP\Capabilities\IInitialStateExcludedCapability; +use OCP\Capabilities\IPublicCapability; use OCP\IRequest; use OCP\Security\Bruteforce\IThrottler; diff --git a/lib/private/Security/Bruteforce/CleanupJob.php b/lib/private/Security/Bruteforce/CleanupJob.php index 45cfe572acb..13628dd300d 100644 --- a/lib/private/Security/Bruteforce/CleanupJob.php +++ b/lib/private/Security/Bruteforce/CleanupJob.php @@ -32,19 +32,18 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class CleanupJob extends TimedJob { - /** @var IDBConnection */ - private $connection; - - public function __construct(ITimeFactory $time, IDBConnection $connection) { + public function __construct( + ITimeFactory $time, + private IDBConnection $connection, + ) { parent::__construct($time); - $this->connection = $connection; // Run once a day $this->setInterval(3600 * 24); $this->setTimeSensitivity(IJob::TIME_INSENSITIVE); } - protected function run($argument) { + protected function run($argument): void { // Delete all entries more than 48 hours old $time = $this->time->getTime() - (48 * 3600); diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php index 2803373e8ba..7e5f1daa28c 100644 --- a/lib/private/Security/Bruteforce/Throttler.php +++ b/lib/private/Security/Bruteforce/Throttler.php @@ -72,8 +72,8 @@ class Throttler implements IThrottler { * {@inheritDoc} */ public function registerAttempt(string $action, - string $ip, - array $metadata = []): void { + string $ip, + array $metadata = []): void { // No need to log if the bruteforce protection is disabled if (!$this->config->getSystemValueBool('auth.bruteforce.protection.enabled', true)) { return; @@ -106,9 +106,6 @@ class Throttler implements IThrottler { /** * Check if the IP is whitelisted - * - * @param string $ip - * @return bool */ public function isBypassListed(string $ip): bool { if (isset($this->ipIsWhitelisted[$ip])) { diff --git a/lib/private/Security/CSP/ContentSecurityPolicy.php b/lib/private/Security/CSP/ContentSecurityPolicy.php index e2d115cf34e..ee525af4c2a 100644 --- a/lib/private/Security/CSP/ContentSecurityPolicy.php +++ b/lib/private/Security/CSP/ContentSecurityPolicy.php @@ -34,33 +34,22 @@ namespace OC\Security\CSP; * @package OC\Security\CSP */ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy { - /** - * @return boolean - */ public function isInlineScriptAllowed(): bool { return $this->inlineScriptAllowed; } - /** - * @param boolean $inlineScriptAllowed - */ - public function setInlineScriptAllowed(bool $inlineScriptAllowed) { + public function setInlineScriptAllowed(bool $inlineScriptAllowed): void { $this->inlineScriptAllowed = $inlineScriptAllowed; } - /** - * @return boolean - */ public function isEvalScriptAllowed(): bool { return $this->evalScriptAllowed; } /** - * @param boolean $evalScriptAllowed - * * @deprecated 17.0.0 Unsafe eval should not be used anymore. */ - public function setEvalScriptAllowed(bool $evalScriptAllowed) { + public function setEvalScriptAllowed(bool $evalScriptAllowed): void { $this->evalScriptAllowed = $evalScriptAllowed; } @@ -72,134 +61,79 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy $this->evalWasmAllowed = $evalWasmAllowed; } - /** - * @return array - */ public function getAllowedScriptDomains(): array { return $this->allowedScriptDomains; } - /** - * @param array $allowedScriptDomains - */ - public function setAllowedScriptDomains(array $allowedScriptDomains) { + public function setAllowedScriptDomains(array $allowedScriptDomains): void { $this->allowedScriptDomains = $allowedScriptDomains; } - /** - * @return boolean - */ public function isInlineStyleAllowed(): bool { return $this->inlineStyleAllowed; } - /** - * @param boolean $inlineStyleAllowed - */ - public function setInlineStyleAllowed(bool $inlineStyleAllowed) { + public function setInlineStyleAllowed(bool $inlineStyleAllowed): void { $this->inlineStyleAllowed = $inlineStyleAllowed; } - /** - * @return array - */ public function getAllowedStyleDomains(): array { return $this->allowedStyleDomains; } - /** - * @param array $allowedStyleDomains - */ - public function setAllowedStyleDomains(array $allowedStyleDomains) { + public function setAllowedStyleDomains(array $allowedStyleDomains): void { $this->allowedStyleDomains = $allowedStyleDomains; } - /** - * @return array - */ public function getAllowedImageDomains(): array { return $this->allowedImageDomains; } - /** - * @param array $allowedImageDomains - */ - public function setAllowedImageDomains(array $allowedImageDomains) { + public function setAllowedImageDomains(array $allowedImageDomains): void { $this->allowedImageDomains = $allowedImageDomains; } - /** - * @return array - */ public function getAllowedConnectDomains(): array { return $this->allowedConnectDomains; } - /** - * @param array $allowedConnectDomains - */ - public function setAllowedConnectDomains(array $allowedConnectDomains) { + public function setAllowedConnectDomains(array $allowedConnectDomains): void { $this->allowedConnectDomains = $allowedConnectDomains; } - /** - * @return array - */ public function getAllowedMediaDomains(): array { return $this->allowedMediaDomains; } - /** - * @param array $allowedMediaDomains - */ - public function setAllowedMediaDomains(array $allowedMediaDomains) { + public function setAllowedMediaDomains(array $allowedMediaDomains): void { $this->allowedMediaDomains = $allowedMediaDomains; } - /** - * @return array - */ public function getAllowedObjectDomains(): array { return $this->allowedObjectDomains; } - /** - * @param array $allowedObjectDomains - */ - public function setAllowedObjectDomains(array $allowedObjectDomains) { + public function setAllowedObjectDomains(array $allowedObjectDomains): void { $this->allowedObjectDomains = $allowedObjectDomains; } - /** - * @return array - */ public function getAllowedFrameDomains(): array { return $this->allowedFrameDomains; } - /** - * @param array $allowedFrameDomains - */ - public function setAllowedFrameDomains(array $allowedFrameDomains) { + public function setAllowedFrameDomains(array $allowedFrameDomains): void { $this->allowedFrameDomains = $allowedFrameDomains; } - /** - * @return array - */ public function getAllowedFontDomains(): array { return $this->allowedFontDomains; } - /** - * @param array $allowedFontDomains - */ - public function setAllowedFontDomains($allowedFontDomains) { + public function setAllowedFontDomains($allowedFontDomains): void { $this->allowedFontDomains = $allowedFontDomains; } /** - * @return array * @deprecated 15.0.0 use FrameDomains and WorkerSrcDomains */ public function getAllowedChildSrcDomains(): array { @@ -210,13 +144,10 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy * @param array $allowedChildSrcDomains * @deprecated 15.0.0 use FrameDomains and WorkerSrcDomains */ - public function setAllowedChildSrcDomains($allowedChildSrcDomains) { + public function setAllowedChildSrcDomains($allowedChildSrcDomains): void { $this->allowedChildSrcDomains = $allowedChildSrcDomains; } - /** - * @return array - */ public function getAllowedFrameAncestors(): array { return $this->allowedFrameAncestors; } @@ -224,7 +155,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy /** * @param array $allowedFrameAncestors */ - public function setAllowedFrameAncestors($allowedFrameAncestors) { + public function setAllowedFrameAncestors($allowedFrameAncestors): void { $this->allowedFrameAncestors = $allowedFrameAncestors; } @@ -232,7 +163,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy return $this->allowedWorkerSrcDomains; } - public function setAllowedWorkerSrcDomains(array $allowedWorkerSrcDomains) { + public function setAllowedWorkerSrcDomains(array $allowedWorkerSrcDomains): void { $this->allowedWorkerSrcDomains = $allowedWorkerSrcDomains; } @@ -249,21 +180,23 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy return $this->reportTo; } - public function setReportTo(array $reportTo) { + public function setReportTo(array $reportTo): void { $this->reportTo = $reportTo; } - /** - * @return boolean - */ public function isStrictDynamicAllowed(): bool { return $this->strictDynamicAllowed; } - /** - * @param boolean $strictDynamicAllowed - */ - public function setStrictDynamicAllowed(bool $strictDynamicAllowed) { + public function setStrictDynamicAllowed(bool $strictDynamicAllowed): void { $this->strictDynamicAllowed = $strictDynamicAllowed; } + + public function isStrictDynamicAllowedOnScripts(): bool { + return $this->strictDynamicAllowedOnScripts; + } + + public function setStrictDynamicAllowedOnScripts(bool $strictDynamicAllowedOnScripts): void { + $this->strictDynamicAllowedOnScripts = $strictDynamicAllowedOnScripts; + } } diff --git a/lib/private/Security/CSP/ContentSecurityPolicyManager.php b/lib/private/Security/CSP/ContentSecurityPolicyManager.php index 4930dcb759c..503933ef980 100644 --- a/lib/private/Security/CSP/ContentSecurityPolicyManager.php +++ b/lib/private/Security/CSP/ContentSecurityPolicyManager.php @@ -35,25 +35,21 @@ use OCP\Security\IContentSecurityPolicyManager; class ContentSecurityPolicyManager implements IContentSecurityPolicyManager { /** @var ContentSecurityPolicy[] */ - private $policies = []; + private array $policies = []; - /** @var IEventDispatcher */ - private $dispatcher; - - public function __construct(IEventDispatcher $dispatcher) { - $this->dispatcher = $dispatcher; + public function __construct( + private IEventDispatcher $dispatcher, + ) { } /** {@inheritdoc} */ - public function addDefaultPolicy(EmptyContentSecurityPolicy $policy) { + public function addDefaultPolicy(EmptyContentSecurityPolicy $policy): void { $this->policies[] = $policy; } /** * Get the configured default policy. This is not in the public namespace * as it is only supposed to be used by core itself. - * - * @return ContentSecurityPolicy */ public function getDefaultPolicy(): ContentSecurityPolicy { $event = new AddContentSecurityPolicyEvent($this); @@ -68,13 +64,11 @@ class ContentSecurityPolicyManager implements IContentSecurityPolicyManager { /** * Merges the first given policy with the second one - * - * @param ContentSecurityPolicy $defaultPolicy - * @param EmptyContentSecurityPolicy $originalPolicy - * @return ContentSecurityPolicy */ - public function mergePolicies(ContentSecurityPolicy $defaultPolicy, - EmptyContentSecurityPolicy $originalPolicy): ContentSecurityPolicy { + public function mergePolicies( + ContentSecurityPolicy $defaultPolicy, + EmptyContentSecurityPolicy $originalPolicy, + ): ContentSecurityPolicy { foreach ((object)(array)$originalPolicy as $name => $value) { $setter = 'set'.ucfirst($name); if (\is_array($value)) { diff --git a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php index 1167b3358d2..6dbf86e5c88 100644 --- a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php +++ b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php @@ -38,27 +38,16 @@ use OCP\IRequest; * @package OC\Security\CSP */ class ContentSecurityPolicyNonceManager { - /** @var CsrfTokenManager */ - private $csrfTokenManager; - /** @var IRequest */ - private $request; - /** @var string */ - private $nonce = ''; + private string $nonce = ''; - /** - * @param CsrfTokenManager $csrfTokenManager - * @param IRequest $request - */ - public function __construct(CsrfTokenManager $csrfTokenManager, - IRequest $request) { - $this->csrfTokenManager = $csrfTokenManager; - $this->request = $request; + public function __construct( + private CsrfTokenManager $csrfTokenManager, + private IRequest $request, + ) { } /** - * Returns the current CSP nounce - * - * @return string + * Returns the current CSP nonce */ public function getNonce(): string { if ($this->nonce === '') { @@ -74,14 +63,13 @@ class ContentSecurityPolicyNonceManager { /** * Check if the browser supports CSP v3 - * - * @return bool */ public function browserSupportsCspV3(): bool { $browserWhitelist = [ Request::USER_AGENT_CHROME, Request::USER_AGENT_FIREFOX, Request::USER_AGENT_SAFARI, + Request::USER_AGENT_MS_EDGE, ]; if ($this->request->isUserAgent($browserWhitelist)) { diff --git a/lib/private/Security/CSRF/CsrfToken.php b/lib/private/Security/CSRF/CsrfToken.php index a76e169e5b9..45e628b3f3c 100644 --- a/lib/private/Security/CSRF/CsrfToken.php +++ b/lib/private/Security/CSRF/CsrfToken.php @@ -36,23 +36,19 @@ namespace OC\Security\CSRF; * @package OC\Security\CSRF */ class CsrfToken { - /** @var string */ - private $value; - /** @var string */ - private $encryptedValue = ''; + private string $encryptedValue = ''; /** * @param string $value Value of the token. Can be encrypted or not encrypted. */ - public function __construct(string $value) { - $this->value = $value; + public function __construct( + private string $value, + ) { } /** * Encrypted value of the token. This is used to mitigate BREACH alike * vulnerabilities. For display measures do use this functionality. - * - * @return string */ public function getEncryptedValue(): string { if ($this->encryptedValue === '') { @@ -66,8 +62,6 @@ class CsrfToken { /** * The unencrypted value of the token. Used for decrypting an already * encrypted token. - * - * @return string */ public function getDecryptedValue(): string { $token = explode(':', $this->value); diff --git a/lib/private/Security/CSRF/CsrfTokenGenerator.php b/lib/private/Security/CSRF/CsrfTokenGenerator.php index 0576fda9e06..c3d89247de1 100644 --- a/lib/private/Security/CSRF/CsrfTokenGenerator.php +++ b/lib/private/Security/CSRF/CsrfTokenGenerator.php @@ -34,21 +34,15 @@ use OCP\Security\ISecureRandom; * @package OC\Security\CSRF */ class CsrfTokenGenerator { - /** @var ISecureRandom */ - private $random; - - /** - * @param ISecureRandom $random - */ - public function __construct(ISecureRandom $random) { - $this->random = $random; + public function __construct( + private ISecureRandom $random, + ) { } /** * Generate a new CSRF token. * * @param int $length Length of the token in characters. - * @return string */ public function generateToken(int $length = 32): string { return $this->random->generate($length); diff --git a/lib/private/Security/CSRF/CsrfTokenManager.php b/lib/private/Security/CSRF/CsrfTokenManager.php index 2c6dd45866d..dceacf45e2a 100644 --- a/lib/private/Security/CSRF/CsrfTokenManager.php +++ b/lib/private/Security/CSRF/CsrfTokenManager.php @@ -34,27 +34,18 @@ use OC\Security\CSRF\TokenStorage\SessionStorage; * @package OC\Security\CSRF */ class CsrfTokenManager { - /** @var CsrfTokenGenerator */ - private $tokenGenerator; - /** @var SessionStorage */ - private $sessionStorage; - /** @var CsrfToken|null */ - private $csrfToken = null; + private SessionStorage $sessionStorage; + private ?CsrfToken $csrfToken = null; - /** - * @param CsrfTokenGenerator $tokenGenerator - * @param SessionStorage $storageInterface - */ - public function __construct(CsrfTokenGenerator $tokenGenerator, - SessionStorage $storageInterface) { - $this->tokenGenerator = $tokenGenerator; + public function __construct( + private CsrfTokenGenerator $tokenGenerator, + SessionStorage $storageInterface, + ) { $this->sessionStorage = $storageInterface; } /** * Returns the current CSRF token, if none set it will create a new one. - * - * @return CsrfToken */ public function getToken(): CsrfToken { if (!\is_null($this->csrfToken)) { @@ -74,8 +65,6 @@ class CsrfTokenManager { /** * Invalidates any current token and sets a new one. - * - * @return CsrfToken */ public function refreshToken(): CsrfToken { $value = $this->tokenGenerator->generateToken(); @@ -87,16 +76,13 @@ class CsrfTokenManager { /** * Remove the current token from the storage. */ - public function removeToken() { + public function removeToken(): void { $this->csrfToken = null; $this->sessionStorage->removeToken(); } /** * Verifies whether the provided token is valid. - * - * @param CsrfToken $token - * @return bool */ public function isTokenValid(CsrfToken $token): bool { if (!$this->sessionStorage->hasToken()) { diff --git a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php index ab05d5b1493..0ffe043e2f9 100644 --- a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php +++ b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php @@ -35,27 +35,18 @@ use OCP\ISession; * @package OC\Security\CSRF\TokenStorage */ class SessionStorage { - /** @var ISession */ - private $session; - - /** - * @param ISession $session - */ - public function __construct(ISession $session) { - $this->session = $session; + public function __construct( + private ISession $session, + ) { } - /** - * @param ISession $session - */ - public function setSession(ISession $session) { + public function setSession(ISession $session): void { $this->session = $session; } /** * Returns the current token or throws an exception if none is found. * - * @return string * @throws \Exception */ public function getToken(): string { @@ -69,23 +60,20 @@ class SessionStorage { /** * Set the valid current token to $value. - * - * @param string $value */ - public function setToken(string $value) { + public function setToken(string $value): void { $this->session->set('requesttoken', $value); } /** * Removes the current token. */ - public function removeToken() { + public function removeToken(): void { $this->session->remove('requesttoken'); } + /** * Whether the storage has a storage. - * - * @return bool */ public function hasToken(): bool { return $this->session->exists('requesttoken'); diff --git a/lib/private/Security/Certificate.php b/lib/private/Security/Certificate.php index fb5b9aa8a93..759c71b2eec 100644 --- a/lib/private/Security/Certificate.php +++ b/lib/private/Security/Certificate.php @@ -30,25 +30,23 @@ namespace OC\Security; use OCP\ICertificate; class Certificate implements ICertificate { - protected $name; + protected string $name; - protected $commonName; + protected ?string $commonName; - protected $organization; + protected ?string $organization; - protected $serial; - protected $issueDate; + protected \DateTime $issueDate; - protected $expireDate; + protected \DateTime $expireDate; - protected $issuerName; + protected ?string $issuerName; - protected $issuerOrganization; + protected ?string $issuerOrganization; /** * @param string $data base64 encoded certificate - * @param string $name * @throws \Exception If the certificate could not get parsed */ public function __construct(string $data, string $name) { @@ -66,67 +64,43 @@ class Certificate implements ICertificate { throw new \Exception('Certificate could not get parsed.'); } - $this->commonName = isset($info['subject']['CN']) ? $info['subject']['CN'] : null; - $this->organization = isset($info['subject']['O']) ? $info['subject']['O'] : null; + $this->commonName = $info['subject']['CN'] ?? null; + $this->organization = $info['subject']['O'] ?? null; $this->issueDate = new \DateTime('@' . $info['validFrom_time_t'], $gmt); $this->expireDate = new \DateTime('@' . $info['validTo_time_t'], $gmt); - $this->issuerName = isset($info['issuer']['CN']) ? $info['issuer']['CN'] : null; - $this->issuerOrganization = isset($info['issuer']['O']) ? $info['issuer']['O'] : null; + $this->issuerName = $info['issuer']['CN'] ?? null; + $this->issuerOrganization = $info['issuer']['O'] ?? null; } - /** - * @return string - */ public function getName(): string { return $this->name; } - /** - * @return string|null - */ public function getCommonName(): ?string { return $this->commonName; } - /** - * @return string|null - */ public function getOrganization(): ?string { return $this->organization; } - /** - * @return \DateTime - */ public function getIssueDate(): \DateTime { return $this->issueDate; } - /** - * @return \DateTime - */ public function getExpireDate(): \DateTime { return $this->expireDate; } - /** - * @return bool - */ public function isExpired(): bool { $now = new \DateTime(); return $this->issueDate > $now or $now > $this->expireDate; } - /** - * @return string|null - */ public function getIssuerName(): ?string { return $this->issuerName; } - /** - * @return string|null - */ public function getIssuerOrganization(): ?string { return $this->issuerOrganization; } diff --git a/lib/private/Security/CertificateManager.php b/lib/private/Security/CertificateManager.php index 3a87b7f1a00..cf5f0f41d56 100644 --- a/lib/private/Security/CertificateManager.php +++ b/lib/private/Security/CertificateManager.php @@ -44,21 +44,14 @@ use Psr\Log\LoggerInterface; * Manage trusted certificates for users */ class CertificateManager implements ICertificateManager { - protected View $view; - protected IConfig $config; - protected LoggerInterface $logger; - protected ISecureRandom $random; - private ?string $bundlePath = null; - public function __construct(View $view, - IConfig $config, - LoggerInterface $logger, - ISecureRandom $random) { - $this->view = $view; - $this->config = $config; - $this->logger = $logger; - $this->random = $random; + public function __construct( + protected View $view, + protected IConfig $config, + protected LoggerInterface $logger, + protected ISecureRandom $random, + ) { } /** @@ -178,7 +171,6 @@ class CertificateManager implements ICertificateManager { * * @param string $certificate the certificate data * @param string $name the filename for the certificate - * @return \OCP\ICertificate * @throws \Exception If the certificate could not get added */ public function addCertificate(string $certificate, string $name): ICertificate { @@ -205,9 +197,6 @@ class CertificateManager implements ICertificateManager { /** * Remove the certificate and re-generate the certificate bundle - * - * @param string $name - * @return bool */ public function removeCertificate(string $name): bool { if (!Filesystem::isValidPath($name)) { @@ -225,8 +214,6 @@ class CertificateManager implements ICertificateManager { /** * Get the path to the certificate bundle - * - * @return string */ public function getCertificateBundle(): string { return $this->getPathToCertificates() . 'rootcerts.crt'; @@ -267,8 +254,6 @@ class CertificateManager implements ICertificateManager { /** * Check if we need to re-bundle the certificates because one of the sources has updated - * - * @return bool */ private function needsRebundling(): bool { $targetBundle = $this->getCertificateBundle(); @@ -282,8 +267,6 @@ class CertificateManager implements ICertificateManager { /** * get mtime of ca-bundle shipped by Nextcloud - * - * @return int */ protected function getFilemtimeOfCaBundle(): int { return filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt'); diff --git a/lib/private/Security/CredentialsManager.php b/lib/private/Security/CredentialsManager.php index 0bddaeda1b0..ea59a24d646 100644 --- a/lib/private/Security/CredentialsManager.php +++ b/lib/private/Security/CredentialsManager.php @@ -40,26 +40,16 @@ use OCP\Security\ICrypto; class CredentialsManager implements ICredentialsManager { public const DB_TABLE = 'storages_credentials'; - /** @var ICrypto */ - protected $crypto; - - /** @var IDBConnection */ - protected $dbConnection; - - /** - * @param ICrypto $crypto - * @param IDBConnection $dbConnection - */ - public function __construct(ICrypto $crypto, IDBConnection $dbConnection) { - $this->crypto = $crypto; - $this->dbConnection = $dbConnection; + public function __construct( + protected ICrypto $crypto, + protected IDBConnection $dbConnection, + ) { } /** * Store a set of credentials * * @param string $userId empty string for system-wide credentials - * @param string $identifier * @param mixed $credentials */ public function store(string $userId, string $identifier, $credentials): void { @@ -77,10 +67,8 @@ class CredentialsManager implements ICredentialsManager { * Retrieve a set of credentials * * @param string $userId empty string for system-wide credentials - * @param string $identifier - * @return mixed */ - public function retrieve(string $userId, string $identifier) { + public function retrieve(string $userId, string $identifier): mixed { $qb = $this->dbConnection->getQueryBuilder(); $qb->select('credentials') ->from(self::DB_TABLE) @@ -108,7 +96,6 @@ class CredentialsManager implements ICredentialsManager { * Delete a set of credentials * * @param string $userId empty string for system-wide credentials - * @param string $identifier * @return int rows removed */ public function delete(string $userId, string $identifier): int { @@ -128,7 +115,6 @@ class CredentialsManager implements ICredentialsManager { /** * Erase all credentials stored for a user * - * @param string $userId * @return int rows removed */ public function erase(string $userId): int { diff --git a/lib/private/Security/Crypto.php b/lib/private/Security/Crypto.php index 2a7905376ef..033456f3f2e 100644 --- a/lib/private/Security/Crypto.php +++ b/lib/private/Security/Crypto.php @@ -32,7 +32,6 @@ namespace OC\Security; use Exception; use OCP\IConfig; use OCP\Security\ICrypto; -use OCP\Security\ISecureRandom; use phpseclib\Crypt\AES; use phpseclib\Crypt\Hash; @@ -47,20 +46,13 @@ use phpseclib\Crypt\Hash; * @package OC\Security */ class Crypto implements ICrypto { - /** @var AES $cipher */ - private $cipher; - /** @var int */ - private $ivLength = 16; - /** @var IConfig */ - private $config; + private AES $cipher; + private int $ivLength = 16; - /** - * @param IConfig $config - * @param ISecureRandom $random - */ - public function __construct(IConfig $config) { + public function __construct( + private IConfig $config, + ) { $this->cipher = new AES(); - $this->config = $config; } /** @@ -84,7 +76,6 @@ class Crypto implements ICrypto { /** * Encrypts a value and adds an HMAC (Encrypt-Then-MAC) * - * @param string $plaintext * @param string $password Password to encrypt, if not specified the secret from config.php will be taken * @return string Authenticated ciphertext * @throws Exception if it was not possible to gather sufficient entropy @@ -115,9 +106,7 @@ class Crypto implements ICrypto { /** * Decrypts a value and verifies the HMAC (Encrypt-Then-Mac) - * @param string $authenticatedCiphertext * @param string $password Password to encrypt, if not specified the secret from config.php will be taken - * @return string plaintext * @throws Exception If the HMAC does not match * @throws Exception If the decryption failed */ diff --git a/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php b/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php index 3aa93ac3da4..bb9fc41332f 100644 --- a/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php +++ b/lib/private/Security/FeaturePolicy/FeaturePolicyManager.php @@ -32,13 +32,11 @@ use OCP\Security\FeaturePolicy\AddFeaturePolicyEvent; class FeaturePolicyManager { /** @var EmptyFeaturePolicy[] */ - private $policies = []; + private array $policies = []; - /** @var IEventDispatcher */ - private $dispatcher; - - public function __construct(IEventDispatcher $dispatcher) { - $this->dispatcher = $dispatcher; + public function __construct( + private IEventDispatcher $dispatcher, + ) { } public function addDefaultPolicy(EmptyFeaturePolicy $policy): void { @@ -60,8 +58,10 @@ class FeaturePolicyManager { * Merges the first given policy with the second one * */ - public function mergePolicies(FeaturePolicy $defaultPolicy, - EmptyFeaturePolicy $originalPolicy): FeaturePolicy { + public function mergePolicies( + FeaturePolicy $defaultPolicy, + EmptyFeaturePolicy $originalPolicy, + ): FeaturePolicy { foreach ((object)(array)$originalPolicy as $name => $value) { $setter = 'set' . ucfirst($name); if (\is_array($value)) { diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php index 85f69263925..23747751053 100644 --- a/lib/private/Security/Hasher.php +++ b/lib/private/Security/Hasher.php @@ -51,19 +51,14 @@ use OCP\Security\IHasher; * @package OC\Security */ class Hasher implements IHasher { - /** @var IConfig */ - private $config; - /** @var array Options passed to password_hash and password_needs_rehash */ - private $options = []; - /** @var string Salt used for legacy passwords */ - private $legacySalt = null; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; - + /** Options passed to password_hash and password_needs_rehash */ + private array $options = []; + /** Salt used for legacy passwords */ + private ?string $legacySalt = null; + + public function __construct( + private IConfig $config, + ) { if (\defined('PASSWORD_ARGON2ID') || \defined('PASSWORD_ARGON2I')) { // password_hash fails, when the minimum values are undershot. // In this case, apply minimum. @@ -106,7 +101,7 @@ class Hasher implements IHasher { * @param string $prefixedHash * @return null|array Null if the hash is not prefixed, otherwise array('version' => 1, 'hash' => 'foo') */ - protected function splitHash(string $prefixedHash) { + protected function splitHash(string $prefixedHash): ?array { $explodedString = explode('|', $prefixedHash, 2); if (\count($explodedString) === 2) { if ((int)$explodedString[0] > 0) { @@ -198,7 +193,7 @@ class Hasher implements IHasher { return password_needs_rehash($hash, $algorithm, $this->options); } - private function getPrefferedAlgorithm() { + private function getPrefferedAlgorithm(): string { $default = PASSWORD_BCRYPT; if (\defined('PASSWORD_ARGON2I')) { $default = PASSWORD_ARGON2I; diff --git a/lib/private/Security/Normalizer/IpAddress.php b/lib/private/Security/Normalizer/IpAddress.php index 98d85ce07a1..f8e55370da7 100644 --- a/lib/private/Security/Normalizer/IpAddress.php +++ b/lib/private/Security/Normalizer/IpAddress.php @@ -37,43 +37,18 @@ namespace OC\Security\Normalizer; * @package OC\Security\Normalizer */ class IpAddress { - /** @var string */ - private $ip; - /** - * @param string $ip IP to normalized + * @param string $ip IP to normalize */ - public function __construct(string $ip) { - $this->ip = $ip; + public function __construct( + private string $ip, + ) { } /** - * Return the given subnet for an IPv4 address and mask bits - * - * @param string $ip - * @param int $maskBits - * @return string - */ - private function getIPv4Subnet(string $ip, int $maskBits = 32): string { - $binary = \inet_pton($ip); - for ($i = 32; $i > $maskBits; $i -= 8) { - $j = \intdiv($i, 8) - 1; - $k = \min(8, $i - $maskBits); - $mask = (0xff - ((2 ** $k) - 1)); - $int = \unpack('C', $binary[$j]); - $binary[$j] = \pack('C', $int[1] & $mask); - } - return \inet_ntop($binary).'/'.$maskBits; - } - - /** - * Return the given subnet for an IPv6 address and mask bits - * - * @param string $ip - * @param int $maskBits - * @return string + * Return the given subnet for an IPv6 address (64 first bits) */ - private function getIPv6Subnet(string $ip, int $maskBits = 48): string { + private function getIPv6Subnet(string $ip): string { if ($ip[0] === '[' && $ip[-1] === ']') { // If IP is with brackets, for example [::1] $ip = substr($ip, 1, strlen($ip) - 2); } @@ -81,15 +56,11 @@ class IpAddress { if ($pos !== false) { $ip = substr($ip, 0, $pos - 1); } + $binary = \inet_pton($ip); - for ($i = 128; $i > $maskBits; $i -= 8) { - $j = \intdiv($i, 8) - 1; - $k = \min(8, $i - $maskBits); - $mask = (0xff - ((2 ** $k) - 1)); - $int = \unpack('C', $binary[$j]); - $binary[$j] = \pack('C', $int[1] & $mask); - } - return \inet_ntop($binary).'/'.$maskBits; + $mask = inet_pton('FFFF:FFFF:FFFF:FFFF::'); + + return inet_ntop($binary & $mask).'/64'; } /** @@ -103,58 +74,34 @@ class IpAddress { if (!$binary) { return null; } - for ($i = 0; $i <= 9; $i++) { - if (unpack('C', $binary[$i])[1] !== 0) { - return null; - } - } - for ($i = 10; $i <= 11; $i++) { - if (unpack('C', $binary[$i])[1] !== 255) { - return null; - } - } - - $binary4 = ''; - for ($i = 12; $i < 16; $i++) { - $binary4 .= $binary[$i]; + $mask = inet_pton('::FFFF:FFFF'); + if (($binary & ~$mask) !== inet_pton('::FFFF:0.0.0.0')) { + return null; } - return inet_ntop($binary4); + return inet_ntop(substr($binary, -4)); } /** * Gets either the /32 (IPv4) or the /64 (IPv6) subnet of an IP address - * - * @return string */ public function getSubnet(): string { - if (\preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->ip)) { - return $this->getIPv4Subnet( - $this->ip, - 32 - ); + if (filter_var($this->ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + return $this->ip.'/32'; } $ipv4 = $this->getEmbeddedIpv4($this->ip); if ($ipv4 !== null) { - return $this->getIPv4Subnet( - $ipv4, - 32 - ); + return $ipv4.'/32'; } - return $this->getIPv6Subnet( - $this->ip, - 64 - ); + return $this->getIPv6Subnet($this->ip); } /** * Returns the specified IP address - * - * @return string */ public function __toString(): string { return $this->ip; diff --git a/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php b/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php index 08091e997ca..baf74927886 100644 --- a/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php +++ b/lib/private/Security/RateLimiting/Exception/RateLimitExceededException.php @@ -27,8 +27,9 @@ namespace OC\Security\RateLimiting\Exception; use OC\AppFramework\Middleware\Security\Exceptions\SecurityException; use OCP\AppFramework\Http; +use OCP\Security\RateLimiting\IRateLimitExceededException; -class RateLimitExceededException extends SecurityException { +class RateLimitExceededException extends SecurityException implements IRateLimitExceededException { public function __construct() { parent::__construct('Rate limit exceeded', Http::STATUS_TOO_MANY_REQUESTS); } diff --git a/lib/private/Security/RateLimiting/Limiter.php b/lib/private/Security/RateLimiting/Limiter.php index c8c0e2ce101..689e7b14558 100644 --- a/lib/private/Security/RateLimiting/Limiter.php +++ b/lib/private/Security/RateLimiting/Limiter.php @@ -30,8 +30,9 @@ use OC\Security\Normalizer\IpAddress; use OC\Security\RateLimiting\Backend\IBackend; use OC\Security\RateLimiting\Exception\RateLimitExceededException; use OCP\IUser; +use OCP\Security\RateLimiting\ILimiter; -class Limiter { +class Limiter implements ILimiter { public function __construct( private IBackend $backend, ) { diff --git a/lib/private/Security/RemoteHostValidator.php b/lib/private/Security/RemoteHostValidator.php index 38129fbd81b..9cc69594c32 100644 --- a/lib/private/Security/RemoteHostValidator.php +++ b/lib/private/Security/RemoteHostValidator.php @@ -38,19 +38,12 @@ use function urldecode; * @internal */ final class RemoteHostValidator implements IRemoteHostValidator { - private IConfig $config; - private HostnameClassifier $hostnameClassifier; - private IpAddressClassifier $ipAddressClassifier; - private LoggerInterface $logger; - - public function __construct(IConfig $config, - HostnameClassifier $hostnameClassifier, - IpAddressClassifier $ipAddressClassifier, - LoggerInterface $logger) { - $this->config = $config; - $this->hostnameClassifier = $hostnameClassifier; - $this->ipAddressClassifier = $ipAddressClassifier; - $this->logger = $logger; + public function __construct( + private IConfig $config, + private HostnameClassifier $hostnameClassifier, + private IpAddressClassifier $ipAddressClassifier, + private LoggerInterface $logger, + ) { } public function isValid(string $host): bool { @@ -59,6 +52,10 @@ final class RemoteHostValidator implements IRemoteHostValidator { } $host = idn_to_utf8(strtolower(urldecode($host))); + if ($host === false) { + return false; + } + // Remove brackets from IPv6 addresses if (str_starts_with($host, '[') && str_ends_with($host, ']')) { $host = substr($host, 1, -1); diff --git a/lib/private/Security/SecureRandom.php b/lib/private/Security/SecureRandom.php index cbd1dc8db6d..f5bc5ddfb5e 100644 --- a/lib/private/Security/SecureRandom.php +++ b/lib/private/Security/SecureRandom.php @@ -44,11 +44,12 @@ class SecureRandom implements ISecureRandom { * @param int $length The length of the generated string * @param string $characters An optional list of characters to use if no character list is * specified all valid base64 characters are used. - * @return string * @throws \LengthException if an invalid length is requested */ - public function generate(int $length, - string $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'): string { + public function generate( + int $length, + string $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + ): string { if ($length <= 0) { throw new \LengthException('Invalid length specified: ' . $length . ' must be bigger than 0'); } diff --git a/lib/private/Security/TrustedDomainHelper.php b/lib/private/Security/TrustedDomainHelper.php index ca6a5cba073..e91f230a9c9 100644 --- a/lib/private/Security/TrustedDomainHelper.php +++ b/lib/private/Security/TrustedDomainHelper.php @@ -34,19 +34,13 @@ use OCP\IConfig; use OCP\Security\ITrustedDomainHelper; class TrustedDomainHelper implements ITrustedDomainHelper { - /** @var IConfig */ - private $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; + public function __construct( + private IConfig $config, + ) { } /** * Strips a potential port from a domain (in format domain:port) - * @param string $host * @return string $host without appended port */ private function getDomainWithoutPort(string $host): string { diff --git a/lib/private/Security/VerificationToken/CleanUpJob.php b/lib/private/Security/VerificationToken/CleanUpJob.php index 1f4af046451..9c1b27d344d 100644 --- a/lib/private/Security/VerificationToken/CleanUpJob.php +++ b/lib/private/Security/VerificationToken/CleanUpJob.php @@ -27,10 +27,10 @@ declare(strict_types=1); namespace OC\Security\VerificationToken; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\IConfig; -use OCP\IUserManager; use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\Job; +use OCP\IConfig; +use OCP\IUserManager; use OCP\Security\VerificationToken\InvalidTokenException; use OCP\Security\VerificationToken\IVerificationToken; |