How to create secure https server in "Qt"? - c++

I am going through the below github source code for implementation of rest server. It has details with respect to http server but when I am trying to create a secure server I am facing problem after adding the certificate and key. Please suggest how to establish a secure https server using Qt.
https://github.com/Tropby/QSimpleRestServer
QFile certFile("demo.cer");
QFile keyFile("demo.key");
QByteArray cert,key;
if(!certFile.open(QIODevice::ReadOnly))
{
qDebug() << "Couldn't Open Resource File.";
qDebug() << "Error: " << certFile.errorString();
}
else {
cert = certFile.readAll();
certFile.close();
}
if(!keyFile.open(QIODevice::ReadOnly))
{
qDebug() << "Couldn't Open Resource File.";
qDebug() << "Error: " << keyFile.errorString();
}
else {
key = keyFile.readAll();
keyFile.close();
}
if(sslSocket->setSocketDescriptor(socket_descriptor)){
qDebug()<<"set passed";
} else {
qDebug()<<"set failed";
}
sslSocket->setProtocol(QSsl::AnyProtocol);
sslSocket->ignoreSslErrors();
QSslKey ssl_key(key,QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,(QByteArray)"demo.key");
QSslCertificate ssl_cert(cert);
sslSocket->setLocalCertificate(cert);
sslSocket->setPrivateKey(ssl_key);
sslSocket->modeChanged(QSslSocket::SslMode::SslServerMode);
sslSocket->startServerEncryption();

Related

Transparent Proxy: why QTcpSocket receives no data when client sends HTTPS request

A proxy application which the client side redirect all connections to the server side application.
At the server side, QTcpServer::newConnection() signal is emitted and we connect QTcpSocket::readyRead() signal to our slot which receives the data from client and redirect the data to 3rd party application for handling HTTP/HTTPS requests. readyRead() signal emitted when client sends HTTP request but this does not happen with HTTPS requests.
Tried: Set QTcpServer::proxy() and QTcpSocket::proxy() to QNetworkProxy::NoProxy, use QSslSocket instead of QTcpSocket with ignoreSslErrors().
Code:
Client::Client(QObject *parent, QTcpSocket* clientCon)
: QObject(parent)
{
client = clientCon;
tunnel = new QSslSocket();
if (serverApp) // If application running as server
tunnel->connectToHost("127.0.0.1", 808); // Connect to CCProxy which handle the requests for us
else
{
tunnel->setProxy(QNetworkProxy::NoProxy);
tunnel->ignoreSslErrors();
tunnel->connectToHost(QHostAddress("serverip"), 9090); // Connect to the server side if running as client
}
tunnel->waitForConnected(5000); // 5 seconds timeout
if (tunnel->state() == tunnel->ConnectedState)
{
QObject::connect(client, SIGNAL(readyRead()), this, SLOT(ClientDataReceived()));
QObject::connect(tunnel, SIGNAL(readyRead()), this, SLOT(TunnelDataReceived()));
QObject::connect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
QObject::connect(tunnel, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
}
}
Client::~Client()
{
}
bool Client::IsTunnelEstablished()
{
return tunnel->state() == tunnel->ConnectedState ? true : false;
}
QString Client::GetTunnelErrorString()
{
return tunnel->errorString();
}
void Client::ClientDataReceived()
{
QByteArray data = client->readAll();
qDebug() << "Client [" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Data Received: " << data.size();
qint64 wr = tunnel->write(data, data.size());
if (wr != data.size())
qDebug() << "QTcpSocket::write() failed!"; // Never happened
data.clear();
tunnel->flush();
}
void Client::TunnelDataReceived()
{
QByteArray data = tunnel->readAll();
qDebug() << "Client Tunnel [" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Data Received: " << data.size();
client->write(data);
data.clear();
client->flush();
}
void Client::ClientDisconnected()
{
/*if (tunnel->state() == tunnel->ConnectedState)
tunnel->close();*/
qDebug() << "[" << client->peerAddress().toString().remove(" ") << ":" << client->peerPort() << "] Disconnected";
QObject::disconnect(client, SIGNAL(readyRead()), this, SLOT(ClientDataReceived()));
QObject::disconnect(tunnel, SIGNAL(readyRead()), this, SLOT(TunnelDataReceived()));
QObject::disconnect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
QObject::disconnect(tunnel, SIGNAL(disconnected()), this, SLOT(ClientDisconnected()));
client->deleteLater();
tunnel->deleteLater();
delete this; // Self delete
}
Server Initialization:
void BaseProtocol::StartServer()
{
server = new QTcpServer();
server->setProxy(QNetworkProxy::NoProxy);
server->listen(QHostAddress("0.0.0.0"), serverApp ? 9090 : 5050); // 9090 for server, 5050 for client
qDebug() << QObject::connect(server, SIGNAL(newConnection()), this, SLOT(ClientConnecting()));
}
void BaseProtocol::ClientConnecting()
{
QTcpSocket *client = server->nextPendingConnection(); // Accept the connection
qDebug() << "Client Connected: " << client->peerAddress().toString() << ":" << client->peerPort();
Client* clientHandler = new Client(this, client);
if (!clientHandler->IsTunnelEstablished())
{
qDebug() << "Tunnel Connection Failed: " << clientHandler->GetTunnelErrorString() << "\n";
client->disconnect();
client->deleteLater();
delete clientHandler;
}
}
As you see the client and server application are the same but start with different ports. The reason why I use a client side application instead of connecting to the server as proxy directly is because I want to encrypt the data between client and server later. (same problem also exist when connecting directly to server side)
This is supposed to be a transparent proxy so there is no need for SSL/TLS at all.
"Internet Options" are used to set the proxy server to "127.0.0.1:5050" at the client side.

QSqlTablelModel cannot find SQL view, but QSqlQuery can

I want to use QSqlTableModel since it seems easier to use. It does however not find my tables.
qDebug() << "connecting";
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName(dbHostName);
db.setPort(dbPort);
db.setUserName(dbUserName);
db.setPassword(dbPassword);
// Connect to database sys to get some info to test (basic communication)
db.setDatabaseName("sys");
// Check if opened and if so get some data
if(db.open()){
qDebug() << "DB succesfully opened";
} else {
qDebug() << "DB failed to open";
return;
}
QSqlTableModel* runsSimulationViewModel = new QSqlTableModel();
runsSimulationViewModel->setTable("results.runs_simulation_view");
qDebug() << runsSimulationViewModel->lastError();
//ERROR: QSqlError("", "Unable to find table results.runs_simulation_view", "")
QSqlQuery anotherQuery;
anotherQuery.prepare("SELECT * FROM results.runs_simulation_view");
if(!anotherQuery.exec()) {
qDebug() << anotherQuery.lastError();
} else {
anotherQuery.next();
qDebug() << anotherQuery.value("simulation_id").toInt();
//Prints "3", which is the first value for this field in the table
}
QSqlQuery works, but QSqlTableView cannot find this (SQL) view (and also no tables).
What am I missing?

POCO websocket messes after 50 minutes of working

I have the following question related to POCO library. My client listens the messages from our backend server using POCO library. All is well the first 50 minutes, then with the socket happens something strange and method "receiveFrame" begins to return an exception. After that, the socket does not become operational. I have made few tests the time after which I receive not operational socket is exactly 50 minutes. Also I need to note that our backend server doesn't send anything during all time. I have no idea what happens... Below is code of our Handshake and Read procedures:
void WebSocketManager::Handshake()
{
qDebug() << "WebSocketManager::Handshake";
try {
HTTPResponse response;
QString origin = Settings::Instance()->GetErPortal();
QString host = origin.remove("http://");
host = host.remove('/');
QString token = "/event/bus/ws/subscribe?auth_token=" + Settings::Instance()->token().toUtf8();
_wssession.setHost(host.toUtf8().constData());
_wssession.setPort(80);
HTTPRequest request(HTTPRequest::HTTP_GET, token.toUtf8().constData(),HTTPMessage::HTTP_1_1);
request.set("origin", origin.toUtf8().constData());
_wssock = new WebSocket(_wssession, request, response);
response.getStatus();
HTTPResponse::HTTPStatus status = response.getStatus();
qDebug() << "Handshake status is : " << status;
if(status == HTTPResponse::HTTPStatus::HTTP_SWITCHING_PROTOCOLS)
_status = true;
}
catch (std::exception &e)
{
qDebug() << "WebSocketManager::Handshake exception " << e.what();
}
}
void WebSocketManager::Read()
{
char receiveBuff[1024];
while(_status)
{
qDebug() << "WebSocketManager::Read wait data...., thread = " << QThread::currentThread();
try {
int flags=0;
int rlen=_wssock->receiveFrame(receiveBuff,1024,flags);
if(!rlen)
{
qDebug() << "WebSocketManager::Read error";
emit ConnectionFailed();
return;
}
else
{
qDebug() << "WebSocketManager::Read, len =" << rlen << ", flags = " << flags << ", data = " << receiveBuff;
ProcessBackendEvent(QString(receiveBuff));
}
}
catch (std::exception &e)
{
qDebug() << "WebSocketManager::Read exception " << e.what();
}
}
}
It seems it is bug of POCO library described here https://github.com/pocoproject/poco/issues/490
On 1.9.0 POCO library all work fine...

How to check database is exist or not?

I am using sqlite database in qt. Database created when i use setDatabase("") function. But i dont know how to check same database is exist or not. Here is my code:
//add database driver
db = QSqlDatabase::addDatabase ("QSQLITE");
//create database
if(db.databaseName () == db_Name){
qDebug() << "Database exist or not created." << endl;
} else {
db.setDatabaseName (db_Name);
qDebug() << "Database created." << endl;
}
//opening connection
db.open ();
//if connection created
if(db.isOpen ()){
qDebug() << "Database connected." << endl;
} else {
qDebug() << "Database not connected." << endl;
}
I get the Database created. message. How to check ? Thanks.
You can simply check the database file whether it exists using QFile:
if (QFile::exists(db_Name)) {
// database exists
}
SQLite creates an empty database when you try to open a nonexisting file.
So if you want to know if you need to create the tables for your application, just run a query to check whether these tables exist:
SELECT * FROM sqlite_master WHERE name = 'MyTable';

mysql cpp connector throwing UnknownException while connecting

I am using mysql library to connect to my database (mysql) to retrieve the data after connecting. Checked that my services are running properly.
Following is the part of code that does the connecting task..
// Specify our connection target and credentials
const string server = "tcp://127.0.0.1:3306";
const string username = "root";
const string password = "";// No password - thanks, WAMP Server!
// Try to get a driver to use to connect to our DBMS
try {
driver = get_driver_instance();
if( driver == NULL )
throw SQLException("Null driver instance returned.");
}
catch (SQLException e) {
cout << "Could not get a database driver. Error message: " << e.what() << endl;
return -3;
}
// Try to connect to the DBMS server
try {
dbConn = driver->connect(server, username, password);
}
catch (sql::SQLException e) {
cout << "Could not connect to database. Error message: " << e.getSQLStateCStr() << " Error Code: " << e.getErrorCode() << endl;
cout << "Could not connect to database. Error: " << e.what() << endl;
return -1;
}
It compiles well but gives an unknown exception with unknown debug info. Something like this. Please help.
This worked after changing the string to SQLString for all the connection params like server, username and password.
This worked out like a charm.