1<?php
2/**
3 * This file is part of the FreeDSx LDAP package.
4 *
5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace FreeDSx\Ldap\Protocol\ServerProtocolHandler;
12
13use FreeDSx\Ldap\Exception\OperationException;
14use FreeDSx\Ldap\Exception\RuntimeException;
15use FreeDSx\Ldap\Operation\Request\BindRequest;
16use FreeDSx\Ldap\Operation\Request\SimpleBindRequest;
17use FreeDSx\Ldap\Operation\ResultCode;
18use FreeDSx\Ldap\Protocol\LdapMessageRequest;
19use FreeDSx\Ldap\Protocol\Queue\ServerQueue;
20use FreeDSx\Ldap\Server\RequestHandler\RequestHandlerInterface;
21use FreeDSx\Ldap\Server\Token\BindToken;
22use FreeDSx\Ldap\Server\Token\TokenInterface;
23
24/**
25 * Handles a simple bind request.
26 *
27 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
28 */
29class ServerBindHandler extends BaseServerHandler implements BindHandlerInterface
30{
31    /**
32     * {@inheritDoc}
33     */
34    public function handleBind(LdapMessageRequest $message, RequestHandlerInterface $dispatcher, ServerQueue $queue, array $options): TokenInterface
35    {
36        /** @var BindRequest $request */
37        $request = $message->getRequest();
38        if (!$request instanceof SimpleBindRequest) {
39            throw new RuntimeException(sprintf(
40                'Expected a SimpleBindRequest, got: %s',
41                get_class($request)
42            ));
43        }
44
45        $this->validateVersion($request);
46        $token = $this->simpleBind($dispatcher, $request);
47        $queue->sendMessage($this->responseFactory->getStandardResponse($message));
48
49        return $token;
50    }
51
52    /**
53     * @throws OperationException
54     */
55    protected function simpleBind(RequestHandlerInterface $dispatcher, SimpleBindRequest $request): TokenInterface
56    {
57        if (!$dispatcher->bind($request->getUsername(), $request->getPassword())) {
58            throw new OperationException(
59                'Invalid credentials.',
60                ResultCode::INVALID_CREDENTIALS
61            );
62        }
63
64        return new BindToken($request->getUsername(), $request->getPassword());
65    }
66
67    /**
68     * @throws OperationException
69     */
70    protected function validateVersion(BindRequest $request): void
71    {
72        # Per RFC 4.2, a result code of protocol error must be sent back for unsupported versions.
73        if ($request->getVersion() !== 3) {
74            throw new OperationException(
75                'Only LDAP version 3 is supported.',
76                ResultCode::PROTOCOL_ERROR
77            );
78        }
79    }
80}
81