Qt5 аутентификация по клиентским сертификатам



  • У меня Qt 5.4.0 на Windows 8.1 и Qt 5.4.2 на последнем ArchLinux и я наблюдаю одну и ту же проблему.

    Есть веб-сайт требующий аутентификацию по клиентским сертификатам. Сервер вроде бы настроет правильно. Во всяком случае вызов

    openssl s_client -connect myserver:443 -cert client.crt -key client.key
    

    печатает

    Verify return code: 0 (ok)
    

    Кроме того, вызов

     curl --cert client.pem https://myserver/
    

    скачивает данные с сайта (заглавную страницу).

    Сертификатс ервера купленный, валидный, ббраузеры его принимают, и т.д. Клиентские сертификаты самоподписанные. На всякий случай вот фрагмент фонфига сервера (это nginx)

    listen                         *:443 ssl;
    
    server_name                    myserver;
    
    ssl                            on;
    ssl_certificate                /etc/nginx/ssl/myserver.crt;
    ssl_certificate_key            /etc/nginx/ssl/myserver.key;
    ssl_dhparam                    /etc/nginx/ssl/myserver.dh;
    ssl_protocols                  TLSv1.1 TLSv1.2;
    ssl_ciphers                    "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_prefer_server_ciphers      on;
    ssl_client_certificate         /etc/nginx/ssl/ca.crt;
    ssl_verify_client              on;
    

    Суть проблемы в том, что следующее простейшее консольное приложение не работает

    #include <qcoreapplication.h>
    #include <qfile.h>
    #include <qnetworkaccessmanager.h>
    #include <qnetworkconfiguration.h>
    #include <qnetworkproxy.h>
    #include <qnetworkreply.h>
    #include <qnetworkrequest.h>
    #include <qsslcertificate.h>
    #include <qsslconfiguration.h>
    #include <qsslkey.h>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        QNetworkProxyFactory::setUseSystemConfiguration(true);
    
        QSslConfiguration sslConfiguration;
    
        QFile privateKeyFile("client.key");
        privateKeyFile.open(QIODevice::ReadOnly);
    
        QFile certificateFile("client.crt");
        certificateFile.open(QIODevice::ReadOnly);
    
        QSslKey privateKey(&privateKeyFile, QSsl::Opaque);
        QSslCertificate certificate(&certificateFile);
    
        qWarning() << QSslSocket::supportsSsl();
        qWarning() << certificate.serialNumber();
        qWarning() << certificate.subjectInfo(QSslCertificate::CommonName);
        qWarning() << certificate.expiryDate();
    
        sslConfiguration.setPrivateKey(privateKey);
        sslConfiguration.setLocalCertificate(certificate);
    
        QNetworkRequest networkRequest(QUrl("https://server/"));
    
        networkRequest.setSslConfiguration(sslConfiguration);
    
        QNetworkAccessManager networkAccessManager;
    
        QNetworkReply* networkReply = networkAccessManager.get(networkRequest);
    
        QEventLoop loop;
    
        QObject::connect(&networkAccessManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    
        loop.exec();
    
        qWarning() << networkReply->error();
        qWarning() << networkReply->errorString();
    
        delete networkReply;
    
        return a.exec();
    }
    

    Под Windows в консоль выводится

    QSslSocket: cannot resolve TLSv1_1_client_method
    QSslSocket: cannot resolve TLSv1_2_client_method
    QSslSocket: cannot resolve TLSv1_1_server_method
    QSslSocket: cannot resolve TLSv1_2_server_method
    QSslSocket: cannot resolve SSL_select_next_proto
    QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
    QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
    true
    "01"
    ("AA-00-00-00")
    QDateTime("2035-06-21 21:41:13.000 UTC Qt::UTC")
    99
    "Unable to init SSL Context: "
    

    Под Linuxв консоль выводится

    true
    "01"
    ("AA-00-00-00")
    QDateTime("2035-06-21 21:41:13.000 UTC Qt::UTC")
    99
    "Unable to init SSL Context: "
    

    Если убрать "networkRequest.setSslConfiguration(sslConfiguration);" то сервер просто возвращает код 400, прося послать клиентский сертификат.

    Если добавить вызов "sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);", то ничего не меняется.

    Буду рад получить любую подсказку в чём может быть причина такого странного поведения.



  • QSslSocket: cannot resolve TLSv1_1_client_method
    QSslSocket: cannot resolve TLSv1_2_client_method
    QSslSocket: cannot resolve TLSv1_1_server_method
    QSslSocket: cannot resolve TLSv1_2_server_method
    QSslSocket: cannot resolve SSL_select_next_proto
    QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
    QSslSocket: cannot resolve SSL_get0_next_proto_negotiated

    Это говорит о том, что QSslSocket не может найти необходимые ему функции ssl. Я бы попробовал пересобрать Qt с подключением либ непосредственно из ssl и соответствующими ключиками в configure. Попробуйте, должно сработать.

    --
    Peace



  • В случае с Win, скачайте OpenSSL Win32 и скопируйте в папку с проектом библиотеки libeay32.dll, libssl32.dll, ssleay32.dll.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.