#c #linux #ssl #openssl #rhel
#c #linux #ssl #openssl #rhel
Вопрос:
Я пишу простую клиент-серверную программу TLS для безопасного обмена данными по сети. Изначально я создаю и запускаю как клиент, так и сервер на одном компьютере под управлением RHEL 8.2.
Во-первых, я использую пользовательский самоподписанный ssl-сертификат и ключ для своих программ. Я поместил RootCA.crt (мой пользовательский сертификат CA в /root/CA/RootCA.crt). Также скопировал файл RootCA.pem в /etc/pki/ca-trust/source/anchors/ и update-ca-trust enable
затем update-ca-trust extract
выполнил установку сертификата в систему. (Не уверен, нужно ли мне перезагрузить систему, чтобы она вступила в силу.)
Первоначально клиент и сервер могли обмениваться данными с помощью протокола TLS, пока я не добавил часть проверки сертификата в код на стороне клиента.
Фрагмент проверки сертификата:
ctx = SSL_CTX_new(method); /* Create new context */
if ( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ctx, 4);
const long flags = SSL_OP_NO_SSLv2 |
SSL_OP_NO_SSLv3 |
SSL_OP_NO_TLSv1 |
SSL_OP_NO_TLSv1_1 |
SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
if(SSL_CTX_load_verify_locations(ctx, NULL,
"/root/CA/") == 0){
ERR_print_errors_fp(stderr);
abort();
}
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if ( SSL_connect(ssl) == FAIL ) /* perform the connection */
ERR_print_errors_fp(stderr);
else
{
sprintf(acClientRequest, "%s", cpRequestMessage); /* construct reply */
printf("nnConnected with %s encryptionn", SSL_get_ciphe
}
когда я запускаю серверную и клиентскую программы, я вижу следующую ошибку messafe =>
Onclient: 140736372886336:ошибка: 1416F086: Процедуры SSL: tls_process_server_certificate:сбой проверки сертификата: ssl / statem / statem_clnt.c: 1915:
На сервере: 140736022137664: ошибка: 14094418: Процедуры SSL: ssl3_read_bytes: предупреждение tlsv1 неизвестно ca: ssl / record / rec_layer_s3.c: 1543: номер предупреждения SSL 48
Не уверен, что происходит не так с процессом проверки сертификата. Может кто-нибудь подсказать мне, как исправить эту ошибку?
Ответ №1:
Простого копирования вашего rootCA.crt
файла /root/CA/
недостаточно.
SSL_CTX_load_verify_locations
явно указывает, что файлы в этом каталоге должны использовать определенный формат:
Если CApath не равен NULL, он указывает на каталог, содержащий сертификаты CA в формате PEM. Каждый файл содержит по одному сертификату центра сертификации. Поиск файлов осуществляется по хэш-значению имени субъекта ЦС, которое, следовательно, должно быть доступно. Если существует более одного сертификата CA с одинаковым значением хэша имени, расширение должно быть другим (например, 9d66eef0.0, 9d66eef0.1 и т.д.). Поиск выполняется в порядке добавочного номера, независимо от других свойств сертификатов. Используйте утилиту c_rehash для создания необходимых ссылок.
Поэтому убедитесь, что ваш rootCa.crt
файл находится в формате PEM. А затем сгенерируйте необходимый хэш и переименуйте его соответствующим образом. Следующая команда генерирует хэш-значение. Переименуйте файл в <hashvalue>.0
.
openssl x509 -inform PEM -subject_hash_old -in rootCa.crt | head -1
Если ваш код все еще не работает, я бы сначала проверил, работает ли ваш код вообще. Для этого измените URL-адрес сервера на реальный сервер, который запрашивает сертификат HTTPS, которому уже доверяют в вашей системе.
Комментарии:
1. Я попытался переименовать CA.crt в <hashvalue>.0 в том же каталоге (/root/CA/). Но проблема сохраняется… Я также попытался подключиться к google.com порт: 443 и увидеть там ту же проблему. Похоже, есть какая-то проблема с моим клиентским кодом. Если я закомментирую действия
SSL_CTX_set_verify
SSL_CTX_set_verify_depth
иSSL_CTX_load_verify_location
в клиентском коде, я смогу увидеть, что соединение происходит нормально как с серверной программой, так и с google.com: 443. Не могли бы вы рассказать мне, как правильно проверить полученный сертификат сервера?2. Наконец-то удалось устранить проблему. Изменен
SSL_CTX_load_verify_location()
вызов функции, чтобы указывать на сертификат RootCA напрямую, а не на каталог, содержащий сертификат. Например: `if(SSL_CTX_load_verify_locations(ctx, «/ root/CA / 01c81d11.0», NULL) <= 0){ ERR_print_errors_fp(stderr); abort(); } ` После изменения клиент и сервер могут снова обмениваться данными без ошибок. Также проверено путем изменения ключа сервера и сертификата на неподписанные, я вижу, что клиентская программа жалуется на ненадежный сертификат, полученный с сервера.