Missing X.509 certificate

Не удается выполнить проверку подлинности сервера или клиента

Описание

Этот дефект возникает, когда вы используете контекст для обработки соединений TLS/SSL с этими функциями, но вы не загружаете сертификат X.509 в контекст.

  • SSL_accept

  • SSL_connect

  • SSL_do_handshake

  • SSL_write

  • SSL_read

  • BIO_do_accept

  • BIO_do_connect

  • BIO_do_handshake

Сертификат X.509 является цифровым сертификатом, который выдается сущности. Он содержит информацию, идентифицирующую сущность. Сертификат используется для проверки подлинности подключений к сущностям, указанным в сертификате.

Шашка поднимает дефект, если:

  • Для проверки подлинности сервера сертификат не загружается перед обработкой подключения.

  • Для проверки подлинности клиента клиент пытается подключиться к серверу второй раз после получения SSL_ERROR_WANT_X509_LOOKUP ошибка при первой попытке подключения.

Риск

Когда вы не загружаете сертификат X.509 в контекст для обработки подключений TLS/SSL, соединение не является безопасным и уязвимо для атак man-in-the-middle (MITM).

Зафиксировать

Загрузите сертификат X.509 в контекст, созданный для обработки соединений TLS/SSL.

Примеры

расширить все

#include <openssl/ssl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;
int len;

SSL_CTX* InitServerCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(SSLv23_server_method());
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

int OpenListener(int port)
{
    /* Create server socket */
}

void func()
{
    SSL_CTX* ctx;
    int server, port;
    int ret;
    SSL_library_init();

    ctx = InitServerCTX();
    server = OpenListener(port);
    while (1) {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL* ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);
        printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client);
        ret = SSL_accept(ssl);
        if (SSL_get_error(ssl, ret) <= 0)
            /* Serve connection */;
        else
            SSL_free(ssl);
    }
    close(server);
    SSL_CTX_free(ctx);
}

В этом примере InitServerCTX() инициализирует контекстные ctx для соединений TLS/SSL, но сертификат не загружен в ctx. Когда SSL_accept проверяет квитирование TLS/SLL для структуры SSL, созданной из ctxнет доступного сертификата для проверки подлинности сервера.

Коррекция - перед созданием структуры SSL загрузите сертификат в контекст

Одной из возможных коррекций является загрузка сертификата в контекст, созданный для соединений TLS/SSL, например с помощью SSL_CTX_use_certificate_file.

#include <openssl/ssl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;
int len;

SSL_CTX* InitServerCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(SSLv23_server_method());
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) {
        /* Handle errors */
    }
}

int OpenListener(int port)
{
    /* Create server socket */
}

void func()
{
    SSL_CTX* ctx;
    int server, port;
    int ret;
    SSL_library_init();

    ctx = InitServerCTX();
    LoadCertificates(ctx, "mycert.pem", "mycert.pem");
    server = OpenListener(port);
    while (1) {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL* ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);
        printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client);
        ret = SSL_accept(ssl);
        if (SSL_get_error(ssl, ret) <= 0)
            /* Serve connection */;
        else
            SSL_free(ssl);
    }
    close(server);
    SSL_CTX_free(ctx);
}

Информация о результатах

Группа: Криптография
Язык: C | C++
По умолчанию: Off
Синтаксис командной строки : CRYPTO_SSL_NO_CERTIFICATE
Влияние: Средний
ИДЕНТИФИКАТОР CWE : 310
Введенный в R2019b