OpenSSL игнорирует ошибку самоподписанного сертификата
Я пишу небольшую программу с библиотекой OpenSSL, которая должна установить соединение с сервером SSLv3. Этот сервер выдает самозаверяющий сертификат, что приводит к сбою рукопожатия с таким сообщением: "Ошибка рукопожатия sslv3 alert, самоподписанный сертификат в цепочке сертификатов".
Есть ли способ заставить соединение установиться? Я пытался вызвать SSL_CTX_set_verify так:
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
Но это, похоже, ничего не меняет.
Какие-либо предложения?
6 ответов
По умолчанию OpenSSL проходит цепочку сертификатов и пытается проверить на каждом шаге, SSL_set_verify()
это не меняет, см. справочную страницу. Цитирую это:
Фактическая процедура проверки выполняется либо с использованием встроенной процедуры проверки, либо с использованием другой функции проверки, предоставляемой приложением, установленной с помощью SSL_CTX_set_cert_verify_callback(3).
Поэтому решение состоит в том, чтобы создать простой обратный вызов и установить его так, чтобы вы переопределяли все обходы цепочки сертификатов:
static int always_true_callback(X509_STORE_CTX *ctx, void *arg)
{
return 1;
}
SSL_CTX_set_cert_verify_callback(CTX, always_true_callback);
Проверьте эти примеры OpenSSL: http://www.rtfm.com/openssl-examples/
Wclient.c подключается к любой странице https, например:
wclient -h www.yahoo.com -p 443
Если вы запустите его с установкой по умолчанию, вы получите ошибку сертификата (хотя вы можете использовать флаг -i, чтобы обойти проверку сертификата).
Чтобы проверить сертификат, вам необходимо загрузить сертификаты CA (Verisign, Thawte, Equifax и т. Д.), Поэтому загрузите этот файл cacert.pem в Google, скачайте и переименуйте его в root.pem, и вы сможете подключиться к веб-сервер и проверить его сертификат.
Вы пытались предоставить вашему приложению сертификат CA сервера, чтобы оно могло проверить цепочку сертификатов?
Вы пытались установить SSL_set_verify?
SSL_set_verify(s, SSL_VERIFY_NONE, NULL);
Вы можете попробовать передать свой собственный обратный вызов SSL_set_verify()
а затем делать свою собственную проверку. Это менее чем идеально, так как я думаю, что вам нужно выполнить всю проверку и затем позволить игнорировать самозаверяющую ошибку, но вы должны быть в состоянии выяснить, что делает стандартный код проверки из исходного кода OpenSSL, а затем просто извлекать ее в свой собственный обратный вызов проверки и разрешить конкретный код ошибки...
Мой пример клиентского кода ( ссылка) отлично работает с самозаверяющим сертификатом сервера. У меня есть приведенный ниже код после SSL_connect, и я полностью контролирую приемлемость самозаверяющих сертификатов в моем клиенте
SSL_CTX* ctx = SSL_CTX_new(SSLv3_method());
// TCP connection and SSL handshake ...
/* Check the certificate */
rc = SSL_get_verify_result(ssl);
if(rc != X509_V_OK) {
if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || rc == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
fprintf(stderr, "self signed certificate\n");
}
else {
fprintf(stderr, "Certificate verification error: %ld\n", SSL_get_verify_result(ssl));
SSL_CTX_free(ctx);
return 0;
}
}