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