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;
  }
}
Другие вопросы по тегам