previous up next index search
Previous: 4.5.18 Сетевая надежность    UP: 4.5 Процедуры Интернет
    Next: 4.5.20 Интернет вещей (IoT)

4.5.19 Протокол LDAP (Lightweight Directory Access Protocol)

Семенов Ю.А. (ИТЭФ-МФТИ)
Yu. Semenov (ITEP-MIPT)

Соглашения
Модель протокола
Взаимоотношение операций и уровня сообщений LDAP
Элементы протокола
Общие элементы
Конверт сообщения
MessageID
Типы строк
Уникальные и относительно уникальные имена
Описание атрибутов
Присвоение значения атрибуту
Идентификатор правила соответствия
Ссылки (referrals)
Контроли
Операция Bind
Обработка запроса Bind
Операция Unbind
Незапрошенное уведомление
Уведомление о разъединении
Операция поиска
Результат поиска
Операция Add
Операция Delete
Операция Modify DN
Операция сравнения
Операция Abandon
Расширенная операция
Сообщение IntermediateResponse
Протокол кодирования, соединения и передачи
Завершение LDAP-сессии
Соображения безопасности
Нормативные ссылки
Приложение

1. Введение

LDAP (Lightweight Directory Access Protocol) представляет собой Интернет-протокол доступа к распределенным службам каталогов, которые организованы в соответствии со стандартом X.500 (1993г). Допускаются и другие модели реализации службы каталогов (например, X.511). Каталог представляет собой "собрание открытых систем, взаимодействующих друг с другом для предоставления службы каталогов" [X.500]. Пользователь каталога, который может быть человеком или другим каким-то объектом, получает доступ к каталогу (Directory) через посредство клиента или DUA (Directory User Agent). Клиент взаимодействует с одним или более серверов или DSA (Directory System Agents). Клиенты взаимодействуют с серверами, используя протокол доступа к каталогу. Слово каталог (directory) используется здесь в значении упорядоченной структуры записей: например, телефонный каталог (справочник) представляет собой алфавитно упорядоченный список людей с их адресами и номерами телефонов в каждой из записей. Доступ к каталогам возможен по каналам TCP/IP через порт 389. Каталог представляет собой дерево каталожных записей (entries). Запись для каталога, то же самое что и запись или строка в случае базы данных. Каждая запись состоит из набора атрибутов. Атрибут имеет имя (тип атрибута или описание атрибута) и одно или более значений. Содержимое записей в субдереве управляется схемой, известной под именем DIT (Directory Information Tree). Атрибуты определяются в рамках этой схемы. Атрибут для каталога, тоже самое, что поле для базы данных. LDAP предоставляет стандартный язык, с помощью которого приложение клиента и каталог сервера взаимодействуют друг с другом по поводу данных в каталоге. LDAP-каталоги отличаются от реляционных баз данных. Данные в этом случае имеют иерархическую древовидную структуру, подобную большинству файловых систем.

Схема каталожного сервера определяет набор правил, которые управляют видами информации, которые сервер может хранить. Схема содержит ряд элементов, включая:

Атрибуты являются элементами, которые ответственны за запоминание информации в каталоге, а схема определяет правила, для которых могут использоваться атрибуты в записи, виды значений, которые эти атрибуты могут иметь, и как клиенты могут взаимодействовать с этими значениями.

Клиенты могут узнать об элементах схемы, которые поддерживает сервер, извлекая соответствующие субсхемы субзаписи.

Схема определяет классы объектов. Каждая запись должна иметь атрибут objectClass, содержащий именованные классы, определенные в схеме. Схемное определение классов записи определяет, какой вид объекта может представлять запись - например, персону, организацию или домен. Определения классов объектов определяет также список атрибутов, которые должны содержать значения и список атрибутов, которые могут содержать значения.

Например, запись, представляющая человека, может принадлежать классам "top" и "person". Членство в классе "person" требует от записи наличия атрибутов "sn" и "cn", и позволяет также записи содержать "userPassword", "telephoneNumber", и другие атрибуты. Так как записи могут иметь несколько значений ObjectClasses, каждая запись имеет совокупность опционных и обязательных наборов атрибутов, образованных путем объединения классов объекта, который они представляют. ObjectClasses может наследоваться, и одиночная запись может иметь несколько значений ObjectClasses, которые определяют доступные и необходимые атрибуты самой записи. Параллельно со схемой objectClass является определением класса и частным примером объектно-ориентированного программирования представляющего LDAP objectClass и LDAP-запись, соответственно.

Серверы каталогов могут опубликовать схему каталога, управляющую записью на уровне базового DN (Distinguished Name). DN так называется, из-за того что делает запись отличной от всех прочих записей. задаваемого операционным атрибутом subschemaSubentry. (Операционный атрибут описывает операцию каталога, а не пользовательскую информацию, и только он присылается при поиске, когда это явно запрошено).

Сервер LDAP может прислать ссылки на другие серверы для запросов, которые не может обслужить сам. Это требует именованной структуры LDAP-записей, так что можно найти сервер, хранящий данное DN. Другим способом локализации LDAP-серверов для организации является ресурсная запись DNS-сервера (SRV).

Организация с доменом example.org может использовать верхний уровень LDAP DN dc=example,dc=org (где dc означает компонент домена). Если LDAP-сервер имеет также имя ldap.example.org, верхним уровнем LDAP URL организации становится ldap://ldap.example.org/dc=example,dc=org.

Первоначально используются два стиля именования, как в X.500 [2008], так и в and LDAPv3, которые документированы в спецификациях ITU и IETF RFC. Исходная форма использует такие объекты верхнего уровня, как страны, например, c=US, c=FR. Модель доменных компонентов использует структуру, описанную выше. Примером именования с использованием национальной принадлежности может быть c=FR, o=некоторая организация, ou=некоторая организационная единица, L=Locality, или в США: c=US, st=CA, o=некоторая организация, ou=организационная единица, L=Locality и CN=общее имя (Common Name).

Смотри также LDAP Tutorial. Brad Marshall (добротное описание применения технологии LDAP) и LDAPSEARCH (руководство по использованию операций поиска в LDAP); LDAP Theory and Management. Brad Marshall.; LDAP Servers and Applications. Brad Marshall.

Каждая запись имеет уникальный идентификатор: его DN. Оно состоит из его RDN (Relative Distinguished Name), сформированного из некоторых атрибутов в виде массива, за которым следует DN родительской записи. DN следует рассматривать в качестве полного прохода к файлу, а RDN - относительный (напр. если C:\foo\bar\myfile.txt, является DN, тогда myfile.txt является RDN). LDAP представляет собой двоичный протокол.

Запись может выглядеть следующим образом (формат обмена данных LDAP = LDIF):

dn: uid=semenov, ou=People, dc=example,dc=com
cn: Yuri Semenov
sn: Semenov
givenname: Yuri
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
ou: Education
ou: People
mail: semenov@itep.rum
telephonenumber: 499 555 5642
roomnumber: 0205
userpassword: hifalutin

Команда для поиска данных при условии dc=example,dc=com для имени Yuri Semenov выглядит как:

$ ldapsearch -b dc=example,dc=com "(cn=Yuri Semenov)".

Если все работает, как положено, поиск выдаст следующий результат.

dn: uid=semenov, ou=People, dc=example,dc=com telephonenumber: 499 555 5642

"dn" уникальное имя записи; это не атрибут и не часть записи. "cn=John Doe" является RDN записи, а "dc=example,dc=com" представляет собой DN родительской записи, где "dc" обозначает 'Domain Component'. В других строках представлены атрибуты записи. Имена атрибутов обычно являются мнемоническими строками, например, "cn" common name (общее имя), "dc" - domain component (компонент домена), "mail" - e-mail адрес и "sn" - фамилия (surname). Иерархия имен-идентификаторов показана на рис. 1.

Рис. 1. Иерархия имен-идентификаторов в LDAP

Сервер хранит субдерево, которое начинается со специфической записи, напр. "dc=example,dc=com" и ее дочерние записи. Серверы могут также хранить ссылки на другие серверы, так что попытка получить доступ к "ou=department,dc=example,dc=com" может привести к получению ссылки на сервер, который содержит нужную часть дерева каталога. Клиент может тогда контактировать с другим сервером. Некоторые серверы могут поддерживать цепочные процедуры, когда сервер контактирует с другим сервером и присылает полученные там данные клиенту.

Ниже рассматривается версия 3 протокола LDAP (LDAPv3 - 1997г)). Описание протокола содержится в следующих документах:

  1. Вводное описание [RFC-4510]
  2. Протокол [RFC-4511]
  3. Информационные модели каталога [RFC-4512]
  4. Методы аутентификации и механизмы безопасности [RFC-4513]
  5. Представление строк выделенных имен [RFC-4514]
  6. Представление строк поисковых фильтров [RFC-4515]
  7. Универсальный ресурсный локатор (URL) [RFC-4516]
  8. Синтаксис и правила соответствия [RFC-4517]
  9. Интернационализированная подготовка строк [RFC-4518]
  10. Схема приложения пользователя [RFC-4519]

Данное описание является развитием ранее принятых норм каталожных сервисов, например RFC-3377, RFC-2830 или RFC-2251, которые считаются устаревшими. Далее следует перевод документа RFC-4511, за исключением приложения С в силу его ненормативности.

2. Соглашения

Названия символов в данном документе представляются в формате Unicode. Например, буква "a" представляется в виде <U+0061> или <LATIN SMALL LETTER A>.

Термин "транспортное соединение" относится нижележащим сервисам, обеспечивающим протокольный обмен.

Термин "уровень TLS" относится к сервисам безопасного транспортного уровня (TLS), используемым для реализации безопасности протокола.

Термин "уровень SASL" относится к уровню сервисов безопасности и аутентификации SASL, используемым для реализации безопасности протокола.

Термин "уровень сообщений LDAP" относится к сервисам протокола сообщений LDAP, обеспечивающим сервисы каталогов.

Термин "сессия LDAP" относится к комбинации сервисов (транспортное соединение, уровень TLS, уровень SASL, уровень сообщений LDAP).

3. Модель протокола

В общей модели, принятой данным протоколом, один из клиентов взаимодействует с одним из серверов. В этой модели, клиент передает протокольный запрос, описывающий операцию, которую должен выполнить сервер. Сервер отвечает за выполнение необходимых операций в каталоге. По завершении операции сервер обычно возвращает клиенту отклик, содержащий соответствующую информацию.

Протокольные операции независимы друг от друга. Каждая операция обрабатывается независимо, оставляя каталог в непротиворечивом состоянии.

Хотя серверы должны присылать отклики, всякий раз, когда такие отклики определяются в протоколе, не задается никаких требований синхронизации клиентов или серверов. Запросы и отклики при нескольких операциях между клиентом и сервером могут следовать в любом порядке. Если необходимо, синхронность поведения может контролироваться приложениями клиента. Базовые протокольные операции, рассмотренные в данном документе, могут быть поставлены в соответствие субнабору операций X.500.

Однако, не существует четкого соотношения между LDAP-операциями и операциями протокола X.500 доступа к каталогу DAP. LDAP является упрощенной версией DAP. Реализации сервера работают как шлюз по отношению к каталогам X.500 и может потребоваться несколько DAP-запросов, чтобы реализовать один запрос LDAP.

3.1. Взаимоотношение операций и уровня сообщений LDAP

Операционный протокольный обмен осуществляется на уровне обмена сообщениями LDAP. Когда транспортное соединение закрывается, любые незавершенные операции уровня LDAP-сообщений прекращаются (когда это возможно) или завершаются без передачи отклика (если прерывание невозможно). Когда транспортное соединение закрыто, клиент не должен полагать, что любая незавершенная операция обновления завершилась успешно или вообще не выполнена.

4. Элементы протокола

Протокол описан с использованием стандарта ASN.1 (Abstract Syntax Notation One) и базовых правил кодирования ([BER]).

В протоколе с самого начала предусмотрены механизмы будущих расширений.

Клиенты могут пытаться определить, какую протокольную версию поддерживает сервер, считывая атрибут 'supportedLDAPVersion' с корневой DSE (Distinguished Service Entry) [RFC4512].

4.1. Общие элементы

Ниже описывается формат протокольного поля данных конверта LDAPMessage, а также определения типов данных, которые используются в процессе реализации протокольных операций.

4.1.1. Конверт сообщения

Для целей протокольных обменов все протокольные операции вкладываются в общий конверт LDAPMessage, который определен следующим образом:

        LDAPMessage ::= SEQUENCE {
             messageID       MessageID,
             protocolOp      CHOICE {
                  bindRequest           BindRequest,
                  bindResponse          BindResponse,
                  unbindRequest         UnbindRequest,
                  searchRequest         SearchRequest,
                  searchResEntry        SearchResultEntry,
                  searchResDone         SearchResultDone,
                  searchResRef          SearchResultReference,
                  modifyRequest         ModifyRequest,
                  modifyResponse        ModifyResponse,
                  addRequest            AddRequest,
                  addResponse           AddResponse,
                  delRequest            DelRequest,
                  delResponse           DelResponse,
                  modDNRequest          ModifyDNRequest,
                  modDNResponse         ModifyDNResponse,
                  compareRequest        CompareRequest,
                  compareResponse       CompareResponse,
                  abandonRequest        AbandonRequest,
                  extendedReq           ExtendedRequest,
                  extendedResp          ExtendedResponse,
                  ...,
                  intermediateResponse  IntermediateResponse },
             controls       [0] Controls OPTIONAL }

        MessageID ::= INTEGER (0 ..  maxInt)

        maxInt INTEGER ::= 2147483647 -- (231 - 1) --

Функцией LDAPMessage является предоставление конверта, который содержит общие поля, необходимые для всех протокольных обменов. На данный момент единственными общими полями являются messageID и субполя управления.

Если сервер получает от клиента LDAPMessage, в котором метка последовательности LDAPMessage не может быть распознана, то messageID не может быть проанализирован, если метка protocolOp не воспринимается как запрос, или структура кодирования или длины полей данных не корректны, сервер должен прислать в ответ сообщения Notice или Disconnection рассмотренные в разделе 4.4.1, при этом resultCode должен быть равен protocolError, а сессия LDAP должна быть немедленно прервана.

В случаях, когда клиент или сервер не могут выполнить разбор LDAP PDU, сессия LDAP немедленно прерывается. В других случаях реализация сервера должна прислать соответствующий отклик с resultCode равным protocolError.

4.1.1.1. MessageID

Все конверты LDAPMessage откликов, содержат значение messageID, соответствующее LDAPMessage запроса.

МessageID запроса должен иметь ненулевое значение, отличное от messageID любого другого активного запроса в рамках текущей сессии LDAP. Нулевое значение зарезервировано для сообщений уведомления.

Клиент обычно инкрементирует счетчик при возникновении любого запроса.

Клиент не должен посылать запрос с тем же messageID, что и более ранний запрос той же самой сессии, если только он не уверен, что сервер уже не обслуживает этот более ранний запрос (напр., после получения финального отклика). В противном случае ситуация становится неоднозначной.

4.1.2. Типы строк

LDAPString является удобным обозначением того, что строка LDAPString-типа представлена в виде строки октетов ASN.1 символьного набора [ISO10646] (используется супернабор [Unicode] с кодировкой согласно алгоритма UTF-8 [RFC3629]). Заметим, что уникодные символы с U+0000 по U+007F совпадают с символами ASCII с 0 по 127, соответственно, и имеют идентичное октетное представление UTF-8. Другие уникодные символы имеют многооктетное представление UTF-8.

        LDAPString ::= OCTET STRING -- UTF-8 encoded,
                                    -- [ISO10646] символы

LDAPOID является удобным обозначением того, что разрешенным значением этой строки является (UTF-8 кодированное) десятично-точечное представление идентификатора объекта. Хотя LDAPOID кодируется как строка октетов, допустимыми значениями являются <numericoid>, описанные в разделе 1.4 [RFC4512].

        LDAPOID ::= OCTET STRING -- Содержит только <numericoid>
                                 -- [RFC4512]

Например,

1.3.6.1.4.1.1466.1.2.3

4.1.3. Уникальные и относительно уникальные имена

LDAPDN определено как уникальное имя DN (Distinguished Name), закодированное согласно спецификации [RFC4514].

        LDAPDN ::= LDAPString
                   -- Содержит только <distinguishedName> [RFC4514]

RelativeLDAPDN определено как относительно уникальное имя RDN (Relative Distinguished Name), закодированное согласно спецификации [RFC4514] .

        RelativeLDAPDN ::= LDAPString
                           -- Содержит только <name-component> [RFC4514]

4.1.4. Описание атрибутов

Определение и правила кодирования атрибута описаны в разделе 2.5 [RFC4512]. Коротко, описание атрибута представляет собой тип атрибута и нуль или более опций.

        AttributeDescription ::= LDAPString
                                -- Содержит только <attributedescription>
                                -- [RFC4512]

4.1.5. Значение атрибута

Поле типа AttributeValue является строкой октетов, содержащей значение атрибута. Значение атрибута кодируется согласно специфическому определению LDAP. Описание кодирования LDAP для различных синтаксисов и типов атрибутов содержится в [RFC4517].

AttributeValue ::= OCTET STRING

Заметим, что верхний предел для такого кодового представления не определен; таким образом, протокольные коды могут включать в себя многомегабайтные значения атрибутов (напр., фотографии).

Значения атрибутов могут иметь произвольный и непечатный синтаксис. Конкретные реализации не должны отображать или пытаться декодировать значение атрибута, если его синтаксис неизвестен. Реализация может попытаться выявить субсхему объекта и получить описание 'attributeTypes' из [RFC4512].

Клиенты должны только посылать в запросе значения атрибута, которые корректны с точки зрения синтаксиса, заданного для данного атрибута.

4.1.6. Присвоение значения атрибуту

Определение типа AttributeValueAssertion (AVA) выполняется в соответствии со стандартами X.500. Оно содержит описание атрибута и правило соответствия ([RFC4512], раздел 4.1.3) при присвоении значения согласно его типу.

        AttributeValueAssertion ::= SEQUENCE {
             attributeDesc   AttributeDescription,
             assertionValue  AssertionValue }
        AssertionValue ::= OCTET STRING

Синтаксис AssertionValue зависит от контекста выполняемой операции LDAP. Например, синтаксис правила соответствия EQUALITY для атрибута используется, когда выполняется операция Compare. Часто это тот же самый синтаксис, который используется для значений типов атрибутов, но в некоторых случаях синтаксис присвоения отличается от синтаксиса значений. Смотри, например, objectIdentiferFirstComponentMatch в [RFC4517].

4.1.7. Атрибут и PartialAttribute

Атрибуты и частичные атрибуты состоят из описаний атрибутов и их значений. Для PartialAttribute допустимо отсутствие значений, в то время как атрибуты требуют, по крайней мере, одного значения.

        PartialAttribute ::= SEQUENCE {
             type       AttributeDescription,
             vals       SET OF value AttributeValue }
        Attribute ::= PartialAttribute(WITH COMPONENTS {
             ...,
             vals (SIZE(1..MAX))})

В соответствии с описанием раздела 2.2 [RFC4512] никакие два значения атрибута не могут быть эквивалентны.

4.1.8. Идентификатор правила соответствия

Правила соответствия описаны в разделе 4.1.3 [RFC4512]. Правила соответствия задаются в протоколе посредством печатного представления либо его <numericoid>, либо одного его дескриптора короткого имени [RFC4512], напр., 'caseIgnoreMatch' или '2.5.13.2'.

MatchingRuleId ::= LDAPString

4.1.9. Сообщение результата

LDAPResult является структурным элементом, используемым в протоколе для того, чтобы сервер мог уведомить клиента об успехе или неудаче запроса. Для различных запросов серверы возвращают отклики, содержащие элементы, найденные в LDAPResult, чтобы индицировать конечное состояние протокольного запроса.

        LDAPResult ::= SEQUENCE {
             resultCode         ENUMERATED {
                  success                      (0),
                  operationsError              (1),
                  protocolError                (2),
                  timeLimitExceeded            (3),
                  sizeLimitExceeded            (4),
                  compareFalse                 (5),
                  compareTrue                  (6),
                  authMethodNotSupported       (7),
                  strongerAuthRequired         (8),
                       -- 9 зарезервировано --
                  referral                     (10),
                  adminLimitExceeded           (11),
                  unavailableCriticalExtension (12),
                  confidentialityRequired      (13),
                  saslBindInProgress           (14),
                  noSuchAttribute              (16),
                  undefinedAttributeType       (17),
                  inappropriateMatching        (18),
                  constraintViolation          (19),
                  attributeOrValueExists       (20),
                  invalidAttributeSyntax       (21),
                       -- 22-31 не используется --
                  noSuchObject                 (32),
                  aliasProblem                 (33),
                  invalidDNSyntax              (34),
                       -- 35 reserved for undefined isLeaf --
                  aliasDereferencingProblem    (36),
                       -- 37-47 не используется --
                  inappropriateAuthentication  (48),
                  invalidCredentials           (49),
                  insufficientAccessRights     (50),
                  busy                         (51),
                  unavailable                  (52),
                  unwillingToPerform           (53),
                  loopDetect                   (54),
                       -- 55-63 не используется --
                  namingViolation              (64),
                  objectClassViolation         (65),
                  notAllowedOnNonLeaf          (66),
                  notAllowedOnRDN              (67),
                  entryAlreadyExists           (68),
                  objectClassModsProhibited    (69),
                  -- 70 зарезервировано для CLDAP --
                  affectsMultipleDSAs          (71),
                    -- 72-79 не используется --
                  other                        (80),
                  ...  },
             matchedDN          LDAPDN,
             diagnosticMessage  LDAPString,
             referral           [3] Referral OPTIONAL }

Нумерация resultCode является гибкой, как это определено в разделе 3.8 [RFC4520]. Сообщения, соответствующие кодам результата, приведены в приложении A. Если сервер детектирует несколько ошибок для одной операции, возвращается только один результат. Сервер должен вернуть результирующий код, который наилучшим образом характеризует природу встретившейся ошибки.

Поле diagnosticMessage этого структурного элемента может, по выбору сервера, использоваться для возврата строки, содержащей текстовое, читаемое человеком диагностическое сообщение, которое дает данные, разъясняющие значение resultCode. Если сервер решит не использовать текстовое сообщение, diagnosticMessage должно быть пустым.

Для определенных кодов результата (обычно, но необязательно noSuchObject, aliasProblem, invalidDNSyntax и aliasDereferencingProblem), поле matchedDN делается равным (субъект управления доступом) имени последней записи (объекта или псевдонима). Это имя используется для выявления адресуемого объекта.

Это будет усеченной формой предоставления имени или, если псевдоним был разыменован в ходе локализации ввода, полученным в результате именем. В противном случае поле matchedDN должно быть пустым.

4.1.10. Ссылки (referrals)

Код результата со ссылкой указывает на то, что запрошенный сервер не может или не выполнит операцию, и что один или более других серверов могут его заменить. Среди причин этого:

Поле referral присутствует в LDAPResult, если код результата (resultCode) равен referral, и он отсутствует во всех остальных кодах результата.

Ссылки-Referrals в LDAP

Он содержит одну или более ссылок на один или более серверов или сервисов, которые осуществимы через LDAP или другие протоколы. Переадресации могут присылаться в откликах на запрос операции (за исключением Unbind и Abandon, которые не требуют откликов). В ReferralAt должен быть по крайней мере один URI.

Во время операции поиска (Search), после того как baseObject найден, а входные данные определены, отклик referral не возвращается. Вместо этого, присылаются ссылки продолжения, если для завершения операции нужно контактировать с другими серверами (см. раздел 4.5.3).

        Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
        URI ::= LDAPString     -- ограничено числом символов, разрешенных для -- URI

Если клиент хочет продолжить операцию, он контактирует с одним серверов, обнаруженных в ссылке (referral). Если присутствует несколько URI, клиент полагает, что для продолжения операции может использоваться любой поддерживаемый URI. Клиенты, которые следуют ссылкам referrals должны гарантировать, что они не сформируют цикл для серверов. Они не должны повторно контактировать с одним и тем же сервером при одном и том же запросе с одними и теми же параметрами. Некоторые клиенты используют счетчик, который инкрементируется каждый раз при использовании referral для каждой из операций, эти типы клиентов должны быть способны при выполнении операции работать, по крайней мере, с десятью вложенными ссылками.

URI для сервера, реализующий LDAP и доступный через TCP/IP (v4 или v6) [RFC793][RFC791], записывается как LDAP URL согласно [RFC4516].

Значения Referral, которые являются LDAP URLs следуют правилам:

Могут возвращаться все разновидности URI. Синтаксис и семантика таких URI оставлена для будущих спецификаций. Клиенты могут игнорировать URI, которые они не поддерживают.

Символы, закодированные в UTF-8, присутствующие в строке DN, поисковом фильтре или других полях значения referral, могут быть нелегальными для URI (напр., пробелы) и должны исключаться путем использования %-представления, описанного в [RFC3986].

4.1.11. Контроли

Controls обеспечивают механизм реализации расширения возможностей, там где семантика и существующие операции LDAP это позволяют. Один или более контролей могут быть добавлены к одному сообщению LDAP. Контроль влияет только на семантику сообщения, к которому он добавлен.

Контроли, посылаемые клиентом, называются контролями запроса, а посланные сервером - контролями отклика.

        Controls ::= SEQUENCE OF control Control

        Control ::= SEQUENCE {
             controlType             LDAPOID,
             criticality             BOOLEAN DEFAULT FALSE,
             controlValue            OCTET STRING OPTIONAL }

Поле controlType представляет собой десятично-точечное представление идентификатора объекта, который уникальным образом идентифицирует контроль. Это гарантирует однозначное именование контролей. Часто, контроли отклика, сопряженные с контролем запроса используют то же значение controlType, что и контроль запроса.

Поле критичности имеет смысл только в контролях, присоединенных к сообщениям запросов (за исключением UnbindRequest). Для контролей, присоединенных к сообщениям откликов и UnbindRequest, поле критичности должно иметь значение FALSE, и должно игнорироваться принимающей протокольной стороной. Значение TRUE означает, что оно неприемлемо для выполнения операции без использования семантики контроля. В частности поле критичности используется следующим образом:

controlValue может содержать информацию, сопряженную с controlType. Его формат определяется спецификацией контроля. Реализации должны быть готовы обрабатывать любые содержания октетной строки controlValue, включая нулевые байты. Оно отсутствует, только если отсутствует информация о значении, которая ассоциирована с контролем его типа.

Серверы предоставляют список контролей запросов controlType, которые они распознают, в атрибуте 'supportedControl' в корневом DSE (раздел 5.1 [RFC4512]).

Контроли не должны объединяться, если только не специфицирована семантика такого объединения. Когда встречается комбинация контролей, семантика которой некорректна, не специфицирована (или неизвестна), сообщение считается неверно сконфигурированным, операция терпит неудачу с protocolError. Контроли с критичностью равной FALSE могут игнорироваться.

Кроме того, если не специфицирована семантика, зависимая от порядка, порядок контролей в комбинации игнорируется (SEQUENCE). Там где порядок следует игнорировать, но сервер этого сделать не может, посылается сообщение о неверном формате, а операция терпит неудачу с кодом protocolError. Контроли с критичностью равной FALSE могут игнорироваться.

Контроли могут специфицироваться в других документах. Документы, определяющие расширения контролей, должны формироваться для каждого контроля отдельно:

4.2. Операция Bind

Функцией операции Bind является разрешение обмена аутентификационной информацией между клиентом и сервером. Операция Bind должна восприниматься как операция аутентификации. Семантика аутенификации и безопасности этой операции представлена в [RFC4513].

Запрос Bind определен следующим образом:

        BindRequest ::= [APPLICATION 0] SEQUENCE {
             version                 INTEGER (1 ..  127),
             name                    LDAPDN,
             authentication          AuthenticationChoice }

        AuthenticationChoice ::= CHOICE {
             simple                  [0] OCTET STRING,
                                     -- 1 и 2 reserved
             sasl                    [3] SaslCredentials,
             ...  }

        SaslCredentials ::= SEQUENCE {
             mechanism               LDAPString,
             credentials             OCTET STRING OPTIONAL }

Полями BindRequest являются:

Текстовые пароли (состоящие из символов определенного символьного набора и кодировки) передаваемые серверу с использованием простого AuthenticationChoice должны передаваться в виде UTF-8 [RFC3629] [Unicode]. Перед передачей клиенты должны подготовить текстовый пароль в виде строк запроса с привлечением профайла SASLprep [RFC4013] алгоритма [RFC3454]. Пароли, содержащие другие данные (такие как произвольные октеты) не должны модифицироваться. Определение того, является ли пароль текстовым, решается клиентом локально.

4.2.1. Обработка запроса Bind

Перед обработкой BindRequest, все незавершенные операции должны быть либо завершены, либо прерваны. Сервер может либо ждать завершения операций, либо прервать их. Сервер затем продолжает аутентифицировать клиента в одношаговом или многошаговом процессе Bind. Каждый шаг требует от сервера посылки BindResponse, чтобы отразить состояние аутентификации.

После посылки BindRequest, клиенты не должны посылать новые LDAP PDU до тех пор пока не получат BindResponse. Аналогично, серверы не должны обрабатывать или реагировать на запросы в ходе обработки BindRequest.

Если клиент не выполнил операцию bind перед посылкой запроса и получает operationsError, он может послать BindRequest. Если это также потерпит неудачу или клиент решит не осуществлять bind в ходе текущей LDAP-сессии, он может завершить сессию, заново ее перезапустить, и начать с посылки BindRequest. Это поможет взаимодействовать с серверами, работающими с другими версиями LDAP.

Клиенты могут послать несколько запросов Bind, чтобы изменить аутентификационные ассоциации и уровень безопасности или чтобы завершить многоэтапный процесс Bind. Аутентификации от предыдущих Bind при этом будут игнорироваться.

Для некоторых механизмов аутентификации SASL, может быть необходимо для клиента отправить BindRequest несколько раз ([RFC4513], раздел 5.2). Клиенты не должны запускать операции между двумя Bind-запросами, выполненными как часть многошагового Bind.

Клиент может абортировать согласование SASL-соединения путем посылки BindRequest с другим значением поля механизма SaslCredentials, или AuthenticationChoice.

Если клиент посылает BindRequest со значением поля sasl-мехнизм равным пустой строке, сервер должен прислать BindResponse со значением resultCode равным authMethodNotSupported. Это позволит клиенту абортировать согласование, если он хочет попытаться снова запустить тот же механизм SASL.

4.2.2. Отклик Bind

Отклик Bind определен следующим образом.

        BindResponse ::= [APPLICATION 1] SEQUENCE {
             COMPONENTS OF LDAPResult,
             serverSaslCreds    [7] OCTET STRING OPTIONAL }

BindResponse представляет собой индикацию сервером состояния запроса аутентификации клиента.

Успешная операция Bind индицируется откликом BindResponse с результирующим кодом resultCode, указывающим на успех. В противном случае соответствующий код результата устанавливается в BindResponse. Для BindResponse, может использоваться код результата protocolError, чтобы индицировать, что номер версии, использованный клиентом, не поддерживается.

Если клиент поучает BindResponse, где resultCode имеет значение protocolError, это предполагает, что сервер не поддерживает эту версию LDAP. В то время как клиент может быть способен продолжать работу с другой версией этого протокола (который может требовать или нет повторного установления транспортного соединения), механизмы реализации такой возможности в данном документе не рассматриваются. Клиенты, которые неспособны или не хотят продолжать операцию, должны завершить LDAP-сессию.

Поле ServerSaslCreds используется в качестве части механизма SASL bind, чтобы позволить клиенту аутентифицировать сервер, с которым он обменивается данными, или выполнить аутентификацию по схеме "запрос-отклик". Если клиент реализует соединение с простым выбором, или серверу не нужен механизм SASL для отправки данных клиенту, тогда это поле не следует включать в BindResponse.

4.3. Операция Unbind

Функцией операции Unbind является завершение сессии LDAP.

Операция Unbind не является противоположностью операции Bind, как это может показаться из названия. Названия этих операций являются историческими.

Операция Unbind следовало бы назвать "завершить" ("quit").

Операция Unbind определена как:

UnbindRequest ::= [APPLICATION 2] NULL

Клиент, после передачи UnbindRequest, и сервер после получения UnbindRequest, должны корректным образом прервать сессию LDAP, как это описано в разделе 5.3.

Незавершенные операции обрабатываются согласно спецификации раздела 3.1.

4.4. Незапрошенное уведомление

Незапрошенное уведомление представляет собой LDAPMessage, посланное сервером клиенту, которое не является откликом на какое-либо сообщение LDAPMessage, полученное сервером.

Эта операция используется для уведомления об экстраординарной ситуации в сервере или в ходе LDAP-сессии между клиентом и сервером.

Уведомление является по своей природе рекомендательным, и сервер не ожидает какой-либо реакции со стороны клиента.

Незапрошенное уведомление структурировано как LDAPMessage, в котором messageID равен нулю а протокольная операция соответствует выбору extendedResp, использующему тип ExtendedResponse (смотри раздел 4.12).

Поле responseName ExtendedResponse всегда содержит LDAPOID, который уникален для этого уведомления.

Одно незапрашиваемое уведомление (уведомление разъединения) описано в данном документе. Спецификация незатребованного уведомления состоит из:

4.4.1. Уведомление о разъединении

Это уведомление может использоваться сервером, чтобы предупредить клиента о намерении сервера завершить LDAP-сессию по своей инициативе.

Это уведомление предназначено для того, чтобы помочь клиентам отличить условия исключений сервера от отказов транспортного канала.

Заметим, что эта нотификация не является откликом на Unbind, запрошенный клиентом. Незавершенные операции обрабатываются в соответствии со спецификацией из раздела 3.1.

responseName имеет идентификатор 1.3.6.1.4.1.1466.20036, поле responseValue отсутствуетt, а resultCode используется для индикации причины разъединения.

Когда strongerAuthRequired возвращает resultCode с таким сообщением, это указывает, что сервер детектировал проблему с ассоциацией безопасности системы клиент-сервер.

После передачи сообщения Notice of Disconnection (нотификация разрыва связи), сервер завершает LDAP-сессию, как это описано в разделе 5.3.

4.5. Операция поиска

Операция Search используется для запроса сервера прислать набор объектов, отвечающих набору критериев поиска с учетом контроля доступа.

Это может использоваться для чтения атрибутов отдельного объекта, части или всего субдерева объектов.

4.5.1. Запрос поиска

Запрос поиска определен следующим образом:

        SearchRequest ::= [APPLICATION 3] SEQUENCE {
             baseObject      LDAPDN,
             scope           ENUMERATED {
                  baseObject              (0),
                  singleLevel             (1),
                  wholeSubtree            (2),
                  ...  },
             derefAliases    ENUMERATED {
                  neverDerefAliases       (0),
                  derefInSearching        (1),
                  derefFindingBaseObj     (2),
                  derefAlways             (3) },
             sizeLimit       INTEGER (0 ..  maxInt),
             timeLimit       INTEGER (0 ..  maxInt),
             typesOnly       BOOLEAN,
             filter          Filter,
             attributes      AttributeSelection }

        AttributeSelection ::= SEQUENCE OF selector LDAPString
                        -- The LDAPString is constrained to
                        -- <attributeSelector> in Section 4.5.1.8

        Filter ::= CHOICE {
             и             [0] SET SIZE (1..MAX) OF filter Filter,
             или              [1] SET SIZE (1..MAX) OF filter Filter,
             not             [2] Filter,

        equalityMatch   [3] AttributeValueAssertion,
             substrings      [4] SubstringFilter,
             greaterOrEqual  [5] AttributeValueAssertion,
             lessOrEqual     [6] AttributeValueAssertion,
             present         [7] AttributeDescription,
             approxMatch     [8] AttributeValueAssertion,
             extensibleMatch [9] MatchingRuleAssertion,
             ...  }

        SubstringFilter ::= SEQUENCE {
             type           AttributeDescription,
             substrings     SEQUENCE SIZE (1..MAX) OF substring CHOICE {
                  initial [0] AssertionValue,  -- can occur at most once
                  any     [1] AssertionValue,
                  final   [2] AssertionValue } -- can occur at most once
             }

        MatchingRuleAssertion ::= SEQUENCE {
             matchingRule    [1] MatchingRuleId OPTIONAL,
             type            [2] AttributeDescription OPTIONAL,
             matchValue      [3] AssertionValue,
             dnAttributes    [4] BOOLEAN DEFAULT FALSE }

Заметим, что операция списочного типа X.500 может быть эмулирована операцией поиска singleLevel с фильтром, проверяющим присутствие атрибута 'objectClass', а операция типа чтения может быть эмулирована операцией поиска baseObject с тем же фильтром. Серверу, который реализует шлюз к X.500, не обязательно использовать операции Read или List.

4.5.1.1. Базовый объект SearchRequest

Имя базового объекта (или возможно корневого) зависит от того, какой поиск должен быть реализован.

4.5.1.2. Зона SearchRequest

Специфицирует зону поиска. Семантика (как это описано в [X.511]) определенных значений этого поля выглядит следующим образом:

baseObject: Зона ограничена содержимым baseObject.

singleLevel: Зона ограничена непосредственно подчиненным объектом, на который указывает baseObject.

wholeSubtree: Зона ограничена объектом, указанным в baseObject и всеми его подчиненными объектами.

4.5.1.3. SearchRequest.derefAliases

Индикатор того, был ли псевдоним объекта (как это определено в [RFC4512]) разыменован на фазе операции Search.

Разыменование псевдонима включает в себя рекурсивную процедуру разыменования псевдонимов, которые ссылаются на псевдонимы.

Серверы должны детектировать зацикливание разыменований, для того чтобы исключить DoS-атаки такого типа.

Семантика определенных значений этого поля имеет вид:

neverDerefAliases: Не разыменовывать псевдонимы при поиске или при локализации базового объекта поиска.
derefInSearching: При поиске подчиненных объектов базового объекта, разыменовывать любые псевдонимы в пределах зоны поиска. Разыменованные объекты становятся вершинами последующих зон поиска, где также реализуется операция Search. Если зона поиска соответствует wholeSubtree, поиск продолжается в субдереве любого разыменованного объекта. Если зона поиска имеет singleLevel, поиск происходит во всех разыменованных объектах, но не касается их соподчиненных объектов.

Серверы должны исключать дублирующие объекты, которые возникают из-за разыменования при поиске.

derefFindingBaseObj:

Разыменовывать псевдонимы при выявлении базового объекта поиска, но не в случае поиска подчиненных объектов базового объекта.

derefAlways:

Разыменовывать псевдонимы, как при поиске, так и при локализации базового объекта поиска.

4.5.1.4. Предельный размер SearchRequest

Предельный размер, который ограничивает максимальное число объектов, возвращаемых в результате поиска. Значение нуль в поле указывает, что не существует какого-либо ограничения на число объектов при поиске со стороны клиента. Серверы могут также ввести ограничение на число возвращаемых объектов.

4.5.1.5. SearchRequest.timeLimit

Временной предел, который ограничивает максимальное время (в секундах) разрешенное для поиска. Значение нуль в этом поле указывает, что нет ограничений на время поиска со стороны клиента. Серверы также могут вводить ограничение на максимальное время поиска.

4.5.1.6. SearchRequest.typesOnly

Индикатор того, содержал ли результат поиска как описания так и значения атрибутов, или только описания атрибутов. Установка поля равным TRUE вызывает возврат только описаний атрибутов (а не величин). Установка поля равным FALSE требует возврата как описаний, так и значений атрибутов.

4.5.1.7. Фильтр SearchRequest

Фильтр, который определяет условия, которые должны быть выполнены при поиске для данного объекта.

При формировании фильтров могут использоваться операторы 'and', 'or' и 'not'. При использовании операторов 'and' или 'or' должен присутствовать, по крайней мере, один фильтрующий элемент.

Сервер должен оценивать фильтры согласно трехзначной логики [X.511] - "TRUE", "FALSE" или "Undefined".

Если фильтр получил TRUE для конкретного объекта, тогда атрибуты этого объекта посылаются в качестве результата поиска.

Если фильтр получил FALSE или Undefined, тогда объект при поиске игнорируется.

Значение фильтра для случая оператора "and" равно TRUE, если все фильтры набора выдали результат TRUE, и FALSE, если, по крайней мере, один фильтр выдал результат FALSE, в противном случае будет получен результат Undefined. Значение фильтра для случая оператора "or" равно FALSE, если все фильтры набора выдали результат FALSE, и TRUE, если хотя бы один фильтр выдал результат TRUE, в противном случае получается результат Undefined. Значение фильтра для случая оператора 'not' равно TRUE, если фильтр выдает результат FALSE.

Фильтр выдает результат Undefined, когда сервер не способен определить соответсвие объекта критериям отбора. В качестве примера можно предложить:

Например, если сервер не распознает тип атрибута shoeSize, abkmnhs (shoeSize=*), (shoeSize=12), (shoeSize>=12), и (shoeSize<=12) будет выдан результат Undefined.

Серверы не должны присылать сигналы ошибки, если описание атрибута или идентификаторы правил отбора нераспознаны, присваиваемые значения некорректны, или не поддерживается синтаксис присвоения.

4.5.1.7.1. SearchRequest.filter.equalityMatch

Правило отбора для фильтра equalityMatch определяется правилом EQUALITY для типа или субтипа атрибута. Фильтр выдает TRUE, когда правило EQUALITY возвращает TRUE для атрибута или субтипа и присвоенного значения.

4.5.1.7.2. SearchRequest.filter.substrings

В субстроках будет не более чем одна 'начальная' и не более чем одна 'оконечная' SubstringFilter. Если присутствует 'начальная', она будет первым элементом субстрок. Если присутствует 'оконечная', она будет последним элементом субстрок.

Правило отбора для AssertionValue в фильтре субстрок определяется правилом отбора SUBSTR для типа или субтипа атрибута.

Фильтр выдает TRUE, когда правило SUBSTR возвращает TRUE в отношении атрибута или субтипа и присвоенного значения.

4.5.1.7.3. SearchRequest.filter.greaterOrEqual

Правило отбора для фильтра greaterOrEqual определено правилом отбора ORDERING для типов или субтипов атрибутов. Фильтр выдает TRUE, когда правило ORDERING возвращает FALSE в отношении атрибута или субтипа и присвоенного значения.

4.5.1.7.4. SearchRequest.filter.lessOrEqual

Правило отбора для фильтра lessOrEqual определено правилами отбора ORDERING и EQUALITY для типа или субтипа атрибута. Фильтр выдает TRUE, когда либо правило ORDERING либо EQUALITY возвращают TRUE в отношении атрибута или субтипа и присвоенного значения.

4.5.1.7.5. SearchRequest.filter.present

Фильтр присутствия выдает TRUE, когда атрибут или субтип специфицированного описания атрибута присутствует в объекте, и FALSE, когда атрибут или субтип специфицированного описания атрибута отсутствует в объекте, и Undefined во всех остальных случаях.

4.5.1.7.6. SearchRequest.filter.approxMatch

Фильтр approxMatch выдает TRUE, когда присутствует значение типа или субтипа атрибута, для которого локально-заданный алгоритм проверки (напр., вариации спеллинга, фонетическое соответствие, и т.д.) выдает TRUE. Если аппрокимационная проверка не поддерживается для атрибута, этот фильтр следует рассматривать в качестве equalityMatch.

4.5.1.7.7. SearchRequest.filter.extensibleMatch

Поля фильтра extensibleMatch вычисляются следующим образом:

matchingRule, применяемое для оценки, использует синтаксис для присвоения значений. Раз matchingRule и атрибуты определены, фильтр выдает результат TRUE, если в записи имеет место соответствие, по крайней мере, по одному типу или субтипу атрибута, FALSE, если в записи нет соответствия ни одному типу и субтипу атрибута, и Undefined, если matchingRule не распознано, matchingRule не приемлемо для использования со специфицированным типом, или assertionValue некорректно.

4.5.1.8. Атрибуты SearchRequest

Выбор списка атрибутов, которые должны быть присланы для каждой записи, которая соответствует поисковому фильтру. Атрибуты, которые являются субтипами атрибутов из списка, включаются по умолчанию. Значения LDAPString этого поля ограничены следующими расширенными формами Бакуса-Наура (ABNF) [RFC4234]:

attributeSelector = attributedescription / selectorspecial
selectorspecial = noattrs / alluserattrs
noattrs = %x31.2E.31 ; "1.1"
alluserattrs = %x2A ; asterisk ("*")

Формирование описаний <attributedescription> определено в разделе 2.5 [RFC4512].

Существует три специальных случая, которые могут встретиться в списках атрибутов:

  1. Пустой список без атрибутов требует возврата всех атрибутов пользователя.
  2. Список, содержащий "*" (с нулем или более описаний атрибутов) требует возврата всех атрибутов пользователя в дополнение к другим атрибутам из списка.
  3. Список, содержащий только OID "1.1", указывает, что никаких атрибутов присылать не нужно. Если "1.1" выдано с другими значениями attributeSelector, "1.1" attributeSelector игнорируется. Этот OID был выбран, так как он не соответствует никакому используемому атрибуту.

Разработчикам клиентов следует учесть, что даже если запрошены все атрибуты пользователя, некоторые атрибуты и/или их значения для записи могут не быть включены в результат поиска из-за контролей доступа или других ограничений. Более того, серверы не вернут операционные атрибуты, такие как objectClasses или attributeTypes, если только они не перечислены по имени. Операционные атрибуты описаны в [RFC4512].

Атрибуты присылаются самое большее один раз на запись. Ели описание атрибута поименовано более одного раза, последующие упоминания игнорируются. Если описание атрибута в списке не распознано, сервер его игнорирует.

4.5.2. Результат поиска

Результаты операции поиска возвращаются в виде нуля или более сообщений SearchResultEntry и/или SearchResultReference, за которыми следует одно сообщение SearchResultDone.

        SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
             objectName      LDAPDN,
             attributes      PartialAttributeList }

        PartialAttributeList ::= SEQUENCE OF
                             partialAttribute PartialAttribute

        SearchResultReference ::= [APPLICATION 19] SEQUENCE
                                  size (1..MAX) OF uri URI

        SearchResultDone ::= [APPLICATION 5] LDAPResult

Каждое SearchResultEntry представляет собою запись, найденную в ходе поиска. Каждое SearchResultReference представляет собою область не охваченную пока поиском. Сообщения SearchResultEntry и SearchResultReference могут прийти в любом порядке. Вслед за всеми откликами SearchResultReference и SearchResultEntry, сервер присылает отклик SearchResultDone, который содержит индикацию успеха или подробности любых ошибок, которые случились.

Каждая запись, возвращенная в SearchResultEntry, будет содержать все соответствующие атрибуты, как это специфицировано в поле атрибутов запроса Search.

Заметим, что PartialAttributeList может не содержать никаких элементов.

Это может случиться, когда не было ни одного атрибута запрошено или не может быть прислано. Заметим также, что набор значений partialAttribute также может содержать нуль элементов. Это может случиться, когда запрошено typesOnly, а контроли доступа не позволяют возвращать значения.

Некоторые атрибуты могут формироваться сервером и появляться в списке атрибутов SearchResultEntry, хотя они не являются атрибутами, занесенными в запись. Клиенты не должны предполагать, что все атрибуты могут быть модифицированя, даже если это допускается контролями доступа.

Если схема клиента определяет для типа атрибута короткие имена [RFC4512], тогда сервер должен использовать одно из этих имен в описании атрибута для данного типа атрибута (предпочтительно используя формат идентификатора типа атрибута <numericoid> [RFC4512]). Сервер не должен использовать короткое имя, если это имя известно серверу как неопределенное, или если это может вызвать проблемы совместимости.

4.5.3. Ссылки продолжения в результате поиска

Если клиент был способен локализовать запись, на которую ссылается baseObject, но не смог или не захотел ее искать или записи не являются локальными, сервер может вернуть одно или более сообщений SearchResultReference, каждое из которых содержит ссылку на другой набор серверов для продолжения операции. Сервер не должен возвращать какое-либо сообщение SearchResultReference, если оно имеет нелокальный baseObject и, таким образом, не подвергался поиску. В этом случае будет возвращен SearchResultDone, содержащий либо ссылку (referral), либо результирующий код noSuchObject (в зависимости от знания сервером имени записи в baseObject).

Если сервер имеет копию или частичную копию соподчиненного контекста имен (раздел 5 [RFC4512]), он может использовать фильтр поиска, чтобы определить, следует или нет посылать отктик SearchResultReference. В противном случае отклики SearchResultReference всегда присылаются, если находятся в пределах зоны.

Тип данных SearchResultReference является тем же, что и у Referral.

Если клиент хочет продолжить поиск, он запускает новую операцию Search для каждого SearchResultReference, который прислан. Если присутствует несколько URI, клиент полагает, что для продолжения операции можно использовать любой поддерживаемый URI.

Клиенты, которые продолжают поиск, следуя ссылкам должны гарантировать, что они не вызовут зацикливание цепочки серверов. Они не должны повторно контактировать с одним и тем же сервером в рамках одного и того же запроса с теми же параметрами. Некоторые клиенты используют счетчик, который инкрементируется всякий раз, когда в процессе поиска обрабатывается ссылка, эти типы клиентов должны быть способны обрабатывать в процессе операции поиска по крайней мере десять вложенных ссылок.

Заметим, что операция Abandon (прекращение), описанная в разделе 4.11, допускается только при определенных операциях обмена между клиентом и сервером. Клиент должен индивидуально отменять последующие операции Search, если он хочет этого.

URI для сервера, реализующего LDAP и доступного через TCP/IP (v4 или v6) [RFC793][RFC791] записываются как LDAP URL в соответствии с [RFC4516].

Значения SearchResultReference, которые являются LDAP URL, должны следовать определенным правилам:

Могут присылаться и другие типы URI. Синтаксис и семантика таких URI будут рассмотрены позднее. Клиенты могут игнорировать URI, которые не поддерживают.

Символы с кодировкой UTF-8, встречающиеся в строке DN, поискового фильтра, или других полях строки referral могут быть нелегальными для URI (напр., пробелы) и должны быть заменены с привлечением %-метода [RFC3986].

4.5.3.1. Примеры

Например, пусть осуществляется контакт с сервером (hosta), который получил запись <DC=Example,DC=NET> и <CN=Manager,DC=Example,DC=NET>. Он знает, что два LDAP-сервера (hostb) и (hostc) содержат <OU=People,DC=Example,DC=NET> (один является основным, другой - теневым ), и что LDAP-сервер (hostd) содержит субдерево <OU=Roles,DC=Example,DC=NET>. Если контактному серверу запрошен поиск wholeSubtree <DC=Example,DC=NET>, он может прислать следующее:

     SearchResultEntry for DC=Example,DC=NET
     SearchResultEntry for CN=Manager,DC=Example,DC=NET
     SearchResultReference {
       ldap://hostb/OU=People,DC=Example,DC=NET??sub
       ldap://hostc/OU=People,DC=Example,DC=NET??sub }
     SearchResultReference {
       ldap://hostd/OU=Roles,DC=Example,DC=NET??sub }
     SearchResultDone (success)

Разработчики клиента должны помнить, что по завершении SearchResultReference, может быть сформирован дополнительный SearchResultReference. Продолжая пример, если клиент, подключенный к серверу (hostb), выдает запрос Search для субдерева <OU=People,DC=Example,DC=NET>, сервер может среагировать следующим образом:

     SearchResultEntry for OU=People,DC=Example,DC=NET
     SearchResultReference {
       ldap://hoste/OU=Managers,OU=People,DC=Example,DC=NET??sub }
     SearchResultReference {
       ldap://hostf/OU=Consultants,OU=People,DC=Example,DC=NET??sub }
     SearchResultDone (success)

Аналогично, если подключенному серверу запрошен поиск singleLevel <DC=Example,DC=NET>, он может прислать следующее:

     SearchResultEntry for CN=Manager,DC=Example,DC=NET
     SearchResultReference {
       ldap://hostb/OU=People,DC=Example,DC=NET??base
       ldap://hostc/OU=People,DC=Example,DC=NET??base }
     SearchResultReference {
       ldap://hostd/OU=Roles,DC=Example,DC=NET??base }
     SearchResultDone (success)

Если подключенный сервер не содержит базового объекта поиска, но он знает о возможном размещении нужных данных, тогда он может прислать клиенту ссылку (referral). В этом случае, если клиент запрашивает поиск для субдерева <DC=Example,DC=ORG> серверу hosta, сервер пришлет SearchResultDone, содержащий ссылку.

     SearchResultDone (referral) {
       ldap://hostg/DC=Example,DC=ORG??sub }

4.6. Результат поиска

Операция Modify позволяет клиенту запрашивать модификацию записи, которая должна быть выполнена сервером. Запрос Modify определен следующим образом:

        ModifyRequest ::= [APPLICATION 6] SEQUENCE {
             object          LDAPDN,
             changes         SEQUENCE OF change SEQUENCE {
                  operation       ENUMERATED {
                       add     (0),
                       delete  (1),
                       replace (2),
                       ...  },
                  modification    PartialAttribute } }

Полями запроса Modify являются:

В то время как отдельные модификации могут нарушать определенные аспекты схемы каталогов (такие как определения классов объектов и правило содержимого для DIT (Directory Information Tree)), результирующая запись после полного списка модификаций, которые нужно выполнить, должна соответствовать требованиям каталожной модели и схеме управления [RFC4512].

Значение этого поля имеет следующую семантику:

add: Добавить значения, перечисленные в атрибуте модификации, создавая атрибут, если это необходимо.

delete: Уничтожает значения, перечисленные в атрибуте модификации. Если список пуст, или если все текущие значения атрибута содержатся в списке, удаляется весь атрибут.

relace: Замещает все существующие значения атрибута модификации новыми значениями из списка, создавая атрибут, если его не было. Замещение при отсутствии нового значения приводит к ликвидации атрибута, если он существовал, и команда игнорируется, если атрибута не было.

После получения запроса Modify, сервер пытается выполнить необходимые модификации в DIT и прислать результат в отклике Modify, определенном как:

ModifyResponse ::= [APPLICATION 7] LDAPResult

Сервер пришлет клиенту один отклик Modify, указывающий на успешное завершение модификации DIT, или причину, по которой операция модификации не выполнена. Из-за требования атомарности при использовании списка модификаций в запросах Modify, клиент может ожидать, что никаких модификаций DIT не было выполнено, если полученный отклик Modify указывает на какую-либо ошибку, и что все запрошенные модификации были выполнены, если отклик Modify Response свидетельствует об успешном завершении операции Modify. Произведена ли модификация или нет, клиент не может узнать, если не получен отклик Modify (напр. , сессия LDAP была завершена или операция Modify прервана).

Серверы должны гарантировать, что записи адаптированы для пользователя, для правил схемы системы или для других ограничений модели данных. Операция Modify не может быть использована для удаления из записи любых существенных данных, т.e., таких значений, которые образуют относительное DN записи. Попытка сделать это приведет к тому, что сервер вернет результирующий код notAllowedOnRDN. Операция Modify DN, описанная в разделе 4.9, используется для переименования записи.

Для типов атрибутов, которые не специфицируют соответствия равенства, правила описаны в разделе 2.5.1 [RFC4512].

Заметим, что благодаря упрощениям выполненным в LDAP, здесь нет прямого соответствия изменений в LDAP ModifyRequest и изменений в операции DAP ModifyEntry.

4.7. Операция Add

Операция Add позволяет клиенту запросить добавление записи в каталог (Directory). Запрос Add определен следующим образом:

        AddRequest ::= [APPLICATION 8] SEQUENCE {
             entry           LDAPDN,
             attributes      AttributeList }

        AttributeList ::= SEQUENCE OF attribute Attribute

Полями запроса Add являются: