diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-03-11 19:39:06 +0200 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-03-11 19:39:06 +0200 |
commit | 95d92e52ed6d71c21433b382f8a178a04b04954b (patch) | |
tree | f7fba616df7a94de37003be7180976bbcc5b87f2 /src | |
parent | repl: import python module (diff) | |
download | smolbote-95d92e52ed6d71c21433b382f8a178a04b04954b.tar.xz |
Add PluginLoader class
- PluginLoader::verify can be used to check if the plugin has a valid
(SHA512/RSA 4096) signature.
- Uses nn OpenSSL public key that is embedded during the compile.
Diffstat (limited to 'src')
-rw-r--r-- | src/browser.cpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/meson.build | 5 | ||||
-rw-r--r-- | src/plugin/pluginloader.cpp | 77 | ||||
-rw-r--r-- | src/plugin/pluginloader.h | 13 |
5 files changed, 101 insertions, 4 deletions
diff --git a/src/browser.cpp b/src/browser.cpp index 69db6b2..db75fa1 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -38,6 +38,7 @@ #include "adblock/adblocklist.h" #include "hostlist/hostlist.h" #include <spdlog/spdlog.h> +#include "plugin/pluginloader.h" Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) @@ -150,7 +151,8 @@ QPluginLoader *Browser::addPlugin(const QString &path) if(path.isEmpty()) return nullptr; - auto *loader = new QPluginLoader(path, this); + auto *loader = new PluginLoader(path, this); + spdlog::info("Verifying plugin: {}", loader->verify() ? "passed" : "failed"); loader->load(); auto *info = new PluginInfo(loader); diff --git a/src/main.cpp b/src/main.cpp index dfe58de..0d6f466 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,7 @@ #include <QFile> #include <QLibraryInfo> #include <QPluginLoader> +#include "plugin/pluginloader.h" #include <QTranslator> #include <memory> #include <plugininterface.h> @@ -69,8 +70,9 @@ int main(int argc, char **argv) CommandHash_t pluginCommands; // Load plugins - for(const QString &path : Util::files(config->value<QString>("plugins.path").value())) { - auto *loader = new QPluginLoader(path); + for(const QString &path : Util::files(config->value<QString>("plugins.path").value(), {"*.so", "*.dll"})) { + auto *loader = new PluginLoader(path); + spdlog::info("Verifying plugin: {}", loader->verify() ? "passed" : "failed"); const bool loaded = loader->load(); spdlog::info("{} plugin {}", loaded ? "Loaded" : "Failed to load", qUtf8Printable(path)); diff --git a/src/meson.build b/src/meson.build index ef0f989..960cc69 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,7 @@ # poi poi_moc = mod_qt5.preprocess( moc_headers: ['browser.h', + 'plugin/pluginloader.h', 'mainwindow/mainwindow.h', 'mainwindow/menubar.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', 'session/savesessiondialog.h', 'session/sessiondialog.h', 'session/sessionform.h', 'subwindow/subwindow.h', 'subwindow/tabwidget.h', @@ -13,13 +14,15 @@ poi_moc = mod_qt5.preprocess( poi = executable(get_option('poiName'), install: true, cpp_args: ['-DQAPPLICATION_CLASS=QApplication'], - dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, dep_genheaders, optional_deps, + dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_openssl, dep_SingleApplication, dep_genheaders, optional_deps, dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_urlfilter, dep_webprofile], include_directories: [include], sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, 'browser.cpp', 'util.cpp', 'util.h', + 'plugin/pluginloader.cpp', + 'mainwindow/mainwindow.cpp', 'mainwindow/menubar.cpp', 'mainwindow/widgets/dockwidget.cpp', diff --git a/src/plugin/pluginloader.cpp b/src/plugin/pluginloader.cpp new file mode 100644 index 0000000..d1626f2 --- /dev/null +++ b/src/plugin/pluginloader.cpp @@ -0,0 +1,77 @@ +#include "pluginloader.h" +#include <QFile> +#include <openssl/evp.h> +#include <openssl/pem.h> +#include "publicKey.h" +#include <spdlog/spdlog.h> + +PluginLoader::PluginLoader(const QString &fileName, QObject *parent) + : QPluginLoader(fileName, parent) +{ +} + +bool PluginLoader::verify(const char *hashName) const +{ + const QString sigName = this->fileName() + ".sig"; + if(!QFile::exists(sigName)) { + spdlog::error("Signature does not exist: {}", qUtf8Printable(sigName)); + return false; + } + + auto *bio = BIO_new_mem_buf(publicKey_pem, publicKey_pem_len); + Q_CHECK_PTR(bio); + + auto *key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + Q_CHECK_PTR(key); + + auto *ctx = EVP_MD_CTX_new(); + Q_CHECK_PTR(ctx); + + const auto *md = EVP_get_digestbyname(hashName); + Q_CHECK_PTR(md); + + int rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, key); + if(rc != 1) { + spdlog::error("DigestVerifyInit failed: %i", rc); + return false; + } + + // read plugin into DigestVerifyUpdate + QFile plugin(this->fileName()); + plugin.open(QIODevice::ReadOnly); + int len = plugin.size(); + int read = 0; + auto *buf = new unsigned char[1024]; + while(len > 0) { + read = plugin.read((char*) buf, 1024); + len -= read; + + rc = EVP_DigestVerifyUpdate(ctx, buf, read); + if(rc != 1) + spdlog::error("DigestVerifyUpdate failed: %i", rc); + } + delete buf; + plugin.close(); + + // read signature into DigestVerifyFinal + QFile sigFile(sigName); + sigFile.open(QIODevice::ReadOnly); + const int sig_len = sigFile.size(); + const auto* sig = [&sigFile, sig_len]() { + auto* buf = new unsigned char[sig_len]; + sigFile.read((char*) buf, sig_len); + return buf; + }(); + sigFile.close(); + + rc = EVP_DigestVerifyFinal(ctx, sig, sig_len); + delete sig; + + if(rc == 1) + return true; + else { + spdlog::error("DigestVerifyFinal failed: %i", rc); + return false; + } +} + diff --git a/src/plugin/pluginloader.h b/src/plugin/pluginloader.h new file mode 100644 index 0000000..8d186aa --- /dev/null +++ b/src/plugin/pluginloader.h @@ -0,0 +1,13 @@ +#include <QPluginLoader> + +class PluginLoader : public QPluginLoader +{ + Q_OBJECT + +public: + PluginLoader(const QString &fileName, QObject *parent = nullptr); + ~PluginLoader() = default; + + bool verify(const char *hashName = "SHA256") const; +}; + |