diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-04-19 17:27:39 +0300 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-04-19 17:27:39 +0300 |
commit | c5576c85c92c464ff3aa53f680ce18d8b51f60ab (patch) | |
tree | 042c50df8fc1b9bb9a08656ca7200fa3af5b1086 | |
parent | Use scdoc to generate manpages (diff) | |
download | smolbote-c5576c85c92c464ff3aa53f680ce18d8b51f60ab.tar.xz |
Add plugin signature verification policies
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Kconfig | 2 | ||||
-rw-r--r-- | lib/pluginloader/Kconfig (renamed from lib/plugin/Kconfig) | 3 | ||||
-rw-r--r-- | lib/pluginloader/meson.build | 13 | ||||
-rw-r--r-- | lib/pluginloader/pluginloader.cpp (renamed from src/plugin/pluginloader.cpp) | 38 | ||||
-rw-r--r-- | lib/pluginloader/pluginloader.h | 55 | ||||
-rw-r--r-- | linux/.config | 1 | ||||
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | src/browser.cpp | 13 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/meson.build | 7 | ||||
-rw-r--r-- | src/plugin/pluginloader.h | 13 |
12 files changed, 110 insertions, 43 deletions
@@ -8,7 +8,7 @@ build* subprojects/ lang/*.qm test/plugins.d - +publicKey.h .config .config.old @@ -10,7 +10,7 @@ endmenu source 'lib/configuration/Kconfig' # Plugin loading -source 'lib/plugin/Kconfig' +source 'lib/pluginloader/Kconfig' config USEPLASMA bool "Enable KDE Frameworks integration" diff --git a/lib/plugin/Kconfig b/lib/pluginloader/Kconfig index 1de9403..28a3b73 100644 --- a/lib/plugin/Kconfig +++ b/lib/pluginloader/Kconfig @@ -12,9 +12,6 @@ menu "Plugin Settings" config PLUGIN_SIGNATURE_IGNORED bool "Don't check plugin signatures" - config PLUGIN_SIGNATURE_NONFATAL - bool "Check signature validity, but always load plugins" - config PLUGIN_SIGNATURE_CHECKED bool "Don't load plugins with invalid signatures" diff --git a/lib/pluginloader/meson.build b/lib/pluginloader/meson.build new file mode 100644 index 0000000..4786156 --- /dev/null +++ b/lib/pluginloader/meson.build @@ -0,0 +1,13 @@ +dep_openssl = dependency('openssl') + +pluginloader_moc = mod_qt5.preprocess( + moc_headers: ['pluginloader.h'], + dependencies: dep_qt5 +) + +dep_pluginloader = declare_dependency( + include_directories: include_directories('.'), + link_with: static_library('plugin', + ['pluginloader.cpp', pluginloader_moc], + dependencies: [dep_qt5, dep_openssl, dep_genheaders]) +) diff --git a/src/plugin/pluginloader.cpp b/lib/pluginloader/pluginloader.cpp index d1626f2..f47c39e 100644 --- a/src/plugin/pluginloader.cpp +++ b/lib/pluginloader/pluginloader.cpp @@ -1,21 +1,28 @@ +/* + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + #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) +PluginLoader::PluginLoader(const QString &fileName, const VerifyState sigLevel, QObject *parent) : QPluginLoader(fileName, parent) + , requiredSignatureLevel(sigLevel) { } -bool PluginLoader::verify(const char *hashName) const +PluginLoader::VerifyState 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; + return SignatureMissing; } auto *bio = BIO_new_mem_buf(publicKey_pem, publicKey_pem_len); @@ -32,8 +39,7 @@ bool PluginLoader::verify(const char *hashName) const int rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, key); if(rc != 1) { - spdlog::error("DigestVerifyInit failed: %i", rc); - return false; + return SignatureMismatched; } // read plugin into DigestVerifyUpdate @@ -48,7 +54,7 @@ bool PluginLoader::verify(const char *hashName) const rc = EVP_DigestVerifyUpdate(ctx, buf, read); if(rc != 1) - spdlog::error("DigestVerifyUpdate failed: %i", rc); + return SignatureComputeFailed; } delete buf; plugin.close(); @@ -68,10 +74,20 @@ bool PluginLoader::verify(const char *hashName) const delete sig; if(rc == 1) - return true; + return SignatureMatched; else { - spdlog::error("DigestVerifyFinal failed: %i", rc); - return false; + return SignatureMismatched; } } +/* +bool PluginLoader::load() +{ + if(signature == SignatureUnverified) + signature = this->verify(); + if(signature > requiredSignatureLevel) + return QPluginLoader::load(); + else + return false; +} +*/ diff --git a/lib/pluginloader/pluginloader.h b/lib/pluginloader/pluginloader.h new file mode 100644 index 0000000..0c8bcd3 --- /dev/null +++ b/lib/pluginloader/pluginloader.h @@ -0,0 +1,55 @@ +/* + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include <QPluginLoader> + +class PluginLoader : public QPluginLoader +{ + Q_OBJECT + +public: + enum VerifyState { + // uninitialized state + SignatureUnverified = -1, + + // signature is optional, match is optional + SignatureCheckIfAvailable = 1, + + SignatureComputeFailed = 2, // error computing signature + SignatureMismatched = 3, // signature does not match + + // signature is optional, match is required + SignatureMatchIfAvailable = 4, + + SignatureMissing = 5, // signature is not available + + // signature required, match is required + SignatureMatchRequired = 10, + + SignatureMatched = 20 // signature is matched + }; + + PluginLoader(const QString &fileName, const VerifyState sigLevel = SignatureMissing, QObject *parent = nullptr); + ~PluginLoader() = default; + + QString errorString() const + { + if(signature < requiredSignatureLevel) + return QString("Required signature level: %2; Signature level: %3").arg(QString::number((int) requiredSignatureLevel), QString::number((int) signature)); + else + return QPluginLoader::errorString(); + } + + VerifyState verify(const char *hashName = "SHA256") const; + //bool load(); + +private: + const VerifyState requiredSignatureLevel; + VerifyState signature = SignatureUnverified; +}; + diff --git a/linux/.config b/linux/.config index 6ba6018..3e8d40c 100644 --- a/linux/.config +++ b/linux/.config @@ -76,7 +76,6 @@ CONFIG_USEPLUGINS=y # Plugin Settings # # CONFIG_PLUGIN_SIGNATURE_IGNORED is not set -# CONFIG_PLUGIN_SIGNATURE_NONFATAL is not set CONFIG_PLUGIN_SIGNATURE_CHECKED=y # CONFIG_PLUGIN_SIGNATURE_ENFORCED is not set CONFIG_PLUGIN_SIGNATURE_HASH="SHA256" diff --git a/meson.build b/meson.build index 121b472..a2b5a17 100644 --- a/meson.build +++ b/meson.build @@ -26,8 +26,6 @@ dep_boost = dependency('boost', modules: ['program_options']) dep_spdlog = dependency('spdlog', fallback: ['spdlog', 'spdlog_dep'], version: '>=1.3.1') -dep_openssl = dependency('openssl') - optional_deps = [] if get_option('Breakpad').enabled() @@ -83,6 +81,7 @@ subdir('lib/addressbar') subdir('lib/bookmarks') subdir('lib/configuration') subdir('lib/downloads') +subdir('lib/pluginloader') subdir('lib/urlfilter') subdir('lib/webprofile') diff --git a/src/browser.cpp b/src/browser.cpp index db75fa1..e11a1da 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -38,7 +38,7 @@ #include "adblock/adblocklist.h" #include "hostlist/hostlist.h" #include <spdlog/spdlog.h> -#include "plugin/pluginloader.h" +#include <pluginloader.h> Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) @@ -151,9 +151,14 @@ QPluginLoader *Browser::addPlugin(const QString &path) if(path.isEmpty()) return nullptr; - auto *loader = new PluginLoader(path, this); - spdlog::info("Verifying plugin: {}", loader->verify() ? "passed" : "failed"); - loader->load(); + auto *loader = new PluginLoader(path, PluginLoader::SignatureMatchIfAvailable, this); + const bool loaded = loader->load(); + spdlog::info("Loading plugin [{}]: {}", qUtf8Printable(path), loaded ? "passed" : "failed"); + + if(!loaded) { + delete loader; + return nullptr; + } auto *info = new PluginInfo(loader); m_plugins.append(info); diff --git a/src/main.cpp b/src/main.cpp index 0d6f466..8063b86 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ #include <QFile> #include <QLibraryInfo> #include <QPluginLoader> -#include "plugin/pluginloader.h" +#include <pluginloader.h> #include <QTranslator> #include <memory> #include <plugininterface.h> @@ -72,7 +72,6 @@ int main(int argc, char **argv) // Load plugins 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 960cc69..8660534 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,6 @@ # 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', @@ -14,15 +13,13 @@ 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_openssl, dep_SingleApplication, dep_genheaders, optional_deps, - dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_urlfilter, dep_webprofile], + dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, dep_genheaders, optional_deps, + dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, 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.h b/src/plugin/pluginloader.h deleted file mode 100644 index 8d186aa..0000000 --- a/src/plugin/pluginloader.h +++ /dev/null @@ -1,13 +0,0 @@ -#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; -}; - |