16.8.10

Basic samples for SSL communication over Qt

1) client
class SSLClient: public QObject
{
Q_OBJECT

public:
SSLClient(QObject* parent = NULL)
: QObject(parent)
{
connect(&client, SIGNAL(encrypted()),
this, SLOT(connectionEstablished()));
connect(&client, SIGNAL(sslErrors(const QList<QSslError> &)),
this, SLOT(errorOccured(const QList<QSslError> &)));
}

void start(QString hostName, quint16 port)
{
client.setProtocol(QSsl::TlsV1);
client.connectToHostEncrypted(hostName, port);
}

public slots:
// handle the signal of QSslSocket.encrypted()
void connectionEstablished()
{
// get the peer's certificate
QSslCertificate cert = client.peerCertificate();

// write on the SSL connection
client.write("hello, world", 13);
}

// handle the signal of QSslSocket.sslErrors()
void errorOccured(const QList<QSslError> &error)
{
// simply ignore the errors
// it should be very careful when ignoring errors
client.ignoreSslErrors();
}

private:
QSslSocket client;
};


int main(int argc, char** argv)
{
QApplication app(argc, argv);

SSLClient client;
client.start("127.0.0.1", 8888);

return app.exec();
}



2) server
class SSLServer: public QTcpServer
{
Q_OBJECT

public:
SSLServer(QObject* parent = NULL)
: QTcpServer(parent)
{
}

void start(QString certPath, QString keyPath, quint16 port)
{
listen(QHostAddress::Any, port);
this->certPath = certPath;
this->keyPath = keyPath;
}

public slots:
void readyToRead()
{
qDebug() << serverSocket->readAll();
}

void errorOccured(const QList &)
{
serverSocket->ignoreSslErrors();
}

protected:
void incomingConnection(int socketDescriptor)
{
serverSocket = new QSslSocket;
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyToRead()));
connect(serverSocket, SIGNAL(sslErrors(const QList &)),
this, SLOT(errorOccured(const QList &)));
serverSocket->setProtocol(QSsl::TlsV1);
serverSocket->setPrivateKey(keyPath);
serverSocket->setLocalCertificate(certPath);
serverSocket->startServerEncryption();
} else {
delete serverSocket;
}
}

private:
QSslSocket *serverSocket;
QString certPath;
QString keyPath;
};

int main(int argc, char** argv)
{
QApplication app(argc, argv);

SSLServer server;
server.start("ca.cer", "ca.key", 8888);

return app.exec();
}


9 comments:

  1. Hello Xi,

    I've copied the config.xml and html file. Followed the steps, but doesn't work. Can you post a link to a downloadable example.wrt with the above files?

    ReplyDelete
  2. Hi. how do we do HTTP GET POST, etc with an SSL site? i'd like to access their webservices.

    ReplyDelete
  3. @Anonymous:
    You can use QNetworkAccessManager for HTTP GET/POST request directly, and handle the sslErrors() signal if needed.

    ReplyDelete
  4. Hi Xizhi,

    I try to compile your ssl server example, and encounter following error message:


    g++ -Wl,-rpath,/usr/local/Trolltech/Qt-4.7.1/lib -o sslserver main.o sslserver.o -L/usr/local/Trolltech/Qt-4.7.1/lib -lQtNetwork -L/usr/local/Trolltech/Qt-4.7.1/lib -lQtCore -lpthread
    main.o: In function `sslserver':
    /home/vincente/QT/Project/sslserver-build-desktop/../sslserver/sslserver.h:16: undefined reference to `vtable for sslserver'
    main.o: In function `~sslserver':
    /home/vincente/QT/Project/sslserver-build-desktop/../sslserver/sslserver.h:11: undefined reference to `vtable for sslserver'
    collect2: ld returned 1 exit status
    make: *** [sslserver] Error 1

    Would you give me a hint how to solve this issue?

    ReplyDelete
  5. @ənonymous
    Is it so that you declared one destructor (~sslserver), but not implement it?

    ReplyDelete
  6. Thank you for posting this wonderfully simple example of qt SSL communication. They are the first examples I have found that don't bury what you want to know to start with in a mess of other code. And they worked first time!

    A couple of issues to get it to compile:

    In the client you have:
    void errorOccured(const QList &error)

    Which is good but in the server you have:

    void errorOccured(const QList &)

    which won't compile. Should be the same as the client. And change the connect calls accordingly.

    I got rid of the vtable errors by spliting things out into separate header and source files and having a separate main.cpp. After qmake and make worked fine.

    Perhaps you should give a little hint about making certs and keys to test this with. I used the introduction to SSL here: http://doc.trolltech.com/solutions/4/qtsslsocket/sslguide.html

    ReplyDelete
  7. Oops I got that a bit wrong in my post just above.

    In the client you have:

    void errorOccured(const QList &error)

    Which is correct, the QList template needs a type, the server should be the same.

    ReplyDelete
  8. Oops I got it wrong again. Seems the angle brackets, used for templates, are being removed from these comments. Still I'm sure you get the point.

    ReplyDelete
  9. when i run my application, always encounter with the following error:
    No such signal QNetworkAccessManager::sslErrors.

    Do you know what the probable reason is?
    I compiled Qt with -openssl, and before that, i have installed openssl.

    ReplyDelete