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\Asn1\Exception\EncoderException;
15use FreeDSx\Ldap\Operation\LdapResult;
16use FreeDSx\Ldap\Operation\Request\ExtendedRequest;
17use FreeDSx\Ldap\Operation\Response\ExtendedResponse;
18use FreeDSx\Ldap\Operation\ResultCode;
19use FreeDSx\Ldap\Protocol\LdapMessageRequest;
20use FreeDSx\Ldap\Protocol\LdapMessageResponse;
21use FreeDSx\Ldap\Protocol\Queue\ServerQueue;
22use FreeDSx\Ldap\Server\RequestHandler\RequestHandlerInterface;
23use FreeDSx\Ldap\Server\Token\TokenInterface;
24use FreeDSx\Socket\Exception\ConnectionException;
25use function extension_loaded;
26
27/**
28 * Handles StartTLS logic.
29 *
30 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
31 */
32class ServerStartTlsHandler implements ServerProtocolHandlerInterface
33{
34    /**
35     * @var bool
36     */
37    protected static $hasOpenssl;
38
39    public function __construct()
40    {
41        if (self::$hasOpenssl === null) {
42            $this::$hasOpenssl = extension_loaded('openssl');
43        }
44    }
45
46    /**
47     * @param LdapMessageRequest $message
48     * @param TokenInterface $token
49     * @param RequestHandlerInterface $dispatcher
50     * @param ServerQueue $queue
51     * @param array $options
52     * @throws ConnectionException
53     * @throws EncoderException
54     */
55    public function handleRequest(LdapMessageRequest $message, TokenInterface $token, RequestHandlerInterface $dispatcher, ServerQueue $queue, array $options): void
56    {
57        # If we don't have a SSL cert or the OpenSSL extension is not available, then we can do nothing...
58        if (!isset($options['ssl_cert']) || !self::$hasOpenssl) {
59            $queue->sendMessage(new LdapMessageResponse($message->getMessageId(), new ExtendedResponse(
60                new LdapResult(ResultCode::PROTOCOL_ERROR),
61                ExtendedRequest::OID_START_TLS
62            )));
63
64            return;
65        }
66        # If we are already encrypted, then consider this an operations error...
67        if ($queue->isEncrypted()) {
68            $queue->sendMessage(new LdapMessageResponse($message->getMessageId(), new ExtendedResponse(
69                new LdapResult(ResultCode::OPERATIONS_ERROR, '', 'The current LDAP session is already encrypted.'),
70                ExtendedRequest::OID_START_TLS
71            )));
72
73            return;
74        }
75
76        $queue->sendMessage(new LdapMessageResponse($message->getMessageId(), new ExtendedResponse(
77            new LdapResult(ResultCode::SUCCESS),
78            ExtendedRequest::OID_START_TLS
79        )));
80        $queue->encrypt();
81    }
82}
83