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\Entry\Entry; 14use FreeDSx\Ldap\Operation\Request\ExtendedRequest; 15use FreeDSx\Ldap\Operation\Request\SearchRequest; 16use FreeDSx\Ldap\Operation\Response\SearchResultDone; 17use FreeDSx\Ldap\Operation\Response\SearchResultEntry; 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\RequestContext; 23use FreeDSx\Ldap\Server\RequestHandler\RequestHandlerInterface; 24use FreeDSx\Ldap\Server\RequestHandler\RootDseHandlerInterface; 25use FreeDSx\Ldap\Server\Token\TokenInterface; 26 27/** 28 * Handles RootDSE based search requests. 29 * 30 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 31 */ 32class ServerRootDseHandler implements ServerProtocolHandlerInterface 33{ 34 /** 35 * {@inheritDoc} 36 */ 37 public function handleRequest(LdapMessageRequest $message, TokenInterface $token, RequestHandlerInterface $dispatcher, ServerQueue $queue, array $options): void 38 { 39 $entry = Entry::fromArray('', [ 40 'namingContexts' => $options['dse_naming_contexts'] ?? '', 41 'supportedExtension' => [ 42 ExtendedRequest::OID_WHOAMI, 43 ], 44 'supportedLDAPVersion' => ['3'], 45 'vendorName' => $options['dse_vendor_name'] ?? '', 46 ]); 47 if (isset($options['ssl_cert'])) { 48 $entry->set('supportedExtension', ExtendedRequest::OID_START_TLS); 49 } 50 if (isset($options['vendor_version'])) { 51 $entry->set('vendorVersion', $options['vendor_version']); 52 } 53 if (isset($options['alt_server'])) { 54 $entry->set('altServer', $options['alt_server']); 55 } 56 57 /** @var SearchRequest $request */ 58 $request = $message->getRequest(); 59 $this->filterEntryAttributes($request, $entry); 60 61 if ($dispatcher instanceof RootDseHandlerInterface) { 62 $entry = $dispatcher->rootDse( 63 new RequestContext($message->controls(), $token), 64 $request, 65 $entry 66 ); 67 } 68 69 $queue->sendMessage( 70 new LdapMessageResponse( 71 $message->getMessageId(), 72 new SearchResultEntry($entry) 73 ), 74 new LdapMessageResponse( 75 $message->getMessageId(), 76 new SearchResultDone(ResultCode::SUCCESS) 77 ) 78 ); 79 } 80 81 /** 82 * Filters attributes from an entry to return only what was requested. 83 */ 84 protected function filterEntryAttributes(SearchRequest $request, Entry $entry): void 85 { 86 if (\count($request->getAttributes()) !== 0) { 87 foreach ($entry->getAttributes() as $dseAttr) { 88 $found = false; 89 foreach ($request->getAttributes() as $attribute) { 90 if ($attribute->equals($dseAttr)) { 91 $found = true; 92 break; 93 } 94 } 95 if ($found === true && $request->getAttributesOnly()) { 96 $dseAttr->reset(); 97 } 98 if ($found === false) { 99 $entry->reset($dseAttr); 100 $entry->changes()->reset(); 101 } 102 } 103 } 104 if ($request->getAttributesOnly()) { 105 foreach ($entry->getAttributes() as $attribute) { 106 $attribute->reset(); 107 } 108 } 109 } 110} 111