OpenSSL представляет сертификат сервера клиенту с центром сертификации?

Я пытаюсь узнать, как использовать библиотеку OpenSSL (всего новичка), и у меня возникли проблемы с выяснением того, как подключить клиента к серверу с правильным сертификатом, и с ошибкой, если сертификат является неправильным. Мой пример использования - создание приложения p2p без центрального ЦС, поэтому я не могу полагаться на сертификат ЦС. В частности, сервер имеет сертификат / ключ как обычно, и клиент будет определять сертификат сервера, запрашивая другие узлы p2p для голосования.

У меня есть два конкретных вопроса:

  • В приведенных ниже фрагментах кода я ожидаю, что клиент не подключится, если я закомментирую выбор под "списком шифров". Это все еще работает! Я что-то упустил, верно?
  • Есть ли способ, чтобы клиент использовал сертификат сервера, и этого достаточно для открытия соединения? Т.е. нет ключа, нет CA?

клиент:

ctx = SSL_CTX_new(DTLSv1_client_method());
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH");

// If I comment out below stuff, client still connects happily!?
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no certificate found!");

if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no private key found!");

if (!SSL_CTX_check_private_key (ctx))
    printf("\nERROR: invalid private key!");

сервер:

SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH"); // high strength ciphers
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);

if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no certificate found!");

if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no private key found!");

if (!SSL_CTX_check_private_key (ctx))
    printf("\nERROR: invalid private key!");

Мой код находится по адресу https://github.com/a34729t/exp/tree/master/tun2udp/dtls; он построен из примеров DTLS Робина Сеггельмана. В частности, я работаю с server3_oo.c.

1 ответ

Решение

SSL/TLS могут работать в разных режимах. Наиболее распространенным режимом является только аутентификация сервера, при которой только сервер имеет сертификат и ключ. Затем существует режим взаимной аутентификации, также называемый аутентификацией клиента, в котором клиент также имеет (клиентский) сертификат и ключ. Кроме того, существует полностью анонимный режим, в котором ни сервер, ни клиент не аутентифицируются, и ни сертификату, ни ключу не нужны.

Если вы не укажете OpenSSL иначе, он будет работать только в режиме аутентификации сервера. В этом режиме эти строки здесь, в клиенте:

if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
    printf("\nERROR: no private key found!");

приведет к тому, что клиент загрузит клиентский сертификат (кстати, вам никогда не придется загружать серверный сертификат и ключ в клиенте). Однако, поскольку сервер не запрашивает у клиента сертификат, клиент никогда не представляет его. Комментирование этих строк приводит к тому, что клиент не загружает какие-либо клиентские сертификаты, что не имеет значения, поскольку они все равно не используются.

Чтобы сервер запросил у клиента сертификат и чтобы сервер отказал в подключении, если он не представлен, вы должны указать серверу следующее (обработка ошибок опущена):

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

SSL_VERIFY_PEER заставляет сервер запрашивать сертификат клиента и SSL_VERIFY_FAIL_IF_NO_PEER_CERT заставляет сервер прервать соединение, если клиент не предоставляет сертификат (см. документацию). Если вы не используете последний вариант, вы можете проверить, отправил ли клиент сертификат с помощью функции SSL_get_peer_certificate.

Другие вопросы по тегам