Интегрированные сети ISDN

         

Обмен сообщениями для упрощенного диалога



Рисунок .2. Обмен сообщениями для упрощенного диалога

7.4. Протокол диалога

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

enum { hello_request(0), client_hello(1), server_hello(2),

certificate(11), server_key_exchange (12),

certificate_request(13), server_hello_done(14),

certificate_verify(15), client_key_exchange(16),

finished(20), (255)

} HandshakeType;



struct { HandshakeType msg_type; /* тип диалога */
uint24 length; /* байтов в сообщении */
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case certificate: Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done: ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished; } body;
} Handshake;

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

7.4.1. Сообщения Hello

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



7.4.1.1. Запрос Hello



Сообщение-запрос hello может быть послано сервером в любое время.

Значение этого сообщения:

Запрос Hello является простым уведомлением о том, что клиент должен начать согласование путем посылки сообщения client hello. Это сообщение будет проигнорировано клиентом, если он участвует в сессии согласования. Это сообщение может игнорироваться клиентом, если он не хочет заново согласовывать параметры сессии, или клиент может, если хочет, реагировать уведомлением no_renegotiation. Так как сообщения диалога предназначены для осуществления определенных действий над прикладными данными, ожидается, что согласование начнется до того, как будут получены новые записи от клиента. Если сервер посылает запрос hello, но не получает отклика client hello, он может разорвать соединение с фатальным уведомлением.

После посылки запроса hello, серверы не должны повторять запрос до тех пор, пока диалог согласования не завершится.

Структура этого сообщения:

struct { } HelloRequest;

Это сообщение не должно никогда включаться в хэши сообщений и использоваться в завершающих сообщениях (finished), а также в сообщении верификации сертификатов.



7.4.1.2. Hello клиента



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

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

struct { uint32 gmt_unix_time; opaque random_bytes[28];} Random;

gmt_unix_time Текущее время и дата согласно стандарта UNIX в 32-битовом формате (число секунд с момента полуночи 1-го января, 1970, GMT) согласно показаниям внутренних часов отправителя. Часы могут и не быть точно выверены на уровне протокола TLS. Прикладные протоколы могут накладывать дополнительные ограничения.
random_bytes 28 байт сформированных безопасным генератором случайных чисел.
<


/p> Сообщение client hello включает в себя идентификатор сессии переменной длины. Если это поле не пусто, его значение идентифицирует сессию, чьи параметры безопасности клиент желает использовать повторно. Идентификатор сессии может соответствовать какому-то предшествующему соединению, текущему соединению, или другому активному соединению. Вторая опция полезна, если клиент хочет изменить случайные структуры и получить текущие значения параметров соединения, в то время как третья опция делает возможным установить несколько независимых безопасных соединений без повторения всей процедуры протоколы диалога. Эти независимые соединения могут существовать последовательно или одновременно; SessionID становится действенным, когда диалог согласования завершается обменом сообщениями Finished, и сохраняется до тех пор, пока не состарится или из-за фатальной ошибки в соединении данной сессии. Действительное содержимое SessionID определяется сервером.

opaque SessionID;

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

Список CipherSuite, передаваемый от клиента серверу в сообщении client hello, содержит комбинации криптографических алгоритмов, поддерживаемых клиентом в порядке их предпочтения (предпочтительный вариант - первый). Каждый CipherSuite определяет алгоритм пересылки ключей, алгоритм массового шифрования (включая длину секретного ключа) и алгоритм MAC. Сервер выберет шифровой набор или, если приемлемого варианта нет, пришлет уведомление об ошибке и прервет соединение.

uint8 CipherSuite[2]; /* Cryptographic suite selector */

Hello клиента включает в себя список алгоритмов сжатия, поддерживаемых клиентом, в порядке их предпочтения.

enum { null(0), (255) } CompressionMethod;

struct { ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites16-1>;
CompressionMethod compression_methods8-1>;
} ClientHello;
<


/p>
client_version Версия протокола TLS, которой хочет воспользоваться клиент во время сессии. Это должна быть последняя версия (с наибольшим кодом), поддерживаемая клиентом. Для данной спецификации значение версии равно 3.1 (Смотри приложение E об обратной совместимости).
Random Псевдослучайная структура, генерируемая клиентом.
session_id ID-сессия, которую клиент хочет использовать для данного соединения. Это поле должно быть пустым, если нет ни одного session_id или клиент хочет выработать новые параметры безопасности.
cipher_suites Список криптографических опций, поддерживаемых клиентом в порядке предпочтения. Если поле session_id не пусто (запрос восстановления сессии), этот вектор должен включать по крайней мере cipher_suite данной сессии. Значения определены в приложении A.5.
compression_methods Список методов сжатия, поддерживаемых клиентом в порядке их предпочтения. Если поле session_id не пусто (запрос восстановления сессии) он должен включать compression_method данной сессии. Этот вектор должен содержать, а все реализации должны поддерживать CompressionMethod.null. Таким образом, клиент и сервер всегда могут согласовать метод сжатия информации.
После посылки сообщения client hello, клиент ждет сообщения server hello. Любое другое сообщение диалога, присланное сервером, за исключением запроса hello, рассматривается как фатальная ошибка.

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



7.4.1.3. Hello сервера



Сервер посылает это сообщение в ответ на сообщение client hello, когда он может найти приемлемый набор алгоритмов. Если он не может сделать приемлемый выбор, он реагирует уведомлением об ошибке диалога.

Структура этого сообщения:



Struct { ProtocolVersion server_version;
Random random;
SessionID session_id;
CipherSuite cipher_suite;
CompressionMethod compression_method;
} ServerHello;
server_version Это поле будет содержать самое низкое значение, которое предлагается клиентом в client hello и наибольшее значение версии, поддерживаемое сервером. Значение версии данной спецификации равно 3.1 (по поводу обратной совместимости смотри Приложение E).
Random Эта структура генерируется сервером и должна быть отличной от ClientHello.random.
session_id Идентифицирует сессию, соответствующую данному соединению. Если ClientHello.session_id не пусто, сервер будет искать соответствие с содержимым своего кэша сессий. Если соответствие найдено и сервер хочет установить новое соединение, используя специфицированное состояние сессии, он откликнется тем же значением ID, что было прислано клиентом. Это индицирует возобновляемую сессию и диктует, что партнеры должны продолжить обмен сообщениями finished. В противном случае это поле будет содержать другое значение идентифицирующее новую сессию. Сервер может вернуть пустое поле session_id, чтобы индицировать, что сессия не будет кэшироваться и, следовательно, не может быть возобновлена. Если сессия возобновлена, она должна использовать тот же шифровой набор, который был согласован ранее.
cipher_suite Шифровой набор, выбранный сервером из списка в ClientHello.cipher_suites. Для возобновленных сессий это поле несет в себе значение, взятое из состояния возобновляемой сессии.
compression_method Алгоритм сжатия, выбранный сервером из списка в ClientHello.compression_methods. Для возобновляемых сессий это поле содержит значение из состояния возобновляемой сессии.


7.4.2. Сертификат сервера



Сервер должен послать сертификат, всякий раз, когда согласованный метод обмена ключами не является анонимным. За этим сообщением всегда непосредственно следует сообщение server hello.

Тип сертификата должен соответствовать выбранному алгоритму обмена ключами шифров, обычно это сертификат X.509v3.


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

Алгоритм обмена ключами Тип сертификата ключа
RSA Общедоступный ключ RSA; сертификат должен допускать использование ключа для шифрования.
RSA_EXPORT Общедоступный ключ RSA с длиной больше чем 512 бит, который может быть использован для подписи, или ключ длиной 512 бит или короче, который может быть использован для шифрования или подписи.
DHE_DSS Общедоступный ключ DSS.
DHE_DSS_EXPORT Общедоступный ключ DSS.
DHE_RSA Общедоступный ключ RSA, который может использоваться для подписи.
DHE_RSA_EXPORT Общедоступный ключ RSA, который может использоваться для подписи.
DH_DSS Ключ Diffie-Hellman. Алгоритмом, используемым для подписи сертификата, должен быть DSS.
DH_RSA Ключ Diffie-Hellman. Алгоритмом, используемым для подписи сертификата, должен быть RSA.
Все сертификатные профайлы, ключи и криптографические форматы определены рабочей группой IETF PKIX [PKIX]. Когда присутствует расширение использования ключа, бит digitalSignature должен быть установлен для ключа выбранного для подписи, как это описано выше, а бит keyEncipherment должен присутствовать, чтобы разрешить шифрование, как это описано выше. Бит keyAgreement должен быть установлен для сертификатов Diffie-Hellman.

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

Структура этого сообщения:

opaque ASN.1Cert24-1>;

struct { ASN.1Cert certificate_list24-1>; } Certificate;

certificate_list Это последовательность (цепочка) сертификатов X.509v3. Сертификат отправителя должен быть записан в списке первым. Каждый следующий сертификат должен непосредственно сертифицировать предшествующий сертификат. Так как верификация сертификата требует, чтобы корневые ключи распределялись независимо, самоподписывающий сертификат, который специфицирует корневой источник сертификата, может быть опционно удален из цепочки, в предположении, что партнер должен уже иметь его, чтобы проверить его в любом случае.
<


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



7.4.3. Сообщение ключевого обмена сервера



Это сообщение будет послано немедленно после сообщения сертификата сервера (или сообщения server hello, если это анонимное согласование параметров).

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

RSA_EXPORT (если открытый ключ в сертификате длиннее, чем 512 бит)

DHE_DSS

DHE_DSS_EXPORT

DHE_RSA

DHE_RSA_EXPORT

DH_anon

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

RSA

RSA_EXPORT (когда открытый ключ в сертификате сервера короче чем или равен 512 бит)

DH_DSS

DH_RSA

Это сообщение передает криптографическую информацию, чтобы позволить клиенту оперировать с premaster секретным кодом: либо общедоступный ключ RSA, чтобы зашифровать предмастерный секретный код, либо общедоступный ключ Diffie-Hellman, с помощью которого клиент может завершить обмен ключами.

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

Согласно настоящему закону США об экспорте, модули RSA больше 512 бит не могут использоваться для ключевого обмена в программах, экспортируемых из США. Более длинные ключи RSA, зашифрованные в сертификатах, могут быть использованы для подписи более коротких ключей RSA в случае метода ключевого обмена RSA_EXPORT.



Структура этого сообщения:

enum { rsa, diffie_hellman } KeyExchangeAlgorithm;

struct { opaque rsa_modulus; opaque rsa_exponent;} ServerRSAParams;

rsa_modulus Модуль временного RSA-ключа сервера.
rsa_exponent Общедоступный показатель временного RSA-ключа сервера.
struct { opaque dh_p;

opaque dh_g

1>;
opaque dh_Ys

1>;} ServerDHParams; /* Временные DH параметры */
dh_p Простой модуль, используемый для операции Diffie-Hellman.
dh_g Генератор, используемый для операции Diffie-Hellman.
dh_Ys Общедоступное значение (gX mod p) метода Diffie-Hellman для сервера.
struct { select (KeyExchangeAlgorithm) {

case diffie_hellman:
ServerDHParams params;
Signature signed_params;
case rsa:
ServerRSAParams params;
Signature signed_params; };
} ServerKeyExchange;
Params Параметры ключевого обмена сервера.
signed_params Для не анонимных ключевых обменов, хэш соответствующих значений параметров с подписью, согласованной с примененным хэшем.
md5_hash MD5(ClientHello.random + ServerHello.random + ServerParams);
sha_hash SHA(ClientHello.random + ServerHello.random + ServerParams);
enum { anonymous, rsa, dsa } SignatureAlgorithm;

select (SignatureAlgorithm)

{ case anonymous: struct { };
case rsa:
digitally-signed struct
{
opaque md5_hash[16];
opaque sha_hash[20];
};
case dsa:
digitally-signed struct {
opaque sha_hash[20];
};
} Signature;
7.4.4. Запрос сертификата



Не анонимный сервер может опционно запросить сертификат от клиента, если это возможно для выбранного шифрового набора. За этим сообщением, если оно послано, непосредственно следует сообщение ключевого обмена сервера (Server Key Exchange) (в противном случае, сообщение сертификата сервера).

Структура этого сообщения:

enum { rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),

(255)} ClientCertificateType;

opaque DistinguishedName16-1>;

struct { ClientCertificateType certificate_types8-1>;

DistinguishedName certificate_authorities16-1>;



} CertificateRequest;

certificate_types Это поле представляет собой список типов запрошенных сертификатов, расположенных в порядке предпочтения сервера.
certificate_authorities Список имен приемлемых провайдеров сертификатов. Эти имена могут специфицировать уникальное имя корневого или подчиненного CA. Таким образом, это сообщение может быть использовано как для описания известных корней и желательного пространства авторизации.
DistinguishedName получается из [X509]. Считается фатальной ошибкой (оповещение handshake_failure), если анонимный сервер запрашивает идентификацию клиента.



7.4.5. Hello done сервера



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

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

По получении сообщения сервера hello done клиент должен проверить, что сервер предоставил корректный сертификат, если это требуется, и что параметры, присланные сервером приемлемы.

Структура этого сообщения: struct { } ServerHelloDone;



7.4.6. Сертификат клиента



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

Когда используется метод ключевого обмена, базирующийся на статическом методе Diffie-Hellman (DH_DSS или DH_RSA), если требуется аутентификация клиента, группа Diffie-Hellman и генератор закодированные в сертификате клиента должны соответствовать параметрам Diffie-Hellman'а, специфицированным сервером, если параметры клиента планируется использовать для ключевого обмена.





7.4.7. Сообщение обмена ключами клиента



Это сообщение посылается клиентом всегда. За ним непосредственно следует сообщение сертификата клиента, если оно посылается. В противном случае оно будет первым сообщением, посылаемым клиентом после получения сообщения сервера hello done.

С помощью этого сообщения устанавливается предмастерный секретный код, либо путем прямой передачи его, зашифровав с применением RSA, либо с помощью передачи параметров Diffie-Hellman, которые позволят каждой из сторон согласовать применение одного и того же предмастерного секретного кода. Когда в качестве метода передачи ключей использован DH_RSA или DH_DSS, запрашивается сертификация клиента, и клиент может откликаться посылкой сертификата, который содержит общедоступный ключ Diffie-Hellman, чьи параметры (группа и генератор) соответствуют, специфицированным в сертификате сервера. Это сообщение не содержит никаких других данных.

Структура этого сообщения:

Выбор сообщений зависит от выбранного метода ключевого обмена. Смотри раздел 7.4.3, где дано определение KeyExchangeAlgorithm.

struct { select (KeyExchangeAlgorithm) { case rsa: EncryptedPreMasterSecret;

case diffie_hellman: ClientDiffieHellmanPublic; } exchange_keys;

} ClientKeyExchange;



7.4.7.1. Сообщение зашифрованного RSA предмастерного секретного кода



Если для согласования ключей и аутентификации применен алгоритм RSA, клиент генерирует 48-байтовый предмастерный секретный код, шифрует его с помощью общедоступного ключа из сертификата сервера или временного RSA-ключа, переданного в сообщении ключевого обмена сервера, и посылает результат в сообщении зашифрованного предмастерного секретного кода (encrypted premaster secret). Эта структура является вариантом сообщения ключевого обмена клиента.

Структура этого сообщения:

struct { ProtocolVersion client_version; opaque random[46];} PreMasterSecret;

client_version Последняя (новейшая) версия, поддерживаемая клиентом. Она используется для детектирования атак связанных с понижением номера версии. По получении предмастерного секретного кода сервер должен проверить, что данное значение согласуется с величиной, переданной клиентом в сообщении hello.
random 46 байт псевдослучайного кода.
<


/p> struct { public-key-encrypted PreMasterSecret pre_master_secret;} EncryptedPreMasterSecret;

Атака, рассмотренная Даниэлем Блайбенбахером (Daniel Bleichenbacher) [BLEI], может быть предпринята против TLS-сервера, который использует PKCS#1, закодированный с помощью RSA.

Наилучший способ избежать уязвимости от этой атаки является обработка некорректно форматированных сообщений точно также как и корректно сформатированные RSA-блоки. Таким образом, когда сервер получает некорректно сформатированный RSA-блок, он должен сформировать случайное 48-байтовое число и использовать его в дальнейшем в качестве предмастерного секретного кода. Таким образом, сервер будет действовать идентично вне зависимости оттого, является ли полученный RSA-блок корректным.

pre_master_secret Это случайное число генерируется клиентом и используется для формирования мастерного секретного кода, как это специфицировано в разделе 8.1.
7.4.7.2. Общедоступный Diffie-Hellman-ключ клиента



Эта структура передает общедоступную величину (Yc) Diffie-Hellman-алгоритма для клиента, если она не была уже включена в сертификат клиента. Шифрование, используемое для Yc, определяется нумерованным параметром PublicValueEncoding. Эта структура является вариантом сообщения ключевого обмена клиента.

Структура этого сообщения:

enum { implicit, explicit } PublicValueEncoding;

implicit Если сертификат клиента уже содержит подходящий ключ алгоритма Diffie-Hellman, тогда Yc является неявным и не должно пересылаться снова. В этом случае будет послано сообщение ключевого обмена клиента (Client Key Exchange), но оно будет пустым.
explicit Yc должно быть послано.
struct { select (PublicValueEncoding) {

case implicit: struct { };

case explicit: opaque dh_Yc; } dh_public;

} ClientDiffieHellmanPublic;

dh_Yc Общедоступный Diffie-Hellman-ключ клиента (Yc).
7.4.8. Верификация сертификата



Это сообщение используется для осуществления в явной форме верификации сертификата клиента. Оно посылается вслед за сертификатом клиента, который имеет возможность подписи (т.e.


все сертификаты кроме тех, которые содержат фиксированные параметры Diffie-Hellman). При посылке это сообщение следует немедленно за сообщением ключевого обмена клиента.

Структура этого сообщения имеет вид:

struct { Signature signature; } CertificateVerify;

Тип подписи определен в 7.4.3.

CertificateVerify.signature.md5_hash MD5(handshake_messages);

Certificate.signature.sha_hash SHA(handshake_messages);

Здесь handshake_messages относятся ко всем сообщениям диалога, посланным или полученным, начиная с hello клиента, и вплоть до (но исключая) данное сообщение, содержащее поля типа и длины сообщений диалога. Это представляет собой соединение всех структур диалога, как это определено в 7.4.



7.4.9. Сообщение Finished



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

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

struct { opaque verify_data[12];} Finished;

verify_data PRF(master_secret, finished_label, MD5(handshake_messages) + SHA1(handshake_messages)) [0..11];
finished_label Для сообщений Finished, посланных клиентом, это строка "client finished". Для сообщений Finished, посланных сервером, это строка "server finished".
handshake_messages Все данные от сообщений диалога до этого сообщение (но не включительно). Это единственные данные, видимые на уровне диалога, они не включают заголовки уровня записей. Это соединение всех структур диалога, определенных в 7.4.
Если в соответствующей точке диалога за сообщением finished не следует сообщение об изменении шифровой спецификации, это считается фатальной ошибкой.

Хэши, содержащиеся в сообщениях finished, посланных серверам, включает в себя Sender.server; а посланные клиентом содержат Sender.client. Значение handshake_messages включает все сообщения диалога, начиная с hello клиента и вплоть до (но не включая) это сообщение finished. Здесь могут быть отличия от handshake_messages из раздела 7.4.8, так как сюда может входить сообщение верификации сертификата. Следует также иметь в виду, что, handshake_messages для сообщения finished, посланного клиентом, будет отличаться от посланного сервером, так как второе, включает первое.

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




Содержание раздела