* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace FreeDSx\Ldap\Protocol; use FreeDSx\Ldap\Operation\Request\AnonBindRequest; use FreeDSx\Ldap\Operation\Request\BindRequest; use FreeDSx\Ldap\Operation\Request\ExtendedRequest; use FreeDSx\Ldap\Operation\Request\RequestInterface; use FreeDSx\Ldap\Operation\Request\SearchRequest; use FreeDSx\Ldap\Operation\Request\SimpleBindRequest; use FreeDSx\Ldap\Operation\Request\UnbindRequest; use FreeDSx\Ldap\Server\Token\AnonToken; use FreeDSx\Ldap\Server\Token\BindToken; use FreeDSx\Ldap\Server\Token\TokenInterface; /** * Abstracts out some of the server authorization logic. * * @author Chad Sikorra */ class ServerAuthorization { /** * @var bool */ protected $isAuthRequired; /** * @var bool */ protected $isAnonymousAllowed; /** * @var TokenInterface */ protected $token; public function __construct(TokenInterface $token = null, array $options = []) { $this->token = $token ?? new AnonToken(); $this->isAuthRequired = isset($options['require_authentication']) ? (bool) $options['require_authentication'] : true; $this->isAnonymousAllowed = isset($options['allow_anonymous']) ? (bool) $options['allow_anonymous'] : false; } /** * Helps determine if a specific request type actually requires authentication to complete. * * @param RequestInterface $request * @return bool */ public function isAuthenticationRequired(RequestInterface $request): bool { if ($this->isAuthRequired === false) { return false; } if ($request instanceof ExtendedRequest && $request->getName() === ExtendedRequest::OID_WHOAMI) { return false; } elseif ($request instanceof ExtendedRequest && $request->getName() === ExtendedRequest::OID_START_TLS) { return false; } elseif ($request instanceof UnbindRequest) { return false; } elseif ($request instanceof BindRequest) { return false; } elseif ($this->isRootDseSearch($request)) { return false; } return true; } /** * Determine if the bind type is actually supported. Anonymous binding may be disabled. */ public function isAuthenticationTypeSupported(RequestInterface $request): bool { if ($request instanceof AnonBindRequest) { return $this->isAnonymousAllowed; } return $request instanceof SimpleBindRequest; } /** * Determine if the incoming request is an authentication attempt. */ public function isAuthenticationRequest(RequestInterface $request): bool { return $request instanceof BindRequest; } /** * Determine if the current token is "authenticated". In the case where authentication is not required, we always * return true. */ public function isAuthenticated(): bool { if ($this->isAuthRequired === false) { return true; } return $this->token instanceof BindToken; } /** * Set the current token. */ public function setToken(TokenInterface $token): void { $this->token = $token; } /** * Get the current token. */ public function getToken(): TokenInterface { return $this->token; } /** * @param RequestInterface $request * @return bool */ protected function isRootDseSearch(RequestInterface $request): bool { if (!$request instanceof SearchRequest) { return false; } return $request->getScope() === SearchRequest::SCOPE_BASE_OBJECT && ((string) $request->getBaseDn() === ''); } }