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.
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.