previous up next index search
Previous: 4.5.15.1 Обмен сообщениями в реальном масштабе времени    UP: 4.5.15 Диалог в локальных сетях и в Интернет
    Next: 4.5.15.3 ICQ

4.5.15.2 Расширяемый протокол обмена сообщениями и данными о присутствии (XMPP): Ядро

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

RFC-3920

ОбзорОбобщенная архитектура
СерверКлиент
ШлюзСеть
Схема адресацииИдентификатор домена
Идентификатор узлаИдентификатор ресурса
Определение адресаXML потоки
Связь с TCPБезопасность потока
Атрибуты потокаПоддержка версии
Декларации пространства именХарактеристики потока
Ошибки потокаПравила
СинтаксисОпределенные условия
Специфические для приложения условияУпрощенные примеры потоков
Использование TLSИдентификатор объекта ASN.1 для XMPP-адреса
ДиалогПример клиент-сервер
Пример сервер-серверИспользование SASL
Определение SASLОшибки SASL
Пример клиент-серверПример сервер-сервер
Подключение ресурсовМетод сервера Dialback ("обратный дозвон")
Порядок событийПротокол
XML-строфыОбщие атрибуты
xml:langБазовая семантика. Семантика сообщений
Семантика присутствияСемантика IQ
Ошибки строфПравила
СинтаксисОпределенные условия
Условия специфические для приложенияПравила сервера для обработки XML-строф
Нет адреса 'to'Чужой домен
СубдоменПолный домен или специфические ресурсы
Узел в том же доменеИспользование XML в XMPP. Ограничения
Имена XML-пространства имен и префиксовПространство имен потоков
Пространство имен по умолчаниюПространство имен Dialback
ВалидацияВключение текстовых деклараций
Кодирование символовОсновные требования совместимости
СерверыКлиенты
Соображения интернационализацииСоображения безопасности
Валидация сертификатовКоммуникации клиент-сервер
Коммуникации сервер-серверПорядок слоев
Необходимость SASL для подключения канала к TLSОбязательные для использования технологии
FirewallsИспользование кодирования base64 в SASL
Профайлы StringprepИмя XML-пространства имен для данных SASL
Имя XML-пространства имен для ошибок потокаИмя XML-пространства имен для подключения ресурсов
Имя XML-пространства имен для ошибок строфNodeprep-профайл Stringprep
Профайл Resourceprep из StringprepИмя сервиса GSSAPI
Номера портовСсылки
Приложение A. NodeprepПриложение B. Resourceprep
Приложение C. XML-схемы 

1. Обзор

Расширяемый протокол обмена сообщениями и данными о присутствии XMPP (Extensible Messaging and Presence Protocol) является открытым протоколом, использующими XML (Extensible Markup Language [1]) для сервисов обмена сообщениями в режиме близком к реальному времени, данными о присутствии, запросами/откликами. Базовый синтаксис и семантика были разработаны первоначально в 1999 году сообществом разработчиков системы Jabber с общедоступным кодом. В 2002 рабочая группа XMPP занялась адаптацией протокола Jabber, который должен стать основой технологии обмена сообщениями в реальном масштабе времени (IM) и данными о присутствии сообщества IETF. Результатом работы группы XMPP стал данный документ, который определяет базовые черты XMPP 1.0; расширения, необходимые для реализации обмена сообщениями и данными о присутствии в реальном масштабе времени, определены в RFC-2779 [2] и специфицированы в протоколе XMPP: передача сообщений и данных о присутствии в реальном масштабе времени [3].

2. Обобщенная архитектура

Хотя XMPP не привязан к какой-то определенной сетевой архитектуре, реализация сессии осуществляется по схеме клиент-сервер, где клиент реализует подключение к серверу с помощью [13] TCP-транспорта, и сами серверы взаимодействуют друг с другом также, используя протокол ТСР.

На рисунке ниже представлена схема высокоуровневой архитектуры подобной сессии (красным цветом выделены коммуникации, использующие какой-либо другой протокол).

Рис. 1. XMPP-архитектура

Символы на рисунке имеют следующие значения:

Сервер

Сервер ответственен за:

Большинство XMPP-совместимых серверов осуществляют также запоминание данных, которые используются клиентами (например, список контактов для пользователей системы обмена сообщениями и данными о присутствии с помощью XMPP); в этом случае, XML-данные обрабатываются непосредственно сервером для клиента, а не переадресуются другому объекту.

Клиент

Большинство клиентов подключается непосредственно к серверу посредством TCP и используют XMPP для получения полной функциональности, доступной на сервере. Для каждого авторизованного клиента к серверу могут одновременно подключаться несколько ресурсов (например, устройств или позиций). Каждый ресурс характеризуется идентификатором XMPP-адреса (например, <node@domain/home> или <node@domain/work>), как это определено схемой адресации (раздел 3). Рекомендованным номером порта для соединения клиента с сервером является 5222, как это фиксировано IANA (смотри "Номера портов" (раздел 15)).

Шлюз

Шлюз является специальной функцией сервера, задача которой заключается в трансляции протокола XMPP для внешних систем обмена сообщениями, которые не поддерживают XMPP, а также преобразовании данных, поступающих из удаленных сетей, не поддерживающих XMPP. Примерами могут служить шлюзы для электронной почты (смотри [4]), IRC (Internet Relay Chat, смотри [5]), SIMPLE (смотри [6]), SMS (Short Message Service), а также сервисы типа AIM, ICQ, MSN Messenger или Yahoo! Instant Messenger.

Сеть

Так как каждый сервер идентифицируется сетевым адресом и так как коммуникации сервер-сервер являются простым расширение протокола клиент-сервер, на практике система представляет собой сеть серверов, которые взаимодействуют друг с другом. Таким образом, например, <juliet@example.com> может обмениваться сообщениями и данными о присутствии, а также другой информацией с <romeo@example.net>. Эта схема подобна протоколам обмена сообщениями (таким как [4]), которые используют стандарты сетевой адресации. Коммуникации между любыми двумя серверами являются опционными. Если они разрешены, такие коммуникации должны осуществляться посредством XML-потоков, которые сопряжены с TCP-соединениями. Рекомендуемым номером порта для соединения серверов является 5269 (смотри главу "Номера портов" (раздел 15)).

3. Схема адресации

Объектом считается нечто, что может рассматриваться, как конечная точка сети (т.е., ID для сети) и что может осуществлять обмен с использованием XMPP. Все такие объекты являются уникально адресуемыми в формате, совместимом с RFC 2396 [7]. По историческим причинам адрес XMPP-объекта называется идентификатором Jabber или JID. JID содержит набор элементов, образующих доменный идентификатор, идентификатор узла или ресурса.

Синтаксис JID описан ниже в формализме Бакуса-Наура, определенном в [8].

jid = [ узел "@" ] домен [ "/" ресурс ]
domain= fqdn / адрес-литерал
fqdn= (субдомен 1*("." субдомен))
sub-domain= (международная метка домена)
address-literal= IPv4-адрес / IPv6-адрес

Все JID базируются на следующей структуре. Наиболее общим использованием этой структуры является идентификация пользователя системы обмена сообщениями, сервера, к которому пользователь подключается и используемых ресурсов в форме <user@host/resource>. однако, возможны типы узлов, отличные от клиентов; например, специальная комната для разговоров, предлагаемая многопользовательским сервисом, может адресоваться как <room@service> (где "room" является именем chat room, а "service" имя машины, предлагающей этот вид сервиса. Определенный участник такой беседы может адресоваться как <room@service/nick> (где "nick" - имя/прозвище участника такой сессии). Возможно много других типов JID (например, <domain/resource> может быть скриптом или сервисом на стороне сервера).

Каждая из возможных частей JID (идентификаторы узла, домена и ресурса) не должны содержать более 1023 байт, что устанавливает максимальный размер, включая символы '@' и '/', равный 3071 байту.

Идентификатор домена

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

Идентификатором домена для каждого сервера или сервиса, который будет обмениваться данными через сеть, может быть IP-адрес, но он должен обязательно соответствовать имени домена. Идентификатор домена должен иметь международное доменное имя, как это определено в [10]. Прежде чем сравнивать два идентификатора доменов сервер должен (также как и клиент) использовать профайл Nameprep для меток (как это задано в [10]).

Идентификатор узла

Идентификатор узла является опционным вторичным идентификатором, размещаемым перед доменным идентификатором, и отделяемым от него символом '@'. Он обычно представляет собой объект, запрашивающий и использующий доступ к сети, предоставляемый сервером или шлюзом (т.е., клиент). Хотя он может представлять собой и другой объект. Объект, представляемый идентификатором узла адресуется в рамках контекста конкретного домена; для задач обмена сообщениями и данными о присутствии приложений XMPP, этот адрес называется "чистым JID" и имеет вид <node@domain>.

Идентификатор узла должен быть сформатирован так, чтобы можно было использовать профайл Nodeprep [11]. Прежде чем сравнивать два идентификатора узлов, сервер должен сначала использовать профайл Nodeprep для каждого идентификатора.

Идентификатор ресурса

Идентификатор ресурса является опционным третичным идентификатором, размещаемым после идентификатора домена и отделенным от последнего символом '/'. Идентификатор ресурса может варьироваться от <node@domain> до <domain>. Он обычно представляет определенную сессию, соединение, например, устройство или положение), или объект (например, участник многопользовательского обмена сообщениями), принадлежащее сущности, ассоциированной с идентификатором узла. Идентификатор ресурса не прозрачен для сервера и других клиентов, и обычно определяется реализацией клиента, когда он выдает информацию, нужную для завершения подключения ресурса (Resource Binding, раздел 7). Объект может содержать несколько подключенных ресурсов. Каждый подключенный ресурс имеет свой идентификатор.

Идентификатор ресурса должен быть сформирован так, чтобы было можно применить профайл Resourceprep [11]. Прежде чем сравнивать два идентификатора ресурсов, сервер должен сначала использовать профайл Resourceprep для каждого идентификатора.

Определение адреса

После согласования SASL (раздел 6) и, если нужно, подключения ресурсов (раздел 7), принимающий объект должен определить начальное значение JID.

Для обменов сервер-сервер, начальное значение JID должно определять авторизационную идентичность, как это определено спецификацией уровня безопасности и простой аутентификации SASL (Simple Authentication and Security Layer) [12] (раздел 6).

Для коммуникаций клиент-клиент "чистый JID" (<node@domain>) должен определять авторизационную идентичность, как это определено спецификацией [12], (раздел 6). Секция идентификатора ресурса "чистого JID" (<node@domain/resource>) должна быть ресурсным идентификатором, согласованным клиентом и сервером при подключении ресурса (раздел 7).

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

4. XML потоки

Два фундаментальных принципа делают возможным быстрый асинхронный обмен при сравнительно небольшом поле данных: XML-потоки и XML-строфы (stanzas). Эти термины определяются следующим образом:

Определение XML-потока: XML-поток является контейнером для обмена XML-элементами между объектами через сеть. Начало XML-потока однозначно определяется открывающим XML-тэгом <stream> (с декларацией соответствующих атрибутов названий позиций), в то время как конец XML-потока однозначно определяется закрывающим XML-тэгом </stream>. Во время существования потока, объект его инициировавший, может посылать произвольное число XML-элементов, либо элементов, используемых для согласования параметров потока (например, для согласования использования TLS (раздел 5), либо использования SASL (раздел 6)), либо XML-строф (как это определяется, <message/>, <presence/> или <iq/>). "Исходный поток" согласуется инициатором сессии (обычно клиентом или сервером) с принимающим объектом (обычно сервером). Исходный поток обеспечивает однонаправленную коммуникацию между инициатором и получателем; для того чтобы разрешить информационный обмен от принимающей стороны к инициатору, приемник должен согласовать поток в обратном направлении ("поток-отклик").

Определение XML строфы: XML-строфа является дискретным семантическим блоком структурированной информации, который посылается одним объектом другому объекту через XML-поток. XML-строфа является дочерним элементом по отношению элементу <stream/>. Начало любой XML-строфа однозначно определяется стартовым тэгом XML-потока (depth=1) (например, <presence>), а конец любой XML-строфы однозначно задается закрывающим тэгом (например, </presence>). XML-строфа может содержать дочерние элементы (сопроводительные атрибуты и XML-символы). Единственными видами XML-строф, определенными здесь, являются: <message/>>, <presence/> и <iq/> (раздел 9). XML-элементы, посланные для целей согласования транспортной безопасности TLS (Transport Layer Security) (раздел 5) и согласования SASL (раздел 6) не рассматриваются как XML-строфы.

Рассмотрим пример клиентской сесии взаимодействия с сервером. Для того чтобы соединиться с сервером, клиент должен инициировать XML-поток путем посылки серверу открывающего тэга <stream>, опционно перед ним может следовать текстовая декларация, специфицирующая XML-версию и символьное кодирование (смотри "Включение текстовых деклараций" (раздел 11); а также Кодирование символов (раздел 11)). В соответствии с локальной политикой и предоставляемыми сервисами сервер должен откликнуться и сформировать XML-поток к клиенту. Как только клиент завершает согласование SASL (раздел 6), он может посылать любое число XML-строф любому получателю в сети. Когда клиент захочет прервать сессию, он просто посылает серверу закрывающий тэг </stream> (поток может быть прерван также и сервером), после этого как клиент так и сервер разрывают ТСР-соединение.

По существу, XML-поток функционирует как конверт для всех XML-строф, посланных во время сессии. Мы можем представит это в упрощенной форме как:

<stream>
<presence>
<show/>
</presence>
<message to='foo'>
<body/>
</message>
<iq to='bar'>
<quary/>
</iq>
...
</stream>

Связь с TCP

Хотя нет необходимости связывать XML-поток с ТСР-соединением [13] (например, два объекта могут установить соединение друг с другом посредством другого механизма, данная спецификация предполагает работу только с TCP-протоколом. В контексте коммуникаций клиент-сервер, сервер должен позволить клиенту разделять одно TCP-соединение для XML-строф, посланных клиентом серверу и от сервера клиенту. В контексте коммуникаций сервер-сервер, сервер должен использовать одно TCP-соединение для XML-строф, посланных сервером своему партнеру, и другое TCP-соединение (инициированное партнером) для передачи строф от партнера серверу.

Безопасность потока

Когда согласуется формирование XML-потоков в XMPP 1.0, следует использовать TLS, как это определено в разделе 5, а SASL должен использоваться при условиях, описанных в разделе 6. Безопасности исходного потока (т.е., потока от инициатора получателю) и поток-отклик (т.е., поток от получателя к инициатору) должны обеспечиваться независимо. Объект не должен пытаться посылать XML-строфы (раздел 9) через поток, прежде чем он будет аутентифицирован, но если он это сделает, тогда другой объект не должен воспринимать такие строфы и должен возвращать уведомление об ошибке <not-authorized/> и затем прерывать XML-поток и TCP-соединение; заметим, что здесь вовлечены только XML-строфы (т.е., элементы '<message/>, <presence/> и <iq/>), а не XML элементы, используемые для согласования параметров потока (например, элементы, используемые для согласования работы с TLS (раздел 5) или с SASL (раздел 6)).

Атрибуты потока

Существуют следующие атрибуты элемента потока:

Мы можем резюмировать следующее:

 инициатор-получательполучатель-инициатор
toИмя машины получателямолча игнорируется
fromмолча игнорируетсяИмя машины получателя
idмолча игнорируетсяключ сессии
xml:langязык по умолчаниюязык по умолчанию
versionСигнал поддержки XMPP 1.0Сигнал поддержки XMPP 1.0

Поддержка версии

Версия XMPP, специфицированная здесь, равна "1.0"; в частности, подразумевает протоколы, ориентированные на потоки, (использование TLS - раздел 5, использование SASL - раздел 6 и ошибки в потоках - раздел 4), а также семантику трех определенных типов XML-строф (<message/>, <presence/> и <iq/>). Схема нумерации версий XMPP имеет формат "<major>.<minor>". Старший и младший коды версии должны рассматриваться как отдельные целые числа и каждое число может инкрементироваться. Таким образом, "XMPP 2.4" будет более ранней версией чем "XMPP 2.13", которая в свою очередь младше, чем версия "XMPP 12.3". Лидирующие нули (например, "XMPP 6.01") должны игнорироваться получателями и не должны пересылаться.

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

Следующие правила следует использовать при генерации и обработке атрибута 'version' в заголовках потоков:

  1. Инициатор должен установить значение атрибута 'version' в заголовке исходного потока равным наивысшей поддерживаемой версии (например, если наивысшая поддерживаемая им версия равна описанной в данном документе, он должен установить ее равной "1.0").
  2. Приемник должен установить значение атрибута 'version' в заголовке потока-отклика равным либо значению версии, присланной инициатором, либо наивысшему поддерживаемому значению приемника, в зависимости от того какое значение ниже. Приемник должен осуществлять числовое сравнение старшего и младшего кодов версии, а не использовать значение строки "<major>.<minor>".
  3. Если номер версии, включенный в заголовок потока-отклика является по крайней мере в старшей части меньше, чем код версии, включенный в заголовок исходного потока, сущности новой версии не смогут работать. Инициатор должен сформировать уведомление об ошибки <unsupported-version/> и прервать XML-поток и разорвать TCP-соединение.
  4. Если какой-либо объект получает заголовок без атрибута 'version', объект должен считать поддерживаемую версию объекта равной "0.0" и не должен включать атрибут 'version' в заголовок потока, который он посылает в виде отклика.

Декларации пространства имен

Потоковый элемент должен содержать декларации потокового пространства имен и пространства имен по умолчанию ("декларация пространства имен" определено XML спецификации пространства имен [17]).

Характеристики потока

Если инициатор включает атрибут 'version' в заголовок исходного потока со значением по крайней мере "1.0", приемник должен послать дочерний элемент <features/> (перед ним размещается префикс пространства имен потока) инициатору, для того чтобы анонсировать любые характеристики поточного уровня, которые могут быть согласованы (или возможности, которые нужно анонсировать). Сейчас, это используется только для анонсирования использования TLS (раздел 5), использования SASL (раздел 6) и подключаемых ресурсов (раздел 7), а также для установления сессий, как это определено в [3]; однако, функциональность потоковых характеристик может использоваться для анонсирования других согласуемых параметров в будущем. Если объект не понимает или не поддерживает некоторые возможности, он должен их молча игнорировать.

Ошибки потока

Корневой потоковый элемент может содержать дочерний элемент <error/>, перед которым следует префикс пространства имен потока. Дочерний элемент ошибки должен быть послан соответствующим объектом (обычно сервером, а не клиентом), если он понимает, что на поточном уровне произошла ошибка.

Правила

Следующие правила используются в отношении ошибок уровня потока:

Синтаксис

Синтаксис потоковых ошибок имеет следующий формат:

   <stream:error>
     <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/$gt;
     <text xmlns='urn:ietf:params:xml:ns:xmpp-streams'
           xml:lang='langcode'>
       OPTIONAL descriptive text
     </text>
     [OPTIONAL application-specific condition element]
   </stream:error>

Элемент <error/>:

Элемент <text/> является опционным. В случае включения он должен использоваться только для описательных и диагностических данных, которые являются дополнительным пояснением условий. Он не должен интерпретироваться приложением программно. Он не должен использоваться в качестве сообщения об ошибке пользователю, но может служить дополнением к сообщению об ошибке.

Определенные условия

Определены следующие условия для ошибок уровня потока:

Специфические для приложения условия

Как было отмечено, приложение может выдать свою информацию об ошибке потока путем включения дочернего элемента ошибки. Специфический для приложения элемент должен быть дополнением к стандартному элементу. Таким образом элемент <error/> будет содержать 2-3 дочерних элементов:

 <stream:error>
     <xml-not-well-formed
         xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
     <text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
       Some special application diagnostic information!
     </text>
     <escape-your-data xmlns='application-ns'/>
   </stream:error>
   </stream:stream>

Упрощенные примеры потоков

Ниже представлены два упрощенных примера сессий, базирующихся на потоках клиент-сервер (где в "C"-строках данные пересылаются от клиента к серверу, а в "S"-строках - от сервера к клиенту); эти примеры включены для целей иллюстрации концепции, изложенной далее.

Базовая "сессия":

C: <?xml version='1.0'?>
      <stream:stream
          to='example.com'
          xmlns='jabber:client'
          xmlns:stream='http://etherx.jabber.org/streams'
          version='1.0'>
   S: <?xml version='1.0'?>
      <stream:stream
          from='example.com'
          id='someid'
          xmlns='jabber:client'
          xmlns:stream='http://etherx.jabber.org/streams'
          version='1.0'>

... шифрование, аутентификация и подключение ресурсов ...

   C:   <message from='juliet@example.com'
                 to='romeo@example.net'
                 xml:lang='en'>
   C:     <body>Art thou not Romeo, and a Montague?</body>
   C:   </message>
   S:   <message from='romeo@example.net'
                 to='juliet@example.com'
                 xml:lang='en'>
   S:     <body>Neither, fair saint, if either thee dislike.</body>
   S:   </message>
   C: </stream:stream>
   S: </stream:stream>

Сессия реализована плохо:

   C: <?xml version='1.0'?>
      <stream:stream
          to='example.com'
          xmlns='jabber:client'
          xmlns:stream='http://etherx.jabber.org/streams'
          version='1.0'>
   S: <?xml version='1.0'?>
      <stream:stream
          from='example.com'
          id='someid'
          xmlns='jabber:client'
          xmlns:stream='http://etherx.jabber.org/streams'
          version='1.0'>

... шифрование, аутентификация и подключение ресурсов ...

   C: <message xml:lang='en'>
        <body>Bad XML, no closing body tag!
      </message>
   S: <stream:error>
       <xml-not-well-formed
           xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
      </stream:error>
   S: </stream:stream>

5. Использование TLS

XMPP включает в себя метод обеспечения безопасности потока от фальсификации и подслушивания. Метод криптозащиты канала использует протокол безопасности транспортного уровня [18], с расширениями "STARTTLS", которые смоделированы для протоколов IMAP [IMAP], POP3 [POP3] и ACAP, как это описано в RFC 2595. Имя пространства имен для расширения STARTTLS = 'urn:ietf:params:xml:ns:xmpp-tls'.

Администратор данного домена может потребовать использования TLS для коммуникаций клиент-сервер и сервер-сервер. Клиенты должны использовать TLS, чтобы обеспечить безопасность потоков, прежде чем пытаться завершить согласование SASL (раздел 6), а серверы должны использовать TLS между двумя доменами для целей обеспечения безопасности коммуникаций сервер-сервер.

Используются следующие правила:

  1. Инициатор, который следует данной спецификации должен включить в заголовок потока атрибут 'version', содержащий значение "1.0".
  2. Если согласование TLS происходит между двумя серверами, коммуникации не должны происходить до тех пор, пока DNS не распознает имена машин, введенные серверами (смотри "Коммуникации сервер-сервер" (раздел 14)).
  3. Когда приемник, который следует данной спецификации, получает заголовок исходного потока, который содержит атрибут 'version', равный по крайней мере "1.0", он должен включить элемент <starttls/> (привязанный к пространству имен 'urn:ietf:params:xml:ns:xmpp-tls') вместе со списком других характеристик потока.
  4. Если приемник намерен использовать TLS, согласование параметров TLS должно быть завершено до согласования использования SASL; такой порядок диалога необходим, чтобы защитить аутентификационную информацию, посланную во время согласования применения SASL.
  5. Во время согласования использования TLS, объект не должен посылать каких-либо символов пробелов в элементе корневого потока в качестве сепараторов между элементами (любой пробел, имеющийся в примерах TLS ниже, включен исключительно из соображений читаемости); этот запрет помогает гарантировать корректность байт на уровне безопасности.
  6. Приемник должен осуществлять согласование применения TLS сразу после посылки завершающего символа ">" элемента <proceed/>. Инициатор должен осуществлять согласование применения TLS сразу после получения завершающего символа ">" элемента <proceed/> от приемника.
  7. Инициатор должен проверить сертификат, представленный приемником; (смотри "Проверка сертификата" (раздел 14)).
  8. Сертификаты должны проверяться по поводу имени машины, выданного инициатором, (например, пользователем), а не имя машины, полученное с помощью DNS; например, если пользователь специфицирует имя машины "example.com", а DNS SRV прислал "im.example.com", сертификат должен проверять версию "example.com". Если JID для любого XMPP-объекта (например, клиента или сервера) присутствует в сертификате, он должен быть представлен, в виде UTF8String в пределах имени некоторого объекта (otherName) внутри subjectAltName. Делается это с привлечением объектного идентификатора [23] "id-on-xmppAddr", специфицированного в разделе 5.
  9. Если согласование применения TLS прошло успешно, приемник должен ликвидировать любые данные, полученные ранее от инициатора небезопасным способом.
  10. Если согласование применения TLS прошло успешно, инициатор должен аннулировать любые данные, полученные ранее от приемника небезопасным способом.
  11. Если согласование применения TLS прошло успешно, приемник не должен предлагать инициатору расширения STARTTLS, а также другие возможности, которые предложены, когда поток рестартовал.
  12. Если согласование применения TLS прошло успешно, инициатор должен приступить к согласованию SASL.
  13. Если согласование применения TLS завершилось неудачей, приемник должен прервать XML-поток и разорвать TCP-соединение.
  14. По поводу механизмов, которые должны быть непременно поддержаны, смотри в "Обязательные для использования технологии" (раздел 14).

Идентификатор объекта ASN.1 для XMPP-адреса

Идентификатор объекта [23] "id-on-xmppAddr", описанный выше, определяется следующим образом:

 id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
           dod(6) internet(1) security(5) mechanisms(5) pkix(7) }

   id-on  OBJECT IDENTIFIER ::= { id-pkix 8 }  -- other name forms

   id-on-xmppAddr  OBJECT IDENTIFIER ::= { id-on 5 }

   XmppAddr ::= UTF8String

Этот объектный идентификатор может быть представлен в точечном формате вида "1.3.6.1.5.5.7.8.5".

Диалог

Когда инициатор обеспечивает безопасность потока с помощью TLS, реализуются следующие шаги:

  1. Инициатор открывает TCP-соединение и инициирует поток путем посылки XML-заголовка получателю. В заголовок потока вставляется атрибут 'version', со значением как минимум "1.0".
  2. Получатель откликается установлением TCP-соединения и посылкой XML-заголовка потока инициатору, включая при этом в заголовок атрибут 'version', содержащий значение как минимум "1.0".
  3. Получатель предлагает инициатору расширение STARTTLS, включив его вместе с другими возможностями потока (если для взаимодействия с получателем требуется TLS, он должен сигнализировать об этом с помощью включения элемента <required/> в качестве дочернего элемента <starttls/>).
  4. Инициатор выдает команду STARTTLS (т.е., элемент <starttls/>, соотнесенный с пространством имен 'urn:ietf:params:xml:ns:xmpp-tls'), чтобы уведомит получателя, что он хочет начать согласование применения TLS.
  5. Получатель должен откликнуться либо элементом <proceed/>, либо элементом <failure/>, соотнесенным с пространством имен 'urn:ietf:params:xml:ns:xmpp-tls'. Если произойдет сбой, получатель должен прервать XML-поток и разорвать TCP-соединение. Если все в порядке, участники должны попытаться завершить согласование применения TLS через имеющееся TCP-соединение и до завершения этого процесса не должны посылать какие-либо XML-данные.
  6. Инициатор и получатель пытаются согласно с [18] завершить согласование TLS.
  7. Если реализация TLS оказалась неудачной, получатель должен разорвать TCP-соединение. В случае же успеха, инициатор должен сформировать новый поток, послав открывающий XML-заголовок получателю (необязательно посылать сначала закрывающий тэг </stream>, так как получатель и инициатор должна рассматривать исходный поток закрытым после успешного завершения согласования применения TLS).
  8. После получения нового заголовка потока от инициатора, получатель должен откликнуться посылкой инициатору нового заголовка XML-потока вмести со всеми доступными возможностями (возможность STARTTLS не включается).

Пример клиент-сервер

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

Шаг 1: Клиент формирует поток к серверу:

 <stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 2: Сервер откликается посылкой тэга потока клиенту:

 <stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       id='c2s_123'
       from='example.com'
       version='1.0'>

Шаг 3: Сервер посылает клиенту расширение STARTTLS и данные о механизме аутентификации и других особенностях потока:

   <stream:features>
     <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
       <required/>
     </starttls>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>PLAIN</mechanism>
     </mechanisms>
   </stream:features>

Шаг 4: Клиент посылает серверу команду STARTTLS:

 <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

Шаг 5: Сервер информирует клиента о том, что он может продолжить работу:

   <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

Шаг 5 (alt): Сервер информирует клиента, что согласование TLS не состоялось и следует прервать поток и разорвать TCP-соединение:

 <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
   </stream:stream>

Шаг 6: Клиент и сервер пытаются завершить согласование применения TLS через существующее TCP-соединение.

Шаг 7: Если согласование TLS успешно, клиент формирует новый поток к серверу:

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 7 (alt): Если согласование TLS не получилось, сервер закрывает TCP-соединение.

Шаг 8: Сервер реагирует посылкой клиенту заголовка потока и любых характеристик потока:

 <stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       from='example.com'
       id='c2s_234'
       version='1.0'>
    <stream:features>
      <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
        <mechanism>DIGEST-MD5 </mechanism>
        <mechanism>PLAIN </mechanism>
        <mechanism>EXTERNAL </mechanism>
      </mechanisms>
    </stream:features>

Шаг 9: Клиент продолжает согласование SASL (раздел 6).

Пример сервер-сервер

Следующий пример показывает поток данных для двух серверов, обеспечивающих безопасность с помощью STARTTLS (заметим: альтернативные шаги, показанные ниже, приведены для иллюстрации работы протокола в случаях сбоев; они не являются обязательными).

Шаг 1: Сервер1 инициирует поток в серверу2:

 <stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 2: Сервер2 откликается посылкой тэга потока Серверу1:

 <stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       from='example.com'
       id='s2s_123'
       version='1.0'>

Шаг 3: Сервер2 посылает расширение STARTTLS Серверу1 вместе с данными о механизме аутентификации и любыми другими возможностями потока:

 <stream:features>
     <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
       <required/>
     </starttls>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>KERBEROS_V4</mechanism>
     </mechanisms>
   </stream:features>

Шаг 4: Сервер1 посылает команду STARTTLS Серверу2:

<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

Шаг 5: Сервер2 информирует Server1 о том, что он может продолжать работу:

  <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

Шаг 5 (alt): Сервер2 информирует Server1 о том, что согласование применения TLS не прошло и поток закрывается:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
   </stream:stream>

Шаг 6: Сервер1 и Сервер2 пытаются завершить согласование применения TLS через TCP.

Шаг 7: Если согласование TLS прошло успешно, Сервер1 формирует новый поток к Серверу2:

   <stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 7 (alt): Если согласование TLS не прошло, Сервер2 закрывает TCP-соединение.

Шаг 8: Сервер2 откликается посылкой заголовка потока Серверу1 вместе с данными о доступных возможностях потока:

 <stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       from='example.com'
       id='s2s_234'
       version='1.0'>
   <stream:features>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>KERBEROS_V4</mechanism>
       <mechanism>EXTERNAL</mechanism>
     </mechanisms>
   </stream:features>

Шаг 9: Сервер1 продолжает согласование применения SASL (раздел 6).

6. Использование SASL

XMPP содержит в себе метод аутентификации потока с помощью XMPP-профайла протокола SASL (Simple Authentication and Security Layer) [12]. SASL предоставляет обобщенный метод добавления поддержки аутентификации для протоколов с установлением соединения, и XMPP использует универсальный профайл XML пространства имен для SASL, который соответствует требованиям [12].

Используются следующие правила:

  1. Если согласование применения SASL происходит между двумя серверами, коммуникации не должны продолжаться до тех пор, пока с помощью DNS не выяснены имена присвоенные серверам (смотри "Коммуникации сервер-сервер" (раздел 14)).
  2. Если инициатор может согласовать применение SASL, он должен включить в заголовок исходного потока атрибут 'version' со значением по крайней мере равным "1.0".
  3. Если получатель может согласовать применение SASL, он должен анонсировать один или более аутентификационных механизмов в элементе <mechanisms/>, сопряженным с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl', в отклике на открывающий тэг потока, полученный от инициатора (если открывающий тэг потока включает в себя атрибут 'version' со значением по крайней мере равным "1.0").
  4. Во время согласования применения SASL, объект не должен в качестве сепараторов элементов посылать символы пробелов (см. процедуру формирования содержимого в [3] и [1]) в элементе корневого потока (любой символ пробела, представленный в примерах SASL, введен исключительно с целью обеспечения читабельности текста); этот запрет помогает гарантировать корректность представления материала на уровне безопасности.
  5. Любые XML символьные данные, содержащиеся в XML-элементах, и используемые при согласовании SASL должны иметь кодировку base64, где кодировка привязана к определениям из раздела 3 RFC 3548 [25].
  6. Если предоставление "simple username" поддерживается выбранным механизмом SASL (например, это поддерживается механизмами DIGEST-MD5 и CRAM-MD5, но не поддерживается механизмами EXTERNAL и GSSAPI), во время аутентификации, инициатор должен обеспечить в качестве простого имени пользователя свой домен (IP-адрес или полное доменное имя, как оно записано в доменном идентификаторе) в случае коммуникаций сервер-сервер, или свое имя аккоунта (имя пользователя или узла, содержащегося в XMPP-идентификаторе узла) в случае коммуникаций клиент-сервер.
  7. Если инициатор хочет действовать в интересах другого объекта и выбранный механизм SASL поддерживает передачу авторизационной идентичности, инициатор должен предоставить авторизационную идентичность в процессе согласования применения SASL. Если инициатор не хочет действовать в интересах другого объекта, он не должен предоставлять идентичность авторизации. Как специфицировано в [12], инициатор не должен предоставлять идентичность авторизации, за исключением случая, когда идентичность авторизации отличается от идентичности по умолчанию, полученной согласно [12]. Если такие данные предоставляются, значение идентичности авторизации должно иметь формат <domain> (т.е., только идентификатор домена) для серверов и формат <node@domain> (т.е., идентификатор узла и идентификатор домена) для клиентов.
  8. В случае успешного согласования SASL, которое включает в себя согласование уровня безопасности, получатель должен ликвидировать любую информацию, полученную от инициатора, которая не получена непосредственно в процессе согласования SASL.
  9. В случае успешного согласования SASL, которое включает в себя согласование уровня безопасности, инициатор должен ликвидировать любую информацию, полученную от получателя, которая не получена непосредственно в процессе согласования SASL.
  10. В отношении механизмов, которые нужно поддерживать смотри "Обязательные для использования технологии" (раздел 14).

Когда инициатор аутентифицирует получателя, используя SASL, процедура включает в себя следующие шаги:

  1. Инициатор запрашивает аутентификацию SASL путем включения атрибута 'version' в открывающий заголовок XML потока, направленного получателю, со значением равным "1.0".
  2. После посылки заголовка XML-потока в виде отклика, получатель анонсирует список доступных механизмов аутентификации SASL; каждый из этих элементов <mechanism/> включаются в качестве дочерних в контейнерный элемент <mechanisms/>, соотнесенный с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl', который в свою очередь является дочерним элементом <features/> в пространстве имен потока. Если TLS (раздел 5) нужно установить, прежде чем использовать какой-то конкретный механизм аутентификации, получатель не должен помещать этот механизм в список механизмов аутентификации SASL, до согласования TLS. Если инициатор предоставляет корректный сертификат при предварительном согласовании TLS, получатель при согласовании SASL должен предложить инициатору механизм SASL EXTERNAL (смотри [12]), хотя механизм EXTERNAL может быть предложен также и при других обстоятельствах.
  3. Инициатор выбирает механизм путем посылки элемента <auth/>, соотнесенного с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl', получателю. Элемент содержит также значение атрибута 'mechanism'. Этот элемент может содержать символьные XML-данные (в терминологии SASL, "исходный отклик"), если механизм поддерживает или требует этого. Если инициатор должен послать исходный отклик нулевой длины, он должен передать отклик в виде одиночного символа равенства ("="), который указывает, что этот отклик не содержит данных .
  4. Если необходимо, получатель направляет вызов инициатору путем посылки инициатору элемента <challenge/>, соотнесенного с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl'. Этот элемент может содержать символьные данные (которые должны быть обработаны в соответствии с определением механизма SASL, который выбрал инициатор).
  5. Инициатор реагирует на вызов посылкой получателю элемента <response/>, соотнесенного с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl'. Этот элемент может содержать символьную XML-информацию (которая должна быть обработана в соответствии с определением механизма SASL, который выбрал инициатор).
  6. Если необходимо, получатель посылает несколько вызовов, а инициатор отправляет несколько откликов.

Эти последовательности вызов/отклик продолжаются до тех пор пока не случится одно из трех событий:

  1. Инициатор обрывает диалог посылкой получателю элемента <abort/>, соотносящегося с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl'. После получения элемента <abort/> получатель должен разрешить конфигурируемое но разумное число повторных попыток (по крайней мере 2), после которых он должен прервать TCP-соединение. Это позволяет инициатору (например, конечному пользователю - клиенту) перепроверить неверно выданные параметры авторизации (например, опечатку в пароле) без необходимости выполнения повторного соединения.
  2. Получатель сообщает о неудаче диалога посылкой инициатору элемента <failure/>, соотносящегося пространству имен 'urn:ietf:params:xml:ns:xmpp-sasl', конкретная причина неудачи должна быть сообщена в соответствующем дочернем элементе элемента <failure/>, как это определено главе "Ошибки SASL" (раздел 6.4). В случае неудачи получатель должен разрешить конфигурируемое, но разумное число повторных попыток (по крайней мере 2), после которых он должен прервать TCP-соединение. Это позволяет инициатору (например, конечному пользователю - клиенту) перепроверить неверно выданные параметры авторизации (например, опечатку в пароле) без необходимости выполнения повторного соединения.
  3. Получатель сообщает об успехе диалога посылкой инициатору элемента <success/>, соотносимого с пространством имен 'urn:ietf:params:xml:ns:xmpp-sasl'. Этот элемент может содержать символьную XML-информацию (в терминологии SASL "дополнительные данные при успехе"), если это требуется выбранным механизмом SASL. После получения элемента <success/> инициатор должен сформировать новый поток, путем посылки открывающего заголовка XML-потока получателю (посылать закрывающий тэг </stream> не нужно, так как приемник и инициатор должны рассматривать исходный поток закрытым после отправки или получения элемента <success/>). После получения заголовка нового потока от инициатора получатель должен реагировать посылкой инициатору нового заголовка потока и информировать партнера об имеющихся возможностях посредством элемента <features/>.

Определение SASL

Требования профайла [12] определяют необходимость предоставления следующей протокольной информации:

имя сервиса: "xmpp"

стартовая последовательность: После того как инициатор выдает открывающий заголовок потока и получатель соответственно откликается, получатель выдает список приемлемых методов аутентификации. Инициатор выбирает один из методов и посылает получателю значение атрибута 'mechanism', содержащегося в элементе <auth/>.

последовательность обмена: Вызовы и отклики реализуются посредством обмена элементами <challenge/>, направляемыми от получателя инициатору, и элементами <response/>, отправляемыми инициатором получателю. Получатель сообщает о неудаче с помощью посылки элемента <failure/>, а об успехе - посредством посылки элемента <success/>. Инициатор абортирует обмен путем посылки элемента <abort/>. После успешного согласования параметров потока, обе стороны считают исходный поток закрытым и посылают друг другу заголовки нового потока.

согласование на уровне безпасности: Уровень безопасности начинает функционировать сразу после посылки завершающего символа ">" элемента <success/> получателю, и сразу после получения инициатором завершающего символа ">" элемента <success/>.

использование авторизационной идентичности: Авторизационная идентичность может использоваться xmpp, чтобы указать <node@domain> клиента (если это не значение по умолчанию) или посылки <domain> сервера.

Ошибки SASL

Определены следующие условия ошибок, сопряженных с SASL:

Пример клиент-сервер

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

Шаг 1: Клиент формирует поток до сервер:

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 2: Сервер реагирует посылкой клиенту тэга потока:

   <stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       id='c2s_234'
       from='example.com'
       version='1.0'>

Шаг 3: Сервер информирует клиента об имеющихся механизмах аутентификации:

<stream:features>
     <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
       <required/>
     </starttls>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>PLAIN</mechanism>
     </mechanisms>
   </stream:features>

Шаг 4: Клиент выбирает механизм аутентификации:

  <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
         mechanism='DIGEST-MD5'/>

Шаг 5: Сервер посылает закодированный вызов [25] клиенту:

 <challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
   LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
   </challenge>

Декодированный вызов имеет вид:

realm="somerealm",nonce="OA6MG9tEQGm2hh",\
   qop="auth",charset=utf-8,algorithm=md5-sess

Шаг 5 (alt): Сервер возвращает клиенту сообщение об ошибке:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <incorrect-encoding/>
   </failure>
   </stream:stream>

Шаг 6: Клиент посылает закодированный отклик [25] на вызов:

<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
   T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
   MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
   LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
   YXJzZXQ9dXRmLTgK
   </response>

Декодированный отклик имеет вид:

username="somenode",realm="somerealm",\
   nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
   nc=00000001,qop=auth,digest-uri="xmpp/example.com",\
   response=d388dad90d4bbd760a152321f2143af7,charset=utf-8

Шаг 7: Сервер посылает еще один закодированный [25] вызов клиенту:

<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
   </challenge>

Декодированный вызов имеет вид:

rspauth=ea40f60335c427b5527b84dbabcdfffd

Шаг 7 (alt): Сервер посылалает клиенту сообщение об ошибке:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <temporary-auth-failure/>
   </failure>
   </stream:stream>

Шаг 8: Клиент откликается на вызов:

<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Шаг 9: Сервер информирует клиента об успешной аутентификации:

<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Шаг 9 (alt): Сервер информирует клиента об ошибке аутентификации:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <temporary-auth-failure/>
   </failure>
   </stream:stream>

Шаг 10: Клиент формирует новый поток к серверу:

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 11: Сервер откликается посылкой заголовка потока клиенту, сообщая о любых дополнительных имеющихся возможностях (если таких возможностей нет, посылается пустой элемент):

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       id='c2s_345'
       from='example.com'
       version='1.0'>
   <stream:features>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
     <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
   </stream:features>

Пример сервер-сервер

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

Шаг 1: Сервер1 инициирует поток к Серверу2:

<stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 2: Сервер2 откликается посылкой Серверу1 тэга потока:

<stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       from='example.com'
       id='s2s_234'
       version='1.0'>

Шаг 3: Сервер2 информирует Server1 о доступных механизмах аутентификации:

<stream:features>
     <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
       <mechanism>DIGEST-MD5</mechanism>
       <mechanism>KERBEROS_V4</mechanism>
     </mechanisms>
   </stream:features>

Шаг 4: Сервер1 выбирает механизм аутентификации:

<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
         mechanism='DIGEST-MD5'/>

Шаг 5: Сервер2 посылает закодированный [25] вызов Серверу1:

<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9
   ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz
   </challenge>

Декодированный вызов имеет вид:

realm="somerealm",nonce="OA6MG9tEQGm2hh",\
   qop="auth",charset=utf-8,algorithm=md5-sess

Шаг 5 (alt): Сервер2 возвращает Серверу1 сообщение об ошибке:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <incorrect-encoding/>
   </failure>
   </stream:stream>

Шаг 6: Сервер1 посылает закодированный отклик [25] на вызов:

<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   dXNlcm5hbWU9ImV4YW1wbGUub3JnIixyZWFsbT0ic29tZXJlYWxtIixub25j
   ZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5j
   PTAwMDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5v
   cmciLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3
   LGNoYXJzZXQ9dXRmLTgK
   </response>

Дешифрованный отклик имеет вид:

username="example.org",realm="somerealm",\
   nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
   nc=00000001,qop=auth,digest-uri="xmpp/example.org",\
   response=d388dad90d4bbd760a152321f2143af7,charset=utf-8

Шаг 7: Сервер2 посылает еще один закодированный [25] вызов Серверу1:

<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
   cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZAo=
   </challenge>

Декодированный вызов имеет вид:

rspauth=ea40f60335c427b5527b84dbabcdfffd

Шаг 7 (alt): Сервер2 возвращает Серверу1 сообщение об ошибке:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <invalid-authzid/>
   </failure>
   </stream:stream>

Шаг 8: Сервер1 откликается на вызов:

>response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Шаг 8 (alt): Сервер1 абортирует согласование:

<abort xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Шаг 9: Сервер2 информирует Сервер1 об успешной аутентификации:

<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>

Шаг 9 (alt): Сервер2 информирует Сервер1 о неудаче аутентификации:

<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
     <aborted/>
   </failure>
   </stream:stream>

Шаг 10: Сервер1 инициирует новый поток к Серверу2:

<stream:stream
       xmlns='jabber:server'
       xmlns:stream='http://etherx.jabber.org/streams'
       to='example.com'
       version='1.0'>

Шаг 11: Сервер2 откликается посылкой Серверу1 заголовка потока, а также данными о любых дополнительных возможностях (при отсутствии последних посылается пустой элемент):

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       from='example.com'
       id='s2s_345'
       version='1.0'>
   <stream:features/>

7. Подключение ресурсов

После согласования применения SASL (раздел 6) с получателем, инициатор может хотеть или не нуждаться в подключении к потоку специфических ресурсов. В основном это относится только к клиентам: для того чтобы адаптироваться к формату адресации (раздел 3) и правил доставки строф (раздел 10), специфицированных в данном документе. Должен существовать идентификатор ресурса, ассоциированный с <node@domain> клиента (который либо генерируется сервером, либо предлагается приложением клиента). Это гарантирует, то, что адрес используемый для данного потока, является "полным JID" формата <node@domain/resource>.

После получения информации об успехе согласования SASL, клиент должен послать серверу новый заголовок, на который сервер должен откликнуться заголовком потока и прислать список доступных возможностей потока. Точнее, если сервер требует, чтобы клиент после успешного согласования SASL подключил ресурс к потоку, он должен включить пустой элемент <bind/>, сопряженный с пространством имен 'urn:ietf:params:xml:ns:xmpp-bind', в список возможностей, которые он предлагает клиенту после отправки заголовка для потока-отклика, посланного после успешного согласования SASL (но не до):

Сервер анонсирует возможность подключения ресурса клиенту:

<stream:stream
       xmlns='jabber:client'
       xmlns:stream='http://etherx.jabber.org/streams'
       id='c2s_345'
       from='example.com'
       version='1.0'>
   <stream:features>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
   </stream:features>

После того как клиент оказывается проинформирован о необходимости подключения ресурса, он должен выполнить подключение ресурса к потоку, посредством посылки серверу IQ-строфы типа "set" (смотри "IQ семантика" (раздел 9)), содержащей данные, соотнесенные с пространством имен 'urn:ietf:params:xml:ns:xmpp-bind'.

Если клиент хочет позволить серверу сформировать идентификатор ресурса, он посылает IQ-строфу типа "set", которая содержит пустой элемент <bind/>:

Клиент просит сервер подключить ресурс:

<iq type='set' id='bind_1'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
   </iq>

Сервер, который поддерживает подключение ресурсов, должен быть способен генерировать идентификатор ресурса для клиента. Идентификатор ресурса, генерируемый сервером, должен быть уникальным для данного <node@domain>.

Если клиент хочет специфицировать идентификатор ресурса, он посылает IQ-строфу типа "set", которая содержит желаемый идентификатор ресурса в виде текстового элемента <resource/>, который является дочерним элементом <bind/>:

Клиент подключает ресурс:

<iq type='set' id='bind_2'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <resource>someresource</resource>
     </bind>
   </iq>

Раз сервер сформировал идентификатор ресурса для клиента или воспринял идентификатор, предложенный клиентом, он должен послать клиенту IQ-строфу типа "result", которая должна содержать дочерний элемент <jid/>, который специфицирует полный JID для подключенного ресурса, как это определено сервером:

Сервер информирует клиента об успешном подключении ресурса:

<iq type='result' id='bind_2'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <jid>somenode@example.com/someresource</jid>
     </bind>
   </iq>

Сервер должен воспринять идентификатор ресурса, присланный клиентом, Но может заменить его на идентификатор, сгенерированный сервером; в этом случае, сервер не должен присылать клиенту строфу ошибки (например, <forbidden/>), а вместо этого прислать клиенту свой сгенерированный идентификатор ресурса в IQ результата, как было показано выше.

Когда клиент выдает идентификатор ресурса, возможна присылка следующей строфы условий ошибки (смотри "Строфы ошибок" (раздел 9)):

Протокол обработки условия ошибки представлен ниже.

Идентификатор ресурса не может быть обработан при условии:

<iq type='error' id='bind_2'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <resource>someresource</resource>
     </bind>
     <error type='modify'>
       <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
     </error>
   </iq>

Клиент не разрешает подключение ресурса:

<iq type='error' id='bind_2'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <resource>someresource</resource>
     </bind>
     <error type='cancel'>
       <not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
     </error>
   </iq>

Идентификатор ресурса уже используется:

<iq type='error' id='bind_2'>
     <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
       <resource>someresource</resource>
     </bind>
     <error type='cancel'>
       <conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
     </error>
   </iq>

Если, до завершения этапа подключения ресурса клиент попытается послать XML-строфу, отличную от IQ-строфы с дочерним <bind/>, привязанным к пространству имен 'urn:ietf:params:xml:ns:xmpp-bind', сервер не должен обрабатывать строфу и ему следует вернуть клиенту строфу ошибки <not-authorized/>.

8. Метод сервера Dialback ("обратный дозвон")

Протоколы Jabber, которые адаптированы для XMPP, были приспособлены к использованию метода сервера "dialback" для защиты от фальсификации домена, таким образом делая сложным фальсификацию XML-строф. Обратный дозвон сервера (dialback) не является механизмом безопасности и связан исключительно со слабыми средствами верификации идентичности сервера (смотри "Коммуникации Сервер-сервер" (раздел 14), где рассмотрены характеристики безопасности этого метода). Домены, требующие надежной безопасности, должны использовать TLS и SASL. Если для аутентификации сервер-сервер используется SASL, обратный дозвон применять не следует (просто бессмысленно).

Метод обратного дозвона сервера возможен благодаря наличию DNS (Domain Name System), так как сервер может выяснить наличие другого сервера в пределах данного домена. Так как обратный дозвон зависит от DNS, междоменные коммуникации не должны запускаться, пока объекты не будут локализованы с помощью DNS сервера (смотри раздел 14)).

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

Метод генерации и верификации ключей, используемый в dialback сервером должен учитывать используемые имена машин, идентификатор потока, формируемый сервером-приемником и секретный ключ, известный всем авторизованным в сети серверам. Идентификатор потока является критическим параметром безопасности в процедуре dialback и, следовательно, должен быть непредсказуемым и неповторимым (смотри [27]).

Любая ошибка, которая происходит во время согласования dialback должна рассматриваться как ошибка потока, которая приводит к прерыванию потока и разрыву TCP-соединения. Возможные условия ошибки специфицированы ниже в описании протокола.

Здесь используется следующая терминология:

Порядок событий

Ниже представлено краткое описание последовательности событий при dialback:

  1. Исходный сервер устанавливает соединение с принимающим сервером.
  2. Исходный сервер посылает через соединение значение 'key' принимающему серверу.
  3. Принимающий сервер устанавливает соединение с управляющим сервером.
  4. Принимающий сервер посылает этот ключ управляющему серверу.
  5. Управляющий сервер подтверждает или не подтверждает корректность ключа.
  6. Принимающий сервер информирует исходный сервер, аутентифицирован он или нет.

Мы можем представить схему диалога следующим образом:

Рис. 2. Информационный диалог между серверами

Протокол

Протокольное взаимодействие между серверами выглядит следующим образом:

  1. Исходный сервер устанавливает ТСР-соединение с принимающим сервером.
  2. Исходный сервер посылает заголовок потока принимающему серверу:
  3. <stream:stream
           xmlns:stream='http://etherx.jabber.org/streams'
           xmlns='jabber:server'
           xmlns:db='jabber:server:dialback'>

    Заметим: атрибуты 'to' и 'from' являются опционными для элемента корневого потока. Включение декларации пространства имен xmlns:db с приведенным именем указывает принимающему серверу, что исходный сервер поддерживает dialback. Если имя пространства имен некорректно, тогда принимающий сервер должен сформировать ошибку потока <invalid-namespace/> и завершить XML-поток, а также разорвать TCP-соединение.

  4. Принимающий сервер должен отослать назад заголовок потока исходному серверу, включая уникальный ID этого взаимодействия:
  5. <stream:stream
           xmlns:stream='http://etherx.jabber.org/streams'
           xmlns='jabber:server'
           xmlns:db='jabber:server:dialback'
           id='457F9224A0...'>

    Заметим: Если имя пространства имен некорректно, тогда исходный сервер должен сформировать ошибку потока <invalid-namespace/>, прервать поток и разорвать TCP-соединение. Принимающий сервер должен ответить, но может молча завершить XML-поток, в зависимости от принятой политики безопасности; однако, если принимающий сервер хочет продолжить, он должен послать исходному серверу заголовок потока.

  6. Исходный сервер посылает ключ dialback принимающему серверу:
  7. <db:result
           to='принимающий сервер'
           from='исходный сервер'>
         98AF014EDC0...
       </db:result>

    Замечание: Этот ключ не просматривается принимающим сервером, так как он не хранит информацию об исходном сервере по завершении сессии. Ключ, генерируемый исходным сервером, должен базироваться частично на значении ID, предоставленном принимающим сервером на предыдущем шаге, а также частично на секретном ключе, совместно используемом исходным и управляющим серверами. Если значение адреса 'to' не соответствует имени машины, распознанному принимающим сервером, тогда последний должен генерировать сообщение ошибки потока <host-unknown/> и прерывать XML-поток. Если значение адреса 'from' соответствует домену, с которым принимающий сервер уже установил соединение, тогда он должен поддерживать существующее соединение до тех пор, пока не будет установлено новое соединение. Кроме того, принимающий сервер может сформировать сообщение об ошибке потока <not-authorized/> для нового соединения и затем прервать XML-поток и его TCP-соединение, связанные с новым запросом.

  8. Принимающий сервер устанавливает TCP-соединение с доменным именем, представленным исходным сервером, как результ установления соединения с управляющим сервером.
  9. Принимающий сервер посылает заголовок потока управляющему серверу:
  10. <stream:stream
           xmlns:stream='http://etherx.jabber.org/streams'
           xmlns='jabber:server'
           xmlns:db='jabber:server:dialback'>

    Замечание: атрибуты 'to' и 'from' являются опционными для элемента корневого потока. Если имя пространства имен некорректно, тогда управляющий сервер должен генерировать сообщение ошибки потока <invalid-namespace/> и прерывать XML-поток и TCP-соединение.

  11. Управляющий сервер посылает заголовок потока принимающему серверу:
  12. <stream:stream
           xmlns:stream='http://etherx.jabber.org/streams'
           xmlns='jabber:server'
           xmlns:db='jabber:server:dialback'
           id='1251A342B...'>

    Замечание: Если имя пространства имен некорректно, тогда принимающий сервер должен сформировать сообщение ошибки потока <invalid-namespace/> и прервать XML-поток и соответствующее TCP-соединение между ним и сервером управления. Если ошибка потока случится между принимающим и управляющим серверами, тогда принимающий сервер должен сформировать сообщение об ошибке потока <remote-connection-failed/> и прервать поток и ТСР-соединение с исходным сервером.

  13. Принимающий сервер посылает управляющему серверу запрос верификации ключа:
  14. <db:verify
           from='принимающий сервер'
           to='исходный сервер'
           id='457F9224A0...'>
         98AF014EDC0...
       </db:verify>

    Замечание: Здесь уже получены имена машин, оригинальный идентификатор из заголовка потока принимающего сервера исходному серверу на шаге 3, и ключ, который исходный сервер послал принимающему серверу на шаге 4. На основе этой информации, а также на секретном, совместно используемом ключе сети управляющего сервера ключ верифицируется. Для генерации ключа может использоваться любой метод верификации. Если значение адреса 'to' не соответствует имени машины, выявленному управляющим сервером, тогда управляющий сервер должен сформировать сообщение об ошибке потока <host-unknown/> и разорвать XML-поток и ТСР-соединение. Если значение адреса 'from' не соответствует имени машины, представленному принимающим сервером при открытии TCP-соединения, тогда управляющий сервер должен сформировать ошибку потока <invalid-from/>.

  15. Управляющий сервер проверяет, является ли ключ корректным:
  16. <db:verify
           from='исходный сервер'
           to='принимающий сервер'
           type='valid'
           id='457F9224A0...'/>

    или

    <db:verify
           from='исходный сервер'
           to='принимающий сервер'
           type='invalid'
           id='457F9224A0...'/>

    Замечание: Если ID не соответствует тому, который предложен принимающим сервером на шаге 3, тогда принимающий сервер должен сгенерировать ошибку потока <invalid-id/> и прервать XML-поток и соответствующее TCP-соединение. Если значение адреса 'to' не соответствует имени машины, распознанному принимающим сервером, тогда принимающий сервер должен выработать ошибку потока <host-unknown/> и разорвать TCP-соединение. Если значение адреса 'from' не соответствует имени машины, представленному исходным сервером при открытии TCP-соединения, тогда принимающий сервер должен выработать ошибку потока <invalid-from/> и разорвать TCP-соединение. После возвращения флага верификации принимающему серверу, управляющий сервер должен прервать поток между ними.

  17. Принимающий сервер информирует исходный сервер о результате:
<db:result
       from='принимающий сервер'
       to='исходный сервер'
       type='valid'/>

Замечание: В этой точке, соединение либо верифицировано type='valid', либо объявлено некорректным. Если соединение некорректно, принимающий сервер должен прервать XML-поток и разорвать TCP-соединение. Если соединение верифицировано, исходный сервер начинает посылать данные, которые читаются принимающим сервером; перед этим все XML-строфы, посланные принимающему серверу должны быть молча отброшены.

Результатом всего предшествующего является то, что принимающий сервер проверил идентичность исходного сервера, таким образом управляющий сервер может посылать, а принимающий сервер принимать XML-строфы через "исходный поток" (т.е., поток от исходного к принимающему серверу). Для того чтобы верифицировать идентичности объектов, используя "поток-отклик" (т.е., поток от принимающего сервера к исходному серверу), должен быть осуществлен также dialback ("обратный дозвон") в обратном направлении.

После успешного выполнения процедуры dialback, принимающий сервер должен воспринять последующие пакеты <db:result/> (например, запросы валидации, посланные субдомену или другой машине, обслуживаемой принимающим сервером) от исходного сервера через имеющееся верифицированное соединение.

Даже если согласование dialback успешно, сервер должен проверить, что все XML-строфы полученные от другого сервера содержат атрибуты 'from' и 'to'; если строфа не следует этому ограничению, сервер, который получает строфу должен сформировать сообщение об ошибке потока <improper-addressing/> и разорвать TCP-соединение. Кроме того, сервер должен проверить, что атрибут 'from' строфы, полученной от другого сервера, содержит верифицированное имя домена для потока; если строфа не отвечает этим ограничениям, сервер, который получает строфу, должен сформировать ошибку потока <invalid-from/> и разорвать соединение.

9. XML-строфы

После согласования применения TLS (раздел 5), SASL (раздел 6) и подключения ресурсов (раздел 7), если требуется, можно начать пересылку через поток XML-строф. Определены три типа XML-строф для пространств имен 'jabber:client' и 'jabber:server': <message/>, <presence/> и <iq/>. Кроме того, существует пять общих атрибутов для трех видов строф. Ниже описаны эти общие атрибуты, так же как базовая семантика трех видов строф, более детальную информацию о синтаксисе XML-строф и их применении можно найти в [3].

Общие атрибуты

Следующие пять атрибутов являются общими для сообщений, данных о присутствии и IQ-строф:

Атрибут 'to' специфицирует JID получателя строфы.

В пространстве имен 'jabber:client', строфа должна иметь атрибут 'to', хотя строфа, посланная от клиента серверу, для обработки сервером (например, данные о присутствии, посланные серверу для широковещательной рассылки другим объектам) не должна содержать атрибут 'to'.

В пространстве имен 'jabber:server' строфа должна иметь атрибут 'to'; если сервер получает строфу, которая не отвечает этим ограничениям, он должен сформировать ошибку потока <improper-addressing/> и разорвать соединение.

Если значение атрибута 'to' некорректно, объект, выяснивший этот факт, должен вернуть соответствующую ошибку отправителю, установив атрибут 'from' строфы-ошибки равной содержимому атрибуту 'to' исходной строфы.

Атрибут 'from' специфицирует JID отправителя.

Когда сервер получает XML-строфа в контексте аутентифицированного потока, сопряженного с пространством имен 'jabber:client', он должен сделать следующее:

  1. проверить, что значение атрибута 'from', предложенное клиентом, соответствует подключенному ресурсу для ассоциированного объекта
  2. добавить адрес 'from' к строфе, чье значение равно чистому JID (<node@domain>) или полный JID (<node@domain/resource>), определенный сервером для подключенного ресурса, который сформировал строфу (смотри "Определение адресов" (раздел 3))

Если клиент пытается послать XML-строфу, для которой значение атрибута 'from' не соответствует одному из подключенных ресурсов для данного объекта, сервер должен прислать клиенту ошибку потока <invalid-from/>. Если клиент пытается послать XML-строфу через поток, который еще не аутентифицирован, сервер должен вернуть клиенту ошибку потока <not-authorized/>. Если имеют место оба эти условия, со соединение прерывается. Это помогает исключить атаку отказа в обслуживании, запущенную недобросовестным клиентом.

Когда сервер генерирует строфу от своего имени для доставки подключенному клиенту (например, в контексте сервиса памяти, предоставляемого сервером клиенту), строфа либо не должна включать в себя атрибут 'from' либо включать атрибут 'from', чье значение является чистым JID аккоунта (<node@domain>) или полным JID клиента (<node@domain/resource>). Сервер не должен посылать клиенту строфу без атрибута 'from', если строфа не была сформирована самим сервером. Когда клиент получает строфу, которая не содержит атрибута 'from', он должен полагать, что строфа пришла от сервера, с которым клиент соединен.

В пространстве имен 'jabber:server', строфа должна иметь атрибут 'from'; если сервер получает строфу, которая не отвечает этому ограничению, он должен генерировать ошибку потока <improper-addressing/>. Кроме того, секция доменного идентификатора JID, содержащаяся в атрибуте 'from', должна соответствовать имени машины отправляющего сервера (или любой проверенный домен, такой как субдомен сервера-отправителя). Если сервер получает строфу, которая не отвечает этому ограничению, он должен сформировать сообщение об ошибке <invalid-from/>.

Опционный атрибут 'id' может использоваться объектом-отправителем для внутреннего отслеживания строф, которые он отправляет и получает (в частности для отслеживания взаимодействий типа запрос-отклик, типичных для семантики IQ-строф). Для атрибута 'id' глобальная уникальность является опционной в рамках домена или потока.

Атрибут 'type' специфицирует данные о целях или контексте сообщения, данные о присутствии или IQ-строфы. Конкретные допустимые значения атрибута 'type' сильно зависят от того, является ли строфа сообщением, данными о присутствии или IQ. Значения для строф сообщений и данных о присутствии являющиеся специфичными для технологии сообщений реального времени, они описаны в [3], тогда как значения для IQ-строф специфицируют роль IQ-строф в структурированном диалоге запрос-отклик (раздел 9). Единственным общим для всех трех типов строф является ошибка; смотри "Ошибки строф" (раздел 9).

xml:lang

Строфа должна иметь атрибут 'xml:lang' (как это описано в разделе 2.12 [1]), если строфа содержит символьные данные, которые предназначены для обычного пользователя-человека (как описано в RFC 2277 [26], "Интернационализация для людей"). Значение атрибут 'xml:lang' специфицирует язык по умолчанию любых символьных данных, которое может быть переписано атрибутом 'xml:lang' дочернего элемента. Если строфа не имеет атрибута 'xml:lang', реализация должна предполагать, что действует значение языка по умолчанию, специфицированное для потока, как это определено выше в раздел 4. Значение атрибута 'xml:lang' должно быть NMTOKEN и должно соответствовать формату, определенному в RFC 3066 [16].

Базовая семантика
Семантика сообщений

Тип строф <message/> можно рассматривать как "push"-механизм, поскольку один объект "проталкивает" информацию другому объекту, подобно коммуникациям, которые осуществляются в системах типа электронной почты. Все строфы сообщений имеют атрибут 'to', который специфицирует получателя сообщения. После получения такой строфы сервер должен переадресовать или доставить ее адресату (смотри "Серверные правила для обработки XML-строф" (раздел 10)).

Семантика присутствия

Элемент <presence/> может рассматриваться как механизм широковещательного уведомления, посредством чего многие объекты получают информацию об объекте, на которую они подписались (в данном случае информация о доступности сети). Вообще, уведомляющий объект должен послать строфу присутствия без атрибута 'to', серверу, который должен широковещательно переслать ее всем объектам-подписчикам. Однако уведомляющий объект может также послать строфу присутствия с атрибутом 'to', в этом случае сервер должен обеспечить доставку строфы конкретному адресату. Общие правила переадресации и доставки строф смотри в главе "Серверные правила обработки XML-строф" (раздел 10) и в [3].

Семантика IQ

Info/Query, или IQ, представляет собой механизм запросов-откликов, сходный в некотором роде с [14]. Семантика IQ делает возможными для объекта отправку запросов и получение откликов другого объекта. Информационное содержание запроса и отклика определяется декларацией пространства имен дочернего объекта IQ-элемента, а диалог отслеживается запрашивающим объектом с помощью атрибута 'id'. Таким образом, за стандартным обменом структурированными данными, такими как get/result или set/result следует IQ-диалог (хотя в отклике на запрос при определенных условиях может быть прислано сообщение об ошибке):

Рис. 3. Диалог запрос-отклик

Для того чтобы усилить данную семантику, применены следующие правила:

  1. Для IQ-строф необходим атрибут 'id'.
  2. Для IQ-строф необходим атрибут 'type'. Значение должно быть из числа перечисленных ниже.



  3. Объект, который получает IQ-запрос типа "get" или "set" должен ответит IQ-откликом типа "result" или "error" (отклик должен сохранить атрибут 'id' запроса).
  4. Объект, который получает строфу типа "result" или "error" не должен откликаться на строфу посылкой следующего IQ-отклика типа "result" или "error"; однако, как показано выше, запрашивающий объект может послать еще один запрос (например, IQ типа "set" для того чтобы предоставить нужную информацию, выявленную в результате обмена get/result).
  5. IQ-строфа типа "get" или "set" должна содержать один и только один дочерний элемент, который специфицирует семантику конкретного запроса или отклика.
  6. IQ-строфа типа "result" должна содержать нуль или один дочерний элемент.
  7. IQ-строфа типа "error" должна содержать дочерний элемент, содержащийся в соответствующем "get" или "set" и должна включать в себя дочерний элемент <error/>. Подробности смотри в главе "ошибки строф" (раздел 9).

Ошибки строф

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

Правила

В отношении ошибок, связанных со строфами, используются следующие правила:

Синтаксис

Синтаксис для ошибок, связанных со строфами, представлен ниже:

<stanza-kind to='sender' type='error'>
     [RECOMMENDED to include sender XML here]
     <error type='error-type'>
       <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
       <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'
             xml:lang='langcode'>
         OPTIONAL descriptive text
       </text>
       [OPTIONAL application-specific condition element]
     </error>
   </stanza-kind>

Вид строфы может принимать значение message (сообщение), presence (присутствие) или iq.

Значение элемента <error/> атрибута 'type' должно принимать одно из следующих значений:

Элемент <error/>:

Элемент <text/> является опционным. Когда включается, он должен использоваться только для передачи описательной и диагностической информации, которая является дополнительной и служит для пояснения специфических условий приложения. Он не должен интерпретироваться приложением программно. Он не должен использоваться в качестве сообщения об ошибке пользователю.

Наконец, для обеспечения обратной совместимости, схема (специфицированная в [3]) позволяет опционное включение атрибута 'code' элемента <error/>.

Определенные условия

Определены следующие условия использования ошибок строф.

Условия специфические для приложения

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

<iq type='error' id='some-id'>
     <error type='modify'>
       <bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
       <too-many-parameters xmlns='application-ns'/>
     </error>
   </iq>

   <message type='error' id='another-id'>
     <error type='modify'>
       <undefined-condition
             xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
       <text xml:lang='en'
             xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
         Some special application diagnostic information...
       </text>
       <special-application-condition xmlns='application-ns'/>
     </error>
   </message>

10. Правила сервера для обработки XML-строф

Адаптивные реализации сервера должны гарантировать надлежащую обработку XML-строф между любыми двумя объектами.

За пределами требований нормальной обработки реализация каждого сервера будет содержать свои собственные "деревья доставки" для обслуживания приходящих к ним строф. Такое дерево определяет, нуждается ли строфа в переадресации в другой домен, будет ли обработана локально или доставлена ресурсу, сопряженному с соседним узлом. Здесь используются следующие правила:

Нет адреса 'to'

Если строфа не имеет атрибута 'to', сервер должен обработать ее для объекта, ее пославшего. Так как все строфы, полученные от других серверов, должны иметь атрибут 'to' , это правило приложимо только к строфам, полученных от зарегистрированных объектов (таких как клиент), т.е. подключенных к серверу. Если сервер получает строфу присутствия без атрибута 'to', сервер должен послать ее широковещательно объектам, которые подписаны на посылку данных присутствия, если это возможно (семантика широковещательных данных для обмена сообщениями и данными присутствия определена в [3]). Если сервер получает IQ-строфу типа "get" или "set" без атрибута 'to' и он понимает пространство имен, которое соотнесено с содержимым строфы, он должен либо обработать строфу от имени отправителя (где под словом "обработать" подразумевается семантика соответствующего пространства имен) или прислать отпраителю сообщение об ошибке.

Чужой домен

Если имя машины секции идентификатора домена JID содержит атрибут 'to', который не согласуется со сконфигурированными именами самого сервера или субдомена, сервер должен переадресовать строфу внешнему домену. Возможны два случая:

Между двумя доменами уже имеется поток сервер-сервер: существуют маршруты строф сервера к управляющему серверу для внешнего домена через существующий поток.

Между двумя доменами не существует потока сервер-сервер: Сервер
(1) выясняет имя машины для внешнего домена (как это определено для коммуникаций сервер-сервер (раздел 14)),
(2) согласует поток сервер-сервер между двумя доменами (как это определено для применения TLS (раздел 5) и использует SASL (раздел 6)), и
(3) переадресует строфу управляющему серверу для внешнего домена через вновь созданный поток.

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

Субдомен

Если имя машины секции идентификатора домена JID, содержащегося в атрибуте 'to', соответствует субдомену одного из сконфигурированных имен самого сервера, сервер должен либо обработать строфу сам, либо переадресовать ее специализированному сервису, который ответственен за субдомен (если субдомен сконфигурирован), или послать уведомление об ошибке отправителю (если субдомен не сконфигурирован).

Полный домен или специфические ресурсы

Если имя машины секции идентификатора домена JID, содержащегося в атрибуте 'to', соответствует сконфигурированному имени самого сервера, а JID, содержащий атрибут 'to', имеет формат <domain> или <domain/resource>, сервер (или определенный ресурс) должен либо обрабатывать строфу или возвращать отправителю ошибку.

Узел в том же домене

Если имя машины секции идентификатора домена JID, содержащееся в атрибуте 'to', соответствует субдомену одного из сконфигурированных имен самого сервера, а JID, содержащий атрибут 'to', имеет формат <node@domain> или <node@domain/resource>, сервер должен доставить строфу адресату строфы, согласно JID, содержащемуся в атрибуте 'to'. Используются следующие правила:

  1. Если JID содержит идентификатор ресурса (т.е., имеет форму <node@domain/resource>) и существует подключенный ресурс, который соответствует полному JID, сервер получателя должен вставить строфу в поток или сессию, которая соответствует идентификатору ресурса.
  2. Если JID содержит идентификатор ресурса и не существует подключенного ресурса, который соответствует полному JID, сервер получателя должен прислать отправителю ошибку строфы <service-unavailable/>.
  3. Если JID имеет формат <node@domain> и в узле существует, по крайней мере, один подключенный ресурс, сервер получателя должен доставить строфу одному из подключенных ресурсов, согласно правилам приложения (набор правил доставки сообщения и данных о положении определен в [3]).

11. Использование XML в XMPP

Ограничения

XMPP является упрощенным и специализированным протоколом для потоковых элементов XML, для того чтобы обмениваться структурированной информацией в режиме близком к реальному времени. Так как XMPP не требует парсинга произвольных XML-документов, не существует никаких требований, которые должен поддерживать XMPP [1]. В частности, используются следующие ограничения.

Что касается XML-генерации, XMPP-реализации не должны вводить в XML-поток следующие вещи:

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

Имена XML-пространства имен и префиксов

Пространство имен XML [17] используется в рамках XMPP-подобных XML, чтобы сформировать четкие границы принадлежности данных. Основной функцией пространства имен является разделение различных словарей XML-элементов, которые структурно перемешаны. Гарантия того, что XMPP-подобные XML знакомы с пространством имен, делает возможным структурное перемешивание любых допустимых XML с любыми элементами данных в рамках XMPP. Правила для пространства имен XML и префиксов определены в следующих подразделах.

Пространство имен потоков

Декларацией пространства имен потока для всех заголовков XML-потока является обязательной. Имя пространства имен потока должно быть 'http://etherx.jabber.org/streams'. Элемент имен элемента <stream/> и его дочерних элементов <features/> и <error/> должны быть заданы во всех случаях префиксом пространства имен потоков. Реализация должна генерировать для этих элементов только префикс 'stream:'.

Пространство имен по умолчанию

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

Реализация сервера должна поддерживать следующие два пространства имен по умолчанию:

Реализация клиента должна поддерживать пространство имен по умолчанию 'jabber:client'.

Реализация не должна генерировать префиксы пространства имен для элементов в пространстве имен по умолчанию, если это пространство имен 'jabber:client' или 'jabber:server'. Реализация не должна генерировать префиксов пространства имен для элементов, квалифицируемых по содержанию (в противоположность потоку) пространства имен, отличного от 'jabber:client' и 'jabber:server'.

Замечание: Пространства имен 'jabber:client' и 'jabber:server' являются почти идентичными, но используются в различных контекстах (коммуникации клиент-сервер для 'jabber:client' и коммуникации сервер-сервер для 'jabber:server'). Единственное отличие между ними заключается в том, что атрибуты 'to' и 'from' являются опционными для строф, посланных в рамках 'jabber:client', в то время как они обязательны для строф, посланных в рамках 'jabber:server'. Если реализация принимает поток, который соотносится с пространствами имен 'jabber:client' или 'jabber:server', она должна поддерживать общие атрибуты (раздел 9) и базовую семантику (раздел 9) всех трех главных видов строф (сообщение, присутствие и IQ).

Пространство имен Dialback

Декларация пространства имен dialback является обязательной для всех элементов, используемых в серверном dialback (раздел 8). Имя пространства имен dialback должно быть 'jabber:server:dialback'. Все элементы, соотнесенные с этим пространством имен, должны иметь префикс. Реализация должна генерировать для таких элементов только префикс 'db:' и может воспринимать только префикс 'db:'.

Валидация

За исключением, как отмечено в отношении адресов 'to' и 'from' для строф из пространства имен 'jabber:server', сервер не несет ответственности за валидацию XML-элементов, переадресуемых клиенту или другому серверу. Конкретная реализация может решить предоставлять только проверенные информационные элементы, но это является опционным (хотя реализация не должна воспринимать XML, которые плохо сформатированы). Клиенты не должны полагаться на возможность посылки данных, неследующих заданным формам, и должны игнорировать любые нестандартные элементы или атрибуты во входном XML-потоке. Валидация XML-потоков и строф является опционной.

Включение текстовых деклараций

Реализации должны посылать текстовые декларации до посылки заголовка потока. Приложения должны следовать правилам из [1], в зависимости от обстоятельств, при которых включается текстовая декларация.

Кодирование символов

Реализации должны поддерживать UTF-8 (RFC 3629 [28]) преобразования универсального символьного набора (ISO/IEC 10646-1 [29]), как этого требует RFC 2277 [26]. Реализации не должны пытаться использовать любые другие виды кодирования.

12. Основные требования совместимости

Этот раздел суммирует специфические аспекты протокола XMPP, которые должны поддерживаться серверами и клиентами, для того чтобы быть совместимыми. Для целей совместимости мы проводим различие между базовыми протоколами (которые должны поддерживаться любым сервером или клиентом, вне зависимости от специфичности приложений) и протокола отправки сообщений в реальном масштабе времени (IM) (которые должны поддерживаться IM и приложениями присутствия, работающими поверх базовых протоколов). Требования совместимости, которые приложимы ко всем серверам и клиентам, специфицированы ниже. Требования совместимости для IM серверов и клиентов описаны в разделе [3].

Серверы

В дополнение ко всем определенным требованиям с учетом безопасности сервер должен поддерживать следующие базовые протоколы:

Кроме того сервер может поддерживать серверный dialback (раздел 8).

Клиенты

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

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

13. Соображения интернационализации

XML-потоки должны кодироваться в UTF-8, как это специфицировано в главе "Кодирование символов" (раздел 11). Согласно описанию атрибутов потока (раздел 4), XML-поток должен содержать атрибут 'xml:lang', значение которого рассматривается как язык по умолчанию для любых символьных XML-данных, пересылаемых через поток, который предназначен для восприятия человеком. Как это специфицировано в xml:lang (раздел 9), XML-строфа должна включать в себя атрибут 'xml:lang', если строфа содержит символьные XML-данные, которые предназначены пользователю-человеку. Сервер должен использовать значение атрибута 'xml:lang' по умолчанию для строф, которые он переадресовывает или доставляет одному из подключенных объектов, и не должен модифицировать или удалять атрибуты 'xml:lang' из строф, которые он получает от других объектов.

14. Соображения безопасности

Высокая безопасность

Для целей XMPP-коммуникаций (клиент-сервер и сервер-сервер), термин "Высокая безопасность" относится к использованию технологий безопасности, которые обеспечивают как взаимную аутентификацию, так и проверку целостности; в частности, когда для гарантии безопасности используется аутентификация, основанная на применении сертификатов, цепочка проверки должна использовать свои маршруты. В отношении процедуры проверки сертификатов смотри раздел 14 ниже.

Реализации должны поддерживать высокую безопасность. Предоставление услуг должно предполагать применение высокой безопасности.

Валидация сертификатов

Когда XMPP-партнер осуществляет связь с другим объектом безопасным образом, он должен проверить сертификат партнера. Существует три возможных варианта:

Случай #1: Партнер имеет сертификат оконечного объекта, который оказывается сертифицирован цепочкой сертификатов (как описано в разделе 6.1 [31]).

Случай #2: Сертификат партнера подтвержден центром сертификации, неизвестным проверяющему партнеру.

Случай #3: Сертификат партнера подписан им самим.

В случае #1, осуществляющий валидацию партнер должен выполнить одну из двух вещей:

  1. Верифицировать сертификат партнера согласно правилам [31]. Сертификат должен быть затем проверен на предмет ожидаемой идентичности партнера согласно правил из [32], за исключением того, что для идентификации партнера должно использоваться расширение subjectAltName типа "xmpp" (если имеется). Если одна из этих проверок не прошла, клиенты, ориентированные на пользователя, должны либо уведомить пользователя (клиенты в любом случае могут дать возможность пользователю сохранить соединение) или разорвать соединение с "неисправимой ошибкой сертификата". Автоматические клиенты должны разорвать соединение и сделать запись в соответствующий журнальный файл. Автоматические клиенты могут предоставить конфигурационные установки, которые блокируют эту проверку, но должны предоставить возможность ее восстановления.
  2. Партнер должен предъявить сертификат пользователю для одобрения, включая всю сертификационную цепочку. Партнер должен кэшировать сертификат (или некоторую неподделываемую презентацию сертификата типа хэша). При будущих соединениях партнер должен верифицировать факт идентичности предъявляемого сертификата и уведомлять пользователя, если он изменился.

В случае #2 и #3, реализации должны действовать как в (2) выше.

Коммуникации клиент-сервер

Совместимые клиентские реализации должны поддерживать для подключения сервера как TLS, так и SASL.

Протокол TLS для криптографического преобразования XML-потоков (определенного в рамках использования TLS (раздел 5)) предоставляет надежный механизм гарантирования конфиденциальности и целостности данных, пересылаемых между двумя объектами.

Протокол SASL для аутентификации XML-потоков (определено в главе "Использование SASL" (раздел 6)) предоставляет надежный механизм валидации того, что клиент, подключенный к серверу, является тем, за кого он себя выдает.

Коммуникации клиент-сервер не должны осуществляться, до тех пор пока имя машины, представленное сервером не будет выявлено. Такие процедуры сначала должны пытаться выяснить имя машины, используя сервис [24] "xmpp-client" и протокол "tcp", получая в результате рекорды типа "_xmpp-client._tcp.example.com." (использование строки "xmpp-client" для идентификатора сервиса согласуется с регламентациями IANA). Если SRV lookup терпит неудачу, методом решения проблемы будет выявление IPv4/IPv6-адресов, используя "xmpp-client" порт 5222, стандартизованный IANA.

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

Коммуникации сервер-сервер

Совместимые реализации сервера должны для междоменных коммуникаций поддерживать как TLS, так и SASL. По историческим причинам, совместимые реализации сервера должны поддерживать Dialback (раздел 8).

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

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

Междоменные соединения не должны функционировать до тех пор, пока имена машин, предоставленные сервером, не были идентифицированы. Такая процедура для получения ресурсных записей "_xmpp-server._tcp.example.com." должна сначала воспользоваться сервисом "xmpp-server" [24] и протоколом "tcp" (использование строки "xmpp-server" для идентификатора сервиса согласуется с требованиями IANA. Заметим, что идентификатор "xmpp-server" заменил ранее использовавшийся "jabber". Если процедура SRV lookup терпит неудачу, следует выяснить традиционный IPv4/IPv6 адрес, используя "xmpp-server" порт 5269, зарегистрированный IANA.

Серверный dialback помогает защититься от фальсификации домена, делая более трудным фальсификацию XML-строф. Это не механизм аутентификации, обеспечения безопасности или шифрования строф между серверами, как это делается с помощью SASL и TLS. Процедура предлагает лишь слабую верификацию идентичности сервера. Кроме того, эта процедура уязвима для атак фальсификации DNS, если только не используется DNSSec [33], и даже если информация DNS корректна, dialback не может защитить от атак, в которых атакер может украсть IP-адрес удаленного домена. Домены, требующие надежной безопасности должны использовать TLS и SASL. Если для аутентификации сервер-сервер используется SASL, dialback не следует использовать в силу полной бесполезности.

Порядок слоев

Порядок протокольных слоев в стеке должен быть следующим:

  1. TCP
  2. TLS
  3. SASL
  4. XMPP

Разумность такого порядка заключается в том, что он является основой [13] упорядочения для всего стека протоколов, работающих поверх TCP.

Необходимость SASL для подключения канала к TLS

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

Обязательные для использования технологии

По минимуму все реализации должны поддерживать следующие механизмы:

для аутентификации: механизм SASL [34]

для конфиденциальности: TLS (используя шифр TLS_RSA_WITH_3DES_EDE_CBC_SHA)

для обоих: TLS плюс SASL EXTERNAL(используя TLS_RSA_WITH_3DES_EDE_CBC_SHA шифр, поддерживающий сертификаты стороны клиента)

Firewalls

Коммуникации, использующие XMPP, в норме происходят поверх соединения через порт 5222 [13] (клиент-сервер) или порт 5269 (сервер-сервер), как это зарегистрировано IANA (смотри "Соображения IANA" (раздел 15)). Использование этих стандартных портов позволяет администраторам легко разрешить или запретить XMPP, делается это с помощью существующих стандартных firewall. Практика использования XMPP показала, что многие сервисы XMPP требуют криптографической защиты, например, посредством TLS.

Использование кодирования base64 в SASL

Как клиент так и сервер должны верифицировать любые данные [25], полученные в ходе согласования SASL. Реализация должна отвергать (или игнорировать) любые символы, которые неявно разрешены в кодировке base64. Это помогает защититься от создания скрытого канала, который может использоваться для "утечки" информации. Реализация не должна разрывать соединение при некорректном вводе, она должна отвергать любую последовательность символов base64, содержащую символ ('='), если такой символ включен не в качестве последнего символа данных (например, "=AAA" или "BBBB=CCC"). Это помогает защититься от атак переполнения буфера и некоторых других атак. Кодировка base64 визуально скрывает легко узнаваемую текстовую информацию, такую как пароли, но не обеспечивает конфиденциальности. Кодировка base64 должна следовать определениям из раздела 3 RFC 3548 [25].

Профайлы Stringprep

XMPP использует профайл [30] из [11] для обработки идентификаторов доменов. Соображения безопасности, относящиеся к Nameprep, рассмотрены в соответствующем разделе [30].

Кроме того, XMPP определяет два профайла [11]: Nodeprep (Приложение A) для идентификаторов узлов и Resourceprep (Приложение B) для идентификаторов ресурсов.

В символьных наборах Unicode и ISO/IEC 10646 имеется много символов, которые выглядят сходным образом. Во многих случаях, пользователи протоколов безопасности могут осуществить визуальное распознавание имен объектов. Так как невозможно установить соответствие для символов идентичного вида без учета контекста (например, знания того, какой шрифт использован) stringprep не делает ничего для установления соответствия между идентично выглядящими символами и не запрещает использования таких символов.

Идентификатор узла может использоваться в качестве части адреса объекта в XMPP. Безопасность таких сервисов может быть скомпрометирована с помощью различной интерпретации интернациализированных идентификаторов узлов. Например, пользователь, вводящий один интернационализированный идентификатор может получить доступ к информации аккоунта другого пользователя.

Идентификатор ресурса может использоваться как часть адреса объекта в XMPP. Одним общим применением является имя пользователя при IM (активная сессия); другим может быть прозвище пользователя при многопользовательской сессии. Безопасность таких сервисов может быть скомпрометирована с помощью разной интерпретации интернациализированных идентификаторов узлов. например, пользователь может попытаться инициировать несколько сессий под одним и тем же именем, или пользователь может послать сообщение кому-то отличному от зарегистрированного получателя многопользовательской сессии.

15. Соображения IANA

Имя XML-пространства имен для данных TLS

Субпространство имен URN для данных, связанных с TLS, в XMPP определено следующим образом. Это пространство имен сопряжено с форматом, определенным в IETF XML Registry [35].

URI: urn:ietf:params:xml:ns:xmpp-tls
   Specification: RFC 3920
   Description: This is the XML namespace name for TLS-related data in the Extensible Messaging and Presence Protocol (XMPP) as defined by RFC 3920.
   Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>

Имя XML-пространства имен для данных SASL

Субпространство имен URN для данных, связанных с SASL, в XMPP определено следующим образом. Это пространство имен сопряжено с форматом, определенным в [35].

URI: urn:ietf:params:xml:ns:xmpp-sasl
   Specification: RFC 3920
   Description: This is the XML namespace name for SASL-related data in the Extensible Messaging and Presence Protocol (XMPP) as defined by RFC 3920.
   Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>

Имя XML-пространства имен для ошибок потока

Субпространство имен URN для данных, связанных ошибками потоков в XMPP определено следующим образом. Это пространство имен сопряжено с форматом, определенным в [35].

URI: urn:ietf:params:xml:ns:xmpp-streams
   Specification: RFC 3920
   Description: This is the XML namespace name for stream-related error data in the Extensible Messaging and Presence Protocol (XMPP) as defined by RFC 3920.
   Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>

Имя XML-пространства имен для подключения ресурсов

Субпространство имен URN для подключения ресурсов в XMPP (Extensible Messaging and Presence Protocol) определяется следующим образом. Это имя пространства имен соответствует формату, определенному в [35].

URI: urn:ietf:params:xml:ns:xmpp-bind
   Specification: RFC 3920
   Description: This is the XML namespace name for resource binding in the Extensible Messaging and Presence Protocol (XMPP) as defined by RFC 3920.
   Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>

Имя XML-пространства имен для ошибок строф

Субпространство имен URN для данных, связанных с ошибками строф в XMPP определено следующим образом. Это имя пространства имен соответствует формату, определенному в [35].

URI: urn:ietf:params:xml:ns:xmpp-stanzas
   Specification: RFC 3920
   Description: This is the XML namespace name for stanza-related error
      data in the Extensible Messaging and Presence Protocol (XMPP) as
      defined by RFC 3920.
   Registrant Contact: IETF, XMPP Working Group, <xmppwg@jabber.org>

Nodeprep-профайл Stringprep

Профайл Nodeprep для stringprep определен в рамках Nodeprep (Приложение A). IANA зарегистрировала Nodeprep в регистре профайлов stringprep.

Имя этого профайла:
Nodeprep

RFC, в котором описан профайл:
RFC 3920

<
h3>Профайл Resourceprep из Stringprep

Профайл Resourceprep из stringprep определен в рамках Resourceprep (Приложение B). IANA зарегистрировала Resourceprep в регистре профайлов stringprep.

Имя сервиса GSSAPI

IANA зарегистрировала "xmpp" в качестве имени сервиса GSSAPI [36], как это задано в рамках определения SASL (раздел 6).

Номера портов

IANA зарегистрировала ключевые слова xmpp-client и xmpp-server для обозначения номеров портов для ТСР-обмена 5222 и 5269, соответственно. Эти номера портов следует использовать для обменов клиент-сервер и сервер-клиент.

16. Ссылки

1 Bray, T., Paoli, J., Sperberg-McQueen, C., and E. Maler, "Extensible Markup Language (XML) 1.0 (2nd ed)", W3C REC-xml, October 2000, .
2Day, M., Aggarwal, S., Mohr, G., and J. Vincent, "Instant Messaging / Presence Protocol Requirements", RFC 2779, February 2000.
3Saint-Andre, P., Ed., "Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence", RFC 3921, October 2004.
4Klensin, J., "Simple Mail Transfer Protocol", RFC 2821, April 2001.
5Oikarinen, J. and D. Reed, "Internet Relay Chat Protocol", RFC 1459, May 1993.
6SIMPLE Working Group, "SIMPLE WG", SIMPLE
7Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
8rocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
9Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, November 1987.
10Faltstrom, P., Hoffman, P., and A. Costello, "Internationalizing Domain Names in Applications (IDNA)", RFC 3490, March 2003.
11Hoffman, P. and M. Blanchet, "Preparation of Internationalized Strings ("stringprep")", RFC 3454, December 2002.
12Myers, J., "Simple Authentication and Security Layer(SASL)", RFC 2222, October 1997.
13Postel, J., "Transmission Control Protocol", STD 7, RFC-793, September 1981.
14Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
15Eastlake 3rd, D., Crocker, S., and J. Schiller, "Randomness Recommendations for Security", RFC 1750, December 1994.
16Alvestrand, H., "Tags for the Identification of Languages", BCP 47, RFC 3066, January 2001.
17Bray, T., Hollander, D., and A. Layman, "Namespaces in XML", W3C REC-xml-names, January 1999, <http://www.w3.org/tr/REC-xml-names>
18Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, January 1999.
19Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", RFC 3501, March 2003.
20Myers, J. and M. Rose, "Post Office Protocol - Version 3", STD 53, RFC 1939, May 1996.
21Newman, C. and J. Myers, "ACAP -- Application Configuration Access Protocol", RFC 2244, November 1997.
22Newman, C., "Using TLS with IMAP, POP3 and ACAP", RFC 2595, June 1999.
23CCITT, "Recommendation X.208: Specification of Abstract Syntax Notation One (ASN.1)", 1988.
24Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC2782, February 2000.
25Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 3548, July 2003.
26Alvestrand, H., "IETF Policy on Character Sets and Languages", BCP 18, RFC 2277, January 1998.
27Eastlake 3rd, D., Crocker, S., and J. Schiller, "Randomness Recommendations for Security", RFC 1750, December 1994
28Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
29International Organization for Standardization, "Information Technology - Universal Multiple-octet coded Character Set (UCS) - Amendment 2: UCS Transformation Format 8 (UTF-8)", ISO Standard 10646-1 Addendum 2, October 1996.
30Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)", RFC 3491, March 2003.
31Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, April 2002.
32Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
33Eastlake 3rd, D., "Domain Name System Security Extensions", RFC 2535, March 1999.
34Leach, P. and C. Newman, "Using Digest Authentication as a SASL Mechanism", RFC 2831, May 2000.
35Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, January 2004.
36Linn, J., "Generic Security Service Application Program Interface Version 2, Update 1", RFC 2743, January 2000.
37Kaes, C., "Definition of Jabber Identifiers (JIDs)", JSF JEP 0029, October 2003.
38Saint-Andre, P., "Non-SASL Authentication", JSF JEP 0078, July 2004.
39Norris, R. and P. Saint-Andre, "Error Condition Mappings", JSF JEP 0086, February 2004.
40Jabber Software Foundation, "Jabber Software Foundation", <http://www.jabber.org/>.

Приложение A. Nodeprep

A.1. Введение

Это приложение определяет профайл "Nodeprep" из [30]. Как таковой, он специфицирует правила обработки, которые позволят пользователям вводить интернационализированные идентификаторы узлов в XMPP и иметь при этом содержимое строк корректным. Идентификатор узла XMPP является опционной частью XMPP-адреса, которая предшествует идентификатору домена и сепаратору '@'. Он часто но не всегда ассоциируется именем пользователя при IM. Эти правила обработки ориентированы только на XMPP идентификаторы узлов, а не для произвольных текстов или любых аспектов XMPP-адреса.

Этот профайл определяет следующее, как это определено в [30]:

A.2. Репертуар символов

Этот профайл использует Unicode 3.2 со списком неприсвоенных кодовых значений таблицы A.1, определенной в Приложение A [30].

A.3. Соответствие

Этот профайл специфицирует соответствие при использовании таблиц из [11]:

      Table B.1
      Table B.2

A.4. Нормализация

Этот профайл специфицирует использование Unicode формы нормализации KC, как это описано в [30].

A.5. Запрещенный вывод

Этот профайл специфицирует запрет использования следующих таблиц из [30].

      Table C.1.1
      Table C.1.2
      Table C.2.1
      Table C.2.2
      Table C.3
      Table C.4
      Table C.5
      Table C.6
      Table C.7
      Table C.8
      Table C.9

Кроме того, запрещены также следующие Unicode-символы:

     #x22 (")
     #x26 (&)
     #x27 (')
     #x2F (/)
     #x3A (:)
     #x3C (<)
     #x3E (>)
     #x40 (@)

A.6. Реверсивные символы

Этот профайл специфицирует проверку реверсивных строк, как это описано в разделе 6 [30].

Приложение B. Resourceprep

B.1. Введение

Это приложение определяет профайл "Resourceprep" [30]. В этом качестве оно специфицирует правила обработки, которые позволят пользователю вводить интернационализированные идентификаторы ресурсов в XMPP и иметь высокий шанс получить содержимое строк корректным. (Идентификатор ресурса XMPP является опционной частью XMPP-адреса, которая следует за доменным идентификатором и сепаратором '/'. Он часто но не всегда является ассоциированным с именем сессии IM. Эти правила обработки предназначены для идентификаторов ресурсов XMPP и не ориентированы на работу с произвольными текстами или любыми другими аспектами XMPP-адреса.

Этот профайл определяет следующее (как это требуется [STRINGPREP]):

B.2. Символьный репертуар

Этот профайл использует Unicode 3.2 со списком неприсвоенных кодов из таблицы A.1, см. Приложение A [STRINGPREP].

B.3. Соответствие

Этот профайл специфицирует соответствие (mapping), использующее таблицу B.1 из [30]:

B.4. Нормализация

Этот профайл специфицирует использование формы KC нормализации Unicode, как это описано в [30].

B.5. Запрещенный вывод

Этот профайл специфицирует запрещенные для использования таблицы из [30].

      Table C.1.2
      Table C.2.1
      Table C.2.2
      Table C.3
      Table C.4
      Table C.5
      Table C.6
      Table C.7
      Table C.8
      Table C.9

B.6. Реверсивные символы

Этот профайл специфицирует проверку реверсивных строк, как это описано в разделе 6 [STRINGPREP].

Приложение C. XML-схемы

Следующие схемы XML являются описательными, а не нормативными. Для схем, определяющих пространства имен 'jabber:client' 'jabber:server', смотри [3].

C.1. Пространство имен потоков

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='http://etherx.jabber.org/streams'
       xmlns='http://etherx.jabber.org/streams'
       elementFormDefault='unqualified'>

     <xs:element name='stream'>
       <xs:complexType>
         <xs:sequence xmlns:client='jabber:client'
                      xmlns:server='jabber:server'
                      xmlns:db='jabber:server:dialback'>
           <xs:element ref='features' minOccurs='0' maxOccurs='1'/>
           <xs:any namespace='urn:ietf:params:xml:ns:xmpp-tls'
                   minOccurs='0'
                   maxOccurs='unbounded'/>
           <xs:any namespace='urn:ietf:params:xml:ns:xmpp-sasl'
                   minOccurs='0'
                   maxOccurs='unbounded'/>
           <xs:choice minOccurs='0' maxOccurs='1'>
             <xs:choice minOccurs='0' maxOccurs='unbounded'>
               <xs:element ref='client:message'/>
               <xs:element ref='client:presence'/>
               <xs:element ref='client:iq'/>
             </xs:choice>
             <xs:choice minOccurs='0' maxOccurs='unbounded'>
               <xs:element ref='server:message'/>
               <xs:element ref='server:presence'/>
               <xs:element ref='server:iq'/>
               <xs:element ref='db:result'/>
               <xs:element ref='db:verify'/>
             </xs:choice>
           </xs:choice>
           <xs:element ref='error' minOccurs='0' maxOccurs='1'/>
         </xs:sequence>
         <xs:attribute name='from' type='xs:string' use='optional'/>
         <xs:attribute name='id' type='xs:NMTOKEN' use='optional'/>
         <xs:attribute name='to' type='xs:string' use='optional'/>
         <xs:attribute name='version' type='xs:decimal' use='optional'/>
         <xs:attribute ref='xml:lang' use='optional'/>
       </xs:complexType>
     </xs:element>

     <xs:element name='features'>
       <xs:complexType>
         <xs:all xmlns:tls='urn:ietf:params:xml:ns:xmpp-tls'
                 xmlns:sasl='urn:ietf:params:xml:ns:xmpp-sasl'
                 xmlns:bind='urn:ietf:params:xml:ns:xmpp-bind'
                 xmlns:sess='urn:ietf:params:xml:ns:xmpp-session'>
           <xs:element ref='tls:starttls' minOccurs='0'/>
           <xs:element ref='sasl:mechanisms' minOccurs='0'/>
           <xs:element ref='bind:bind' minOccurs='0'/>
           <xs:element ref='sess:session' minOccurs='0'/>
         </xs:all>
       </xs:complexType>
     </xs:element>

     <xs:element name='error'>
       <xs:complexType>
         <xs:sequence  xmlns:err='urn:ietf:params:xml:ns:xmpp-streams'>
           <xs:group   ref='err:streamErrorGroup'/>
           <xs:element ref='err:text'
                       minOccurs='0'
                       maxOccurs='1'/>
         </xs:sequence>
       </xs:complexType>

     </xs:element>

   </xs:schema>

C.2. Пространство имен потоковых ошибок

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='urn:ietf:params:xml:ns:xmpp-streams'
       xmlns='urn:ietf:params:xml:ns:xmpp-streams'
       elementFormDefault='qualified'>

     <xs:element name='bad-format' type='empty'/>
     <xs:element name='bad-namespace-prefix' type='empty'/>
     <xs:element name='conflict' type='empty'/>
     <xs:element name='connection-timeout' type='empty'/>
     <xs:element name='host-gone' type='empty'/>
     <xs:element name='host-unknown' type='empty'/>
     <xs:element name='improper-addressing' type='empty'/>
     <xs:element name='internal-server-error' type='empty'/>
     <xs:element name='invalid-from' type='empty'/>
     <xs:element name='invalid-id' type='empty'/>
     <xs:element name='invalid-namespace' type='empty'/>
     <xs:element name='invalid-xml' type='empty'/>
     <xs:element name='not-authorized' type='empty'/>
     <xs:element name='policy-violation' type='empty'/>
     <xs:element name='remote-connection-failed' type='empty'/>
     <xs:element name='resource-constraint' type='empty'/>
     <xs:element name='restricted-xml' type='empty'/>
     <xs:element name='смотри-other-host' type='xs:string'/>
     <xs:element name='system-shutdown' type='empty'/>
     <xs:element name='undefined-condition' type='empty'/>
     <xs:element name='unsupported-encoding' type='empty'/>
     <xs:element name='unsupported-stanza-type' type='empty'/>
     <xs:element name='unsupported-version' type='empty'/>
     <xs:element name='xml-not-well-formed' type='empty'/>

     <xs:group name='streamErrorGroup'>
       <xs:choice>
         <xs:element ref='bad-format'/>
         <xs:element ref='bad-namespace-prefix'/>
         <xs:element ref='conflict'/>
         <xs:element ref='connection-timeout'/>
         <xs:element ref='host-gone'/>
         <xs:element ref='host-unknown'/>
         <xs:element ref='improper-addressing'/>
         <xs:element ref='internal-server-error'/>
         <xs:element ref='invalid-from'/>
         <xs:element ref='invalid-id'/>
         <xs:element ref='invalid-namespace'/>
         <xs:element ref='invalid-xml'/>
         <xs:element ref='not-authorized'/>
         <xs:element ref='policy-violation'/>
         <xs:element ref='remote-connection-failed'/>
         <xs:element ref='resource-constraint'/>
         <xs:element ref='restricted-xml'/>
         <xs:element ref='смотри-other-host'/>
         <xs:element ref='system-shutdown'/>
         <xs:element ref='undefined-condition'/>
         <xs:element ref='unsupported-encoding'/>
         <xs:element ref='unsupported-stanza-type'/>
         <xs:element ref='unsupported-version'/>
         <xs:element ref='xml-not-well-formed'/>
       </xs:choice>
     </xs:group>

     <xs:element name='text'>
       <xs:complexType>
         <xs:simpleContent>
           <xs:extension base='xs:string'>
             <xs:attribute ref='xml:lang' use='optional'/>
           </xs:extension>
         </xs:simpleContent>
       </xs:complexType>
     </xs:element>

     <xs:simpleType name='empty'>
       <xs:restriction base='xs:string'>
         <xs:enumeration value=''/>
       </xs:restriction>
     </xs:simpleType>

   </xs:schema>

C.3. Пространство имен TLS

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='urn:ietf:params:xml:ns:xmpp-tls'
       xmlns='urn:ietf:params:xml:ns:xmpp-tls'
     <xs:element name='starttls'>
       <xs:complexType>
         <xs:sequence>
           <xs:element
               name='required'
               minOccurs='0'
               maxOccurs='1'
               type='empty'/>
         </xs:sequence>
       </xs:complexType>
     </xs:element>

     <xs:element name='proceed' type='empty'/>
     <xs:element name='failure' type='empty'/>

     <xs:simpleType name='empty'>
       <xs:restriction base='xs:string'>
         <xs:enumeration value=''/>
       </xs:restriction>
     </xs:simpleType>

   </xs:schema>

C.4. Пространство имен SASL

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='urn:ietf:params:xml:ns:xmpp-sasl'
       xmlns='urn:ietf:params:xml:ns:xmpp-sasl'
       elementFormDefault='qualified'>

     <xs:element name='mechanisms'>
       <xs:complexType>
         <xs:sequence>
           <xs:element name='mechanism'
                       maxOccurs='unbounded'
                       type='xs:string'/>
         </xs:sequence>
       </xs:complexType>
     </xs:element>

     <xs:element name='auth'>
       <xs:complexType>
         <xs:simpleContent>
           <xs:extension base='empty'>
             <xs:attribute name='mechanism'
                           type='xs:string'
                           use='optional'/>
           </xs:extension>
         </xs:simpleContent>
       </xs:complexType>
     </xs:element>

     <xs:element name='challenge' type='xs:string'/>
     <xs:element name='response' type='xs:string'/>
     <xs:element name='abort' type='empty'/>
     <xs:element name='success' type='empty'/>

     <xs:element name='failure'>
       <xs:complexType>
         <xs:choice minOccurs='0'>
           <xs:element name='aborted' type='empty'/>
           <xs:element name='incorrect-encoding' type='empty'/>
           <xs:element name='invalid-authzid' type='empty'/>
           <xs:element name='invalid-mechanism' type='empty'/>
           <xs:element name='mechanism-too-weak' type='empty'/>
           <xs:element name='not-authorized' type='empty'/>
           <xs:element name='temporary-auth-failure' type='empty'/>
         </xs:choice>
       </xs:complexType>
     </xs:element>
     <xs:simpleType name='empty'>
       <xs:restriction base='xs:string'>
         <xs:enumeration value=''/>
       </xs:restriction>
     </xs:simpleType>

   </xs:schema>

C.5. Пространство имен подключения ресурсов

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='urn:ietf:params:xml:ns:xmpp-bind'
       xmlns='urn:ietf:params:xml:ns:xmpp-bind'
       elementFormDefault='qualified'>

     <xs:element name='bind'>
       <xs:complexType>
         <xs:choice minOccurs='0' maxOccurs='1'>
           <xs:element name='resource' type='xs:string'/>
           <xs:element name='jid' type='xs:string'/>
         </xs:choice>
       </xs:complexType>
     </xs:element>

   </xs:schema>

C.6. Пространство имен Dialback

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='jabber:server:dialback'
       xmlns='jabber:server:dialback'
       elementFormDefault='qualified'>

     <xs:element name='result'>
       <xs:complexType>
         <xs:simpleContent>
           <xs:extension base='xs:token'>
             <xs:attribute name='from' type='xs:string' use='required'/>
             <xs:attribute name='to' type='xs:string' use='required'/>
             <xs:attribute name='type' use='optional'>
               <xs:simpleType>
                 <xs:restriction base='xs:NCName'>
                   <xs:enumeration value='invalid'/>
                   <xs:enumeration value='valid'/>
                 </xs:restriction>
               </xs:simpleType>
             </xs:attribute>
           </xs:extension>
         </xs:simpleContent>
       </xs:complexType>
     </xs:element>

     <xs:element name='verify'>
       <xs:complexType>
         <xs:simpleContent>
           <xs:extension base='xs:token'>
             <xs:attribute name='from' type='xs:string' use='required'/>
             <xs:attribute name='id' type='xs:NMTOKEN' use='required'/>
             <xs:attribute name='to' type='xs:string' use='required'/>
             <xs:attribute name='type' use='optional'>
               <xs:simpleType>
                 <xs:restriction base='xs:NCName'>
                   <xs:enumeration value='invalid'/>
                   <xs:enumeration value='valid'/>
                 </xs:restriction>
               </xs:simpleType>
             </xs:attribute>
           </xs:extension>
         </xs:simpleContent>
       </xs:complexType>
     </xs:element>

   </xs:schema>

C.7. Пространство имен ошибок строф

<?xml version='1.0' encoding='UTF-8'?>

   <xs:schema
       xmlns:xs='http://www.w3.org/2001/XMLSchema'
       targetNamespace='urn:ietf:params:xml:ns:xmpp-stanzas'
       xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'
       elementFormDefault='qualified'>

     <xs:element name='bad-request' type='empty'/>
     <xs:element name='conflict' type='empty'/>
     <xs:element name='feature-not-implemented' type='empty'/>
     <xs:element name='forbidden' type='empty'/>
     <xs:element name='gone' type='xs:string'/>
     <xs:element name='internal-server-error' type='empty'/>
     <xs:element name='item-not-found' type='empty'/>
     <xs:element name='jid-malformed' type='empty'/>
     <xs:element name='not-acceptable' type='empty'/>
     <xs:element name='not-allowed' type='empty'/>
     <xs:element name='payment-required' type='empty'/>
     <xs:element name='recipient-unavailable' type='empty'/>
     <xs:element name='redirect' type='xs:string'/>
     <xs:element name='registration-required' type='empty'/>
     <xs:element name='remote-server-not-found' type='empty'/>
     <xs:element name='remote-server-timeout' type='empty'/>
     <xs:element name='resource-constraint' type='empty'/>
     <xs:element name='service-unavailable' type='empty'/>
     <xs:element name='subscription-required' type='empty'/>
     <xs:element name='undefined-condition' type='empty'/>
     <xs:element name='unexpected-request' type='empty'/>

     <xs:group name='stanzaErrorGroup'>
       <xs:choice>
         <xs:element ref='bad-request'/>
         <xs:element ref='conflict'/>
         <xs:element ref='feature-not-implemented'/>
         <xs:element ref='forbidden'/>
         <xs:element ref='gone'/>
         <xs:element ref='internal-server-error'/>
         <xs:element ref='item-not-found'/>
         <xs:element ref='jid-malformed'/>
         <xs:element ref='not-acceptable'/>
         <xs:element ref='not-allowed'/>
         <xs:element ref='payment-required'/>
         <xs:element ref='recipient-unavailable'/>
         <xs:element ref='redirect'/>
         <xs:element ref='registration-required'/>
         <xs:element ref='remote-server-not-found'/>
         <xs:element ref='remote-server-timeout'/>
         <xs:element ref='resource-constraint'/>
         <xs:element ref='service-unavailable'/>
         <xs:element ref='subscription-required'/>
         <xs:element ref='undefined-condition'/>
         <xs:element ref='unexpected-request'/>
       </xs:choice>
     </xs:group>

     <xs:element name='text'>
       <xs:complexType>
         <xs:simpleContent>
           <xs:extension base='xs:string'>
             <xs:attribute ref='xml:lang' use='optional'/>
           </xs:extension>
         </xs:simpleContent>
       </xs:complexType>
     </xs:element>

     <xs:simpleType name='empty'>
       <xs:restriction base='xs:string'>
         <xs:enumeration value=''/>
       </xs:restriction>
     </xs:simpleType>

   </xs:schema>

Previous: 4.5.15.1 Обмен сообщениями в реальном масштабе времени    UP: 4.5.15 Диалог в локальных сетях и в Интернет
    Next: 4.5.15.3 ICQ