Hello to all. I'm programming client-server where both need to identify to the other with certificate (they both also check if the certificate is really from who it says to be - with CA).
So here's the code of server and client program. The problem is it never starts a SSL handshake, it keeps saying: the socket is not encrypted:
Server.cpp
/* listen for incoming connections on localhost:PORT */
qFatal("Unable to start the server on localhost:%d",PORT);
}
//connect(tcpServer, SIGNAL(incomingConnection(int)), this, SLOT(check_ssl_connection()));
/* newConnection() signal is emitted every time a client connects to server */
//connect(tcpServer, SIGNAL(newConnection(int &)), this, SLOT(incomingConnection2(int &)));
}
/**
* This function is called by QTcpServer whenever a new connection is available
**/
void Server::incomingConnection(int socket_descriptor) {
(void)new SSLServer(socket_descriptor, this);
}
Server::Server(QObject *parent) : QTcpServer(parent) {
/* listen for incoming connections on localhost:PORT */
if(!this->listen(QHostAddress::LocalHost, PORT)) {
qFatal("Unable to start the server on localhost:%d",PORT);
}
//connect(tcpServer, SIGNAL(incomingConnection(int)), this, SLOT(check_ssl_connection()));
/* newConnection() signal is emitted every time a client connects to server */
//connect(tcpServer, SIGNAL(newConnection(int &)), this, SLOT(incomingConnection2(int &)));
}
/**
* This function is called by QTcpServer whenever a new connection is available
**/
void Server::incomingConnection(int socket_descriptor) {
(void)new SSLServer(socket_descriptor, this);
}
To copy to clipboard, switch view to plain text mode
SSLServer.cpp
SSLServer
::SSLServer(int socket_descriptor,
QObject *parent
) : QObject(parent
) { /* create server socket */
server = new QSslSocket(this);
/* set socket descriptor */
if(!server->setSocketDescriptor(socket_descriptor)) {
qWarning("Failed to set socket descriptor in SSLServer");
close(socket_descriptor);
delete this;
return;
}
//TODO: dynamic filename
/* add CA certificate: it is used by the handshake process to validate the peer's certificate*/
QSslCertificate ca_cert = handle_certificate("/cert/ca.crt");
server->addCaCertificate(ca_cert);
/* set the server's (LOCAL) digital certificate */
QSslCertificate server_cert = handle_certificate("/cert/server.crt");
server->setLocalCertificate(server_cert);
/* set the server's (LOCAL) private key -> [key+certificate == prove identity to SSL peer] */
server->setPrivateKey("/cert/server.key", QSsl::Rsa, QSsl::Pem, "");
/* set cipher protocol */
server->setProtocol(QSsl::SslV3);
/* wait for socket to complete SSL handshake -> when encrypted it emits encrypted signal */
if(server->waitForEncrypted(5000))
qDebug() << "Socket is encrypted." << endl;
QFile file("/home/eleanor/client.p12");
server->write(data);
print_socket_info();
/* handshake is successful and encrypted socket is ready to use */
connect(server, SIGNAL(encrypted()), this, SLOT(connection_established()));
/* if error occurs the sslErrors() signal is emitted */
connect(server, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(error_occured(const QList<QSslError> &)));
/* socket has changed the mode from unencrypted to client/server mode */
connect(server, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(mode_has_changed(QSslSocket::SslMode)));
}
void SSLServer::mode_has_changed(QSslSocket::SslMode mode) {
qDebug() << "SSL Handshake Mode is: " << mode << endl;
}
/**
* This function prints useful information about a SSL socket
**/
void SSLServer::print_socket_info() {
/* if the socket is encrypted */
if(server->isEncrypted()) {
qDebug() << "Server socket is encrypted" << endl;
}
else {
qDebug() << "Server socket is not encryted" << endl;
}
}
/**
* This function reads the certificate from:
* - disk - if available
* - network - if not avalable it downloads the certificate from the server and store it on disk
* Then return the certificate
**/
QSslCertificate SSLServer
::handle_certificate(QString filename
) { /* read the CA certificate */
/* if file exists */
if(!file.exists()) {
qWarning("Filename %s doesn't exists.", qPrintable(filename));
//TODO: download the file from server and store it on disk (predefined location)
}
/* open file */
qWarning("Cannot open filename %s.", qPrintable(filename));
}
/* read the whole file into array */
/* construct new certificate */
QSslCertificate cert(data, QSsl::Pem);
/* check if the certificate is null */
if(cert.isNull()) {
qWarning("The CA certificate has no content.");
}
/* check if the certificate is valid */
if(!cert.isValid()) {
qWarning("The CA certificate expired.");
}
return cert;
}
void SSLServer::connection_established() {
qDebug() << "SSL Handshake succedded. The socket is now encrypted." << endl;
/* get client's (PEER) digital certificate - for diagnostic purposes */
QSslCertificate client_cert = server->peerCertificate();
}
void SSLServer::error_occured(const QList<QSslError> &error) {
/* ignore the errors */
//server->ignoreSslErrors();
qDebug() << "The following errors occured duing SSH Handshake: " << endl;
for(quint16 i=0;i<error.count(); i++) {
qDebug() << error[i] << endl;
}
}
SSLServer::SSLServer(int socket_descriptor, QObject *parent) : QObject(parent) {
/* create server socket */
server = new QSslSocket(this);
/* set socket descriptor */
if(!server->setSocketDescriptor(socket_descriptor)) {
qWarning("Failed to set socket descriptor in SSLServer");
close(socket_descriptor);
delete this;
return;
}
//TODO: dynamic filename
/* add CA certificate: it is used by the handshake process to validate the peer's certificate*/
QSslCertificate ca_cert = handle_certificate("/cert/ca.crt");
server->addCaCertificate(ca_cert);
/* set the server's (LOCAL) digital certificate */
QSslCertificate server_cert = handle_certificate("/cert/server.crt");
server->setLocalCertificate(server_cert);
/* set the server's (LOCAL) private key -> [key+certificate == prove identity to SSL peer] */
server->setPrivateKey("/cert/server.key", QSsl::Rsa, QSsl::Pem, "");
/* set cipher protocol */
server->setProtocol(QSsl::SslV3);
/* wait for socket to complete SSL handshake -> when encrypted it emits encrypted signal */
if(server->waitForEncrypted(5000))
qDebug() << "Socket is encrypted." << endl;
QFile file("/home/eleanor/client.p12");
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
server->write(data);
print_socket_info();
/* handshake is successful and encrypted socket is ready to use */
connect(server, SIGNAL(encrypted()), this, SLOT(connection_established()));
/* if error occurs the sslErrors() signal is emitted */
connect(server, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(error_occured(const QList<QSslError> &)));
/* socket has changed the mode from unencrypted to client/server mode */
connect(server, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(mode_has_changed(QSslSocket::SslMode)));
}
void SSLServer::mode_has_changed(QSslSocket::SslMode mode) {
qDebug() << "SSL Handshake Mode is: " << mode << endl;
}
/**
* This function prints useful information about a SSL socket
**/
void SSLServer::print_socket_info() {
/* if the socket is encrypted */
if(server->isEncrypted()) {
qDebug() << "Server socket is encrypted" << endl;
}
else {
qDebug() << "Server socket is not encryted" << endl;
}
}
/**
* This function reads the certificate from:
* - disk - if available
* - network - if not avalable it downloads the certificate from the server and store it on disk
* Then return the certificate
**/
QSslCertificate SSLServer::handle_certificate(QString filename) {
/* read the CA certificate */
QFile file(filename);
/* if file exists */
if(!file.exists()) {
qWarning("Filename %s doesn't exists.", qPrintable(filename));
//TODO: download the file from server and store it on disk (predefined location)
}
/* open file */
if(!file.open(QIODevice::ReadOnly)) {
qWarning("Cannot open filename %s.", qPrintable(filename));
}
/* read the whole file into array */
QByteArray data = file.readAll();
/* construct new certificate */
QSslCertificate cert(data, QSsl::Pem);
/* check if the certificate is null */
if(cert.isNull()) {
qWarning("The CA certificate has no content.");
}
/* check if the certificate is valid */
if(!cert.isValid()) {
qWarning("The CA certificate expired.");
}
return cert;
}
void SSLServer::connection_established() {
qDebug() << "SSL Handshake succedded. The socket is now encrypted." << endl;
/* get client's (PEER) digital certificate - for diagnostic purposes */
QSslCertificate client_cert = server->peerCertificate();
}
void SSLServer::error_occured(const QList<QSslError> &error) {
/* ignore the errors */
//server->ignoreSslErrors();
qDebug() << "The following errors occured duing SSH Handshake: " << endl;
for(quint16 i=0;i<error.count(); i++) {
qDebug() << error[i] << endl;
}
}
To copy to clipboard, switch view to plain text mode
Client.cpp
/* create client socket */
client = new QSslSocket();
//TODO: dynamic filename
/* CA certificate: it is used by the handshake process to validate the peer's certificate */
QSslCertificate ca_cert = handle_certificate("/cert/ca.crt");
client->addCaCertificate(ca_cert);
/* set the client's (LOCAL) digital certificate */
QSslCertificate client_cert = handle_certificate("/cert/client.crt");
client->setLocalCertificate(client_cert);
/* set the client's (LOCAL) private key -> [key+certificate == prove identity to SSL peer] */
client->setPrivateKey("/cert/client.key", QSsl::Rsa, QSsl::Pem, "");
/* set cipher protocol */
client->setProtocol(QSsl::SslV3);
/* get server's (PEER) digital certificate */
//QSslCertificate server_cert = client->peerCertificate();
client->connectToHostEncrypted("127.0.0.1", 8088);
//client->startClientEncryption();
/* handshake is successful and encrypted socket is ready to use */
connect(client, SIGNAL(encrypted()), this, SLOT(connection_established()));
/* if error occurs the sslErrors() signal is emitted */
connect(client, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(error_occured(const QList<QSslError> &)));
}
/**
* This function reads the certificate from:
* - disk - if available
* - network - if not avalable it downloads the certificate from the server and store it on disk
* Then return the certificate
**/
QSslCertificate SSLClient
::handle_certificate(QString filename
) { /* read the CA certificate */
/* if file exists */
if(!file.exists()) {
qWarning("Filename %s doesn't exists.", qPrintable(filename));
//TODO: download the file from server and store it on disk (predefined location)
}
/* open file */
qWarning("Cannot open filename %s.", qPrintable(filename));
}
/* read the whole file into array */
/* construct new certificate */
QSslCertificate cert(data, QSsl::Pem);
/* check if the certificate is null */
if(cert.isNull()) {
qWarning("The CA certificate has no content.");
}
/* check if the certificate is valid */
if(!cert.isValid()) {
qWarning("The CA certificate expired.");
}
/* add CA certificate - to validate the peer's certificate during handshake */
//client->addCaCertificate(cert);
return cert;
}
void SSLClient::connection_established() {
/* get the server's certificate */
QSslCertificate server_cert = client->peerCertificate();
/* write on the ssl connection */
client->write("Hello, world",13);
}
void SSLClient::error_occured(const QList<QSslError> &error) {
/* ignore the errors */
//client->ignoreSslErrors();
}
SSLClient::SSLClient(QObject *parent) : QObject(parent) {
/* create client socket */
client = new QSslSocket();
//TODO: dynamic filename
/* CA certificate: it is used by the handshake process to validate the peer's certificate */
QSslCertificate ca_cert = handle_certificate("/cert/ca.crt");
client->addCaCertificate(ca_cert);
/* set the client's (LOCAL) digital certificate */
QSslCertificate client_cert = handle_certificate("/cert/client.crt");
client->setLocalCertificate(client_cert);
/* set the client's (LOCAL) private key -> [key+certificate == prove identity to SSL peer] */
client->setPrivateKey("/cert/client.key", QSsl::Rsa, QSsl::Pem, "");
/* set cipher protocol */
client->setProtocol(QSsl::SslV3);
/* get server's (PEER) digital certificate */
//QSslCertificate server_cert = client->peerCertificate();
client->connectToHostEncrypted("127.0.0.1", 8088);
//client->startClientEncryption();
/* handshake is successful and encrypted socket is ready to use */
connect(client, SIGNAL(encrypted()), this, SLOT(connection_established()));
/* if error occurs the sslErrors() signal is emitted */
connect(client, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(error_occured(const QList<QSslError> &)));
}
/**
* This function reads the certificate from:
* - disk - if available
* - network - if not avalable it downloads the certificate from the server and store it on disk
* Then return the certificate
**/
QSslCertificate SSLClient::handle_certificate(QString filename) {
/* read the CA certificate */
QFile file(filename);
/* if file exists */
if(!file.exists()) {
qWarning("Filename %s doesn't exists.", qPrintable(filename));
//TODO: download the file from server and store it on disk (predefined location)
}
/* open file */
if(!file.open(QIODevice::ReadOnly)) {
qWarning("Cannot open filename %s.", qPrintable(filename));
}
/* read the whole file into array */
QByteArray data = file.readAll();
/* construct new certificate */
QSslCertificate cert(data, QSsl::Pem);
/* check if the certificate is null */
if(cert.isNull()) {
qWarning("The CA certificate has no content.");
}
/* check if the certificate is valid */
if(!cert.isValid()) {
qWarning("The CA certificate expired.");
}
/* add CA certificate - to validate the peer's certificate during handshake */
//client->addCaCertificate(cert);
return cert;
}
void SSLClient::connection_established() {
/* get the server's certificate */
QSslCertificate server_cert = client->peerCertificate();
/* write on the ssl connection */
client->write("Hello, world",13);
}
void SSLClient::error_occured(const QList<QSslError> &error) {
/* ignore the errors */
//client->ignoreSslErrors();
}
To copy to clipboard, switch view to plain text mode
Thank you for all your help...
Bookmarks