Can't get QSslSocket working.
-
I can't seem to find a complete working client server sample code where each uses SSL (QSslSocket). The QT doc gives half of the equation for the SSL client when it starts an immediate SSL handshake
@
QSslSocket *socket = new QSslSocket(this);
connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));socket->connectToHostEncrypted("imap.example.com", 993);
@but doesn't give corresponding server code that would go with that. The client part seems to be the easy part. But I don't quite understand what the server side is supposed to do once a connection has been established.
Can somebody point me to something like that? Or if you know yourself explain to me how to properly establish an SSL handshake in QT.
I would really appreciate this.
Thanks.
-
Hello,
A while ago I wrote an article about SMTP protocol which uses QSslSocket class.
"SMTP example":http://morf.lv/modules.php?name=tutorials&lasit=20However, I'm only covering the client side of communication.
So the question is, are you struggling with the server side? From the code, I can see the client side. -
Yes definitely the server side. My QT ssl client seems to be working because I tested it against an SSL server I wrote in VS C++ and winsock library. So let me add the relevant code of my QT SSL server and client which cannot establish a handshake.
QT SSL Client cpp:
@
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
...
connect( connect_button, SIGNAL(clicked()), this, SLOT(connect_to_sslserver()) );
....
}bool MainWindow::connect_to_sslserver()
{
if(connected_)
return true;//Set the default destination port quint32 iport = 1111; tcpsocket_ = new QSslSocket; tcpsocket_->setPeerVerifyMode(QSslSocket::VerifyNone); QSslConfiguration sslConfig = tcpsocket_->sslConfiguration(); sslConfig.setSslOption(QSsl::SslOptionDisableSessionTickets, true); sslConfig.setProtocol(QSsl::SslV3); tcpsocket_->setSslConfiguration(sslConfig); connect(tcpsocket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error_handler(QAbstractSocket::SocketError))); connect(tcpsocket_, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ssl_error_handler(QList<QSslError>))); connect(tcpsocket_, SIGNAL(encrypted()), this, SLOT(sslsocket_ready())); tcpsocket_->connectToHostEncrypted("my-host", iport); if(!tcpsocket_->waitForEncrypted()) { qDebug() << Q_FUNC_INFO << "failed to establish a SSL handshake with server"; return false; } return true;
}
@QT SSL Server header:
@
class SSLServer : public QTcpServer
{
Q_OBJECT
public:
explicit SSLServer(QObject *parent = 0);
void incomingConnection(int handle);
signals:public slots:
void ready();
void error_handler(QAbstractSocket::SocketError);
void ssl_error_handler(QList<QSslError> ssl_errors);
void read_data_from_client();private:
QSslSocket tcpCommandSocket_;
QThread tcp_thread_;
QObject * mainwin_;};
@QT SSL Server cpp:
@#include "secureserver.h"
#include "mainwindow.h"SSLServer::SSLServer(QObject *parent) :
QTcpServer(parent)
{
mainwin_ = parent;
}void SSLServer::incomingConnection(int sd)
{
tcpCommandSocket_ = new QSslSocket;
if( tcpCommandSocket_->setSocketDescriptor(sd))
{
QFile sslkeyfile("certs/server-priv-key.pem");
if (!sslkeyfile.exists())
{
qDebug() << Q_FUNC_INFO << "file could not be found";
return;
}
if (!sslkeyfile.open(QFile::ReadOnly| QFile::Text))
{
qDebug() << Q_FUNC_INFO << "file could not be opened";
return;
}
QString private_key = sslkeyfile.readAll();
tcpCommandSocket_->setPrivateKey(private_key);QFile sslServerCertfile("certs/server-cert.pem"); if (!sslServerCertfile.exists()) { qDebug() << Q_FUNC_INFO << "file could not be found"; return; } if (!sslServerCertfile.open(QFile::ReadOnly| QFile::Text)) { qDebug() << Q_FUNC_INFO << "file could not be opened"; return; } QString server_cert = sslServerCertfile.readAll(); tcpCommandSocket_->setLocalCertificate(server_cert); tcpCommandSocket_->setPeerVerifyMode(QSslSocket::VerifyNone); tcpCommandSocket_->setProtocol(QSsl::SslV3); connect(tcpCommandSocket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error_handler(QAbstractSocket::SocketError))); connect(tcpCommandSocket_, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ssl_error_handler(QList<QSslError>))); tcpCommandSocket_->startServerEncryption(); if(!tcpCommandSocket_->waitForEncrypted()) { qDebug() << Q_FUNC_INFO << "failed to perform SSL handshake with client"; return; } connect(tcpCommandSocket_, SIGNAL(encrypted()), this, SLOT(ready())); connect(tcpCommandSocket_, SIGNAL(readyRead()), this, SLOT(read_data_from_client())); } else { qDebug() << Q_FUNC_INFO << "failed to set socket descriptor"; }
}
void SSLServer::read_data_from_client()
{
QByteArray qstrbytes = tcpCommandSocket_->readAll();
qDebug() << Q_FUNC_INFO << qstrbytes;
}void SSLServer::ready()
{
qDebug() << Q_FUNC_INFO;}
void SSLServer::error_handler(QAbstractSocket::SocketError in_error)
{
qDebug() << Q_FUNC_INFO << in_error;
}void SSLServer::ssl_error_handler(QList<QSslError> ssl_errors)
{
foreach (QSslError err, ssl_errors)
{
qDebug() << Q_FUNC_INFO << err.errorString();
}
}
@Errors messages on the Server:
void SSLServer::error_handler(QAbstractSocket::SocketError) QAbstractSocket::SocketError( 13 )
virtual void SSLServer::incomingConnection(int) failed to perform SSL handshake with clientErrors messages on the client:
void MainWindow::error_handler(QAbstractSocket::SocketError) QAbstractSocket::RemoteHostClosedError bool MainWindow::connect_to_sslserver() failed to establish a SSL handshake with server
-
A little more info that might help understand what is happening.
I ran openssl client against my QT server like this:
@openssl s_client -connect my-hostl:1111@here is the output
@Loading 'screen' into random state - done
CONNECTED(000001AC)
4940:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:.\ssl\s23_lib.c:177:no peer certificate available
No client certificate CA names sent
SSL handshake has read 0 bytes and written 321 bytes
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE@Hope this helps somebody out there understand what the problem is.
Thanks