How to use the TLS protocol on Qt?

8k views Asked by At

Please give an example of the server side, which shows use TLS.

Now I have the following code:

#include <QCoreApplication>
#include "server.h"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    Server h;
    return a.exec();
}

///////////////////////////////////////

#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>

class Server : public QTcpServer {
    public:
    Server();

    void incomingConnection(int);
};

#endif // SERVER_H


///////////////////////////////////////////

#include "server.h"

#include <QSslSocket>
#include <QSslCertificate>

Server::Server() {
    if (!listen(QHostAddress::Any, 80)) {
        //error
    }
}

void Server::incomingConnection(int d) {
    QSslSocket * socket = new QSslSocket();
    if(socket->setSocketDescriptor(d)) {
        QString c, k;
        c = "site.crt";
        k = "site.key";
        socket->setLocalCertificate(c);
        socket->setPrivateKey(k);
        socket->startServerEncryption();
        if(socket->waitForEncrypted()) {
            if(socket->waitForReadyRead()) {
                socket->write(socket->readAll());
                socket->waitForBytesWritten();
                socket->disconnectFromHost();
                if(socket->state() == QTcpSocket::UnconnectedState) {
                    socket->waitForDisconnected();
                }
                socket->close();
                socket->deleteLater();
            }
            else {
                delete socket;
            }
        }
        else {
            delete socket;
        }
    }
}

How can I change it to first use protocol TLS, and then SSL?

Common task is to write a server with support for SNI.

1

There are 1 answers

7
Nejat On BEST ANSWER

Here is a sample SSL or TLS server which uses a server.key and a server.crt file for encryption:

#include <QtNetwork>
#include <QMessageBox>

class server : public QTcpServer
{
    Q_OBJECT
public:
    explicit server(QObject *parent = 0);
    ~server();

    QSslSocket server_socket;

public slots:


      void tcpReady();

      void encrypted();

      void sslError( QList<QSslError> errors );

      bool start_listen(int port_no);

protected:
    void incomingConnection(qintptr descriptor );

};

server::server(QObject *parent) :
    QTcpServer(parent)
{

    server_socket.setProtocol(QSsl::AnyProtocol);

    QByteArray key;
    QByteArray cert;

    QFile file_key("server.key");
    if(file_key.open(QIODevice::ReadOnly))
    {
        key = file_key.readAll();
        file_key.close();
    }
    else
    {
        qDebug() << file_key.errorString();
    }

    QFile file_cert("server.crt");
    if(file_cert.open(QIODevice::ReadOnly))
    {
        cert = file_cert.readAll();
        file_cert.close();
    }
    else
    {
        qDebug() << file_cert.errorString();
    }


    QSslKey ssl_key(key, QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,"server");

    QSslCertificate ssl_cert(cert);

    server_socket.addCaCertificate(ssl_cert);
    server_socket.setLocalCertificate(ssl_cert);
    server_socket.setPrivateKey(ssl_key);


    connect( &server_socket, SIGNAL(sslErrors(QList<QSslError>)),
            this, SLOT(sslError(QList<QSslError>)) );

    connect(&server_socket,SIGNAL(encrypted()),this,SLOT(encrypted()));

    server_socket.setSocketOption(QAbstractSocket::KeepAliveOption, true );
}

server::~server()
{
    server_socket.disconnectFromHost();
    server_socket.waitForDisconnected();
}

void server::tcpReady()
{
    QByteArray array = server_socket.read( server_socket.bytesAvailable() );
    //...
}

void server::encrypted()
{
    connect( &server_socket, SIGNAL(readyRead()),
             this, SLOT(tcpReady()) );
    emit connection_established();
}

void server::sslError(QList<QSslError> errors)
{
    QString erroStr="";
    foreach (const QSslError &e, errors)
        erroStr.append(e.errorString()).append("\n");

    QMessageBox::warning( (QWidget *)this->parent(), tr("Error"),erroStr );

    server_socket.ignoreSslErrors();
}


bool server::start_listen(int port_no)
{
    if( !this->listen( QHostAddress::Any, port_no ) )
    {
        QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Cannot listen to port %1").arg(port_no) );

    }
    else
        return true;
}

void server::incomingConnection(qintptr descriptor)
{
    if(server_socket.state()!=QAbstractSocket::UnconnectedState)
        return;
    if( !server_socket.setSocketDescriptor( descriptor ) )
    {
        QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Socket error!") );
        return;
    }
    else
    {
        server_socket.startServerEncryption();
    }
}

you can set the protocol to QSsl::SslV3 or QSsl::TlsV1 to only accept SSL or TLS connections.