aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php')
-rw-r--r--lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php70
1 files changed, 61 insertions, 9 deletions
diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
index eb8c1b8dc43..8e0794f9645 100644
--- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
@@ -48,6 +48,12 @@ use OC\Settings\AuthorizedGroupMapper;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\Attribute\PublicPage;
+use OCP\AppFramework\Http\Attribute\StrictCookiesRequired;
+use OCP\AppFramework\Http\Attribute\SubAdminRequired;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\Response;
@@ -61,6 +67,7 @@ use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Util;
use Psr\Log\LoggerInterface;
+use ReflectionMethod;
/**
* Used to do all the authentication and checking stuff for a controller method
@@ -145,22 +152,24 @@ class SecurityMiddleware extends Middleware {
$this->navigationManager->setActiveEntry('spreed');
}
+ $reflectionMethod = new ReflectionMethod($controller, $methodName);
+
// security checks
- $isPublicPage = $this->reflector->hasAnnotation('PublicPage');
+ $isPublicPage = $this->hasAnnotationOrAttribute($reflectionMethod, 'PublicPage', PublicPage::class);
if (!$isPublicPage) {
if (!$this->isLoggedIn) {
throw new NotLoggedInException();
}
$authorized = false;
- if ($this->reflector->hasAnnotation('AuthorizedAdminSetting')) {
+ if ($this->hasAnnotationOrAttribute($reflectionMethod, 'AuthorizedAdminSetting', AuthorizedAdminSetting::class)) {
$authorized = $this->isAdminUser;
- if (!$authorized && $this->reflector->hasAnnotation('SubAdminRequired')) {
+ if (!$authorized && $this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)) {
$authorized = $this->isSubAdmin;
}
if (!$authorized) {
- $settingClasses = explode(';', $this->reflector->getAnnotationParameter('AuthorizedAdminSetting', 'settings'));
+ $settingClasses = $this->getAuthorizedAdminSettingClasses($reflectionMethod);
$authorizedClasses = $this->groupAuthorizationMapper->findAllClassesForUser($this->userSession->getUser());
foreach ($settingClasses as $settingClass) {
$authorized = in_array($settingClass, $authorizedClasses, true);
@@ -174,14 +183,14 @@ class SecurityMiddleware extends Middleware {
throw new NotAdminException($this->l10n->t('Logged in user must be an admin, a sub admin or gotten special right to access this setting'));
}
}
- if ($this->reflector->hasAnnotation('SubAdminRequired')
+ if ($this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)
&& !$this->isSubAdmin
&& !$this->isAdminUser
&& !$authorized) {
throw new NotAdminException($this->l10n->t('Logged in user must be an admin or sub admin'));
}
- if (!$this->reflector->hasAnnotation('SubAdminRequired')
- && !$this->reflector->hasAnnotation('NoAdminRequired')
+ if (!$this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class)
+ && !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoAdminRequired', NoAdminRequired::class)
&& !$this->isAdminUser
&& !$authorized) {
throw new NotAdminException($this->l10n->t('Logged in user must be an admin'));
@@ -189,14 +198,15 @@ class SecurityMiddleware extends Middleware {
}
// Check for strict cookie requirement
- if ($this->reflector->hasAnnotation('StrictCookieRequired') || !$this->reflector->hasAnnotation('NoCSRFRequired')) {
+ if ($this->hasAnnotationOrAttribute($reflectionMethod, 'StrictCookieRequired', StrictCookiesRequired::class) ||
+ !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoCSRFRequired', NoCSRFRequired::class)) {
if (!$this->request->passesStrictCookieCheck()) {
throw new StrictCookieMissingException();
}
}
// CSRF check - also registers the CSRF token since the session may be closed later
Util::callRegister();
- if (!$this->reflector->hasAnnotation('NoCSRFRequired')) {
+ if (!$this->hasAnnotationOrAttribute($reflectionMethod, 'NoCSRFRequired', NoCSRFRequired::class)) {
/*
* Only allow the CSRF check to fail on OCS Requests. This kind of
* hacks around that we have no full token auth in place yet and we
@@ -233,6 +243,48 @@ class SecurityMiddleware extends Middleware {
}
/**
+ * @template T
+ *
+ * @param ReflectionMethod $reflectionMethod
+ * @param string $annotationName
+ * @param class-string<T> $attributeClass
+ * @return boolean
+ */
+ protected function hasAnnotationOrAttribute(ReflectionMethod $reflectionMethod, string $annotationName, string $attributeClass): bool {
+ if (!empty($reflectionMethod->getAttributes($attributeClass))) {
+ return true;
+ }
+
+ if ($this->reflector->hasAnnotation($annotationName)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param ReflectionMethod $reflectionMethod
+ * @return string[]
+ */
+ protected function getAuthorizedAdminSettingClasses(ReflectionMethod $reflectionMethod): array {
+ $classes = [];
+ if ($this->reflector->hasAnnotation('AuthorizedAdminSetting')) {
+ $classes = explode(';', $this->reflector->getAnnotationParameter('AuthorizedAdminSetting', 'settings'));
+ }
+
+ $attributes = $reflectionMethod->getAttributes(AuthorizedAdminSetting::class);
+ if (!empty($attributes)) {
+ foreach ($attributes as $attribute) {
+ /** @var AuthorizedAdminSetting $setting */
+ $setting = $attribute->newInstance();
+ $classes[] = $setting->getSettings();
+ }
+ }
+
+ return $classes;
+ }
+
+ /**
* If an SecurityException is being caught, ajax requests return a JSON error
* response and non ajax requests redirect to the index
*