4
1
mirror of https://github.com/QuasarApp/Heart.git synced 2025-05-13 01:49:41 +00:00

add HEART_SSL define. This define enable ssl sockets

This commit is contained in:
Andrei Yankovich 2021-05-10 18:13:01 +03:00
parent 666415b5b3
commit 1f1ea0299a
5 changed files with 129 additions and 90 deletions

@ -43,6 +43,14 @@ if (NOT DEFINED HEART_DB_CACHE)
endif()
endif()
if (NOT DEFINED HEART_SSL)
set(HEART_SSL ON)
endif()
if (HEART_SSL)
add_definitions(-DHEART_SSL)
endif()
if (HEART_DB_CACHE)
add_definitions(-DHEART_DB_CACHE)
endif()

@ -15,9 +15,13 @@
#include <QSslSocket>
#include <badrequest.h>
#include <quasarapp.h>
#ifdef HEART_SSL
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#endif
#include <QMetaObject>
#include <QtConcurrent>
#include <closeconnection.h>
@ -224,6 +228,7 @@ AbstractNode::~AbstractNode() {
delete _socketWorker;
}
#ifdef HEART_SSL
QSslConfiguration AbstractNode::getSslConfig() const {
return _ssl;
}
@ -358,6 +363,77 @@ QSslConfiguration AbstractNode::selfSignedSslConfiguration(const SslSrtData & ss
return res;
}
void AbstractNode::incomingSsl(qintptr socketDescriptor) {
AsyncLauncher::Job action = [this, socketDescriptor]() -> bool {
QSslSocket *socket = new QSslSocket;
socket->setSslConfiguration(_ssl);
if (!isBanned(socket) && socket->setSocketDescriptor(socketDescriptor)) {
connect(socket, &QSslSocket::encrypted, [this, socket]() {
if (!registerSocket(socket)) {
socket->deleteLater();
}
});
connect(socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
[socket](const QList<QSslError> &errors){
for (auto &error : errors) {
QuasarAppUtils::Params::log(error.errorString(), QuasarAppUtils::Error);
}
socket->deleteLater();
});
socket->startServerEncryption();
return true;
} else {
delete socket;
return false;
}
};
_socketWorker->run(action);
}
bool AbstractNode::useSelfSignedSslConfiguration(const SslSrtData &crtData) {
if (isListening()) {
return false;
}
_ssl = selfSignedSslConfiguration(crtData);
_mode = SslMode::InitSelfSigned;
return !_ssl.isNull();
}
bool AbstractNode::useSystemSslConfiguration(const QSslConfiguration &sslConfig) {
if (isListening()) {
return false;
}
_ssl = sslConfig;
_mode = SslMode::InitFromSystem;
return !_ssl.isNull();
}
bool AbstractNode::disableSSL() {
if (isListening()) {
return false;
}
_mode = SslMode::NoSSL;
return true;
}
#endif
AbstractNodeInfo *AbstractNode::createNodeInfo(QAbstractSocket *socket,
const HostAddress* clientAddress) const {
return new AbstractNodeInfo(socket, clientAddress);
@ -658,12 +734,16 @@ bool AbstractNode::isBanned(QAbstractSocket *socket) const {
}
void AbstractNode::incomingConnection(qintptr handle) {
#ifdef HEART_SSL
if (_mode == SslMode::NoSSL) {
incomingTcp(handle);
} else {
incomingSsl(handle);
}
#else
incomingTcp(handle);
#endif
}
bool AbstractNode::changeTrust(const HostAddress &id, int diff) {
@ -686,43 +766,6 @@ bool AbstractNode::changeTrust(const HostAddress &id, int diff) {
return true;
}
void AbstractNode::incomingSsl(qintptr socketDescriptor) {
AsyncLauncher::Job action = [this, socketDescriptor]() -> bool {
QSslSocket *socket = new QSslSocket;
socket->setSslConfiguration(_ssl);
if (!isBanned(socket) && socket->setSocketDescriptor(socketDescriptor)) {
connect(socket, &QSslSocket::encrypted, [this, socket]() {
if (!registerSocket(socket)) {
socket->deleteLater();
}
});
connect(socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
[socket](const QList<QSslError> &errors){
for (auto &error : errors) {
QuasarAppUtils::Params::log(error.errorString(), QuasarAppUtils::Error);
}
socket->deleteLater();
});
socket->startServerEncryption();
return true;
} else {
delete socket;
return false;
}
};
_socketWorker->run(action);
}
void AbstractNode::incomingTcp(qintptr socketDescriptor) {
AsyncLauncher::Job action = [this, socketDescriptor]() -> bool {
@ -931,39 +974,6 @@ SslMode AbstractNode::getMode() const {
return _mode;
}
bool AbstractNode::useSelfSignedSslConfiguration(const SslSrtData &crtData) {
if (isListening()) {
return false;
}
_ssl = selfSignedSslConfiguration(crtData);
_mode = SslMode::InitSelfSigned;
return !_ssl.isNull();
}
bool AbstractNode::useSystemSslConfiguration(const QSslConfiguration &sslConfig) {
if (isListening()) {
return false;
}
_ssl = sslConfig;
_mode = SslMode::InitFromSystem;
return !_ssl.isNull();
}
bool AbstractNode::disableSSL() {
if (isListening()) {
return false;
}
_mode = SslMode::NoSSL;
return true;
}
void AbstractNode::incomingData(const AbstractData *pkg, const AbstractNodeInfo *sender) {
Q_UNUSED(pkg)
Q_UNUSED(sender)

@ -9,13 +9,16 @@
#define ABSTRACTNODE_H
#include "abstractnodeinfo.h"
#ifdef HEART_SSL
#include <openssl/evp.h>
#include <QSslConfiguration>
#endif
#include <QAbstractSocket>
#include <QFutureWatcher>
#include <QMutex>
#include <QSharedPointer>
#include <QSslConfiguration>
#include <QTcpServer>
#include <QThreadPool>
#include <QTimer>
@ -29,9 +32,11 @@
#include "packagemanager.h"
#include "abstracterrorcodes.h"
#ifdef HEART_SSL
class QSslCertificate;
class QSslKey;
class QSslConfiguration;
#endif
namespace QH {
@ -66,12 +71,16 @@ enum class ParserResult {
enum class SslMode {
/// This is not secure connection without ssl encription. It is default value of new any node see AbstractNode(SslMode mode = SslMode::NoSSL, QObject * ptr = nullptr).
NoSSL,
#ifdef HEART_SSL
/// This option try enable ssl connection from system configuration form fore information see Qt Documentation https://doc.qt.io/qt-5/qsslconfiguration.html
InitFromSystem,
/// This option force a current node geneerate self signed sertificat and work with it. For more information see a SslSrtData struct.
InitSelfSigned
#endif
};
#ifdef HEART_SSL
/**
* @brief The SslSrtData struct This structure contains base information for generate self signed ssl certefication.
* If you want change selfSigned certificate then use method AbstractNode::useSelfSignedSslConfiguration.
@ -82,7 +91,7 @@ struct SslSrtData {
QString commonName = "Dev";
long long endTime = 31536000L; //1 year
};
#endif
#define CRITICAL_ERROOR -50
#define LOGICK_ERROOR -20
@ -178,12 +187,14 @@ public:
*/
HostAddress address() const;
#ifdef HEART_SSL
/**
* @brief getSslConfig - This method return ssl configuration of current node (server).
* @return current ssl configuration on this node (server).
*/
QSslConfiguration getSslConfig() const;
#endif
/**
* @brief getMode - This method return SSL mode of corrent node (server).
* @return current mode for more information see SslMode.
@ -240,6 +251,8 @@ signals:
protected:
#ifdef HEART_SSL
/**
* @brief generateRSAforSSL This method generate ssl rsa pair keys for using in selfsigned cetificate.
* By default generate RSA 2048, if you want change algorithm or keys size then override this method.
@ -247,7 +260,6 @@ protected:
* @return True if keys generated successful.
*/
virtual bool generateRSAforSSL(EVP_PKEY* pkey) const;
/**
* @brief generateSslDataPrivate This method generate a ssl certificate and a ssl keys using The SslSrtData structure.
* @param data The data for generate a selfSigned certificate.
@ -263,6 +275,7 @@ protected:
* @return The new selfsigned ssl configuration.
*/
virtual QSslConfiguration selfSignedSslConfiguration( const SslSrtData& data = {});
#endif
/**
* @brief createNodeInfo This method create a nodeInfo object.
@ -404,18 +417,19 @@ protected:
*/
virtual bool changeTrust(const HostAddress& id, int diff);
/**
* @brief incomingConnection This methiod work with incomming ssl sockets.
* @param handle - handle of socket.
*/
virtual void incomingSsl(qintptr handle);
/**
* @brief incomingConnection This methiod work with incomming tcp sockets.
* @param handle - handle of socket.
*/
virtual void incomingTcp(qintptr handle);
#ifdef HEART_SSL
/**
* @brief incomingConnection This methiod work with incomming ssl sockets.
* @param handle - handle of socket.
*/
virtual void incomingSsl(qintptr handle);
/**
* @brief useSelfSignedSslConfiguration This method reconfigure current node to use selfSigned certificate.
* @note Befor invoke this method stop this node (server) see AbstractNode::stop.
@ -442,7 +456,7 @@ protected:
* @return true if changes is completed.
*/
bool disableSSL();
#endif
/**
* @brief incomingData This method invoked when node get command or ansver.
@ -598,7 +612,9 @@ private:
void deinitThreadPool();
SslMode _mode = SslMode::NoSSL;
#ifdef HEART_SSL
QSslConfiguration _ssl;
#endif
QHash<HostAddress, AbstractNodeInfo*> _connections;
QHash<HostAddress, ReceiveData*> _receiveData;

@ -19,8 +19,10 @@ set(CMAKE_AUTORCC ON)
add_definitions(-DHEART_LIBRARY)
list(APPEND CMAKE_FIND_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}")
find_package(OpenSSL REQUIRED)
if (HEART_SSL)
list(APPEND CMAKE_FIND_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}")
find_package(OpenSSL REQUIRED)
endif()
if (${HEART_BUILD_LVL} GREATER_EQUAL 0)
@ -76,13 +78,15 @@ set(SOURCE_CPP ${SOURCE_CPP_LVL_0} ${SOURCE_CPP_LVL_1} ${SOURCE_CPP_LVL_2})
add_library(${PROJECT_NAME} ${SOURCE_CPP})
target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Network Qt::Sql Qt::Concurrent QuasarApp)
if (ANDROID)
set(OPENSSL_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}")
target_include_directories(${PROJECT_NAME} PUBLIC ${OPENSSL_ROOT_PATH}/include)
if (HEART_SSL)
if (ANDROID)
set(OPENSSL_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}")
target_include_directories(${PROJECT_NAME} PUBLIC ${OPENSSL_ROOT_PATH}/include)
target_link_libraries(${PROJECT_NAME} PUBLIC ${OPENSSL_ROOT_PATH}/lib/libcrypto.a ${OPENSSL_ROOT_PATH}/lib/libssl.a)
else()
target_link_libraries(${PROJECT_NAME} PUBLIC OpenSSL::Crypto OpenSSL::SSL)
target_link_libraries(${PROJECT_NAME} PUBLIC ${OPENSSL_ROOT_PATH}/lib/libcrypto.a ${OPENSSL_ROOT_PATH}/lib/libssl.a)
else()
target_link_libraries(${PROJECT_NAME} PUBLIC OpenSSL::Crypto OpenSSL::SSL)
endif()
endif()
if (${HEART_BUILD_LVL} GREATER_EQUAL 2)

@ -33,6 +33,7 @@
#include <itoken.h>
#include <sqlitedbcache.h>
#include <sqldb.h>
#include <QCryptographicHash>
#define THIS_NODE "this_node_key"
namespace QH {