Qt Notes: Working with QSslSocket

The Qt cross-platform application and UI framework provides a great deal of functionality to explore.  After working with it off and on for the past two years I am still finding new and useful features to include in my projects.  Recently I have had the opportunity to work with the Secure Sockets Layer (SSL) support, and have put together some notes to group some key documentation points together and to clarify a few points from the documentation that I found to be unclear.  

1.  Detecting SSL support

The main class that you will be working with when using Qt's SSL support, QSslSocket, provides a static member function named supportsSsl(), which will tell you if SSL is supported by the library.  SSL may not be supported if your version of Qt was compiled with SSL disabled, or if the OpenSSL libraries on which Qt depends for its SSL support are not installed on your system.

QSslSocket::supportsSsl() can be used to programmatically detect that SSL is not supported, so that the application's user can be informed of the lack of SSL support.  

void MyApplication::openConnection(const QString &hostname, unsigned short port) {
  if (QSslSocket::supportsSsl()) {
    QSslSocket *socket = new QSslSocket(this);
    connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));
    socket->connectToHostEncrypted(hostname, port);
  } else {
    QMessageBox::critical(this, "No SSL Support",
      "SSL is not supported by your version of Qt. You must obtain a version of Qt"
      "that has SSL support enabled. If you believe that your version of Qt has"
      "SSL support enabled, you may need to install the OpenSSL run-time libraries.");
  }
}

 

2.  Accepting an SSL connection

The QSslSocket documentation provides an example of accepting an SSL connection with a server socket that omits the important steps of key and certificate specification.  If a valid key and certificate pair is not specified, the SSL handshake will fail.  

The Qt "Guide to SSL certificates and certificate authorities" contains an example where the key and certificate are specified for a server socket, but this example references functions that no longer exist in the current version of the QSslSocket API.

Qt does not currently provide support for creating keys and certificates.  As described by the Qt SSL certificate guide, the OpenSSL utilities can be used to create key and certificate files that are loaded by a Qt application.

// Intercept new socket connection and enable SSL
void SslServer::incomingConnection(int socketDescriptor) {
  QSslSocket *socket = new QSslSocket();
  if (socket->setSocketDescriptor(socketDescriptor)) {
    connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));
    socket->setPrivateKey("server.key");
    socket->setLocalCertificate("server.csr");
    socket->startServerEncryption();
  } else {
    delete socket;
  }
}

 

3.  The sslErrors(const QList<QSslError> &) signal

According to the QSslSocket documentation, the QSslSocket::sslErrors(const QList<QSslError> &) signal is emitted when one or more errors have occurred while establishing the identity of the peer.  My experience has been that this signal is always emitted, even if no errors have occurred.  If no errors have occurred the error list contains a single entry, QSslError::NoError [update: this appears to be a bug related to the OpenSSL version being used, and is not normal behavior; see QTBUG-19981].

Errors reported by QSslSocket::sslErrors(const QList<QSslError> &) are not necessarily fatal errors.  It is possible that the handshake will succeed and the connection will complete, even if an error occurs while establishing the identity of the peer.  Receipt of this signal should not be treated as an indication of connection failure.

Errors indicating that authentication of a peer's certificate has failed may be received, but if the peer verify mode is set to QSslSocket::VerifyNone the handshake will succeed and the connection will complete successfully.  As noted by the QSslSocket documentation, when the peer verify mode is not set to QSslSocket::VerifyNone, SSL errors can be ignored by calling QSslSocket::ignoreSslErrors() from within the slot receiving the QSslSocket::sslErrors(const QList<QSslError &) signal.  

 

That should help you get started writing Qt applications with SSL support.  It will also serve as a nice reminder to me of what must be done to enable SSL support for a Qt application the next time I need to do it.  

 

Update (July 14, 2011):  I have created simple chat client and server applications to demonstrate the use of QSslSocket when opening secure connections as a client and accepting secure connections as a server.  These examples provide notifications to the user when SSL support is not available, when key and certificate files are needed, and when SSL errors are encountered.  They can be found in the following Github repository:

git://github.com/dgraves/QSslChat.git

Programming: 

Comments

Hi, I am beginning to work with SSL in Qt, but still having problems. As you said, this part is poorly documented, and it's hard to find up-to-date examples. I followed the steps on this tutorial, but it's still not working. So my question is

how can I generate de SSL key and certificate for the connection?

Thanks for your time

Hi George, you will need to generate the SSL key and certificate with the third-party openssl tool.  The Qt "Guide to SSL certificates and certificate authorities" has some examples demonstrating how this is done.  The easiest option to get a key and certificate pair for testing is to generate a self-signed certificate like this:

openssl req -x509 -newkey rsa:2048 -keyout server.key -nodes -days 365 -out server.csr

The files generated by this command are the ones that will be specified to the QSslSocket.  In my example I specify the files as:

socket->setPrivateKey("server.key");
socket->setLocalCertificate("server.csr");

This assumes the files are stored in the application's current working directory.  You'll most likely need to specify the full path to the files.  The key and certificate files are also only needed by server sockets.  Client sockets should not require these files.

I think that it is also worth noting that the Qt libraries for Windows that are distributed by Nokia have SSL support enabled, but are not packaged with the OpenSSL DLLs that are required to make SSL work.  If you are working on Windows and using the libraries provided by Nokia, you will need to install OpenSSL.  I have been using the Win32 OpenSSL install package found here: http://www.slproweb.com/products/Win32OpenSSL.html

I'll try to put a simple QSslSocket example together, which includes working server and client code, and post it here.

I have created some sample applications to demonstrate the use of QSslSocket with clients and servers.  Details for obtaining the applications have been added to the post.

This is the only up to date info out there on the subject; your notes (combined with your examples) were exactly what I needed. Thanks a million!

Hi,

I downloaded your QSslChat application and tried to run it.  The Client runs OK but the Server has the following comipler error:

   sslserver.cpp: In member function ‘virtual void SslServer::incomingConnection(int)’:
   sslserver.cpp:11: error: ‘addPendingConnection’ was not declared in this scope
 

I could not figure out where "addPendingConnection()" came from.  It is not a member function of QTcpServer.

Thanks,

Du 

 

Hi Du,

The addPendingConnection() function is a protected member of QTcpServer.  According to the documentation on qt-project.org it is available with Qt versions 4.7, 4.8, and 5.0:

http://qt-project.org/doc/qt-4.8/qtcpserver.html#addPendingConnection

Which version of Qt are you using?

-Dustin

saved my day! :)

On Gnu/Linux (Ubuntu 11.10)  and Qt 5 it crashes.

On line    QSslSocket *socket = dynamic_cast<QSslSocket *>(server.nextPendingConnection()); socket is null. :(

Any idea why?