From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Paul Wolneykien To: devel@lists.altlinux.org References: <20180808163302.GG30895@altlinux.org> Organization: ALT Linux Team Message-ID: <4dc9df5d-c0f3-39d4-e287-9af074f2f446@altlinux.org> Date: Fri, 10 Aug 2018 15:52:26 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: ru Content-Transfer-Encoding: 8bit Subject: Re: [devel] X509v3: CRL Distribution Points: help is needed X-BeenThere: devel@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: ALT Linux Team development discussions List-Id: ALT Linux Team development discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Aug 2018 12:52:33 -0000 Archived-At: List-Archive: List-Post: 08.08.2018 19:52, Paul Wolneykien пишет: > 08.08.2018 19:33, Alexey V. Vissarionov пишет: >> On 2018-08-08 18:43:25 +0300, manowar@altlinux.org wrote: >> > Вот как выглядит в разобранном виде та часть файла подписи, >> > которая отвечает за CRL: [...] >> > Теперь, собственно, сам вопрос: структура выше соответствует >> > двум разным CRL? >> >> Нет - это один CRL, для которого предусмотрена возможность взять >> его как с локального зеркала (pki-lan), так и снаружи у ГРЧЦ. Итак, я, прежде всего, точно выяснил, что же записано в оговоренной секции сертификата. Разберу подробно тут, вдруг кому будет полезно (что называется --- отвечаю сам себе). Начинается всё с SEQUENCE(2 elem) --- Так кодируется экземпляр расширения (extension) X.509. Элементами списка (именно --- 2 элемента) являются: OBJECT IDENTIFIER 2.5.29.31 --- кодовый номер расширения и OCTET STRING (длинная строка, длиной 153 байта) --- его содержимое, которое мы разбираем ниже: SEQUENCE(2 elem) --- Снова список. На этот раз --- это список, состоящий из нескольких DistributionPoint, каждый из которых является тоже списком с количеством элементов от 0 до 3 (поскольку все они опциональные): SEQUENCE(1 elem) --- Это DistributionPoint с единственным указанным элементом, осталось понять, каким: [0](1 elem) --- Теперь ясно, что это элемент с тегом [0], а именно --- DistributionPointName. Он, в свою очередь может быть представлен двумя различными способами, поэтому следом снова указывается: [0](1 elem) --- Тем самым выбирается вариант fullName, помеченный в схеме тегом [0] и имеющим тип GeneralNames. Тип GeneralNames представляет собой список из 1 или более альтернативных значений, в котором каждая альтернатива обозначается тегом с номером от [0] до [8]. Поэтому следом идёт наконец: [6]http://pki-lan/ocsp... --- Это uniformResourceIdentifier (тег [6]) типа IA5String. Второй DistributionPoint оформлен точно так же, как первый. Поэтому формально --- это именно два разных DistributionPoint, т.е. два разных CRL. И в каждом DistributionPoint только один URI. То, что возможно сделать иначе: задать несколько URI для каждой DistributionPoint --- можно узнать, например, и следующей инструкции: https://www.pixelstech.net/article/1445498968-Generate-certificate-with-cRLDistributionPoints-extension-using-OpenSSL 08.08.2018 19:33, Alexey V. Vissarionov пишет: > On 2018-08-08 18:43:25 +0300, manowar@altlinux.org wrote: > > не Интернет. А это значит, что издатель подписи (сертификата) > > рассчитывал на то, что оба указанных им адреса будут расценены > > как альтернативные и, при недоступности первого, проверяющий > > перейдёт по второму. > > Именно так. Локальное зеркало - best practice, ибо недоступность > CRL может привести к тому, что отозванный сертификат будет принят > как рабочий. > > > Но dirmngr (из пакета gnupg2) считает иначе: он расценивает > > указанную информацию как список из двух различных CRL, которые, > > следовательно, оба требуются для проверки подписи. > > Идея здравая, но реализована, мягко говоря, per rectum. > ... > Проверять, действительно, нужно все источники (на случай, если > какое-то свежее изменение в апстриме не доехало до зеркала), но > отваливаться по UTV (unable to verify|validate) следует только > когда недоступны _все_ источники. А вот теперь вопрос, чья это идея (последний абзац выше): это твоё личное представление о том, как должно быть или всё таки нечто общепринятое? Допустим, ты сомневаешься насчёт верности реализации в GnuPG. Но как тебе такое: static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) { int i; const char *urlptr = NULL; for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); urlptr = get_dp_url(dp); if (urlptr) return load_crl(urlptr, FORMAT_HTTP); } return NULL; } Это я обнаружил в OpenSSL. И там, как видно, внутри цикла выход по return на _первой_ же непустой DistributionPoint. Следовательно, реализация OpenSSL рассчитана на то, что _все_ указанные источники будут доступны. И если какой-то недоступен, то будет ошибка (там bio_err внутри load_crl). Проверяем на нашем примере: $ openssl verify -engine gost -CAfile parsed2.txt -crl_download -crl_check parsed.txt engine "gost" set. Error loading CRL from http://pki-lan/ocsp/6b00868389d200cf56b86be4e336101e1f72aec3.crl 140430750978520:error:2006A066:BIO routines:BIO_get_host_ip:bad hostname lookup:b_sock.c:146:host=pki-lan parsed.txt: 1.2.643.100.3 = ... error 3 at 0 depth lookup:unable to get certificate CRL Получаем тот же результат, что и через GnuPG. С той лишь разницей, что в GnuPG заложен перебор нескольких альтернативных URI для одной DistributionPoint, а вот OpenSSL даже не предполагает альтернатив --- все должны быть доступны. Получается, что предположение о том, что в разбираемом сертификате оба URI нужно расценивать как альтернативные, не подтверждается ни теорией (структурой в ASN.1), ни практикой (openssl verify). Или скажешь, что OpenSSL тоже не аргумент? А кто же тогда у них главный?