/** * Checks if the specified method matches against the method name * expression. * * Returns TRUE if method name, visibility and arguments constraints match and the target * method is not final. * * @param string $className Ignored in this pointcut filter * @param string $methodName Name of the method to match against * @param string $methodDeclaringClassName Name of the class the method was originally declared in * @param mixed $pointcutQueryIdentifier Some identifier for this query - must at least differ from a previous identifier. Used for circular reference detection. * @return boolean TRUE if the class matches, otherwise FALSE * @throws \TYPO3\Flow\Aop\Exception */ public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier) { $matchResult = preg_match('/^' . $this->methodNameFilterExpression . '$/', $methodName); if ($matchResult === false) { throw new \TYPO3\Flow\Aop\Exception('Error in regular expression', 1168876915); } elseif ($matchResult !== 1) { return false; } switch ($this->methodVisibility) { case 'public': if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodPublic($methodDeclaringClassName, $methodName))) { return false; } break; case 'protected': if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodProtected($methodDeclaringClassName, $methodName))) { return false; } break; } if ($methodDeclaringClassName !== null && $this->reflectionService->isMethodFinal($methodDeclaringClassName, $methodName)) { return false; } $methodArguments = $methodDeclaringClassName === null ? array() : $this->reflectionService->getMethodParameters($methodDeclaringClassName, $methodName); foreach (array_keys($this->methodArgumentConstraints) as $argumentName) { $objectAccess = explode('.', $argumentName, 2); $argumentName = $objectAccess[0]; if (!array_key_exists($argumentName, $methodArguments)) { $this->systemLogger->log('The argument "' . $argumentName . '" declared in pointcut does not exist in method ' . $methodDeclaringClassName . '->' . $methodName, LOG_NOTICE); return false; } } return true; }
/** * Lists all public controller actions not covered by the active security policy * * @return void */ public function showUnprotectedActionsCommand() { $controllerClassNames = $this->reflectionService->getAllSubClassNamesForClass('TYPO3\\Flow\\Mvc\\Controller\\AbstractController'); $allActionsAreProtected = TRUE; foreach ($controllerClassNames as $controllerClassName) { if ($this->reflectionService->isClassAbstract($controllerClassName)) { continue; } $methodNames = get_class_methods($controllerClassName); $foundUnprotectedAction = FALSE; foreach ($methodNames as $methodName) { if (preg_match('/.*Action$/', $methodName) === 0 || $this->reflectionService->isMethodPublic($controllerClassName, $methodName) === FALSE) { continue; } if ($this->policyService->hasPolicyEntryForMethod($controllerClassName, $methodName) === FALSE) { if ($foundUnprotectedAction === FALSE) { $this->outputLine(PHP_EOL . '<b>' . $controllerClassName . '</b>'); $foundUnprotectedAction = TRUE; $allActionsAreProtected = FALSE; } $this->outputLine(' ' . $methodName); } } } if ($allActionsAreProtected === TRUE) { $this->outputLine('All public controller actions are covered by your security policy. Good job!'); } }
/** * Resolves and checks the current action method name * * @return string Method name of the current action * @throws NoSuchActionException * @throws InvalidActionVisibilityException */ protected function resolveActionMethodName() { $actionMethodName = $this->request->getControllerActionName() . 'Action'; if (!is_callable(array($this, $actionMethodName))) { throw new NoSuchActionException(sprintf('An action "%s" does not exist in controller "%s".', $actionMethodName, get_class($this)), 1186669086); } if (!$this->reflectionService->isMethodPublic(get_class($this), $actionMethodName)) { throw new InvalidActionVisibilityException(sprintf('The action "%s" in controller "%s" is not public!', $actionMethodName, get_class($this)), 1186669086); } return $actionMethodName; }
/** * Lists all public controller actions not covered by the active security policy * * @return void */ public function showUnprotectedActionsCommand() { $methodPrivileges = array(); foreach ($this->policyService->getRoles(true) as $role) { $methodPrivileges = array_merge($methodPrivileges, $role->getPrivilegesByType(\TYPO3\Flow\Security\Authorization\Privilege\Method\MethodPrivilegeInterface::class)); } $controllerClassNames = $this->reflectionService->getAllSubClassNamesForClass(\TYPO3\Flow\Mvc\Controller\AbstractController::class); $allActionsAreProtected = true; foreach ($controllerClassNames as $controllerClassName) { if ($this->reflectionService->isClassAbstract($controllerClassName)) { continue; } $methodNames = get_class_methods($controllerClassName); $foundUnprotectedAction = false; foreach ($methodNames as $methodName) { if (preg_match('/.*Action$/', $methodName) === 0 || $this->reflectionService->isMethodPublic($controllerClassName, $methodName) === false) { continue; } /** @var MethodPrivilegeInterface $methodPrivilege */ foreach ($methodPrivileges as $methodPrivilege) { if ($methodPrivilege->matchesMethod($controllerClassName, $methodName)) { continue 2; } } if ($foundUnprotectedAction === false) { $this->outputLine(PHP_EOL . '<b>' . $controllerClassName . '</b>'); $foundUnprotectedAction = true; $allActionsAreProtected = false; } $this->outputLine(' ' . $methodName); } } if ($allActionsAreProtected === true) { $this->outputLine('All public controller actions are covered by your security policy. Good job!'); } }