From 19fb6499abe9ebd7168409088ef2fe0045c0633f Mon Sep 17 00:00:00 2001 From: alashkova Date: Tue, 19 Nov 2024 17:08:58 +0300 Subject: [PATCH 01/10] =?UTF-8?q?SUPPORT-8714.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE?= =?UTF-8?q?=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D1=83=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D0=B2=20=D0=95=D0=A1=D0=98=D0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/modules/service_verify.c | 47 ++++++++++++++++++++++++++++++++---- src/modules/service_verify.h | 3 ++- src/utils/cryptopro.c | 7 +++++- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1855d16..c29c0b8 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,4 @@ sign_cert_password = \*\*\*\* *\# пароль от контейнера* - В секции **\[verify\]** задать настройки проверки подписи маркера доступа: location = /verify *\# значение по умолчанию: /verify* -esia_cert_thumbprint = sha1_thumbprint_of_esia_cert *\# SHA1 отпечаток сертификата ЕСИА* +esia_cert_thumbprint = sha1_thumbprint_of_esia_cert0 sha1_thumbprint_of_esia_cert1 *\# список SHA1 отпечатков сертификатов ЕСИА, указанных через пробел* diff --git a/src/modules/service_verify.c b/src/modules/service_verify.c index fd82789..8d5292c 100644 --- a/src/modules/service_verify.c +++ b/src/modules/service_verify.c @@ -63,8 +63,8 @@ verify_conf_load(verify_conf_t *conf, const conf_file_context_t conf_file) { VERIFY_CONF_SECTION, VERIFY_CONF_KEY_THUMBPRINT, - &conf->esia_cert_thumbprint, - CONF_FILE_VALUE_STRT, + &conf->esia_cert_thumbprint_list, + CONF_FILE_VALUE_STRING_LIST, CONF_FILE_VALUE_NONE, NULL }, @@ -91,7 +91,7 @@ verify_conf_clear(verify_conf_t *conf) if (conf == NULL) return; str_t_clear(&conf->location); - str_t_clear(&conf->esia_cert_thumbprint); + string_list_clear(&conf->esia_cert_thumbprint_list); memset(conf, 0, sizeof(verify_conf_t)); } @@ -238,6 +238,42 @@ fcgi_verify_request_clear(fcgi_verify_request_t *req_info) memset(req_info, 0, sizeof(fcgi_verify_request_t)); } +static int +verify_sign_using_thumbprint_list(const string_list_t* thumbprint_list, const str_t* alg, + const str_t* header_payload, const str_t* sign, + bool* is_verified, char** verify_error) +{ + int rc = -1; + + LOG_TRACE("verify_sign_using_thumbprint_list enter"); + + for (size_t i = 0; i < thumbprint_list->size; i++) { + const char *cert_thumbprint = thumbprint_list->list[i]; + str_t thumbprint = { + .data = (char*) cert_thumbprint, + .len = strlen(cert_thumbprint) + }; + + LOG_DEBUG("Try to verify jwt using cert with thumbprint '%s'...", cert_thumbprint); + + rc = cryptopro_verify(&thumbprint, alg, header_payload, sign, is_verified, verify_error); + if (rc) { + LOG_ERROR("cryptopro_verify() failed for cert with thumbprint '%s'", cert_thumbprint); + } + + if (*is_verified) { + LOG_DEBUG("jwt verified using cert with thumbprint '%s'", cert_thumbprint); + break; + } else { + LOG_DEBUG("Could not veify jwt using cert with thumbprint '%s'. Desc: %s", + cert_thumbprint, *verify_error); + } + } + + LOG_TRACE("verify_sign_using_thumbprint_list exit"); + return rc; +} + static fcgi_handler_status_t verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx) { @@ -286,8 +322,9 @@ verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx) goto error; } - if (cryptopro_verify(&ctx->conf->esia_cert_thumbprint, &alg, &header_payload, &sign, - &is_verified, &req_info->verify_error)) { + if (verify_sign_using_thumbprint_list(&ctx->conf->esia_cert_thumbprint_list, &alg, + &header_payload, &sign, &is_verified, + &req_info->verify_error)) { goto error; } diff --git a/src/modules/service_verify.h b/src/modules/service_verify.h index fdf7153..b6346ce 100644 --- a/src/modules/service_verify.h +++ b/src/modules/service_verify.h @@ -5,12 +5,13 @@ #include "utils/conf_file_context.h" #include "utils/str_t.h" +#include "utils/types.h" typedef struct verify_service_t* HVerify; typedef struct verify_conf_s { str_t location; - str_t esia_cert_thumbprint; + string_list_t esia_cert_thumbprint_list; } verify_conf_t; diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index b93b91f..90c31cf 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -371,6 +371,10 @@ get_verify_error(char** verify_error) size_t size = strlen(err_string) + 4 /*error code*/ + 1 /*terminating null*/; + if (*verify_error != NULL) { + free(*verify_error); // в ответе отдаем последнюю ошибку + } + *verify_error = malloc(size); if (*verify_error == NULL) { LOG_ERROR("get_verify_error failed. Could not allocate memory for error string " @@ -461,7 +465,8 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t* da if (*verify_error == NULL) { goto exit; } - LOG_WARN("%s", *verify_error); + LOG_WARN("%s, cert_thumbprint: %.*s", *verify_error, + (int) cert_thumbprint->len, cert_thumbprint->data); } rc = 0; From 81ae4285b537934774c621c6a23f1fadfe871a38 Mon Sep 17 00:00:00 2001 From: alashkova Date: Mon, 25 Nov 2024 12:51:10 +0300 Subject: [PATCH 02/10] =?UTF-8?q?SUPPORT-8714.=20=D0=97=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=B5=20(=D1=81=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B1=D0=B5=D0=BB=D0=B0=20=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=8F=D1=82=D1=83=D1=8E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/utils/conf_file_context.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c29c0b8..1a7a620 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,4 @@ sign_cert_password = \*\*\*\* *\# пароль от контейнера* - В секции **\[verify\]** задать настройки проверки подписи маркера доступа: location = /verify *\# значение по умолчанию: /verify* -esia_cert_thumbprint = sha1_thumbprint_of_esia_cert0 sha1_thumbprint_of_esia_cert1 *\# список SHA1 отпечатков сертификатов ЕСИА, указанных через пробел* +esia_cert_thumbprint = sha1_thumbprint_of_esia_cert0,sha1_thumbprint_of_esia_cert1 *\# список SHA1 отпечатков сертификатов ЕСИА, указанных через запятую (без пробелов)* diff --git a/src/utils/conf_file_context.c b/src/utils/conf_file_context.c index 92b0d02..b8007d1 100644 --- a/src/utils/conf_file_context.c +++ b/src/utils/conf_file_context.c @@ -4,7 +4,7 @@ #include -#define KEY_FILE_DEFAULT_LIST_SEPARATOR ' ' +#define KEY_FILE_DEFAULT_LIST_SEPARATOR ',' typedef GKeyFile conf_file_context_s; From a3c7e63cfc59e6161c68a11d6d63d294f538d0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Mon, 25 Nov 2024 13:06:44 +0300 Subject: [PATCH 03/10] =?UTF-8?q?SUPPORT-8703.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20=D1=86=D0=B5=D0=BF=D0=BE=D1=87=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ПМИ (прод ЕСИА + mnsv126).txt | 76 +++++++++++++++++ docs/ПМИ (тест ЕСИА + mnsv93).txt | 74 ++++++++++++++++ docs/ПМИ.txt | 114 +++++++++++++++++++++++++ entrypoint.sh | 7 ++ src/utils/capi.c | 3 + src/utils/capi.h | 28 ++++++ src/utils/cryptopro.c | 132 +++++++++++++++++++++++++++++ Инструкция по установке.md | 46 +++++++++- 8 files changed, 478 insertions(+), 2 deletions(-) create mode 100644 docs/ПМИ (прод ЕСИА + mnsv126).txt create mode 100644 docs/ПМИ (тест ЕСИА + mnsv93).txt create mode 100644 docs/ПМИ.txt diff --git a/docs/ПМИ (прод ЕСИА + mnsv126).txt b/docs/ПМИ (прод ЕСИА + mnsv126).txt new file mode 100644 index 0000000..eb7853b --- /dev/null +++ b/docs/ПМИ (прод ЕСИА + mnsv126).txt @@ -0,0 +1,76 @@ +Подписание (в автоматическом режиме) запросов в ЕСИА ключом ЭП. + +Должно быть выполнено тестирование со следующими вариантами статуса сертификата ключа проверки ЭП: + +1. Действительный сертификат компонента ervu-sign-module, изготовленный Удостоверяющим центром – запрос в ЕСИА должен быть успешно отправлен: + + 1.1. Установить сертификат в систему, согласно "Инструкции по установке". + + 1.2. Открыть приложение - запрос в ЕСИА должен быть успешно отправлен. + +2. Проверка статуса сертификата не может быть выполнена, так как в Системе отсутствует CRL, соответствующий Удостоверяющему центру – запрос в ЕСИА не должен быть отправлен: + + 2.1. Удалить CRL, соответствующий Удостоверяющему центру, изготовившему сертификат компонента ervu-sign-module, выполнив команду от имени ervu: + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store ucache -dn uc_fk@roskazna.ru + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store uca -dn uc_fk@roskazna.ru + + 2.2. Отключить доступ к УЦ (например, прописав в /etc/hosts недоступный ip-адрес для хоста УЦ, указанного в свойствах сертификата): + Пример /etc/hosts: + 127.0.0.1 crl.roskazna.ru + + 2.3. Перезапустить сервис подписания ervu-sign-module, чтобы сбросить кэш: + systemctl restart ervu-sign-module + + 2.4. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000040' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x00000000 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000040 (CERT_TRUST_REVOCATION_STATUS_UNKNOWN) означает, что статус отзыва сертификата или одного из сертификатов в цепочке сертификатов неизвестен. + + 2.5. Восстановить доступ к УЦ. Все CRL будут автоматически установлены при следующих запросах на подпись. + +3. Сертификат действителен, но выдан УЦ, корневой сертификат которого не установлен в системе – запрос в ЕСИА не должен быть отправлен: + + 3.1. Получить цепочку сертификатов и SHA1 отпечаток корневого сертификата УЦ, выполнив команду от имени ervu: + /opt/cprocsp/bin/amd64/certmgr -list -thumbprint 0f948ba2b4866bf92e77f768a01add655daa5748 -chain + + Результатом команды будет цепочка сертификатов с перечнем их свойств, из которого необходимо получить значение поля "SHA1 отпечаток" для одного из корневых сертификатов. + + 3.2. Из Системы удалить корневой сертификат Удостоверяющего центра, выполнив команду от имени root. Например, удалить сертификат Минцифры России, выполнив команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -delete -store mRoot -thumbprint 2f0cb09be3550ef17ec4f29c90abd18bfcaad63a + + 3.3. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000020' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x80092004 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000020 (CERT_TRUST_IS_UNTRUSTED_ROOT) означает, что сертификат или цепочка сертификатов основана на ненадежном корневом сертификате. + + 3.4. Восстановить все корневые сертификаты, которые были удалены, выполнив для каждого команду от имени root. Для восстановления сертификата Минцифры России выполните команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file guc2022.crt + + Сертификат Минцифры России доступен по ссылке: http://reestr-pki.ru/cdp/guc2022.crt diff --git a/docs/ПМИ (тест ЕСИА + mnsv93).txt b/docs/ПМИ (тест ЕСИА + mnsv93).txt new file mode 100644 index 0000000..916d6f7 --- /dev/null +++ b/docs/ПМИ (тест ЕСИА + mnsv93).txt @@ -0,0 +1,74 @@ +Подписание (в автоматическом режиме) запросов в ЕСИА ключом ЭП. + +Должно быть выполнено тестирование со следующими вариантами статуса сертификата ключа проверки ЭП: + +1. Действительный сертификат компонента ervu-sign-module, изготовленный Удостоверяющим центром – запрос в ЕСИА должен быть успешно отправлен: + + 1.1. Установить сертификат в систему, согласно "Инструкции по установке". + + 1.2. Открыть приложение - запрос в ЕСИА должен быть успешно отправлен. + +2. Проверка статуса сертификата не может быть выполнена, так как в Системе отсутствует CRL, соответствующий Удостоверяющему центру – запрос в ЕСИА не должен быть отправлен: + + 2.1. Удалить CRL, соответствующий Удостоверяющему центру, изготовившему сертификат компонента ervu-sign-module: + sudo -u ervu /opt/cprocsp/bin/amd64/certmgr -delete -crl -store ucache -all + sudo -u ervu /opt/cprocsp/bin/amd64/certmgr -delete -crl -store uca -all + + 2.2. Отключить доступ к УЦ (например, прописав в /etc/hosts недоступный ip-адрес для хоста УЦ, указанного в свойствах сертификата): + Пример /etc/hosts: + 127.0.0.1 testgost2012.cryptopro.ru + + 2.3. Перезапустить сервис подписания ervu-sign-module, чтобы сбросить кэш: + sudo systemctl restart ervu-sign-module + + 2.4. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000040' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x00000000 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000040 (CERT_TRUST_REVOCATION_STATUS_UNKNOWN) означает, что статус отзыва сертификата или одного из сертификатов в цепочке сертификатов неизвестен. + + 2.5. Восстановить доступ к УЦ. Все CRL будут автоматически установлены при следующих запросах на подпись. + +3. Сертификат действителен, но выдан УЦ, корневой сертификат которого не установлен в системе – запрос в ЕСИА не должен быть отправлен: + + 3.1. Получить цепочку сертификатов и SHA1 отпечаток корневого сертификата УЦ: + sudo -u ervu /opt/cprocsp/bin/amd64/certmgr -list -thumbprint 1f5ab193354a7701e4964711163c6b46d4a361e0 -chain + + Результатом команды будет цепочка сертификатов с перечнем их свойств, из которого необходимо получить значение поля "SHA1 отпечаток" для одного из корневых сертификатов. + + 3.2. Из Системы удалить корневой сертификат Удостоверяющего центра. Например, удалить сертификат Тестового УЦ ООО Крипто-Про, выполнив команду: + sudo /opt/cprocsp/bin/amd64/certmgr -delete -store mRoot -thumbprint 41dcbff2ae102339bcedd0d5100ffb8e6018353d + + 3.3. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000020' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x80092004 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000020 (CERT_TRUST_IS_UNTRUSTED_ROOT) означает, что сертификат или цепочка сертификатов основана на ненадежном корневом сертификате. + + 3.4. Восстановить все корневые сертификаты, которые были удалены, выполнив для каждого команду от имени root. Для восстановления сертификата Тестового УЦ ООО Крипто-Про выполните команду: + sudo /opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file ~/work/ervu/certs/lkrp-mnsv93/testgost2012\(10\).crt diff --git a/docs/ПМИ.txt b/docs/ПМИ.txt new file mode 100644 index 0000000..414474a --- /dev/null +++ b/docs/ПМИ.txt @@ -0,0 +1,114 @@ +1. Подписание (в автоматическом режиме) запросов в ЕСИА ключом ЭП. + +Должно быть выполнено тестирование со следующими вариантами статуса сертификата ключа проверки ЭП: + + 1.1. Действительный сертификат компонента ervu-sign-module, изготовленный Удостоверяющим центром – запрос в ЕСИА должен быть успешно отправлен: + + 1.1.1. Установить сертификат в систему, согласно "Инструкции по установке". + + 1.1.2. Открыть приложение - запрос в ЕСИА должен быть успешно отправлен. + + 1.2. Проверка статуса сертификата не может быть выполнена, так как в Системе отсутствует CRL, соответствующий Удостоверяющему центру – запрос в ЕСИА не должен быть отправлен: + + 1.2.1. Удалить CRL, соответствующий Удостоверяющему центру, изготовившему сертификат компонента ervu-sign-module: + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store ucache -all + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store uca -all + + 1.2.2. Отключить доступ к УЦ. + + 1.2.3. Перезапустить сервис подписания ervu-sign-module, чтобы сбросить кэш. + + 1.2.4. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000040' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x00000000 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000040 (CERT_TRUST_REVOCATION_STATUS_UNKNOWN) означает, что статус отзыва сертификата или одного из сертификатов в цепочке сертификатов неизвестен. + + 1.2.5. Восстановить доступ к УЦ. Все CRL будут автоматически установлены при следующих запросах на подпись. + + 1.3. Сертификат действителен, но выдан УЦ, корневой сертификат которого не установлен в системе – запрос в ЕСИА не должен быть отправлен: + + 1.3.1. Получить цепочку сертификатов и SHA1 отпечаток корневого сертификата УЦ: + /opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain + где - это SHA1 отпечаток сертификата компонента ervu-sign-module. + + Результатом команды будет цепочка сертификатов с перечнем их свойств, из которого необходимо получить значение поля "SHA1 отпечаток". + + 1.3.2. Из Системы удалить корневой сертификат Удостоверяющего центра, выполнив команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -delete -store mRoot -thumbprint + где - это SHA1 отпечаток корневого сертификата УЦ, полученный на предыдущем шаге. + + 1.3.3. Открыть приложение - запрос в ЕСИА не должен быть отправлен. Пользователю отобразится ошибка. + + В логах ЛК РП должно быть следующее: + Caused by: java.lang.RuntimeException: 500 500 Internal Server Error + at ru.micord.ervu.security.esia.service.EsiaAuthService.errorHandler(EsiaAuthService.java:351) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.signMap(EsiaAuthService.java:340) ~[classes/:1.10.0-SNAPSHOT] + at ru.micord.ervu.security.esia.service.EsiaAuthService.generateAuthCodeUrl(EsiaAuthService.java:101) ~[classes/:1.10.0-SNAPSHOT] + + В логах ervu-sign-module должно быть следующее: + + WARN: The certificate is not trusted. CERT_TRUST_STATUS: '0x00000020' + ERROR: get_cert_chain exit with error + ERROR: sign_hash_data exit with error. Last error code: 0x80092004 + ERROR: cryptopro_sign exit with error + ERROR: sign_content exit with error + ERROR: response status: '500 Internal Server Error' + + CERT_TRUST_STATUS = 0x00000020 (CERT_TRUST_IS_UNTRUSTED_ROOT) означает, что сертификат или цепочка сертификатов основана на ненадежном корневом сертификате. + + 1.3.4. Восстановить все корневые сертификаты, которые были удалены, выполнив для каждого команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .crt + +2. Проверка ЭП маркера доступа, полученного от ЕСИА. + +Должно быть выполнено тестирование со следующими вариантами статуса сертификата ключа проверки ЭП: + + 2.1. Действительный сертификат ЕСИА – ответ ЕСИА должен быть принят: + + 2.1.1. Установить сертификат ЕСИА в систему, согласно "Инструкции по установке". + + 2.1.2. Выполнить вход через ЕСИА - ответ ЕСИА должен быть принят. + + 2.2. Проверка статуса сертификата не может быть выполнена, так как в Системе отсутствует CRL, соответствующий Удостоверяющему центру, изготовившему сертификат ЕСИА - ответ ЕСИА не должен быть принят: + + 2.2.1. Удалить CRL, соответствующий Удостоверяющему центру, изготовившему сертификат ЕСИА: + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store ucache + /opt/cprocsp/bin/amd64/certmgr -delete -crl -store uCA + + 2.2.2. Отключить доступ к УЦ. + + 2.2.3. Перезапустить сервис подписания ervu-sign-module, чтобы сбросить кэш. + + 2.2.4. Выполнить вход через ЕСИА - ответ ЕСИА должен быть отклонен с ошибкой. + + 2.2.5. Восстановить доступ к УЦ. Все CRL будут автоматически установлены при следующих запросах на проверку ЭП маркера доступа, полученного от ЕСИА. + + 2.3. Сертификат действителен, но выдан УЦ, корневой сертификат которого не установлен в системе – ответ ЕСИА не должен быть принят: + + 2.3.1. Получить цепочку сертификатов и SHA1 отпечаток корневого сертификата УЦ: + /opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain + где - это SHA1 отпечаток сертификата ЕСИА. + + Результатом команды будет цепочка сертификатов с перечнем их свойств, из которого необходимо получить значение поля "SHA1 отпечаток". + + 2.3.2. Из Системы удалить корневой сертификат Удостоверяющего центра, выполнив команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -delete -store mRoot -thumbprint + где - это SHA1 отпечаток корневой сертификата УЦ, полученный на предыдущем шаге. + + 2.3.3. Выполнить вход через ЕСИА - обработка ответа от ЕСИА должна завершиться ошибкой. + + 2.3.4. Восстановить все корневые сертификаты, которые были удалены, выполнив для каждого команду от имени root: + /opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .crt \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh index 3c491b8..f8ef189 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -7,4 +7,11 @@ if [ ! -d /var/opt/cprocsp/keys/ervu ]; fi /opt/cprocsp/bin/amd64/csptest -absorb -certs -autoprov + +set +e +cd /home/ervu/cacerts +echo o | /opt/cprocsp/bin/amd64/certmgr -install -store uRoot -file testgost2012_10.crt +echo o | /opt/cprocsp/bin/amd64/certmgr -install -store uRoot -thumbprint 67aea9fc8041cfafafbb77c4837038f05e727501 -file testroot.p7b +set -e + /opt/ervu-sign-module/ervu-sign-module diff --git a/src/utils/capi.c b/src/utils/capi.c index 8cba246..c6458e7 100644 --- a/src/utils/capi.c +++ b/src/utils/capi.c @@ -28,6 +28,9 @@ capi_function_list_init(library_t *lib, capi_function_list_t *fl) LIBRARY_RESOLVE(fl->GetLastError, lib, "GetLastError"); LIBRARY_RESOLVE(fl->CryptImportPublicKeyInfo, lib, "CryptImportPublicKeyInfo"); LIBRARY_RESOLVE(fl->CryptDestroyKey, lib, "CryptDestroyKey"); + LIBRARY_RESOLVE(fl->CertGetCertificateChain, lib, "CertGetCertificateChain"); + LIBRARY_RESOLVE(fl->CertVerifyCertificateChainPolicy, lib, "CertVerifyCertificateChainPolicy"); + LIBRARY_RESOLVE(fl->CertFreeCertificateChain, lib, "CertFreeCertificateChain"); #ifdef UNICODE LIBRARY_RESOLVE(fl->CryptSignHash, lib, "CryptSignHashW"); diff --git a/src/utils/capi.h b/src/utils/capi.h index 555ffb9..71fe5c4 100644 --- a/src/utils/capi.h +++ b/src/utils/capi.h @@ -175,6 +175,31 @@ DECLARE_FN(WINADVAPI, CRYPT_DESTROY_KEY, (HCRYPTKEY hKey)); +DECLARE_FN(WINADVAPI, + BOOL, + CERT_GET_CERTIFICATE_CHAIN, + (HCERTCHAINENGINE hChainEngine, + PCCERT_CONTEXT pCertContext, + LPFILETIME pTime, + HCERTSTORE hAdditionalStore, + PCERT_CHAIN_PARA pChainPara, + DWORD dwFlags, + LPVOID pvReserved, + PCCERT_CHAIN_CONTEXT* ppChainContext)); + +DECLARE_FN(WINADVAPI, + BOOL, + CERT_VERIFY_CERTIFICATE_CHAIN_POLICY, + (LPCSTR pszPolicyOID, + PCCERT_CHAIN_CONTEXT pChainContext, + PCERT_CHAIN_POLICY_PARA pPolicyPara, + PCERT_CHAIN_POLICY_STATUS pPolicyStatus)); + +DECLARE_FN(WINADVAPI, + VOID, + CERT_FREE_CERTIFICATE_CHAIN, + (PCCERT_CHAIN_CONTEXT pChainContext)); + #ifdef UNICODE #define CRYPT_SIGN_HASH_FN CRYPT_SIGN_HASH_W_FN #define CRYPT_VERIFY_SIGNATURE_FN CRYPT_VERIFY_SIGNATURE_W_FN @@ -205,6 +230,9 @@ typedef struct { CRYPT_ACQUIRE_CONTEXT_FN CryptAcquireContext; CRYPT_IMPORT_PUBLIC_KEY_INFO_FN CryptImportPublicKeyInfo; CRYPT_DESTROY_KEY_FN CryptDestroyKey; + CERT_GET_CERTIFICATE_CHAIN_FN CertGetCertificateChain; + CERT_VERIFY_CERTIFICATE_CHAIN_POLICY_FN CertVerifyCertificateChainPolicy; + CERT_FREE_CERTIFICATE_CHAIN_FN CertFreeCertificateChain; } capi_function_list_t; diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index b93b91f..ae93f49 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -79,6 +79,130 @@ error: return -1; } +static void +free_cert_chain(PCCERT_CHAIN_CONTEXT chain_ctx) +{ + LOG_TRACE("free_cert_chain enter"); + + if (chain_ctx) { + cp_function_list.CertFreeCertificateChain(chain_ctx); + } + + LOG_TRACE("free_cert_chain exit"); +} + +static PCCERT_CHAIN_CONTEXT +get_cert_chain(PCCERT_CONTEXT certificate) +{ + LOG_TRACE("get_cert_chain enter"); + + CERT_CHAIN_PARA chain_para = {0}; + chain_para.cbSize = sizeof(CERT_CHAIN_PARA); + + PCCERT_CHAIN_CONTEXT chain_ctx = NULL; + + + if (!cp_function_list.CertGetCertificateChain(NULL, + certificate, + NULL, + NULL, + &chain_para, + (CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT), + NULL, + &chain_ctx)) { + LOG_ERROR("CertGetCertificateChain() failed"); + goto error; + } + + if (chain_ctx->TrustStatus.dwErrorStatus) { + LOG_WARN("The certificate is not trusted. CERT_TRUST_STATUS: '0x%08x'", + chain_ctx->TrustStatus.dwErrorStatus); + goto error; + } + + LOG_TRACE("get_cert_chain exit"); + return chain_ctx; + +error: + free_cert_chain(chain_ctx); + LOG_ERROR("get_cert_chain exit with error"); + return NULL; +} + +static bool +check_cert_chain_policy(PCCERT_CHAIN_CONTEXT chain_ctx) +{ + LOG_TRACE("check_cert_chain_policy enter"); + + bool is_valid = false; + + CERT_CHAIN_POLICY_PARA policy_para = {0}; + policy_para.cbSize = sizeof(policy_para); + + CERT_CHAIN_POLICY_STATUS status = {0}; + status.cbSize = sizeof(status); + + CPSIGNATURE_EXTRA_CERT_CHAIN_POLICY_STATUS extraStatus = {0}; + extraStatus.cbSize = sizeof(extraStatus); + + status.pvExtraPolicyStatus = &extraStatus; + + if (!cp_function_list.CertVerifyCertificateChainPolicy( + CPCERT_CHAIN_POLICY_SIGNATURE, + chain_ctx, + &policy_para, + &status)) { + LOG_ERROR("CertVerifyCertificateChainPolicy() failed. Error code: 0x%08x", + cp_function_list.GetLastError()); + goto exit; + } + + if (status.dwError != 0) { + LOG_WARN("The certificate chain cannot be validated. " + "CERT_CHAIN_POLICY_STATUS: '0x%08x'", status.dwError); + goto exit; + } + + if (extraStatus.dwError != 0) { + LOG_WARN("The certificate chain cannot be validated. " + "CPSIGNATURE_EXTRA_CERT_CHAIN_POLICY_STATUS: '0x%08x'", extraStatus.dwError); + goto exit; + } + + is_valid = true; + +exit: + LOG_TRACE("check_cert_chain_policy exit"); + return is_valid; +} + +static bool +verify_cert_chain(PCCERT_CONTEXT certificate) +{ + bool is_verified = false; + + LOG_TRACE("verify_cert_chain enter"); + + PCCERT_CHAIN_CONTEXT chain_ctx = get_cert_chain(certificate); + if (chain_ctx == NULL) { + goto exit; + } + + if (!check_cert_chain_policy(chain_ctx)) { + goto exit; + } + + is_verified = true; + +exit: + free_cert_chain(chain_ctx); + + LOG_DEBUG("cert_chain: %s", is_verified ? "verified" : "failed"); + + LOG_DEBUG("verify_cert_chain exit"); + return is_verified; +} + static int sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t *sign) { @@ -101,6 +225,10 @@ sign_hash_data(const cryptopro_context_t *ctx, const str_t *data, /*out*/ str_t goto exit; } + if (!verify_cert_chain(pSignerCert)) { + goto exit; + } + if (!cp_function_list.CryptAcquireCertificatePrivateKey( pSignerCert, CRYPT_ACQUIRE_SILENT_FLAG, @@ -425,6 +553,10 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t* da goto exit; } + if (!verify_cert_chain(certificate)) { + goto exit; + } + if (!cp_function_list.CryptAcquireContext(&hCryptProv, NULL, CP_KC1_GR3410_2001_PROV, PROV_GOST_2001_DH, CRYPT_VERIFYCONTEXT)) { LOG_ERROR("CryptAcquireContext() failed"); diff --git a/Инструкция по установке.md b/Инструкция по установке.md index 2f1391d..5ad3274 100644 --- a/Инструкция по установке.md +++ b/Инструкция по установке.md @@ -58,11 +58,32 @@ chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/ Получить следующие значения: - Поле "SHA1 отпечаток": это значение нужно будет указать в конфигурационном файле модуля подписания в качестве настройки \ - Поле "Ссылка на ключ": убедиться, что значение равно "Есть" (иначе необходимо проверить выполнение предыдущих шагов) +- Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) +- Поля "URL списка отзыва": по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) -4. (опционально) Сделать тестовую подпись с помощью установленного контейнера и полученных значений \ и \: +4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +``` + +6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**): +``` bash +/opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain +``` + +Результатом команды должна быть строка "Цепочка сертификатов: Успешно проверена." + +Подробнее о проверке цепочки сертификатов здесь: https://www.altlinux.org/%D0%9A%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%9F%D1%80%D0%BE#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0_%D1%86%D0%B5%D0%BF%D0%BE%D1%87%D0%BA%D0%B8_%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2 + +7. (опционально) Сделать тестовую подпись с помощью установленного контейнера и полученных значений \ и \: ``` bash touch test.txt -/opt/cprocsp/bin/amd64/cryptcp -signf -thumbprint ./test.txt +/opt/cprocsp/bin/amd64/cryptcp -signf -thumbprint -errchain ./test.txt rm -f test.txt test.txt.sgn ``` @@ -91,6 +112,27 @@ rm -f test.txt test.txt.sgn - Поле "SHA1 отпечаток": это значение нужно будет указать в конфигурационном файле модуля подписания в качестве настройки \. - Поле "Алгоритм подписи": проверить, что значение совпадает с настройками ИС в ЕСИА. - Поле "Истекает": проверить, что срок действия сертификата не истёк. +- Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) +- Поля "URL списка отзыва": по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) + +4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +``` + +6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**): +``` bash +/opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain +``` + +Результатом команды должна быть строка "Цепочка сертификатов: Успешно проверена." + +Подробнее о проверке цепочки сертификатов здесь: https://www.altlinux.org/%D0%9A%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%9F%D1%80%D0%BE#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0_%D1%86%D0%B5%D0%BF%D0%BE%D1%87%D0%BA%D0%B8_%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2 ### Установка и настройка nginx From a6b1c503251602dbfb0be87718a88aae724ea83d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Mon, 25 Nov 2024 13:09:51 +0300 Subject: [PATCH 04/10] =?UTF-8?q?SUPPORT-8703.=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D0=BD=D0=BE=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fcgisrv/fcgi_utils.h | 28 ++++++++++++++++++++-------- src/modules/service_verify.c | 2 ++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/fcgisrv/fcgi_utils.h b/src/fcgisrv/fcgi_utils.h index bd3197c..080531b 100644 --- a/src/fcgisrv/fcgi_utils.h +++ b/src/fcgisrv/fcgi_utils.h @@ -146,17 +146,29 @@ typedef fcgi_handler_status_t (*fcgi_request_handler_pt)(const FCGX_Request* req typedef fcgi_request_handler_pt (*FCGI_REQUEST_FINALIZE_HANDLER)(int rc); +static inline void +fcgi_print_log(const FCGX_Request* request, const char* status) +{ + const char* uri = fcgi_request_get_param(request, FCGI_PARAM_NAME_REQUEST_URI, NULL); + uri = uri != NULL ? uri : "nil"; + + const char* method = fcgi_request_get_param(request, FCGI_PARAM_NAME_REQUEST_METHOD, NULL); + method = method != NULL ? method : "nil"; + + LOG_INFO("%s %s, '%s'", method, uri, status); +} + static inline fcgi_handler_status_t fcgi_200_ok_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '200 OK'"); + LOG_DEBUG("response status: '200 OK'"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_200_RESPONSE_FORMAT, 200); } static inline fcgi_handler_status_t fcgi_400_bad_request_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '400 Bad Request'"); + fcgi_print_log(request, "400 Bad Request"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_400_RESPONSE_FORMAT, 400); } @@ -164,7 +176,7 @@ fcgi_400_bad_request_handler(const FCGX_Request* request, void* ctx __attribute_ static inline fcgi_handler_status_t fcgi_401_unauthorized_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '401 Unauthorized'"); + fcgi_print_log(request, "401 Unauthorized"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_401_RESPONSE_FORMAT, 401); } @@ -172,7 +184,7 @@ fcgi_401_unauthorized_handler(const FCGX_Request* request, void* ctx __attribute static inline fcgi_handler_status_t fcgi_404_not_found_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '404 Not Found'"); + fcgi_print_log(request, "404 Not Found"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_404_RESPONSE_FORMAT, 404); } @@ -180,7 +192,7 @@ fcgi_404_not_found_handler(const FCGX_Request* request, void* ctx __attribute__( static inline fcgi_handler_status_t fcgi_405_method_not_allowed_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '405 Method Not Allowed'"); + fcgi_print_log(request, "405 Method Not Allowed"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_405_RESPONSE_FORMAT, 405); } @@ -188,7 +200,7 @@ fcgi_405_method_not_allowed_handler(const FCGX_Request* request, void* ctx __att static inline fcgi_handler_status_t fcgi_406_not_acceptable_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '406 Not Acceptable'"); + fcgi_print_log(request, "406 Not Acceptable"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_406_RESPONSE_FORMAT, 406); } @@ -196,7 +208,7 @@ fcgi_406_not_acceptable_handler(const FCGX_Request* request, void* ctx __attribu static inline fcgi_handler_status_t fcgi_413_request_entity_too_large_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_INFO("response status: '413 Request Entity Too Large'"); + fcgi_print_log(request, "413 Request Entity Too Large'"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_413_RESPONSE_FORMAT, 413); } @@ -204,7 +216,7 @@ fcgi_413_request_entity_too_large_handler(const FCGX_Request* request, void* ctx static inline fcgi_handler_status_t fcgi_500_internal_server_error_handler(const FCGX_Request* request, void* ctx __attribute__((unused))) { - LOG_ERROR("response status: '500 Internal Server Error'"); + fcgi_print_log(request, "500 Internal Server Error"); return FCGI_CHECK_PRINTF_STATUS(request, FCGI_500_RESPONSE_FORMAT, 500); } diff --git a/src/modules/service_verify.c b/src/modules/service_verify.c index fd82789..5a67ac2 100644 --- a/src/modules/service_verify.c +++ b/src/modules/service_verify.c @@ -188,6 +188,8 @@ fcgi_401_bad_signature_handler(const FCGX_Request* request, void *ctx) return HANDLER_ERROR; } + fcgi_print_log(request, "401 Unauthorized"); + return HANDLER_SUCCESS; } From 486638db65e9643178cdfda14c0a2a5bc7f2f5a5 Mon Sep 17 00:00:00 2001 From: alashkova Date: Mon, 25 Nov 2024 13:30:15 +0300 Subject: [PATCH 05/10] =?UTF-8?q?SUPPORT-8714.=20=D0=A3=D0=B4=D0=B0=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B9=20assert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fcgisrv/fcgi_utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fcgisrv/fcgi_utils.c b/src/fcgisrv/fcgi_utils.c index 9066d7f..64ab5b3 100644 --- a/src/fcgisrv/fcgi_utils.c +++ b/src/fcgisrv/fcgi_utils.c @@ -73,7 +73,6 @@ fcgi_request_get_param(const FCGX_Request* request, const char* name, /*out*/ bo { assert(request != NULL); assert(name != NULL); - assert(err != NULL); char* param_value = FCGX_GetParam(name, request->envp); if (param_value == NULL) { From 5ac3357c809645704a071d3419cbc001618c2348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B0=D0=B8=D0=BB=D1=8F=20=D0=90=D0=BB=D0=B0=D1=88?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Mon, 25 Nov 2024 13:32:52 +0300 Subject: [PATCH 06/10] =?UTF-8?q?SUPPORT-8714.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE?= =?UTF-8?q?=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D1=83=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D0=B2=20=D0=95=D0=A1=D0=98=D0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/fcgisrv/fcgi_utils.c | 1 - src/modules/service_verify.c | 47 +++++++++++++++++++++++++++++++---- src/modules/service_verify.h | 3 ++- src/utils/conf_file_context.c | 2 +- src/utils/cryptopro.c | 7 +++++- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1855d16..1a7a620 100644 --- a/README.md +++ b/README.md @@ -95,4 +95,4 @@ sign_cert_password = \*\*\*\* *\# пароль от контейнера* - В секции **\[verify\]** задать настройки проверки подписи маркера доступа: location = /verify *\# значение по умолчанию: /verify* -esia_cert_thumbprint = sha1_thumbprint_of_esia_cert *\# SHA1 отпечаток сертификата ЕСИА* +esia_cert_thumbprint = sha1_thumbprint_of_esia_cert0,sha1_thumbprint_of_esia_cert1 *\# список SHA1 отпечатков сертификатов ЕСИА, указанных через запятую (без пробелов)* diff --git a/src/fcgisrv/fcgi_utils.c b/src/fcgisrv/fcgi_utils.c index 9066d7f..64ab5b3 100644 --- a/src/fcgisrv/fcgi_utils.c +++ b/src/fcgisrv/fcgi_utils.c @@ -73,7 +73,6 @@ fcgi_request_get_param(const FCGX_Request* request, const char* name, /*out*/ bo { assert(request != NULL); assert(name != NULL); - assert(err != NULL); char* param_value = FCGX_GetParam(name, request->envp); if (param_value == NULL) { diff --git a/src/modules/service_verify.c b/src/modules/service_verify.c index 5a67ac2..1fcfd80 100644 --- a/src/modules/service_verify.c +++ b/src/modules/service_verify.c @@ -63,8 +63,8 @@ verify_conf_load(verify_conf_t *conf, const conf_file_context_t conf_file) { VERIFY_CONF_SECTION, VERIFY_CONF_KEY_THUMBPRINT, - &conf->esia_cert_thumbprint, - CONF_FILE_VALUE_STRT, + &conf->esia_cert_thumbprint_list, + CONF_FILE_VALUE_STRING_LIST, CONF_FILE_VALUE_NONE, NULL }, @@ -91,7 +91,7 @@ verify_conf_clear(verify_conf_t *conf) if (conf == NULL) return; str_t_clear(&conf->location); - str_t_clear(&conf->esia_cert_thumbprint); + string_list_clear(&conf->esia_cert_thumbprint_list); memset(conf, 0, sizeof(verify_conf_t)); } @@ -240,6 +240,42 @@ fcgi_verify_request_clear(fcgi_verify_request_t *req_info) memset(req_info, 0, sizeof(fcgi_verify_request_t)); } +static int +verify_sign_using_thumbprint_list(const string_list_t* thumbprint_list, const str_t* alg, + const str_t* header_payload, const str_t* sign, + bool* is_verified, char** verify_error) +{ + int rc = -1; + + LOG_TRACE("verify_sign_using_thumbprint_list enter"); + + for (size_t i = 0; i < thumbprint_list->size; i++) { + const char *cert_thumbprint = thumbprint_list->list[i]; + str_t thumbprint = { + .data = (char*) cert_thumbprint, + .len = strlen(cert_thumbprint) + }; + + LOG_DEBUG("Try to verify jwt using cert with thumbprint '%s'...", cert_thumbprint); + + rc = cryptopro_verify(&thumbprint, alg, header_payload, sign, is_verified, verify_error); + if (rc) { + LOG_ERROR("cryptopro_verify() failed for cert with thumbprint '%s'", cert_thumbprint); + } + + if (*is_verified) { + LOG_DEBUG("jwt verified using cert with thumbprint '%s'", cert_thumbprint); + break; + } else { + LOG_DEBUG("Could not veify jwt using cert with thumbprint '%s'. Desc: %s", + cert_thumbprint, *verify_error); + } + } + + LOG_TRACE("verify_sign_using_thumbprint_list exit"); + return rc; +} + static fcgi_handler_status_t verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx) { @@ -288,8 +324,9 @@ verify_jwt_sign(fcgi_verify_request_t* req_info, const verify_service_t *ctx) goto error; } - if (cryptopro_verify(&ctx->conf->esia_cert_thumbprint, &alg, &header_payload, &sign, - &is_verified, &req_info->verify_error)) { + if (verify_sign_using_thumbprint_list(&ctx->conf->esia_cert_thumbprint_list, &alg, + &header_payload, &sign, &is_verified, + &req_info->verify_error)) { goto error; } diff --git a/src/modules/service_verify.h b/src/modules/service_verify.h index fdf7153..b6346ce 100644 --- a/src/modules/service_verify.h +++ b/src/modules/service_verify.h @@ -5,12 +5,13 @@ #include "utils/conf_file_context.h" #include "utils/str_t.h" +#include "utils/types.h" typedef struct verify_service_t* HVerify; typedef struct verify_conf_s { str_t location; - str_t esia_cert_thumbprint; + string_list_t esia_cert_thumbprint_list; } verify_conf_t; diff --git a/src/utils/conf_file_context.c b/src/utils/conf_file_context.c index 92b0d02..b8007d1 100644 --- a/src/utils/conf_file_context.c +++ b/src/utils/conf_file_context.c @@ -4,7 +4,7 @@ #include -#define KEY_FILE_DEFAULT_LIST_SEPARATOR ' ' +#define KEY_FILE_DEFAULT_LIST_SEPARATOR ',' typedef GKeyFile conf_file_context_s; diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index ae93f49..e7a8de1 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -499,6 +499,10 @@ get_verify_error(char** verify_error) size_t size = strlen(err_string) + 4 /*error code*/ + 1 /*terminating null*/; + if (*verify_error != NULL) { + free(*verify_error); // в ответе отдаем последнюю ошибку + } + *verify_error = malloc(size); if (*verify_error == NULL) { LOG_ERROR("get_verify_error failed. Could not allocate memory for error string " @@ -593,7 +597,8 @@ cryptopro_verify(const str_t* cert_thumbprint, const str_t* alg, const str_t* da if (*verify_error == NULL) { goto exit; } - LOG_WARN("%s", *verify_error); + LOG_WARN("%s, cert_thumbprint: %.*s", *verify_error, + (int) cert_thumbprint->len, cert_thumbprint->data); } rc = 0; From f0cba181ca524e87b22f86117963ce7d92e92aa8 Mon Sep 17 00:00:00 2001 From: alashkova Date: Mon, 25 Nov 2024 16:33:57 +0300 Subject: [PATCH 07/10] =?UTF-8?q?SUPPORT-8709.=20=D0=98=D0=BD=D1=81=D1=82?= =?UTF-8?q?=D1=80=D1=83=D0=BA=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8E=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Инструкция по обновлению сертификатов.md | 152 ++++++++++++++++++ Инструкция по установке.md | 6 +- 2 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 docs/Инструкция по обновлению сертификатов.md diff --git a/docs/Инструкция по обновлению сертификатов.md b/docs/Инструкция по обновлению сертификатов.md new file mode 100644 index 0000000..381cf66 --- /dev/null +++ b/docs/Инструкция по обновлению сертификатов.md @@ -0,0 +1,152 @@ +## Обновление сертификата для подписи + +### Установка ключевой пары ИС, зарегистрированной в ЕСИА + +1. Запросить у руководителя проекта реестра повесток контейнер с новым ключом ИС, зарегистрированной в ЕСИА. + +2. Установить полученную ключевую пару для пользователя, от которого запускается модуль подписания (команды выполняются от имени **ervu**). +Внимание! В следующих командах необходимо заменить ***key_cont.000*** на название контейнера, полученного на предыдущем шаге. + +``` +mkdir /var/opt/cprocsp/keys/ervu/ +cp -r key_cont.000/ /var/opt/cprocsp/keys/ervu/ +chmod 700 /var/opt/cprocsp/keys/ervu/key_cont.000 +chmod 600 /var/opt/cprocsp/keys/ervu/key_cont.000/* +chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/ +/opt/cprocsp/bin/amd64/csptest -absorb -certs -autoprov +``` + +3. Получить перечень сертификатов: +``` +/opt/cprocsp/bin/amd64/certmgr -list +``` + +Для нового сертификата получить следующие значения: +- Поле "SHA1 отпечаток": это значение нужно будет указать в конфигурационном файле модуля подписания в качестве настройки +- Поле "Ссылка на ключ": убедиться, что значение равно "Есть" (иначе необходимо проверить выполнение предыдущих шагов) +- Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) +- Поля "URL списка отзыва": в случае отсутствия доступа к УЦ, по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) + +4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +``` + +6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**): +``` bash +/opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain +``` + +Результатом команды должна быть строка "Цепочка сертификатов: Успешно проверена." + +Подробнее о проверке цепочки сертификатов здесь: https://www.altlinux.org/%D0%9A%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%9F%D1%80%D0%BE#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0_%D1%86%D0%B5%D0%BF%D0%BE%D1%87%D0%BA%D0%B8_%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2 + +7. (опционально) Сделать тестовую подпись с помощью установленного контейнера и полученных значений \ и \: +``` bash +touch test.txt +/opt/cprocsp/bin/amd64/cryptcp -signf -thumbprint -pin -errchain ./test.txt +rm -f test.txt test.txt.sgn +``` + +### Настройка ervu-sign-module. + +1. В конфигурационном файле /etc/ervu-sign-module.conf в секции [sign] прописать новые значения: +``` +[sign] +sign_cert_thumbprint = sha1_thumbprint_of_signer_cert # SHA1 отпечаток сертификата, которым ИС подписывает секрет +sign_cert_password = **** # пароль от контейнера +``` + +2. Перезапустить службу: +``` +systemctl restart ervu-sign-module +``` + +3. (опционально) Удалить старый сертификат для подписи + + 3.1. Удалить старый сертификат из хранилища: + ``` + /opt/cprocsp/bin/amd64/certmgr -delete -thumbprint + ``` + где - SHA1 отпечаток старого сертификата + + 3.2. Удалить директорию со старым контейнером: + ``` + rm -rf /var/opt/cprocsp/keys/ervu/ + ``` + где - название директории со старым контейнером + + +## Обновление сертификата ЕСИА для проверки ЭП маркера доступа + +### Установка сертификата ЕСИА. + +1. Скачать сертификаты тестовой и продуктивной сред ЕСИА, используемые для формирования электронных подписей ответов как поставщика, по ссылке: https://esia.gosuslugi.ru/public/esia.zip + +2. Из списка сертификатов выбрать тот, который подходит под конфигурацию стенда (в зависимости от алгоритма подписи и от того, является ли среда тестовой или продуктивной). + +3. Установить выбранный сертификат для пользователя, выполнив команду от имени **ervu**: +``` +/opt/cprocsp/bin/amd64/certmgr -install -file '.cer' +``` +где .cer - название файла выбранного сертификата. + +Результатом команды будет список полей сертификата. Из него необходимо получить следующие значения: +- Поле "SHA1 отпечаток": это значение нужно будет указать в конфигурационном файле модуля подписания в качестве настройки . +- Поле "Алгоритм подписи": проверить, что значение совпадает с настройками ИС в ЕСИА. +- Поле "Истекает": проверить, что срок действия сертификата не истёк. +- Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) +- Поля "URL списка отзыва": в случае отсутствия доступа к УЦ, по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) + +4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: + +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: + +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +``` + +6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**): + +``` bash +/opt/cprocsp/bin/amd64/certmgr -list -thumbprint -chain +``` + +Результатом команды должна быть строка "Цепочка сертификатов: Успешно проверена." + +Подробнее о проверке цепочки сертификатов здесь: https://www.altlinux.org/%D0%9A%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%9F%D1%80%D0%BE#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0_%D1%86%D0%B5%D0%BF%D0%BE%D1%87%D0%BA%D0%B8_%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2 + +### Настройка ervu-sign-module. + +1. В конфигурационном файле /etc/ervu-sign-module.conf в секции \[verify\] добавить новое значение: + +``` +[verify] +esia_cert_thumbprint = old_esia_cert_thumbprint,esia_cert_thumbprint # список SHA1 отпечатков сертификатов ЕСИА, указанных через запятую (без пробелов) +``` + +где - SHA1 отпечаток старого сертификата ЕСИА. + +Примечание. SHA1 отпечаток старого сертификата ЕСИА необходимо оставить в списке esia_cert_thumbprint до тех пор, пока срок его действия не истечет. + +2. Перезапустить службу: + +``` +systemctl restart ervu-sign-module +``` + +3. (опционально) Удалить старый сертификат ЕСИА. + +``` +/opt/cprocsp/bin/amd64/certmgr -delete -thumbprint +``` +где - SHA1 отпечаток старого сертификата ЕСИА. \ No newline at end of file diff --git a/Инструкция по установке.md b/Инструкция по установке.md index 5ad3274..495c9cd 100644 --- a/Инструкция по установке.md +++ b/Инструкция по установке.md @@ -59,7 +59,7 @@ chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/ - Поле "SHA1 отпечаток": это значение нужно будет указать в конфигурационном файле модуля подписания в качестве настройки \ - Поле "Ссылка на ключ": убедиться, что значение равно "Есть" (иначе необходимо проверить выполнение предыдущих шагов) - Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) -- Поля "URL списка отзыва": по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) +- Поля "URL списка отзыва": в случае отсутствия доступа к УЦ, по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) 4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: ``` bash @@ -83,7 +83,7 @@ chown -R ervu:ervu /var/opt/cprocsp/keys/ervu/key_cont.000/ 7. (опционально) Сделать тестовую подпись с помощью установленного контейнера и полученных значений \ и \: ``` bash touch test.txt -/opt/cprocsp/bin/amd64/cryptcp -signf -thumbprint -errchain ./test.txt +/opt/cprocsp/bin/amd64/cryptcp -signf -thumbprint -pin -errchain ./test.txt rm -f test.txt test.txt.sgn ``` @@ -113,7 +113,7 @@ rm -f test.txt test.txt.sgn - Поле "Алгоритм подписи": проверить, что значение совпадает с настройками ИС в ЕСИА. - Поле "Истекает": проверить, что срок действия сертификата не истёк. - Поля "URL сертификата УЦ": по ссылкам, указанным в этом значении, скачать сертификаты УЦ и установить их (описано далее) -- Поля "URL списка отзыва": по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) +- Поля "URL списка отзыва": в случае отсутствия доступа к УЦ, по ссылкам, указанным в этом значении, скачать CRL и установить их (описано далее) 4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: ``` bash From 5f8438c600295689c0e78b04a0b734126f108cca Mon Sep 17 00:00:00 2001 From: Pavel Zilke Date: Fri, 29 Nov 2024 11:11:50 +0300 Subject: [PATCH 08/10] DEVOPS-1866 Update base image --- Dockerfile.micord | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.micord b/Dockerfile.micord index ac1de79..06ebcb9 100644 --- a/Dockerfile.micord +++ b/Dockerfile.micord @@ -1,4 +1,4 @@ -ARG BUILDER_IMAGE=repo.micord.ru/alt/alt-cprocsp:c10f1-5.0.13000-20240827 +ARG BUILDER_IMAGE=repo.micord.ru/alt/alt-cprocsp:c10f1-5.0.13000-20241129 ARG RUNTIME_IMAGE=registry.altlinux.org/basealt/altsp:c10f1 FROM ${BUILDER_IMAGE} AS builder From 1ffe42a385595dc36b86760c4c4959e84c53b37b Mon Sep 17 00:00:00 2001 From: alashkova Date: Fri, 29 Nov 2024 13:18:39 +0300 Subject: [PATCH 09/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BD=D0=B5=20=D1=83=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BF=D0=B0=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BE=D1=82=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D0=B9=D0=BD=D0=B5=D1=80=D0=B0=20=D1=81=20=D1=81=D0=B5=D1=80?= =?UTF-8?q?=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/cryptopro.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils/cryptopro.c b/src/utils/cryptopro.c index e7a8de1..d15bdd3 100644 --- a/src/utils/cryptopro.c +++ b/src/utils/cryptopro.c @@ -383,8 +383,10 @@ get_signer_cert(const cryptopro_context_t *ctx, HCERTSTORE hStoreHandle) goto error; } - if (set_password(cert_ctx, ctx->password)) { - goto error; + if (!str_t_is_null(*ctx->password)) { + if (set_password(cert_ctx, ctx->password)) { + goto error; + } } LOG_DEBUG("The signer's certificate was found"); From a9407486c4747565a348a480201b1f46e443c50d Mon Sep 17 00:00:00 2001 From: alashkova Date: Fri, 29 Nov 2024 16:37:23 +0300 Subject: [PATCH 10/10] =?UTF-8?q?=D0=98=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BE=D0=B1=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8E=20=D1=81=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=B8=D0=B8=201.1.0=20=D0=B4=D0=BE=201.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- docs/Инструкция по обновлению сертификатов.md | 4 +- ...укция по обновлению с версии 1.1.0 до 1.2.0.txt | 40 +++++++++++++++++++ Инструкция по установке.md | 4 +- 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 Инструкция по обновлению с версии 1.1.0 до 1.2.0.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b6c24f..5ad9918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED (VERSION 3.0) SET (CMAKE_C_COMPILER "gcc") -PROJECT (ervu-sign-module VERSION 1.1.0 LANGUAGES C) +PROJECT (ervu-sign-module VERSION 1.2.0 LANGUAGES C) IF (CMAKE_VERBOSE) SET (CMAKE_VERBOSE_MAKEFILE 1) diff --git a/docs/Инструкция по обновлению сертификатов.md b/docs/Инструкция по обновлению сертификатов.md index 381cf66..6d75f2e 100644 --- a/docs/Инструкция по обновлению сертификатов.md +++ b/docs/Инструкция по обновлению сертификатов.md @@ -106,13 +106,13 @@ systemctl restart ervu-sign-module 4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: ``` bash -/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer ``` 5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: ``` bash -/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl ``` 6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**): diff --git a/Инструкция по обновлению с версии 1.1.0 до 1.2.0.txt b/Инструкция по обновлению с версии 1.1.0 до 1.2.0.txt new file mode 100644 index 0000000..a1badc8 --- /dev/null +++ b/Инструкция по обновлению с версии 1.1.0 до 1.2.0.txt @@ -0,0 +1,40 @@ +В версии 1.2.0 появились следующие функции: +- Проверка цепочки сертификатов при подписи секрета +- Проверка цепочки сертификатов при проверке ЭП маркера доступа. + +Для обновления приложения необходимо выполнить следующие шаги (команды выполняются от имени root): + +1. Остановить службу: +``` +systemctl stop ervu-sign-module +``` + +2. Обновить приложение: +``` +cp ./ervu-sign-module /opt/ervu-sign-module/ +``` + +3. Установить корневые сертификаты УЦ для сертификата, используемого для подписи секрета (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени root: + +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +4. Установить корневые сертификаты УЦ для сертификата ЕСИА (поля "URL сертификата УЦ" в свойствах сертификата ЕСИА). Для каждого сертификата выполнить команду от имени root: + +``` bash +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +``` + +5. Запустить службу: +``` +systemctl start ervu-sign-module +``` + +6. Проверить версию приложения: +``` +curl -v http://127.0.0.1/version +``` + +Статус-код ответа должен быть равен 200 OK. +В ответе должна быть возвращена строчка "1.2.0". \ No newline at end of file diff --git a/Инструкция по установке.md b/Инструкция по установке.md index 495c9cd..0e74d09 100644 --- a/Инструкция по установке.md +++ b/Инструкция по установке.md @@ -117,12 +117,12 @@ rm -f test.txt test.txt.sgn 4. Установить сертификаты УЦ (поля "URL сертификата УЦ" в свойствах сертификата). Для каждого сертификата выполнить команду от имени **root**: ``` bash -/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer +/opt/cprocsp/bin/amd64/certmgr -install -store mRoot -file .cer ``` 5. В случае отсутствия доступа к УЦ, установить CRL (поле "URL списка отзыва" в свойствах сертификата). Для каждого CRL выполнить команду от имени **ervu**: ``` bash -/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl +/opt/cprocsp/bin/amd64/certmgr -install -store uCA -crl -file .crl ``` 6. Проверить цепочку сертификатов (команда выполняется от имени **ervu**):