Initial import

This commit is contained in:
Nextcloud Team 2021-11-30 11:20:42 +01:00 committed by Lukas Reschke
commit 2295a33590
884 changed files with 93939 additions and 0 deletions

22
php/vendor/slim/csrf/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,22 @@
# Change Log
## 2016-08-14
Now supports "persistence mode", to persist a single CSRF name/value pair throughout the life of a user's session. Added the following methods:
- `protected getLastKeyPair` - gets the most recently generated key/value pair from storage.
- `protected loadLastKeyPair` - gets the most recently generated key/value pair from storage, and assign it to `$this->keyPair`.
- `public setPersistentTokenMode`
- `public getPersistentTokenMode`
Note that if CSRF token validation fails, then the token should be renewed regardless of the persistence setting.
The methods `getTokenName` and `getTokenValue` now return `null` if `$this->keyPair` has not yet been set.
### Tests added:
- `testPersistenceModeTrueBetweenRequestsArray` - Token should persist between requests after initial creation, when stored in an array.
- `testPersistenceModeTrueBetweenRequestsArrayAccess` - Token should persist between requests after initial creation, when stored in an ArrayObject.
- `testPersistenceModeFalseBetweenRequestsArray` - Token should be changed between requests, when stored in an array.
- `testPersistenceModeFalseBetweenRequestsArrayAccess` - Token should be changed between requests, when stored in an ArrayObject.
- `testUpdateAfterInvalidTokenWithPersistenceModeTrue` - New token should be generated after an invalid request, even if persistence mode is enabled.

19
php/vendor/slim/csrf/LICENSE.md vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2012-2015 Josh Lockhart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

41
php/vendor/slim/csrf/composer.json vendored Normal file
View file

@ -0,0 +1,41 @@
{
"name": "slim/csrf",
"type": "library",
"description": "Slim Framework 4 CSRF protection PSR-15 middleware",
"keywords": ["slim","framework","middleware","csrf"],
"homepage": "http://slimframework.com",
"license": "MIT",
"authors": [
{
"name": "Josh Lockhart",
"email": "hello@joshlockhart.com",
"homepage": "http://joshlockhart.com"
}
],
"config": {
"sort-packages": true
},
"require": {
"php": "^7.3|^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"phpspec/prophecy": "^1.12",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.5.8"
},
"autoload": {
"psr-4": {
"Slim\\Csrf\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Slim\\Csrf\\Tests\\": "tests"
}
}
}

479
php/vendor/slim/csrf/src/Guard.php vendored Normal file
View file

@ -0,0 +1,479 @@
<?php
/**
* Slim Framework (https://slimframework.com)
*
* @license https://github.com/slimphp/Slim-Csrf/blob/master/LICENSE.md (MIT License)
*/
declare(strict_types=1);
namespace Slim\Csrf;
use ArrayAccess;
use Countable;
use Exception;
use Iterator;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
class Guard implements MiddlewareInterface
{
/**
* @var ResponseFactoryInterface
*/
protected $responseFactory;
/**
* Prefix for CSRF parameters (omit trailing "_" underscore)
*
* @var string
*/
protected $prefix;
/**
* CSRF storage
*
* Should be either an array or an object. If an object is used, then it must
* implement ArrayAccess and should implement Countable and Iterator
* if storage limit enforcement is required.
*
* @var array|ArrayAccess
*/
protected $storage;
/**
* Number of elements to store in the storage array
*
* @var int
*/
protected $storageLimit;
/**
* CSRF Strength
*
* @var int
*/
protected $strength;
/**
* Callable to be executed if the CSRF validation fails
* It must return a ResponseInterface
*
* @var callable|null
*/
protected $failureHandler;
/**
* Determines whether or not we should persist the token throughout the duration of the user's session.
*
* For security, Slim-Csrf will *always* reset the token if there is a validation error.
* @var bool True to use the same token throughout the session (unless there is a validation error),
* false to get a new token with each request.
*/
protected $persistentTokenMode;
/**
* Stores the latest key-pair generated by the class
*
* @var array|null
*/
protected $keyPair = null;
/**
* @param ResponseFactoryInterface $responseFactory
* @param string $prefix
* @param null|array|ArrayAccess $storage
* @param null|callable $failureHandler
* @param integer $storageLimit
* @param integer $strength
* @param boolean $persistentTokenMode
* @throws RuntimeException if the session cannot be found
*/
public function __construct(
ResponseFactoryInterface $responseFactory,
string $prefix = 'csrf',
&$storage = null,
?callable $failureHandler = null,
int $storageLimit = 200,
int $strength = 16,
bool $persistentTokenMode = false
) {
if ($strength < 16) {
throw new RuntimeException('CSRF middleware instantiation failed. Minimum strength is 16.');
}
$this->responseFactory = $responseFactory;
$this->prefix = rtrim($prefix, '_');
$this->strength = $strength;
$this->setStorage($storage);
$this->setFailureHandler($failureHandler);
$this->setStorageLimit($storageLimit);
$this->setPersistentTokenMode($persistentTokenMode);
}
/**
* @param null|array|ArrayAccess $storage
*
* @return self
*
* @throws RuntimeException
*/
public function setStorage(&$storage = null): self
{
if (is_array($storage)
|| ($storage instanceof ArrayAccess
&& $storage instanceof Countable
&& $storage instanceof Iterator
)
) {
$this->storage = &$storage;
return $this;
}
if (session_status() !== PHP_SESSION_ACTIVE) {
throw new RuntimeException(
'Invalid CSRF storage. ' .
'Use session_start() before instantiating the Guard middleware or provide array storage.'
);
}
if (!array_key_exists($this->prefix, $_SESSION) || !is_array($_SESSION[$this->prefix])) {
$_SESSION[$this->prefix] = [];
}
$this->storage = &$_SESSION[$this->prefix];
return $this;
}
/**
* @param callable|null $failureHandler Value to set
* @return self
*/
public function setFailureHandler(?callable $failureHandler): self
{
$this->failureHandler = $failureHandler;
return $this;
}
/**
* @param bool $persistentTokenMode True to use the same token throughout the session
* (unless there is a validation error), false to get a new token with each request.
* @return self
*/
public function setPersistentTokenMode(bool $persistentTokenMode): self
{
$this->persistentTokenMode = $persistentTokenMode;
return $this;
}
/**
* @param integer $storageLimit Value to set
*
* @return $this
*/
public function setStorageLimit(int $storageLimit): self
{
$this->storageLimit = $storageLimit;
return $this;
}
/**
* @return string
*
* @throws Exception
*/
protected function createToken(): string
{
return bin2hex(random_bytes($this->strength));
}
/**
* @return array
*
* @throws Exception
*/
public function generateToken(): array
{
// Generate new CSRF token
$name = uniqid($this->prefix);
$value = $this->createToken();
$this->saveTokenToStorage($name, $value);
$this->keyPair = [
$this->getTokenNameKey() => $name,
$this->getTokenValueKey() => $value
];
return $this->keyPair;
}
/**
* Validate CSRF token from current request against token value
* stored in $_SESSION or user provided storage
*
* @param string $name CSRF name
* @param string $value CSRF token value
*
* @return bool
*/
public function validateToken(string $name, string $value): bool
{
if (!isset($this->storage[$name])) {
return false;
}
$token = $this->storage[$name];
if (function_exists('hash_equals')) {
return hash_equals($token, $value);
}
return $token === $value;
}
/**
* @return string
*/
public function getTokenName(): ?string
{
return $this->keyPair[$this->getTokenNameKey()] ?? null;
}
/**
* @return string
*/
public function getTokenValue(): ?string
{
return $this->keyPair[$this->getTokenValueKey()] ?? null;
}
/**
* @return string
*/
public function getTokenNameKey(): string
{
return $this->prefix . '_name';
}
/**
* @return string
*/
public function getTokenValueKey(): string
{
return $this->prefix . '_value';
}
/**
* @return bool
*/
public function getPersistentTokenMode(): bool
{
return $this->persistentTokenMode;
}
/**
* @return string[]|null
*/
protected function getLastKeyPair(): ?array
{
if (
(is_array($this->storage) && empty($this->storage))
|| ($this->storage instanceof Countable && count($this->storage) < 1)
) {
return null;
}
$name = null;
$value = null;
if (is_array($this->storage)) {
end($this->storage);
$name = key($this->storage);
$value = $this->storage[$name];
reset($this->storage);
} elseif ($this->storage instanceof Iterator) {
$this->storage->rewind();
while ($this->storage->valid()) {
$name = $this->storage->key();
$value = $this->storage->current();
$this->storage->next();
}
$this->storage->rewind();
}
return $name !== null && $value !== null
? [
$this->getTokenNameKey() => $name,
$this->getTokenValueKey() => $value
]
: null;
}
/**
* Load the most recent key pair in storage.
*
* @return bool `true` if there was a key pair to load in storage, false otherwise.
*/
protected function loadLastKeyPair(): bool
{
return (bool) $this->keyPair = $this->getLastKeyPair();
}
/**
* @param string $name CSRF token name
* @param string $value CSRF token value
*
* @return void
*/
protected function saveTokenToStorage(string $name, string $value): void
{
$this->storage[$name] = $value;
}
/**
* Remove token from storage
*
* @param string $name CSRF token name
*/
public function removeTokenFromStorage(string $name): void
{
$this->storage[$name] = '';
unset($this->storage[$name]);
}
/**
* Remove the oldest tokens from the storage array so that there
* are never more than storageLimit tokens in the array.
*
* This is required as a token is generated every request and so
* most will never be used.
*/
protected function enforceStorageLimit(): void
{
if ($this->storageLimit === 0
|| (
!is_array($this->storage)
&& !($this->storage instanceof Countable && $this->storage instanceof Iterator)
)
) {
return;
}
if (is_array($this->storage)) {
while (count($this->storage) > $this->storageLimit) {
array_shift($this->storage);
}
return;
}
if ($this->storage instanceof Iterator) {
while (count($this->storage) > $this->storageLimit) {
$this->storage->rewind();
unset($this->storage[$this->storage->key()]);
}
}
}
/**
* @param ServerRequestInterface $request
*
* @return ServerRequestInterface
*
* @throws Exception
*/
public function appendNewTokenToRequest(ServerRequestInterface $request): ServerRequestInterface
{
$token = $this->generateToken();
return $this->appendTokenToRequest($request, $token);
}
/**
* @param ServerRequestInterface $request
* @param array $pair
*
* @return ServerRequestInterface
*/
protected function appendTokenToRequest(ServerRequestInterface $request, array $pair): ServerRequestInterface
{
$name = $this->getTokenNameKey();
$value = $this->getTokenValueKey();
return $request
->withAttribute($name, $pair[$name])
->withAttribute($value, $pair[$value]);
}
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
*
* @return ResponseInterface
*
* @throws Exception
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$body = $request->getParsedBody();
$name = null;
$value = null;
if (is_array($body)) {
$name = $body[$this->getTokenNameKey()] ?? null;
$value = $body[$this->getTokenValueKey()] ?? null;
}
if (in_array($request->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) {
$isValid = $this->validateToken((string) $name, (string) $value);
if ($isValid && !$this->persistentTokenMode) {
// successfully validated token, so delete it if not in persistentTokenMode
$this->removeTokenFromStorage($name);
}
if ($name === null || $value === null || !$isValid) {
$request = $this->appendNewTokenToRequest($request);
return $this->handleFailure($request, $handler);
}
} else {
// Method is GET/OPTIONS/HEAD/etc, so do not accept the token in the body of this request
if ($name !== null) {
return $this->handleFailure($request, $handler);
}
}
if (!$this->persistentTokenMode || !$this->loadLastKeyPair()) {
$request = $this->appendNewTokenToRequest($request);
} else {
$pair = $this->loadLastKeyPair() ? $this->keyPair : $this->generateToken();
$request = $this->appendTokenToRequest($request, $pair);
}
$this->enforceStorageLimit();
return $handler->handle($request);
}
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
*
* @return ResponseInterface
*/
public function handleFailure(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!is_callable($this->failureHandler)) {
$response = $this->responseFactory->createResponse();
$body = $response->getBody();
$body->write('Failed CSRF check!');
return $response
->withStatus(400)
->withHeader('Content-Type', 'text/plain')
->withBody($body);
}
return call_user_func($this->failureHandler, $request, $handler);
}
}