├── .gitignore ├── LICENSE ├── README.md ├── Sample ├── Sample.pro ├── certs │ ├── ca.xdb │ ├── root.crt │ └── server.p12 ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── sample.qrc ├── server.cpp └── server.h ├── qsslserver.cpp ├── qsslserver.h └── qsslserver.pri /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | moc_*.h 24 | qrc_*.cpp 25 | ui_*.h 26 | Makefile* 27 | *build-* 28 | 29 | # QtCreator 30 | 31 | *.autosave 32 | 33 | # QtCtreator Qml 34 | *.qmlproject.user 35 | *.qmlproject.user.* 36 | 37 | # QtCtreator CMake 38 | CMakeLists.txt.user* 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Felix Barz 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QSslServer 2 | An extension of QTcpServer to support ssl. The counterpart to QSslSocket. 3 | 4 | ## Features 5 | - Works like a normal `QTcpServer`, but with `QSslSocket` instead of `QTcpSocket` 6 | - Adds a variety of useful method to setup the server. Mainly loading certificates and keys. 7 | - You can configure the server as deeply as you want by directly using `QSslConfiguration` 8 | 9 | ## Installation 10 | The package is provided via qdep, as `Skycoder42/QSslServer`. To use it simply: 11 | 12 | 1. Install and enable qdep (See [qdep - Installing](https://github.com/Skycoder42/qdep#installation)) 13 | 2. Add the following to your pro file: 14 | ```qmake 15 | QDEP_DEPENDS += Skycoder42/QSslServer 16 | !load(qdep):error("Failed to load qdep feature! Run 'qdep prfgen --qmake $$QMAKE_QMAKE' to create it.") 17 | ``` 18 | 19 | ## Usage 20 | It works exactly like the TCP server. The only difference: you need to set a certificate before connecting: 21 | ```cpp 22 | auto server = new QSslServer(this); 23 | 24 | //emits newConnection just like the tcp variant 25 | connect(server, &QSslServer::newConnection, this, [this](){ 26 | while(server->hasPendingConnections()) { 27 | auto socket = server->nextPendingConnection(); 28 | 29 | //work with the new socket 30 | } 31 | }); 32 | 33 | //load a certificate and private key, then start listening 34 | if(!server->importPkcs12(QStringLiteral("/path/to/cert.p12"))) 35 | qCritical() << "Failed to import certificates"; 36 | else 37 | server->listen(QHostAddress::Any, 4711); 38 | ``` 39 | 40 | This code sample is basically it. For a more advanced example, check the project in the 41 | Sample subfolder. It's a widgets application with an SSL based echo server. Certificates are included to emulate a real life situation: 42 | 43 | - `Sample/certs/root.crt` is a PEM encoded CA certificate that is added as CA cert to the client 44 | - `Sample/certs/server.p12` is a PKCS#12 container with the root CA certificate, the server certificate (signed by the CA cert) and the servers private key. It is loaded by the server. 45 | 46 | Note: For this example the p12 file is unencrypted. Typically a password should be used to protect it. 47 | -------------------------------------------------------------------------------- /Sample/Sample.pro: -------------------------------------------------------------------------------- 1 | QT += core gui widgets network 2 | 3 | TARGET = Sample 4 | TEMPLATE = app 5 | 6 | include(../qsslserver.pri) 7 | 8 | HEADERS += \ 9 | mainwindow.h \ 10 | server.h 11 | 12 | SOURCES += \ 13 | main.cpp \ 14 | mainwindow.cpp \ 15 | server.cpp 16 | 17 | FORMS += \ 18 | mainwindow.ui 19 | 20 | RESOURCES += \ 21 | sample.qrc 22 | -------------------------------------------------------------------------------- /Sample/certs/ca.xdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Skycoder42/QSslServer/53b67c329fc80f19d140c61a7f066ff110c3e6e0/Sample/certs/ca.xdb -------------------------------------------------------------------------------- /Sample/certs/root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIE7zCCAtegAwIBAgIBATANBgkqhkiG9w0BAQsFADAAMCAXDTE4MDMyMDE2MjQw 3 | MFoYDzk5OTkxMjMxMjM1OTU5WjAAMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 4 | CgKCAgEAr10vlCdxehbgNBLAnd/sgi6LPonlWMFGBaCsyIo1hBp6K8I9xfCruBWO 5 | al8QXpVYLvEIl0aggUwOcj18b+6KMjm5CvrDTMOhz1LGpwEPYmv4D5M3+zDLrZQe 6 | sH+gwiLltxP5n/d+S+zIsJUrSRK1BmoEbaES+0TeSpe/1pSwrvL7zHbl+HetRbXF 7 | 26tTP+ghF59VyyPjQLY3biWOEK2xoLmW7hQJWR5t5h6IB7fvMYQ97QpF8Kndo5tl 8 | LqZpKkx09cEMKVvm2cMqUO/qQPncB8xSJ7UVBAevLjfIKd195oyNN+fVZ0Y/Z5V+ 9 | Hlmn6qWUUawJ43NzyLjR3L4lywq005T1tN/6Fi0TWgKQzz5ESFxpmTacQ+BSgPNS 10 | jJW22ieo/Gu0mPUjw27OgNAKV9q3TBZaXYWGb0ABcdnGFb9hKjzNJ4KXJK7xcg+1 11 | HFDz6SZ/7EuY1su9ZyDqykLF8sRKTGJE7Jzy31AfP4CwRdXMKKzPiP+5Pt/v9Q1V 12 | 4Q4zKsACl5R8VZJatubQXLYg/BRpgWwq5ttFqwFdKxzDFUVngzlX6eoEc7JdDhvr 13 | Y01lsnVk9XW8qNKnKbjXtfJ5raT/3+7jq56pgCkyXB7aGu60xpAztYUypg1eYEsm 14 | dxdPyrg/YJO/KUPxetv4WYxAJ3TX5uVKuhKNFUfHhIJddp38QisCAwEAAaNyMHAw 15 | DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU4l3P5Iuodml1jjMwaCZKBpDzJ1Iw 16 | CwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAeBglghkgBhvhCAQ0EERYP 17 | eGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBCwUAA4ICAQBg+JJ0mIBwG34W4xt4 18 | /TJyK2rs+oBDccmDuPtOldw5CyRtOv3QD9e2kWhndNlaWmMW0LbO+BpAfwg1BuGO 19 | Z8E8DR4vhxp12eZOHGo6VsqI2Wp8tDXFHEdhBRgZyG32Awa2J1bf/rz1QmHbC/14 20 | TKOqjCzSBH+gQyj8rg67vVnHXBR/banWXcTyS/q3wgcJMjzKKZj11K5JjKXLj9D7 21 | TrEF+pbcusE1k/vEdQyMLqCVx7O+SXfJ557SEj/Hn/lItar7FW2nSg2rkAroug3s 22 | /y3cR75GSWLsGRkFqgGKzhLr+S7Z+4HIW3Rv45ARGy3086oOFkQbfdtjvNwU1els 23 | v/bmvg0vOfmgIL5ymYjEy4aR2b3oOrxRfv3oTLsjvYa2JLcg8vmnH3NiR03LVbcC 24 | qYz0qlF1++/j+e8cP143LZjSvPQex1oTcbV0WhG3i4ZvSCHIbnYBlCGRQdKE2lUD 25 | GFr5VBpukgWHmAaq4gyjsAL8/8sRxHDJ5Kb0F1MP+C6BJ2Fhr2jmygg2WcdDfsr6 26 | 8bIbLhgG+TOzxogQGWIVBPP19EyWA7z46+1uWfv6ibjzqMF3r/W2mRqFUz6dJPjJ 27 | 1iDxfY/tMu7UYNuOc0AM4O8mCG/d+YOvEh+I90eoQtXQqxEq5oub5gi4QK7wJBHy 28 | 3xXGpUwxp5Whsyg44IZytAFbzg== 29 | -----END CERTIFICATE----- 30 | -------------------------------------------------------------------------------- /Sample/certs/server.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Skycoder42/QSslServer/53b67c329fc80f19d140c61a7f066ff110c3e6e0/Sample/certs/server.p12 -------------------------------------------------------------------------------- /Sample/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mainwindow.h" 4 | #include "server.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | 10 | QThread serverThread; 11 | QObject::connect(qApp, &QApplication::aboutToQuit, &serverThread, [&](){ 12 | serverThread.quit(); 13 | serverThread.wait(); 14 | }); 15 | 16 | auto svr = new Server{}; 17 | svr->moveToThread(&serverThread); 18 | QObject::connect(&serverThread, &QThread::finished, 19 | svr, &Server::stop); 20 | QObject::connect(&serverThread, &QThread::started, 21 | svr, &Server::start); 22 | 23 | MainWindow w; 24 | QObject::connect(svr, &Server::connected, 25 | &w, &MainWindow::connectTo, 26 | Qt::QueuedConnection); 27 | 28 | serverThread.start(); 29 | w.show(); 30 | return a.exec(); 31 | } 32 | -------------------------------------------------------------------------------- /Sample/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | #include 5 | 6 | MainWindow::MainWindow(QWidget *parent) : 7 | QMainWindow{parent}, 8 | ui{new Ui::MainWindow}, 9 | socket{new QSslSocket{this}} 10 | { 11 | ui->setupUi(this); 12 | 13 | socket->addCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/certs/root.crt"))); 14 | 15 | connect(socket, &QSslSocket::readyRead, 16 | this, &MainWindow::readyRead); 17 | connect(socket, QOverload::of(&QSslSocket::error), 18 | this, &MainWindow::error); 19 | connect(socket, QOverload &>::of(&QSslSocket::sslErrors), 20 | this, &MainWindow::sslErrors); 21 | } 22 | 23 | MainWindow::~MainWindow() 24 | { 25 | delete ui; 26 | } 27 | 28 | void MainWindow::connectTo(quint16 port) 29 | { 30 | socket->connectToHostEncrypted(QStringLiteral("127.0.0.1"), port); 31 | } 32 | 33 | void MainWindow::on_sendButton_clicked() 34 | { 35 | socket->write(ui->lineEdit->text().toUtf8()); 36 | ui->lineEdit->clear(); 37 | } 38 | 39 | void MainWindow::readyRead() 40 | { 41 | ui->plainTextEdit->appendPlainText(QString::fromUtf8(socket->readAll())); 42 | } 43 | 44 | void MainWindow::error() 45 | { 46 | ui->plainTextEdit->appendPlainText(QStringLiteral(" >>> ERROR: %1").arg(socket->errorString())); 47 | } 48 | 49 | void MainWindow::sslErrors(const QList &errors) 50 | { 51 | for(const auto &error : errors) 52 | ui->plainTextEdit->appendPlainText(QStringLiteral(" >>> SSL-ERROR: %1").arg(error.errorString())); 53 | } 54 | -------------------------------------------------------------------------------- /Sample/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui { 8 | class MainWindow; 9 | } 10 | 11 | class MainWindow : public QMainWindow 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit MainWindow(QWidget *parent = nullptr); 17 | ~MainWindow() override; 18 | 19 | public slots: 20 | void connectTo(quint16 port); 21 | 22 | private slots: 23 | void on_sendButton_clicked(); 24 | 25 | void readyRead(); 26 | void error(); 27 | void sslErrors(const QList &errors); 28 | 29 | private: 30 | Ui::MainWindow *ui; 31 | QSslSocket *socket; 32 | }; 33 | 34 | #endif // MAINWINDOW_H 35 | -------------------------------------------------------------------------------- /Sample/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 520 10 | 381 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | 23 | 24 | 25 | 26 | 27 | 28 | Ping: 29 | 30 | 31 | 32 | 33 | 34 | 35 | Send 36 | 37 | 38 | 39 | 40 | 41 | 42 | Pong: 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 0 55 | 0 56 | 520 57 | 23 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Sample/sample.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | certs/server.p12 4 | certs/root.crt 5 | 6 | 7 | -------------------------------------------------------------------------------- /Sample/server.cpp: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | 3 | Server::Server(QObject *parent) : 4 | QObject{parent}, 5 | server{new QSslServer{this}} 6 | { 7 | if(!server->importPkcs12(QStringLiteral(":/certs/server.p12"))) 8 | qCritical() << " >>> SERVER ERROR: Failed to import certificates"; 9 | 10 | connect(server, &QSslServer::newConnection, 11 | this, &Server::newConnection); 12 | connect(server, &QSslServer::acceptError, 13 | this, &Server::error); 14 | } 15 | 16 | void Server::start() 17 | { 18 | if(server->listen(QHostAddress::LocalHost)) 19 | emit connected(server->serverPort()); 20 | else 21 | error(); 22 | } 23 | 24 | void Server::stop() 25 | { 26 | server->close(); 27 | } 28 | 29 | void Server::newConnection() 30 | { 31 | while(server->hasPendingConnections()) { 32 | auto socket = server->nextPendingConnection(); 33 | 34 | connect(socket, &QSslSocket::readyRead, socket, [socket]{ 35 | socket->write(socket->readAll()); 36 | }); 37 | connect(socket, &QSslSocket::disconnected, 38 | socket, &QSslSocket::deleteLater); 39 | connect(socket, QOverload::of(&QSslSocket::error), 40 | socket, [socket](){ 41 | qCritical() << " >>> SERVER SOCKET ERROR:" << socket->errorString(); 42 | }); 43 | connect(socket, QOverload &>::of(&QSslSocket::sslErrors), 44 | this, [](const QList &errors){ 45 | for(const auto &error : errors) 46 | qCritical() << " >>> SERVER SOCKET SSL ERROR:" << error.errorString(); 47 | }); 48 | } 49 | } 50 | 51 | void Server::error() 52 | { 53 | qCritical() << " >>> SERVER ERROR:" << server->errorString(); 54 | } 55 | -------------------------------------------------------------------------------- /Sample/server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #include 5 | #include 6 | 7 | class Server : public QObject 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit Server(QObject *parent = nullptr); 13 | 14 | public slots: 15 | void start(); 16 | void stop(); 17 | 18 | signals: 19 | void connected(quint16 port); 20 | 21 | private slots: 22 | void newConnection(); 23 | void error(); 24 | 25 | private: 26 | QSslServer *server; 27 | }; 28 | 29 | #endif // SERVER_H 30 | -------------------------------------------------------------------------------- /qsslserver.cpp: -------------------------------------------------------------------------------- 1 | #include "qsslserver.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | QSslServer::QSslServer(QObject *parent) : 9 | QTcpServer{parent}, 10 | _configuration{QSslConfiguration::defaultConfiguration()} 11 | {} 12 | 13 | QSslSocket *QSslServer::nextPendingConnection() 14 | { 15 | return qobject_cast(QTcpServer::nextPendingConnection()); 16 | } 17 | 18 | QSslConfiguration QSslServer::sslConfiguration() const 19 | { 20 | return _configuration; 21 | } 22 | 23 | void QSslServer::setSslConfiguration(QSslConfiguration configuration) 24 | { 25 | _configuration = std::move(configuration); 26 | } 27 | 28 | void QSslServer::setLocalCertificateChain(const QList &localChain) 29 | { 30 | _configuration.setLocalCertificateChain(localChain); 31 | } 32 | 33 | void QSslServer::setLocalCertificateChain(const QString &fileName, QSsl::EncodingFormat format, QSslCertificate::PatternSyntax syntax) 34 | { 35 | _configuration.setLocalCertificateChain(QSslCertificate::fromPath(fileName, format, syntax)); 36 | } 37 | 38 | QList QSslServer::localCertificateChain() const 39 | { 40 | return _configuration.localCertificateChain(); 41 | } 42 | 43 | void QSslServer::setLocalCertificate(const QSslCertificate &certificate) 44 | { 45 | _configuration.setLocalCertificate(certificate); 46 | } 47 | 48 | void QSslServer::setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format) 49 | { 50 | QFile file{fileName}; 51 | if(file.open(QIODevice::ReadOnly)) { 52 | QSslCertificate certificate{&file, format}; 53 | if(!certificate.isNull()) 54 | _configuration.setLocalCertificate(certificate); 55 | file.close(); 56 | } 57 | } 58 | 59 | QSslCertificate QSslServer::localCertificate() const 60 | { 61 | return _configuration.localCertificate(); 62 | } 63 | 64 | void QSslServer::setPrivateKey(const QSslKey &key) 65 | { 66 | _configuration.setPrivateKey(key); 67 | } 68 | 69 | void QSslServer::setPrivateKey(const QString &fileName, QSsl::KeyAlgorithm algorithm, QSsl::EncodingFormat format, const QByteArray &passPhrase) 70 | { 71 | QFile file{fileName}; 72 | if(file.open(QIODevice::ReadOnly)) { 73 | QSslKey newKey{&file, algorithm, format, QSsl::PrivateKey, passPhrase}; 74 | if(!newKey.isNull()) 75 | _configuration.setPrivateKey(newKey); 76 | file.close(); 77 | } 78 | } 79 | 80 | QSslKey QSslServer::privateKey() const 81 | { 82 | return _configuration.privateKey(); 83 | } 84 | 85 | bool QSslServer::addCaCertificates(const QString &path, QSsl::EncodingFormat format, QSslCertificate::PatternSyntax syntax) 86 | { 87 | auto certs = QSslCertificate::fromPath(path, format, syntax); 88 | if (!certs.isEmpty()) { 89 | addCaCertificates(certs); 90 | return true; 91 | } else 92 | return false; 93 | } 94 | 95 | void QSslServer::addCaCertificate(const QSslCertificate &certificate) 96 | { 97 | auto certs = _configuration.caCertificates(); 98 | certs.append(certificate); 99 | _configuration.setCaCertificates(certs); 100 | } 101 | 102 | void QSslServer::addCaCertificates(const QList &certificates) 103 | { 104 | auto certs = _configuration.caCertificates(); 105 | certs.append(certificates); 106 | _configuration.setCaCertificates(certs); 107 | } 108 | 109 | bool QSslServer::importPkcs12(const QString &path, const QByteArray &passPhrase, bool replaceCaCerts) 110 | { 111 | QFile file{path}; 112 | if(file.open(QIODevice::ReadOnly)) { 113 | QSslKey key; 114 | QSslCertificate cert; 115 | QList caCerts; 116 | if (QSslCertificate::importPkcs12(&file, &key, &cert, &caCerts, passPhrase)) { 117 | file.close(); 118 | if(!caCerts.isEmpty()) { 119 | if(replaceCaCerts) 120 | _configuration.setCaCertificates(caCerts); 121 | else 122 | addCaCertificates(caCerts); 123 | } 124 | if(!cert.isNull()) 125 | _configuration.setLocalCertificate(cert); 126 | if(!key.isNull()) 127 | _configuration.setPrivateKey(key); 128 | return true; 129 | } else 130 | file.close(); 131 | } 132 | 133 | return false; 134 | } 135 | 136 | QSsl::SslProtocol QSslServer::protocol() const 137 | { 138 | return _configuration.protocol(); 139 | } 140 | 141 | void QSslServer::setProtocol(QSsl::SslProtocol protocol) 142 | { 143 | _configuration.setProtocol(protocol); 144 | } 145 | 146 | void QSslServer::incomingConnection(qintptr handle) 147 | { 148 | //Create Socket 149 | auto socket = new QSslSocket{}; 150 | if (!socket->setSocketDescriptor(handle)) { 151 | emit acceptError(socket->error()); 152 | delete socket; 153 | return; 154 | } 155 | 156 | //set ssl data 157 | socket->setSslConfiguration(_configuration); 158 | socket->startServerEncryption(); 159 | addPendingConnection(socket); 160 | } 161 | -------------------------------------------------------------------------------- /qsslserver.h: -------------------------------------------------------------------------------- 1 | #ifndef QSSLSERVER_H 2 | #define QSSLSERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Q_SSL_SERVER_EXPORT QSslServer : public QTcpServer 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit QSslServer(QObject *parent = nullptr); 14 | 15 | QSslSocket *nextPendingConnection(); 16 | 17 | // SSL configuration 18 | QSslConfiguration sslConfiguration() const; 19 | void setSslConfiguration(QSslConfiguration configuration); 20 | 21 | // Certificate 22 | void setLocalCertificateChain(const QList &localChain); 23 | void setLocalCertificateChain(const QString &fileName, 24 | QSsl::EncodingFormat format = QSsl::Pem, 25 | QSslCertificate::PatternSyntax syntax = QSslCertificate::PatternSyntax::FixedString); 26 | QList localCertificateChain() const; 27 | 28 | void setLocalCertificate(const QSslCertificate &certificate); 29 | void setLocalCertificate(const QString &fileName, 30 | QSsl::EncodingFormat format = QSsl::Pem); 31 | QSslCertificate localCertificate() const; 32 | 33 | // Private keys 34 | void setPrivateKey(const QSslKey &key); 35 | void setPrivateKey(const QString &fileName, 36 | QSsl::KeyAlgorithm algorithm = QSsl::Rsa, 37 | QSsl::EncodingFormat format = QSsl::Pem, 38 | const QByteArray &passPhrase = QByteArray{}); 39 | QSslKey privateKey() const; 40 | 41 | // CA settings 42 | bool addCaCertificates(const QString &path, 43 | QSsl::EncodingFormat format = QSsl::Pem, 44 | QSslCertificate::PatternSyntax syntax = QSslCertificate::PatternSyntax::FixedString); 45 | void addCaCertificate(const QSslCertificate &certificate); 46 | void addCaCertificates(const QList &certificates); 47 | 48 | // PKCS#12 49 | bool importPkcs12(const QString &path, 50 | const QByteArray &passPhrase = QByteArray(), 51 | bool replaceCaCerts = false); 52 | 53 | QSsl::SslProtocol protocol() const; 54 | void setProtocol(QSsl::SslProtocol protocol); 55 | 56 | protected: 57 | void incomingConnection(qintptr handle) override; 58 | 59 | private: 60 | QSslConfiguration _configuration; 61 | }; 62 | 63 | #endif // QSSLSERVER_H 64 | -------------------------------------------------------------------------------- /qsslserver.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | 3 | HEADERS += \ 4 | $$PWD/qsslserver.h 5 | 6 | SOURCES += \ 7 | $$PWD/qsslserver.cpp 8 | 9 | QDEP_PACKAGE_EXPORTS += Q_SSL_SERVER_EXPORT 10 | !qdep_build: DEFINES += "Q_SSL_SERVER_EXPORT=" 11 | --------------------------------------------------------------------------------