Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt5 client certificate authentication

I have Qt 5.4.0 on Windows 8.1 and Qt 5.4.2 on ArchLinux latest and get exactly the same result.

I have web-site which requires client SSL certificate. Server seems to be configured properly since execution of

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

prints

Verify return code: 0 (ok)

Also,

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

works just fine.

Server certificate is valid, browsers accept it, etc. Client certificate is self signed. Just in case, server is nginx and here is relevant config fragment

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;

But the following simplest Qt5 application

#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();
}

fails with the following console output on 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: "

and the following console output on Linux

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

If I remove "networkRequest.setSslConfiguration(sslConfiguration);" I just get 400 error from server stating I need to send client certificate.

Adding "sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);" changes nothing.

I will be happy to get any advice what can be cause of Qt5 code failure.

like image 234
adontz Avatar asked Nov 09 '22 10:11

adontz


1 Answers

Qt resolves OpenSSL functions at runtime and those warnings are result of it. It may be your program doesn't find OpenSSL at all or it finds too old version. From Qt 5.2 onwards OpenSSL v1.0.0 or later is required.

From Qt documentation:

Support for Secure Sockets Layer (SSL) communication is provided by the OpenSSL Toolkit, which must be obtained separately.

From Qt version 5.2 onwards, the officially supported version for OpenSSL is 1.0.0 or later. Versions >= 0.9.7 and < 1.0.0 might work, but are not guaranteed to.

like image 61
talamaki Avatar answered Nov 15 '22 08:11

talamaki