diff options
| author | Felix (xq) Queißner <git@mq32.de> | 2020-06-10 21:38:05 +0200 |
|---|---|---|
| committer | Felix (xq) Queißner <git@mq32.de> | 2020-06-10 21:38:05 +0200 |
| commit | ab3e5ad5f25862985c17ba557163a1902b54747f (patch) | |
| tree | ab91f5b8a245a6b506a00e9b0533b096d0753ea4 /src | |
| parent | feb37f7d6b8730e94821fc6d70fb742ff393517d (diff) | |
| download | kristall-ab3e5ad5f25862985c17ba557163a1902b54747f.tar.gz | |
Adds install target to makefile, adds support for transient client certificates.
Diffstat (limited to 'src')
| -rw-r--r-- | src/browsertab.cpp | 85 | ||||
| -rw-r--r-- | src/browsertab.hpp | 12 | ||||
| -rw-r--r-- | src/browsertab.ui | 33 | ||||
| -rw-r--r-- | src/builtins.qrc | 6 | ||||
| -rw-r--r-- | src/certificatehelper.cpp | 79 | ||||
| -rw-r--r-- | src/certificatehelper.hpp | 17 | ||||
| -rw-r--r-- | src/certificateselectiondialog.cpp | 71 | ||||
| -rw-r--r-- | src/certificateselectiondialog.hpp | 46 | ||||
| -rw-r--r-- | src/certificateselectiondialog.ui | 154 | ||||
| -rw-r--r-- | src/cryptoidentity.cpp | 2 | ||||
| -rw-r--r-- | src/cryptoidentity.hpp | 24 | ||||
| -rw-r--r-- | src/geminiclient.cpp | 21 | ||||
| -rw-r--r-- | src/geminiclient.hpp | 5 | ||||
| -rw-r--r-- | src/icons.qrc | 4 | ||||
| -rw-r--r-- | src/icons/shield-lock.svg | 1 | ||||
| -rw-r--r-- | src/icons/shield-outline.svg | 1 | ||||
| -rw-r--r-- | src/kristall.pro | 10 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 2 |
18 files changed, 552 insertions, 21 deletions
diff --git a/src/browsertab.cpp b/src/browsertab.cpp index d9f2ffa..d566da6 100644 --- a/src/browsertab.cpp +++ b/src/browsertab.cpp @@ -7,6 +7,8 @@ #include "geminirenderer.hpp" #include "plaintextrenderer.hpp" +#include "certificateselectiondialog.hpp" + #include "ioutil.hpp" #include "kristall.hpp" @@ -108,7 +110,6 @@ void BrowserTab::navigateTo(const QUrl &url, PushToHistory mode) this->redirection_count = 0; this->successfully_loaded = false; - this->push_to_history_after_load = (mode == PushAfterSuccess); if(url.scheme() == "gemini") { @@ -146,10 +147,6 @@ void BrowserTab::navigateTo(const QUrl &url, PushToHistory mode) else if(url.scheme() == "about") { this->redirection_count = 0; - this->push_to_history_after_load = false; - - if(mode == PushAfterSuccess) - mode = PushImmediate; if(url.path() == "blank") { this->on_requestComplete("", "text/gemini"); @@ -186,7 +183,6 @@ void BrowserTab::navigateTo(const QUrl &url, PushToHistory mode) switch(mode) { case DontPush: - case PushAfterSuccess: break; case PushImmediate: @@ -403,11 +399,6 @@ File Size: %2 this->successfully_loaded = true; - if(this->push_to_history_after_load) { - this->pushToHistory(this->current_location); - this->push_to_history_after_load = false; - } - this->updateUI(); } @@ -494,13 +485,21 @@ void BrowserTab::on_permanentFailure(PermanentFailure reason, const QString &inf void BrowserTab::on_transientCertificateRequested(const QString &reason) { - QMessageBox::warning(this, "Kristall", "Transient certificate requirested:\n" + reason); + if(not trySetClientCertificate(reason)) { + setErrorMessage(QString("The page requested a transient client certificate, but none was provided.\r\nOriginal query was: %1").arg(reason)); + } else { + this->navigateTo(this->current_location, DontPush); + } this->updateUI(); } void BrowserTab::on_authorisedCertificateRequested(const QString &reason) { - QMessageBox::warning(this, "Kristall", "Authorized certificate requirested:\n" + reason); + if(not trySetClientCertificate(reason)) { + setErrorMessage(QString("The page requested a authorized client certificate, but none was provided.\r\nOriginal query was: %1").arg(reason)); + } else { + this->navigateTo(this->current_location, DontPush); + } this->updateUI(); } @@ -530,8 +529,11 @@ void BrowserTab::on_linkHovered(const QString &url) void BrowserTab::setErrorMessage(const QString &msg) { - // this->page.setContent(QString("An error happened:\n%0").arg(msg).toUtf8(), "text/plain charset=utf-8"); - QMessageBox::warning(this, "Kristall", msg); + this->on_requestComplete( + QString("An error happened:\r\n%0").arg(msg).toUtf8(), + "text/plain charset=utf-8" + ); + this->updateUI(); } @@ -560,7 +562,7 @@ void BrowserTab::on_text_browser_anchorClicked(const QUrl &url) auto support = mainWindow->protocols.isSchemeSupported(real_url.scheme()); if(support == ProtocolSetup::Enabled) { - this->navigateTo(real_url, PushAfterSuccess); + this->navigateTo(real_url, PushImmediate); } else { bool use_os_proxy = global_settings.value("use_os_scheme_handler").toBool(); @@ -624,6 +626,48 @@ void BrowserTab::updateUI() this->ui->fav_button->setChecked(this->mainWindow->favourites.contains(this->current_location)); } +bool BrowserTab::trySetClientCertificate(const QString &query) +{ + CertificateSelectionDialog dialog { this }; + + dialog.setServerQuery(query); + + if(dialog.exec() != QDialog::Accepted) { + this->gemini_client.disableClientCertificate(); + this->ui->enable_client_cert_button->setChecked(false); + return false; + } + + this->current_identitiy = dialog.identity(); + + if(not current_identitiy.isValid()) { + QMessageBox::warning(this, "Kristall", "Failed to generate temporary crypto-identitiy"); + this->gemini_client.disableClientCertificate(); + this->ui->enable_client_cert_button->setChecked(false); + return false; + } + + this->gemini_client.enableClientCertificate(this->current_identitiy); + this->ui->enable_client_cert_button->setChecked(true); + + return true; +} + +void BrowserTab::resetClientCertificate() +{ + if(this->current_identitiy.isValid() and not this->current_identitiy.is_persistent) + { + auto respo = QMessageBox::question(this, "Kristall", "You currently have a transient session active!\r\nIf you disable the session, you will not be able to restore it. Continue?"); + if(respo != QMessageBox::Yes) { + this->ui->enable_client_cert_button->setChecked(true); + return; + } + } + + this->gemini_client.disableClientCertificate(); + this->ui->enable_client_cert_button->setChecked(false); +} + #include <QClipboard> void BrowserTab::on_text_browser_customContextMenuRequested(const QPoint &pos) @@ -657,3 +701,12 @@ void BrowserTab::on_text_browser_customContextMenuRequested(const QPoint &pos) menu.exec(ui->text_browser->mapToGlobal(pos)); } + +void BrowserTab::on_enable_client_cert_button_clicked(bool checked) +{ + if(checked) { + trySetClientCertificate(QString{ }); + } else { + resetClientCertificate(); + } +} diff --git a/src/browsertab.hpp b/src/browsertab.hpp index 644da70..04e6c0d 100644 --- a/src/browsertab.hpp +++ b/src/browsertab.hpp @@ -18,6 +18,8 @@ #include "gopherclient.hpp" #include "fingerclient.hpp" +#include "cryptoidentity.hpp" + namespace Ui { class BrowserTab; } @@ -31,7 +33,6 @@ public: enum PushToHistory { DontPush, PushImmediate, - PushAfterSuccess, }; public: @@ -104,12 +105,18 @@ private slots: void on_text_browser_customContextMenuRequested(const QPoint &pos); + void on_enable_client_cert_button_clicked(bool checked); + private: void setErrorMessage(QString const & msg); void pushToHistory(QUrl const & url); void updateUI(); + + bool trySetClientCertificate(QString const & query); + + void resetClientCertificate(); public: Ui::BrowserTab *ui; @@ -122,7 +129,6 @@ public: FingerClient finger_client; int redirection_count = 0; - bool push_to_history_after_load = false; bool successfully_loaded = false; DocumentOutlineModel outline; @@ -135,6 +141,8 @@ public: QByteArray current_buffer; QString current_mime; QElapsedTimer timer; + + CryptoIdentity current_identitiy; }; #endif // BROWSERTAB_HPP diff --git a/src/browsertab.ui b/src/browsertab.ui index 7be4d3c..46ff31f 100644 --- a/src/browsertab.ui +++ b/src/browsertab.ui @@ -51,6 +51,9 @@ <property name="enabled"> <bool>false</bool> </property> + <property name="toolTip"> + <string>Navigate back</string> + </property> <property name="text"> <string/> </property> @@ -65,6 +68,9 @@ <property name="enabled"> <bool>false</bool> </property> + <property name="toolTip"> + <string>Navigate forward</string> + </property> <property name="text"> <string>...</string> </property> @@ -79,6 +85,9 @@ <property name="enabled"> <bool>true</bool> </property> + <property name="toolTip"> + <string>Stop loading</string> + </property> <property name="text"> <string/> </property> @@ -93,6 +102,9 @@ <property name="enabled"> <bool>true</bool> </property> + <property name="toolTip"> + <string>Refresh current location</string> + </property> <property name="text"> <string/> </property> @@ -114,6 +126,9 @@ <property name="enabled"> <bool>false</bool> </property> + <property name="toolTip"> + <string>Add/remove from favourites</string> + </property> <property name="text"> <string/> </property> @@ -130,6 +145,24 @@ </property> </widget> </item> + <item> + <widget class="QToolButton" name="enable_client_cert_button"> + <property name="toolTip"> + <string>Enable/disable client certificate for this tab</string> + </property> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="icons.qrc"> + <normaloff>:/icons/shield-outline.svg</normaloff> + <normalon>:/icons/shield-lock.svg</normalon>:/icons/shield-outline.svg</iconset> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> </layout> </item> <item> diff --git a/src/builtins.qrc b/src/builtins.qrc new file mode 100644 index 0000000..fae4cc3 --- /dev/null +++ b/src/builtins.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>about/easter-egg.gemini</file> + <file>about/help.gemini</file> + </qresource> +</RCC> diff --git a/src/certificatehelper.cpp b/src/certificatehelper.cpp new file mode 100644 index 0000000..2b6acb8 --- /dev/null +++ b/src/certificatehelper.cpp @@ -0,0 +1,79 @@ +#include "certificatehelper.hpp" + +#include <openssl/rsa.h> +#include <openssl/x509.h> +#include <openssl/pem.h> + +CryptoIdentity CertificateHelper::createNewIdentity(const QString &common_name, QDateTime expiry_date) +{ + CryptoIdentity identity; + + auto const now = QDateTime::currentDateTime(); + if(expiry_date < now) + return identity; + + identity.display_name = common_name; + + QByteArray common_name_utf8 = common_name.toUtf8(); + + EVP_PKEY * pkey = EVP_PKEY_new(); + q_check_ptr(pkey); + RSA * rsa = RSA_generate_key(2048, RSA_F4, nullptr, nullptr); + q_check_ptr(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + X509 * x509 = X509_new(); + q_check_ptr(x509); + ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); + X509_gmtime_adj(X509_get_notBefore(x509), 0); // not before current time + X509_gmtime_adj(X509_get_notAfter(x509), now.secsTo(expiry_date)); // not after a year from this point + X509_set_pubkey(x509, pkey); + X509_NAME * name = X509_get_subject_name(x509); + q_check_ptr(name); + // X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); + // X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"My Organization", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char const *>(common_name_utf8.data()), common_name_utf8.size(), -1, 0); + X509_set_issuer_name(x509, name); + X509_sign(x509, pkey, EVP_sha1()); + BIO * bp_private = BIO_new(BIO_s_mem()); + q_check_ptr(bp_private); + if(PEM_write_bio_PrivateKey(bp_private, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) + { + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free_all(bp_private); + qFatal("PEM_write_bio_PrivateKey"); + } + BIO * bp_public = BIO_new(BIO_s_mem()); + q_check_ptr(bp_public); + if(PEM_write_bio_X509(bp_public, x509) != 1) + { + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free_all(bp_public); + BIO_free_all(bp_private); + qFatal("PEM_write_bio_PrivateKey"); + } + + const char * buffer = nullptr; + size_t size = BIO_get_mem_data(bp_public, &buffer); + q_check_ptr(buffer); + identity.certificate = QSslCertificate(QByteArray(buffer, size)); + if(identity.certificate.isNull()) + { + qFatal("Failed to generate a random client certificate"); + } + size = BIO_get_mem_data(bp_private, &buffer); + q_check_ptr(buffer); + identity.private_key = QSslKey(QByteArray(buffer, size), QSsl::Rsa); + if(identity.private_key.isNull()) + { + qFatal("Failed to generate a random private key"); + } + + EVP_PKEY_free(pkey); // this will also free the rsa key + X509_free(x509); + BIO_free_all(bp_public); + BIO_free_all(bp_private); + + return identity; +} diff --git a/src/certificatehelper.hpp b/src/certificatehelper.hpp new file mode 100644 index 0000000..e395666 --- /dev/null +++ b/src/certificatehelper.hpp @@ -0,0 +1,17 @@ +#ifndef CERTIFICATEHELPER_HPP +#define CERTIFICATEHELPER_HPP + +#include "cryptoidentity.hpp" + +struct CertificateHelper +{ + CertificateHelper() = delete; + + + + static CryptoIdentity createNewIdentity( + QString const & common_name, + QDateTime expiry_date); +}; + +#endif // CERTIFICATEHELPER_HPP diff --git a/src/certificateselectiondialog.cpp b/src/certificateselectiondialog.cpp new file mode 100644 index 0000000..70dac42 --- /dev/null +++ b/src/certificateselectiondialog.cpp @@ -0,0 +1,71 @@ +#include "certificateselectiondialog.hpp" +#include "ui_certificateselectiondialog.h" + +#include "certificatehelper.hpp" + +CertificateSelectionDialog::CertificateSelectionDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::CertificateSelectionDialog) +{ + ui->setupUi(this); + this->ui->server_request->setVisible(false); +} + +CertificateSelectionDialog::~CertificateSelectionDialog() +{ + delete ui; +} + +void CertificateSelectionDialog::setServerQuery(const QString &query) +{ + this->ui->server_request->setText(query); + this->ui->server_request->setVisible(not query.isEmpty()); +} + +CryptoIdentity CertificateSelectionDialog::identity() const +{ + return cryto_identity; +} + +void CertificateSelectionDialog::on_use_temp_cert_30m_clicked() +{ + acceptTemporaryWithTimeout(QDateTime::currentDateTime().addSecs(1800 * 12)); +} + +void CertificateSelectionDialog::on_use_temp_cert_1h_clicked() +{ + acceptTemporaryWithTimeout(QDateTime::currentDateTime().addSecs(3600)); +} + +void CertificateSelectionDialog::on_use_temp_cert_12h_clicked() +{ + acceptTemporaryWithTimeout(QDateTime::currentDateTime().addSecs(3600 * 12)); +} + +void CertificateSelectionDialog::on_use_temp_cert_24h_clicked() +{ + acceptTemporaryWithTimeout(QDateTime::currentDateTime().addDays(1)); +} + +void CertificateSelectionDialog::on_use_temp_cert_48h_clicked() +{ + acceptTemporaryWithTimeout(QDateTime::currentDateTime().addDays(2)); +} + +#include <QRandomGenerator> + +void CertificateSelectionDialog::acceptTemporaryWithTimeout(QDateTime timeout) +{ + QRandomGenerator rng; + + char items[8]; + for(auto & c : items) { + c = rng.bounded(std::numeric_limits<char>::min(), std::numeric_limits<char>::max()); + } + + this->cryto_identity = CertificateHelper::createNewIdentity( + QByteArray(items, sizeof items).toBase64(QByteArray::OmitTrailingEquals), + timeout); + + this->accept(); +} diff --git a/src/certificateselectiondialog.hpp b/src/certificateselectiondialog.hpp new file mode 100644 index 0000000..55fe909 --- /dev/null +++ b/src/certificateselectiondialog.hpp @@ -0,0 +1,46 @@ +#ifndef CERTIFICATESELECTIONDIALOG_HPP +#define CERTIFICATESELECTIONDIALOG_HPP + +#include <QDialog> + +#include "cryptoidentity.hpp" + +namespace Ui { +class CertificateSelectionDialog; +} + +class CertificateSelectionDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CertificateSelectionDialog(QWidget *parent = nullptr); + ~CertificateSelectionDialog(); + + void setServerQuery(QString const & query); + + CryptoIdentity identity() const; + +private slots: + void on_use_temp_cert_30m_clicked(); + + void on_use_temp_cert_1h_clicked(); + + void on_use_temp_cert_12h_clicked(); + + void on_use_temp_cert_24h_clicked(); + + void on_use_temp_cert_48h_clicked(); + +private: + //! Creates an anonymous identity with a randomly chosen name that + //! will time out on `timeout`, then accepts the dialog. + void acceptTemporaryWithTimeout(QDateTime timeout); + +private: + Ui::CertificateSelectionDialog *ui; + + CryptoIdentity cryto_identity; +}; + +#endif // CERTIFICATESELECTIONDIALOG_HPP diff --git a/src/certificateselectiondialog.ui b/src/certificateselectiondialog.ui new file mode 100644 index 0000000..d7179ae --- /dev/null +++ b/src/certificateselectiondialog.ui @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CertificateSelectionDialog</class> + <widget class="QDialog" name="CertificateSelectionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>474</width> + <height>355</height> + </rect> + </property> + <property name="windowTitle"> + <string>Select client certificate</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Select existing certificate:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="server_request"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="create_new_cert"> + <property name="text"> + <string>Create new identity</string> + </property> + <property name="icon"> + <iconset resource="icons.qrc"> + <normaloff>:/icons/plus.svg</normaloff>:/icons/plus.svg</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="use_selected_cert"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Use</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Create transient session certificate:</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="use_temp_cert_30m"> + <property name="text"> + <string>30 Minutes</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="use_temp_cert_1h"> + <property name="text"> + <string>1 Hour</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="use_temp_cert_12h"> + <property name="text"> + <string>12 Hours</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="use_temp_cert_24h"> + <property name="text"> + <string>24 Hours</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="use_temp_cert_48h"> + <property name="text"> + <string>48 Hours</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="icons.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>CertificateSelectionDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>236</x> + <y>333</y> + </hint> + <hint type="destinationlabel"> + <x>236</x> + <y>177</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/cryptoidentity.cpp b/src/cryptoidentity.cpp new file mode 100644 index 0000000..921a422 --- /dev/null +++ b/src/cryptoidentity.cpp @@ -0,0 +1,2 @@ +#include "cryptoidentity.hpp" + diff --git a/src/cryptoidentity.hpp b/src/cryptoidentity.hpp new file mode 100644 index 0000000..a5fbb7f --- /dev/null +++ b/src/cryptoidentity.hpp @@ -0,0 +1,24 @@ +#ifndef CRYPTOIDENTITIY_HPP +#define CRYPTOIDENTITIY_HPP + +#include <QObject> + +#include <QSslCertificate> +#include <QSslKey> + +//! Cryptographic user identitiy consisting +//! of a key-certificate pair and some user information. +struct CryptoIdentity +{ + QSslCertificate certificate; + QSslKey private_key; + QString display_name; + + bool is_persistent = false; + + bool isValid() const { + return (not this->certificate.isNull()) and (not this->private_key.isNull()); + } +}; + +#endif // CRYPTOIDENTITIY_HPP diff --git a/src/geminiclient.cpp b/src/geminiclient.cpp index 0809120..e3036ce 100644 --- a/src/geminiclient.cpp +++ b/src/geminiclient.cpp @@ -1,6 +1,7 @@ #include "geminiclient.hpp" #include <cassert> #include <QDebug> +#include <QSslConfiguration> GeminiClient::GeminiClient(QObject *parent) : QObject(parent) { @@ -9,6 +10,14 @@ GeminiClient::GeminiClient(QObject *parent) : QObject(parent) connect(&socket, &QSslSocket::disconnected, this, &GeminiClient::socketDisconnected); connect(&socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors), this, &GeminiClient::sslErrors); connect(&socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error), this, &GeminiClient::socketError); + + + QSslConfiguration ssl_config; + ssl_config.setProtocol(QSsl::TlsV1_2); + // ssl_config.setLocalCertificate(QSslCertificate::1 + + socket.setSslConfiguration(ssl_config); + } GeminiClient::~GeminiClient() @@ -53,6 +62,18 @@ bool GeminiClient::cancelRequest() return true; } +void GeminiClient::enableClientCertificate(const CryptoIdentity &ident) +{ + this->socket.setLocalCertificate(ident.certificate); + this->socket.setPrivateKey(ident.private_key); +} + +void GeminiClient::disableClientCertificate() +{ + this->socket.setLocalCertificate(QSslCertificate{}); + this->socket.setPrivateKey(QSslKey { }); +} + void GeminiClient::socketEncrypted() { QString request = target_url.toString(QUrl::FormattingOptions(QUrl::FullyEncoded)) + "\r\n"; diff --git a/src/geminiclient.hpp b/src/geminiclient.hpp index 2578102..67e767b 100644 --- a/src/geminiclient.hpp +++ b/src/geminiclient.hpp @@ -6,6 +6,8 @@ #include <QSslSocket> #include <QUrl> +#include "cryptoidentity.hpp" + enum class TemporaryFailure { unspecified, server_unavailable, @@ -44,6 +46,9 @@ public: bool cancelRequest(); + void enableClientCertificate(CryptoIdentity const & ident); + void disableClientCertificate(); + signals: void requestProgress(qint64 transferred); diff --git a/src/icons.qrc b/src/icons.qrc index 22c2d11..12e429a 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -34,8 +34,8 @@ <file>icons/gopher/telnet.svg</file> <file>icons/gopher/text.svg</file> <file>icons/info.svg</file> - <file>about/help.gemini</file> - <file>about/easter-egg.gemini</file> <file>icons/help-box.svg</file> + <file>icons/shield-outline.svg</file> + <file>icons/shield-lock.svg</file> </qresource> </RCC> diff --git a/src/icons/shield-lock.svg b/src/icons/shield-lock.svg new file mode 100644 index 0000000..b4def0f --- /dev/null +++ b/src/icons/shield-lock.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1M12,7C13.4,7 14.8,8.1 14.8,9.5V11C15.4,11 16,11.6 16,12.3V15.8C16,16.4 15.4,17 14.7,17H9.2C8.6,17 8,16.4 8,15.7V12.2C8,11.6 8.6,11 9.2,11V9.5C9.2,8.1 10.6,7 12,7M12,8.2C11.2,8.2 10.5,8.7 10.5,9.5V11H13.5V9.5C13.5,8.7 12.8,8.2 12,8.2Z" /></svg>
\ No newline at end of file diff --git a/src/icons/shield-outline.svg b/src/icons/shield-outline.svg new file mode 100644 index 0000000..c46cd12 --- /dev/null +++ b/src/icons/shield-outline.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M21,11C21,16.55 17.16,21.74 12,23C6.84,21.74 3,16.55 3,11V5L12,1L21,5V11M12,21C15.75,20 19,15.54 19,11.22V6.3L12,3.18L5,6.3V11.22C5,15.54 8.25,20 12,21Z" /></svg>
\ No newline at end of file diff --git a/src/kristall.pro b/src/kristall.pro index 0321179..91aabf2 100644 --- a/src/kristall.pro +++ b/src/kristall.pro @@ -18,12 +18,17 @@ DEFINES += QT_DEPRECATED_WARNINGS QMAKE_CFLAGS += -Wno-unused-parameter QMAKE_CXXFLAGS += -Wno-unused-parameter +LIBS += -lcrypto + INCLUDEPATH += $$PWD/../lib/luis-l-gist/ DEPENDPATH += $$PWD/../lib/luis-l-gist/ SOURCES += \ ../lib/luis-l-gist/interactiveview.cpp \ browsertab.cpp \ + certificatehelper.cpp \ + certificateselectiondialog.cpp \ + cryptoidentity.cpp \ documentoutlinemodel.cpp \ documentstyle.cpp \ favouritecollection.cpp \ @@ -45,6 +50,9 @@ SOURCES += \ HEADERS += \ ../lib/luis-l-gist/interactiveview.hpp \ browsertab.hpp \ + certificatehelper.hpp \ + certificateselectiondialog.hpp \ + cryptoidentity.hpp \ documentoutlinemodel.hpp \ documentstyle.hpp \ favouritecollection.hpp \ @@ -65,6 +73,7 @@ HEADERS += \ FORMS += \ browsertab.ui \ + certificateselectiondialog.ui \ mainwindow.ui \ mediaplayer.ui \ settingsdialog.ui @@ -79,6 +88,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin RESOURCES += \ ../lib/BreezeStyleSheets/breeze.qrc \ + builtins.qrc \ icons.qrc DISTFILES += \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7f668db..4cd1919 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -367,7 +367,7 @@ void MainWindow::on_actionGo_to_home_triggered() { BrowserTab * tab = qobject_cast<BrowserTab*>(this->ui->browser_tabs->currentWidget()); if(tab != nullptr) { - tab->navigateTo(QUrl(global_settings.value("start_page").toString()), BrowserTab::PushAfterSuccess); + tab->navigateTo(QUrl(global_settings.value("start_page").toString()), BrowserTab::PushImmediate); } } |
