1
0
mirror of https://github.com/QRouland/UTPass.git synced 2025-07-04 03:02:28 +00:00

Fix build rnp for arm64

This commit is contained in:
2025-02-03 17:48:30 +01:00
parent b9b038b1ae
commit 93361f9ba5
27 changed files with 365 additions and 147 deletions

View File

@ -6,10 +6,12 @@ set(
plugin.cpp
pass.cpp
passkeymodel.h
passphraseprovider2.h
jobs/rmjob.cpp
jobs/rnpjob.cpp
jobs/getkeysjob.cpp
jobs/importkeyjob.cpp
jobs/decryptjob.cpp
)
set(CMAKE_AUTOMOC ON)
@ -29,37 +31,23 @@ set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
qt5_use_modules(${PLUGIN} Qml Quick DBus)
set(RNP_BUILD_DIR "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/rnp/install")
set(RNP_INSTALL_DIR "${CMAKE_SOURCE_DIR}/build/${ARCH_TRIPLET}/rnp/install")
find_package(OpenSSL REQUIRED)
find_package(JSON-C 0.11)
INCLUDE_DIRECTORIES(${RNP_BUILD_DIR}/include)
INCLUDE_DIRECTORIES(${RNP_INSTALL_DIR}/include)
add_library(rnp STATIC IMPORTED)
set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/librnp.a")
# add_library(rnp STATIC IMPORTED)
# set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/librnp.a")
add_library(sexpp STATIC IMPORTED)
set_property(TARGET sexpp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/libsexpp.a")
# add_library(sexpp STATIC IMPORTED)
# set_property(TARGET sexpp PROPERTY IMPORTED_LOCATION "${RNP_BUILD_DIR}/lib/libsexpp.a")
add_library(gpgerror SHARED IMPORTED)
set_property(TARGET gpgerror PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpg-error.so.0.28.0")
add_library(rnp SHARED IMPORTED)
set_property(TARGET rnp PROPERTY IMPORTED_LOCATION "${RNP_INSTALL_DIR}/lib/librnp.so")
add_library(libassuan SHARED IMPORTED)
set_property(TARGET libassuan PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libassuan.so")
add_library(libgpgme SHARED IMPORTED)
set_property(TARGET libgpgme PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpgme.so")
add_library(libgpgmepp SHARED IMPORTED)
set_property(TARGET libgpgmepp PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libgpgmepp.so")
add_library(libqgpgme SHARED IMPORTED)
set_property(TARGET libqgpgme PROPERTY IMPORTED_LOCATION "/usr/lib/${ARCH_TRIPLET}/libqgpgme.so")
target_link_libraries(${PLUGIN} rnp sexpp gpgerror libassuan libgpgme libgpgmepp libqgpgme OpenSSL::Crypto JSON-C::JSON-C)
target_link_libraries(${PLUGIN} rnp OpenSSL::Crypto JSON-C::JSON-C)
set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)

View File

@ -1,7 +1,13 @@
#include "decryptjob.h"
#include "qdebug.h"
extern "C" {
#include <rnp/rnp.h>
#include <rnp/rnp_err.h>
}
DecryptJob::DecryptJob(QString path, QString keyfile):
m_path(path)
DecryptJob::DecryptJob(QDir rnp_homedir, QString path):
RnpJob(rnp_homedir),
m_encrypted_file_path(path)
{
this->setObjectName("DecryptJob");
}
@ -9,7 +15,33 @@ DecryptJob::DecryptJob(QString path, QString keyfile):
void DecryptJob::run()
{
this->load_sec_keyring();
rnp_input_from_path(&keyfile, "secring.pgp"));
qFatal("To be implemented !")
qDebug() << "[DecryptJob] Starting";
this->load_sec_keyring(NULL);
rnp_input_t input = NULL;
rnp_output_t output = NULL;
uint8_t * buf = NULL;
size_t buf_len = 0;
auto ret = rnp_input_from_path(&input, this->m_encrypted_file_path.toLocal8Bit().data());
if (ret == RNP_SUCCESS) {
ret = rnp_output_to_memory(&output, 0);
}
if (ret == RNP_SUCCESS) {
ret = rnp_decrypt(this->m_ffi, input, output);
}
if (ret == RNP_SUCCESS) {
ret = rnp_output_memory_get_buf(output, &buf, &buf_len, false);
}
if (ret == RNP_SUCCESS) {
emit resultSuccess(this->m_encrypted_file_path, QString::fromUtf8((char*)buf));
}
rnp_input_destroy(input);
rnp_output_destroy(output);
terminateOnError(ret);
emit resultSuccess(this->m_encrypted_file_path, QString::fromUtf8((char*)buf));
qDebug() << "[DecryptJob] Finished Successfully ";
}

View File

@ -34,7 +34,7 @@ signals:
* @param encrypted_file_path The path to the encrypted file that was decrypted.
* @param clear_txt The decrypted content in clear-text. If an error occurs, this may be empty.
*/
void resultReady(QString encrypted_file_path, QString clear_txt);
void resultSuccess(QString encrypted_file_path, QString clear_txt);
private:
QString m_encrypted_file_path; /**< The path to the encrypted file that is to be decrypted. */
@ -46,9 +46,10 @@ public:
* This constructor initializes the DecryptJob with the encrypted file path. The decryption
* operation will be executed in a background thread when the job is started.
*
* @param rnp_homedir The directory containing the keyrings.
* @param path The path to the encrypted file that needs to be decrypted.
*/
DecryptJob(QString path);
DecryptJob(QDir rnp_homedir, QString path);
};
#endif // DECRYPTJOB_H

View File

@ -32,13 +32,14 @@ void GetKeysJob::run()
QSet<QString> fingerprints = QSet<QString>();
this->load_full_keyring(&fingerprints);
//Get infos keys
auto key_infos = QList<QJsonDocument>();
QList<QJsonDocument>::iterator i;
for (auto i = fingerprints.begin(), end = fingerprints.end(); i != end; ++i) {
key_infos.append(this->fingerprint_map_key_info(*i));
}
//Get all infos keys
// Emit result
emit resultSuccess(key_infos);
qDebug() << "[GetKeysJob] Finished Successfully ";
}

View File

@ -52,7 +52,7 @@ bool RnpJob::passProvider(rnp_ffi_t ffi,
void RnpJob::load_key_file(QSet<QString> *result_fingerprints, const QString path, const uint32_t flags)
{
qDebug() << "[RnpJob] load keyring at" << path;
qDebug() << "[RnpJob] Load keyring at" << path;
rnp_input_t input = NULL;
if (QFileInfo::exists(this->pubringPath())) {
auto ret = rnp_input_from_path(&input, path.toLocal8Bit().constData());
@ -75,9 +75,9 @@ void RnpJob::load_key_file(QSet<QString> *result_fingerprints, const QString pat
rnp_input_destroy(input);
rnp_buffer_destroy(json);
terminateOnError(ret);
qDebug() << "[RnpJob] keyring loaded successfully";
qDebug() << "[RnpJob] Keyring loaded successfully";
} else {
qDebug() << "[RnpJob] No keyring" << path << "not found";
qDebug() << "[RnpJob] Keyring" << path << "not found";
}
}
@ -85,18 +85,15 @@ void RnpJob::load_key_file(QSet<QString> *result_fingerprints, const QString pat
void RnpJob::load_pub_keyring(QSet<QString> *result_fingerprints = NULL)
{
this->load_key_file(result_fingerprints, this->pubringPath(), RNP_LOAD_SAVE_PUBLIC_KEYS);
qDebug() << "[RnpJob] pub fingerprints" << *result_fingerprints;
}
void RnpJob::load_sec_keyring(QSet<QString> *result_fingerprints = NULL)
{
this->load_key_file(result_fingerprints, this->secringPath(), RNP_LOAD_SAVE_SECRET_KEYS);
qDebug() << "[RnpJob] sec fingerprints" << *result_fingerprints;
}
void RnpJob::load_full_keyring(QSet<QString> *result_fingerprints = NULL)
{
this->load_pub_keyring(result_fingerprints);
this->load_sec_keyring(result_fingerprints);
qDebug() << "[RnpJob] full fingerprints" << *result_fingerprints;
}

View File

@ -153,6 +153,11 @@ public:
* the RNP FFI handle.
*/
~RnpJob();
void setPassProvider(rnp_password_cb pass_provider_cb) {
rnp_ffi_set_pass_provider(this->m_ffi, pass_provider_cb, NULL);
}
};
#endif // RNPJOB_H

View File

@ -2,9 +2,12 @@
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include "jobs/decryptjob.h"
#include "jobs/getkeysjob.h"
#include "jobs/importkeyjob.h"
#include "pass.h"
#include "passphraseprovider2.h"
//#include "passphraseprovider2.h"
@ -13,18 +16,19 @@ Pass::Pass():
QStandardPaths::AppDataLocation).append("/.password-store")),
m_gpg_home (QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.rnp")),
m_passphrase_provider(&UTPassphraseProvider::get_pass_provider),
m_sem(std::unique_ptr<QSemaphore>(new QSemaphore(1)))
{
}
{}
void Pass::initialize(QObject *window)
{
if (!window) {
qWarning("[Pass] Window should be null only for testing");
}
this->initGpgHome();
this->initPasswordStore();
if (!window) {
qWarning("[Pass] Window should be null only for testing");
} else {
UTPassphraseProvider::instance().setWindow(window);
}
}
@ -53,36 +57,37 @@ void Pass::initPasswordStore()
qInfo() << "[Pass] Password Store is :" << m_password_store;
}
// bool Pass::show(QUrl url)
// {
// if (!this->m_sem->tryAcquire(1, 500)) {
// return false;
// }
// auto path = url.toLocalFile();
// qInfo() << "Pass show " << path;
// QFileInfo file_info(path);
// this->m_show_filename = file_info.completeBaseName();
// return this->m_gpg->decryptFromFile(path);
// }
bool Pass::show(QUrl url)
{
if (!this->m_sem->tryAcquire(1, 500)) {
qInfo() << "[Pass] A command is already running";
return false;
}
auto job = new DecryptJob(this->m_gpg_home, url.toLocalFile());
job->setPassProvider(this->m_passphrase_provider);
QObject::connect(job, &DecryptJob::resultError, this, &Pass::slotShowError);
QObject::connect(job, &DecryptJob::resultSuccess, this, &Pass::slotShowSucceed);
connect(job, &DecryptJob::finished, job, &QObject::deleteLater);
job->start();
return true;
}
// void Pass::showResult(Error err, QString plain_text)
// {
// qDebug() << "Pass show Result";
// if (err) {
// qInfo() << "Pass show Failed";
// emit showFailed(err.asString());
void Pass::slotShowError(rnp_result_t err)
{
qInfo() << "[Pass] Show Failed";
emit showFailed(rnp_result_to_string(err));
this->m_sem->release(1);
}
// } else if (err.isCanceled()) {
// qInfo() << "Pass show Cancelled";
// emit showCancelled();
// } else {
// qInfo() << "Pass show Succeed";
// emit showSucceed(this->m_show_filename, plain_text);
// }
// this->m_show_filename = QString();
// this->m_sem->release(1);
// }
void Pass::slotShowSucceed(QString encrypted_file_path, QString plain_text)
{
qDebug() << "[Pass] Show Succeed";
QFileInfo file_info(encrypted_file_path);
emit showSucceed(file_info.completeBaseName(), plain_text);
this->m_sem->release(1);
}
// bool Pass::deletePasswordStore()
// {

View File

@ -6,14 +6,10 @@
#include <QObject>
#include <QUrl>
#include <QVariant>
#include <gpgme++/context.h>
#include <QSemaphore>
extern "C" {
#include <rnp/rnp.h>
}
using namespace GpgME;
/**
* @class Pass
* @brief A class for managing password storage using GPG encryption.
@ -33,13 +29,15 @@ private slots:
* @param err The error that occurred during the operation.
* @param plain_text The decrypted plain text (password).
*/
void showResult(Error err, QString plain_text);
void slotShowError(rnp_result_t err);
void slotShowSucceed(QString encrypted_file_path, QString plain_text);
/**
* @brief Slot to handle the result of a GPG key deletion operation.
* @param err The error that occurred during the operation.
*/
void deleteGPGKeyResult(Error err);
// void deleteGPGKeyResult(Error err);
/**
* @brief Slot to handle the error result of a GPG key import operation.
@ -148,7 +146,7 @@ private:
QString m_gpg_home; /**< The path to the gpg home. */
std::unique_ptr<PassKeyringModel>
m_keyring_model; /**< Meta data on the keyring uid, name, secrecy ... of the availble keys. */
PassphraseProvider *m_passphrase_provider; /**< Pointer on passphrase povider for operations using secret keys. */
rnp_password_cb m_passphrase_provider; /**< Pointer on passphrase povider for operations using secret keys. */
std::unique_ptr<QSemaphore> m_sem; /**< Semaphore for managing concurrent operations. */
@ -206,14 +204,8 @@ public:
this->m_gpg_home = gpg_home;
};
/**
* @brief Sets the window passphrase provider used for GPG authentication.
*
* PassphraseProvider will be deleted with destructor.
*
* @param The window used by passphrase provider.
*/
void set_passphrase_provider(PassphraseProvider* passphrase_provider)
void set_passphrase_provider(rnp_password_cb passphrase_provider)
{
this->m_passphrase_provider = passphrase_provider;
}

View File

@ -11,12 +11,6 @@
* @class PassKeyModel
* @brief A model representing a GPG (GNU Privacy Guard) key.
*
* This class encapsulates the properties of a GPG key, such as its key ID, associated
* user IDs, secret key status, and expiration status. It is used within an application
* to manage and represent GPG keys, providing easy access to key data and related user information.
*
* This class supports properties such as the key's fingerprint, key ID, user IDs, and whether
* the key has a secret key associated with it.
*/
class PassKeyModel : public QObject
{

View File

@ -0,0 +1,132 @@
#ifndef UTPASSPHRASEPROVIDER2_H
#define UTPASSPHRASEPROVIDER2_H
#include <QDebug>
#include <memory>
#include <stdio.h>
#include <QObject>
#include <QQmlProperty>
#include <QEventLoop>
#include <QSemaphore>
extern "C" {
#include <rnp/rnp.h>
}
/**
* @class UTPassphraseProvider
* @brief A passphrase provider for GPG operations that interacts with a QML dialog.
*/
class UTPassphraseProvider : public QObject
{
Q_OBJECT
public slots:
/**
* @brief Slot to handle the user's response from the passphrase dialog.
*
* This method processes the response from the passphrase dialog. If the user provides a passphrase,
* it is stored; if the operation is canceled, a flag is set.
*
* @param canceled Whether the user canceled the passphrase entry.
* @param passphrase The passphrase entered by the user.
*/
void handleResponse(bool canceled, QString passphrase)
{
qDebug() << "call handleResponse";
if (!canceled)
this->m_passphrase = passphrase;
else
m_canceled = true;
emit unlockEventLoop();
};
signals:
/**
* @brief Signal to unlock the event loop.
*
* This signal is emitted when the passphrase has been entered or the operation has been canceled,
* unlocking the event loop waiting for the response.
*/
void unlockEventLoop();
private:
explicit UTPassphraseProvider(QObject * parent = nullptr)
: m_sem(std::make_unique<QSemaphore>(1)),
m_passphrase(QString::Null()),
m_canceled(false)
{}
QObject *m_window; /**< The window object that triggers the QML dialog. */
std::unique_ptr<QSemaphore> m_sem; /**< Semaphore for managing access. */
QString m_passphrase; /**< The passphrase provided by the user. */
bool m_canceled; /**< Flag indicating whether the passphrase operation was canceled. */
public:
~UTPassphraseProvider() = default;
static UTPassphraseProvider& instance()
{
static UTPassphraseProvider instance;
return instance;
}
UTPassphraseProvider(UTPassphraseProvider const &) = delete;
void operator=(UTPassphraseProvider const &) = delete;
static bool
get_pass_provider(rnp_ffi_t ffi,
void * app_ctx,
rnp_key_handle_t key,
const char * pgp_context,
char buf[],
size_t buf_len)
{
qDebug() << "Call the getPassphrase";
if (!UTPassphraseProvider::instance().m_sem->tryAcquire(1, 500))
{
qWarning() << "Cannot acquire UTPassphraseProvider semaphore.";
UTPassphraseProvider::instance().m_canceled = true;
return false;
}
UTPassphraseProvider::instance().m_passphrase = nullptr;
UTPassphraseProvider::instance().m_canceled = false;
qDebug() << "Call the QML Dialog Passphrase Provider";
QMetaObject::invokeMethod(
UTPassphraseProvider::instance().m_window, "callPassphraseDialog",
Q_ARG(QVariant, "useridHint"), // TODO
Q_ARG(QVariant, "description"), // TODO
Q_ARG(QVariant, "previousWasBad") // TODO
);
qDebug() << "Waiting for response";
QEventLoop loop;
QObject::connect(&UTPassphraseProvider::instance(), &UTPassphraseProvider::unlockEventLoop, &loop, &QEventLoop::quit);
loop.exec();
qDebug() << "Prepare Returns";
auto ret = false;
if(!UTPassphraseProvider::instance().m_canceled) {
strncpy(buf, UTPassphraseProvider::instance().m_passphrase.toLocal8Bit().data(), buf_len);
ret = true;
};
qDebug() << "Clean";
if (UTPassphraseProvider::instance().m_passphrase.isNull())
{
UTPassphraseProvider::instance().m_passphrase = QString::Null();
}
UTPassphraseProvider::instance().m_canceled = false;
UTPassphraseProvider::instance().m_sem->release(1);
return ret;
}
void setWindow(QObject* window){
this->m_window = window;
}
};
#endif