SSL: Handshake failed for requests made from QML.



  • Hey, I make some https requests directly from my qml views, for instance for image sources. As I have a self signed certificate server side, I need to tell qt to ignore some ssl errors. (I control both the server and the client applications, so this shouldn't be a problem really.)

    I've made a QQmlNetworkAccessManagerFactory to create NAMs, where I connect to the sslErrors signal.

    UltraQmlAccessManagerFactory.h

    #ifndef FACKFACKTORy_H
    #define FACKFACKTORy_H
    
    
    #include <QQmlNetworkAccessManagerFactory>
    #include <QObject>
    #include <QNetworkReply>
    #include <QList>
    #include <QSslError>
    #include <QNetworkAccessManager>
    #include <QDebug>
    #include <QSslCertificate>
    
    class UltraQmlNetworkAccessManagerFactory : public QObject,
                                                public QQmlNetworkAccessManagerFactory {
      Q_OBJECT
    private:
      QNetworkAccessManager* nam;
      QList<QSslError> expectedSslErrors;
    public:
      explicit UltraQmlNetworkAccessManagerFactory();
      ~UltraQmlNetworkAccessManagerFactory();
      virtual QNetworkAccessManager* create(QObject* parent);
    
    public slots:
      void onIgnoreSslErrors(QNetworkReply* reply, QList<QSslError> errors);
    };
    
    #endif
    

    UltraQmlNetworkAccessManagerFactory.cpp

    #include "UltraQmlNetworkAccessManagerFactory.h"
    
    UltraQmlNetworkAccessManagerFactory::UltraQmlNetworkAccessManagerFactory() {
    
      // disregard this for now...
      QList<QSslCertificate> cert = QSslCertificate::fromPath(":/public.crt");
      QSslError self_signed_error(QSslError::SelfSignedCertificate, cert.at(0));
      QSslError host_name_error(QSslError::HostNameMismatch, cert.at(0));
      //  QSslError untrusted_error(QSslError::CertificateUntrusted, cert.at(0));
      expectedSslErrors.append(self_signed_error);
      //  expectedSslErrors.append(host_name_error);
      //  expectedSslErrors.append(untrusted_error);
    
    
    }
    
    UltraQmlNetworkAccessManagerFactory::~UltraQmlNetworkAccessManagerFactory() {
      delete nam;
    }
    
    QNetworkAccessManager* UltraQmlNetworkAccessManagerFactory::create(QObject* parent) {
      QNetworkAccessManager* nam = new QNetworkAccessManager(parent);
      QObject::connect(nam, SIGNAL(sslErrors(QNetworkReply*, QList<QSslError>)),
                       this, SLOT(onIgnoreSslErrors(QNetworkReply*,QList<QSslError>))
                       );
      return nam;
    
    }
    
    
    void UltraQmlNetworkAccessManagerFactory::onIgnoreSslErrors(QNetworkReply *reply, QList<QSslError> errors) {
    
      QNetworkRequest req = reply->request();
      
      qDebug() << "Hello!" << endl;
    
      for (int i = 0; i < errors.size(); i++) {
        qDebug() << "e: " << errors.at(i) << endl;
    
      }
    
      reply->ignoreSslErrors(errors);
    }
    

    There is also some glue in main.cpp that sets this factory to be used, I doubt that part is a source of errors as the qDebug prints are visible in the output.

    As you can see in the .cpp file in the function/slot onIgnoreSslErrors, I try to ignore every error (as a test) that I receive, but as you can see in the output I do not get the expected results.

    Output

    Hello! 
    
    e:  "The certificate is self-signed, and untrusted" 
    
    qrc:/qml/file/ImageView.qml:16:5: QML Image: SSL handshake failed
    

    I have successfully made QNetworkRequests from c++ directly with a QSslConfiguration, specifying TLSV1_0 and a certificate. As I have a suspicion that the handshake fails because one side expects SSL and the other TLS I have also tried to set the QSslConfiguration on the QNetworkRequest object throgh reply->request(); This however, changes nothing.

    Thanks for taking time to read my post.

    Pelle K


  • Moderators

    @PelleKrogstad
    I too had the same requirement. Looking further into I found out that the slot for onIgnoreSslErrors was never called as it is required for Self Signed Certificates and which cause these SSL errors.
    So actually the request needs to modified a bit which could be done by re-implementing createRequest
    Thus in QNAM subclassed class:

    QNetworkReply *MyNam::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
    {
        QNetworkRequest req = request;
        QSslConfiguration conf = req.sslConfiguration();
        conf.setProtocol(QSsl::AnyProtocol);
        req.setSslConfiguration(conf);
    
        QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
        qDebug() << req.url();
        return reply;
    }
    

    And thus the ignoreSSLErrors slot was called where the errors were ignored. This worked for me. Let me know if it works for you.


Log in to reply
 

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