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

Я пытаюсь научиться использовать библиотеку OpenSSL (всего newb), и у меня возникают проблемы с выяснением того, как подключить клиента к серверу с правильным сертификатом и потерпеть неудачу, если сертификат неверен. Мой вариант использования — создание 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.


person nflacco    schedule 22.01.2013    source источник


Ответы (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.

person Daniel Roethlisberger    schedule 22.01.2013