aboutsummaryrefslogtreecommitdiff
path: root/lib/pluginloader/pluginloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pluginloader/pluginloader.cpp')
-rw-r--r--lib/pluginloader/pluginloader.cpp107
1 files changed, 57 insertions, 50 deletions
diff --git a/lib/pluginloader/pluginloader.cpp b/lib/pluginloader/pluginloader.cpp
index e5c4b89..082a449 100644
--- a/lib/pluginloader/pluginloader.cpp
+++ b/lib/pluginloader/pluginloader.cpp
@@ -1,38 +1,45 @@
/*
* 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
+ * location: https://library.iserlohn-fortress.net/aqua/smolbote.git
*
* SPDX-License-Identifier: GPL-3.0
*/
#include "pluginloader.h"
+#include "publicKey.h"
#include <QFile>
+#include <filesystem>
+#include <fstream>
#include <openssl/evp.h>
#include <openssl/pem.h>
-#include "publicKey.h"
-
-PluginLoader::PluginLoader(const QString &fileName, PluginLoader::SignatureState state, QObject *parent)
- : QPluginLoader(fileName, parent)
- , m_state(state)
-{
-}
bool PluginLoader::verify(const char *hashName)
{
- const QString sigName = this->fileName() + ".sig";
- if(!QFile::exists(sigName)) {
- if(m_state.ignored || m_state.checked)
- return true;
-
- m_sigError = tr("A signature is required, but none was found.");
+ const std::filesystem::path plugin_path(fileName().toStdString());
+ if(!std::filesystem::is_regular_file(plugin_path)) {
+ m_sigError = tr("A plugin is required, but none was found.");
return false;
}
+ if(m_state <= SigIgnored) {
+ return true;
+ }
+
+ const std::filesystem::path signature_path(fileName().toStdString() + ".sig");
+ if(!std::filesystem::is_regular_file(signature_path)) {
+ if(m_state >= SigEnforced) {
+ m_sigError = tr("A signature is required, but none was found.");
+ return false;
+ }
+
+ return true;
+ }
+
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);
+ auto *key = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
Q_CHECK_PTR(key);
auto *ctx = EVP_MD_CTX_new();
@@ -41,53 +48,53 @@ bool PluginLoader::verify(const char *hashName)
const auto *md = EVP_get_digestbyname(hashName);
Q_CHECK_PTR(md);
- int rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, key);
+ int rc = EVP_DigestVerifyInit(ctx, nullptr, md, nullptr, key);
if(rc != 1) {
m_sigError = tr("Failed to compute signature (stage=init)");
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(reinterpret_cast<char*>(buf), 1024);
- len -= read;
-
- rc = EVP_DigestVerifyUpdate(ctx, buf, read);
- if(rc != 1) {
- m_sigError = tr("Failed to compute signature (staga=update)");
- return false;
+ {
+ std::ifstream plugin(plugin_path, std::ios::binary);
+ plugin.unsetf(std::ios::skipws);
+ if(!plugin.is_open()) {
+ m_sigError = tr("Cannot read plugin during signature check");
+ return true;
+ }
+
+ const std::size_t buffer_size = 1024;
+ std::vector<char> buffer(buffer_size);
+ while(const auto sz = plugin.readsome(&buffer.front(), buffer_size)) {
+ rc = EVP_DigestVerifyUpdate(ctx, reinterpret_cast<unsigned char *>(buffer.data()), sz);
+ if(rc != 1) {
+ m_sigError = tr("Failed to compute signature (stage=update)");
+ return false;
+ }
}
}
- 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(reinterpret_cast<char*>(buf), sig_len);
- return buf;
- }();
- sigFile.close();
-
- rc = EVP_DigestVerifyFinal(ctx, sig, sig_len);
- delete sig;
-
- if(rc == 1)
- return true;
- else {
- if(m_state.ignored)
- return true;
+ {
+ std::ifstream signature(signature_path, std::ios::binary);
+ signature.unsetf(std::ios::skipws);
+ if(!signature.is_open()) {
+ m_sigError = tr("Cannot read signature during signature check");
+ return false;
+ }
+
+ const auto buffer_size = std::filesystem::file_size(signature_path);
+ std::vector<unsigned char> buffer(buffer_size);
+ buffer.insert(buffer.begin(), std::istream_iterator<unsigned char>(signature), std::istream_iterator<unsigned char>());
+ signature.close();
+
+ rc = EVP_DigestVerifyFinal(ctx, buffer.data(), buffer_size);
+ }
+
+ if(rc != 1) {
m_sigError = tr("Signature does not match");
return false;
}
+ return true;
}
-