Téléverser les fichiers vers "workstation-setup/src"

This commit is contained in:
2026-08-19 08:48:20 +02:00
parent 9fe105bae8
commit 24f75b70b3
2 changed files with 257 additions and 117 deletions
+240 -110
View File
@@ -1,29 +1,19 @@
#include "ProvisioningBackend.h" #include "ProvisioningBackend.h"
#include "Config.h"
#include <QDateTime> #include <QDateTime>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QSaveFile>
#include <QTimer> #include <QTimer>
#include <utility>
#include <pwd.h> #include <pwd.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#ifndef PASSWORD_HELPER_PATH #include <utility>
#error PASSWORD_HELPER_PATH must be defined
#endif
#ifndef PIN_HELPER_PATH
#error PIN_HELPER_PATH must be defined
#endif
#ifndef TARGET_USER
#error TARGET_USER must be defined
#endif
namespace { namespace {
constexpr int kHelperTimeoutMs = 60000; constexpr int kHelperTimeoutMs = 60000;
@@ -32,15 +22,38 @@ bool containsLineBreak(const QString &value)
{ {
return value.contains(QLatin1Char('\n')) || value.contains(QLatin1Char('\r')); return value.contains(QLatin1Char('\n')) || value.contains(QLatin1Char('\r'));
} }
QString homeDirectoryForEffectiveUser()
{
if (passwd *entry = getpwuid(geteuid())) {
return QString::fromLocal8Bit(entry->pw_dir);
}
return QDir::homePath();
}
} }
ProvisioningBackend::ProvisioningBackend(QObject *parent) ProvisioningBackend::ProvisioningBackend(QString targetUser, QObject *parent)
: QObject(parent) : QObject(parent)
, m_currentUser(effectiveUserName()) , m_currentUser(effectiveUserName())
, m_targetUser(QStringLiteral(TARGET_USER)) , m_targetUser(std::move(targetUser))
, m_authorizedUser(m_currentUser == m_targetUser) , m_authorizedUser(!m_targetUser.isEmpty() && m_currentUser == m_targetUser)
{ {
refreshState(); refreshState();
appendLog(QStringLiteral("START currentUser=%1 targetUser=%2 authorized=%3 passwordDone=%4 pinDone=%5")
.arg(m_currentUser,
m_targetUser,
m_authorizedUser ? QStringLiteral("yes") : QStringLiteral("no"),
m_passwordDone ? QStringLiteral("yes") : QStringLiteral("no"),
m_pinDone ? QStringLiteral("yes") : QStringLiteral("no")));
}
ProvisioningBackend::~ProvisioningBackend()
{
secureClear(m_pendingPayload);
if (m_process && m_process->state() != QProcess::NotRunning) {
m_process->kill();
m_process->waitForFinished(1000);
}
} }
QString ProvisioningBackend::effectiveUserName() QString ProvisioningBackend::effectiveUserName()
@@ -56,16 +69,19 @@ QString ProvisioningBackend::stateDirectory() const
{ {
const QByteArray xdgState = qgetenv("XDG_STATE_HOME"); const QByteArray xdgState = qgetenv("XDG_STATE_HOME");
if (!xdgState.isEmpty()) { if (!xdgState.isEmpty()) {
return QString::fromLocal8Bit(xdgState) const QString candidate = QString::fromLocal8Bit(xdgState);
+ QStringLiteral("/nixos-workstations"); if (QDir::isAbsolutePath(candidate)) {
return QDir::cleanPath(candidate + QStringLiteral("/nixos-workstations"));
}
} }
if (passwd *entry = getpwuid(geteuid())) { return QDir::cleanPath(homeDirectoryForEffectiveUser()
return QString::fromLocal8Bit(entry->pw_dir) + QStringLiteral("/.local/state/nixos-workstations"));
+ QStringLiteral("/.local/state/nixos-workstations"); }
}
return QDir::homePath() + QStringLiteral("/.local/state/nixos-workstations"); QString ProvisioningBackend::diagnosticLogPath() const
{
return stateDirectory() + QStringLiteral("/setup.log");
} }
QString ProvisioningBackend::passwordMarker() const QString ProvisioningBackend::passwordMarker() const
@@ -91,7 +107,6 @@ void ProvisioningBackend::refreshState()
} }
} }
bool ProvisioningBackend::ensureStateWritable() bool ProvisioningBackend::ensureStateWritable()
{ {
const QString dir = stateDirectory(); const QString dir = stateDirectory();
@@ -99,26 +114,31 @@ bool ProvisioningBackend::ensureStateWritable()
return false; return false;
} }
QFile::setPermissions(dir,
QFileDevice::ReadOwner
| QFileDevice::WriteOwner
| QFileDevice::ExeOwner);
const QString probePath = dir + QStringLiteral("/.write-test"); const QString probePath = dir + QStringLiteral("/.write-test");
QFile probe(probePath); QFile probe(probePath);
if (!probe.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!probe.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false; return false;
} }
probe.write("ok\n");
const bool writeOk = probe.write("ok\n") == 3;
probe.close(); probe.close();
probe.remove(); probe.remove();
return true; return writeOk;
} }
bool ProvisioningBackend::createMarker(const QString &path) bool ProvisioningBackend::createMarker(const QString &path)
{ {
const QFileInfo info(path); if (!ensureStateWritable()) {
if (!QDir().mkpath(info.absolutePath())) {
return false; return false;
} }
QFile marker(path); QSaveFile marker(path);
if (!marker.open(QIODevice::WriteOnly | QIODevice::Truncate)) { if (!marker.open(QIODevice::WriteOnly)) {
return false; return false;
} }
@@ -128,13 +148,47 @@ bool ProvisioningBackend::createMarker(const QString &path)
+ '\n'; + '\n';
if (marker.write(content) != content.size()) { if (marker.write(content) != content.size()) {
marker.close(); marker.cancelWriting();
return false; return false;
} }
marker.close(); if (!marker.commit()) {
marker.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner); return false;
return true; }
return QFile::setPermissions(path,
QFileDevice::ReadOwner
| QFileDevice::WriteOwner);
}
void ProvisioningBackend::appendLog(const QString &message) const
{
const QString dir = stateDirectory();
if (!QDir().mkpath(dir)) {
return;
}
QFile::setPermissions(dir,
QFileDevice::ReadOwner
| QFileDevice::WriteOwner
| QFileDevice::ExeOwner);
QFile log(diagnosticLogPath());
if (!log.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
return;
}
const QByteArray line =
QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs).toUtf8()
+ QByteArrayLiteral(" ")
+ message.toUtf8()
+ '\n';
log.write(line);
log.close();
QFile::setPermissions(diagnosticLogPath(),
QFileDevice::ReadOwner
| QFileDevice::WriteOwner);
} }
void ProvisioningBackend::setBusy(bool busy) void ProvisioningBackend::setBusy(bool busy)
@@ -148,11 +202,21 @@ void ProvisioningBackend::setBusy(bool busy)
void ProvisioningBackend::secureClear(QByteArray &data) void ProvisioningBackend::secureClear(QByteArray &data)
{ {
volatile char *p = data.data(); if (!data.isEmpty()) {
for (qsizetype i = 0; i < data.size(); ++i) { volatile char *p = data.data();
p[i] = 0; for (qsizetype i = 0; i < data.size(); ++i) {
p[i] = 0;
}
} }
data.clear(); data.clear();
data.squeeze();
}
QString ProvisioningBackend::operationName(Operation operation)
{
return operation == Operation::Password
? QStringLiteral("PASSWORD")
: QStringLiteral("PIN");
} }
void ProvisioningBackend::changePassword(const QString &currentPassword, void ProvisioningBackend::changePassword(const QString &currentPassword,
@@ -160,12 +224,15 @@ void ProvisioningBackend::changePassword(const QString &currentPassword,
const QString &confirmation) const QString &confirmation)
{ {
if (!m_authorizedUser) { if (!m_authorizedUser) {
appendLog(QStringLiteral("PASSWORD refused: unauthorized user"));
emit passwordChangeFinished(false, emit passwordChangeFinished(false,
QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur.")); QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
return; return;
} }
if (m_busy) { if (m_busy) {
emit passwordChangeFinished(false,
QStringLiteral("Une opération de configuration est déjà en cours."));
return; return;
} }
@@ -187,8 +254,6 @@ void ProvisioningBackend::changePassword(const QString &currentPassword,
return; return;
} }
// Les helpers utilisent un protocole interne délimité par des retours ligne.
// Un secret interactif passwd/FIDO2 ne doit donc jamais en contenir.
if (containsLineBreak(currentPassword) || containsLineBreak(newPassword) if (containsLineBreak(currentPassword) || containsLineBreak(newPassword)
|| containsLineBreak(confirmation)) { || containsLineBreak(confirmation)) {
emit passwordChangeFinished(false, emit passwordChangeFinished(false,
@@ -196,16 +261,15 @@ void ProvisioningBackend::changePassword(const QString &currentPassword,
return; return;
} }
// Vérifie avant toute modification que l'état de provisioning pourra
// effectivement être persisté dans le HOME de l'utilisateur.
if (!ensureStateWritable()) { if (!ensureStateWritable()) {
appendLog(QStringLiteral("PASSWORD refused: state directory is not writable"));
emit passwordChangeFinished(false, emit passwordChangeFinished(false,
QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique.")); QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique."));
return; return;
} }
startHelper(Operation::Password, startHelper(Operation::Password,
QStringLiteral(PASSWORD_HELPER_PATH), QString::fromUtf8(NIXOS_WORKSTATIONS_PASSWORD_HELPER_PATH),
currentPassword, currentPassword,
newPassword, newPassword,
confirmation); confirmation);
@@ -216,12 +280,15 @@ void ProvisioningBackend::changePin(const QString &currentPin,
const QString &confirmation) const QString &confirmation)
{ {
if (!m_authorizedUser) { if (!m_authorizedUser) {
appendLog(QStringLiteral("PIN refused: unauthorized user"));
emit pinChangeFinished(false, emit pinChangeFinished(false,
QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur.")); QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
return; return;
} }
if (m_busy) { if (m_busy) {
emit pinChangeFinished(false,
QStringLiteral("Une opération de configuration est déjà en cours."));
return; return;
} }
@@ -257,13 +324,14 @@ void ProvisioningBackend::changePin(const QString &currentPin,
} }
if (!ensureStateWritable()) { if (!ensureStateWritable()) {
appendLog(QStringLiteral("PIN refused: state directory is not writable"));
emit pinChangeFinished(false, emit pinChangeFinished(false,
QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique.")); QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique."));
return; return;
} }
startHelper(Operation::Pin, startHelper(Operation::Pin,
QStringLiteral(PIN_HELPER_PATH), QString::fromUtf8(NIXOS_WORKSTATIONS_PIN_HELPER_PATH),
currentPin, currentPin,
newPin, newPin,
confirmation); confirmation);
@@ -275,8 +343,11 @@ void ProvisioningBackend::startHelper(Operation operation,
const QString &secondSecret, const QString &secondSecret,
const QString &thirdSecret) const QString &thirdSecret)
{ {
if (!QFileInfo::exists(helperPath)) { const QFileInfo helperInfo(helperPath);
const QString message = QStringLiteral("Le composant système requis est introuvable."); if (!helperInfo.exists() || !helperInfo.isFile() || !helperInfo.isExecutable()) {
appendLog(operationName(operation)
+ QStringLiteral(" failed: helper missing or not executable"));
const QString message = QStringLiteral("Le composant système requis est introuvable ou inutilisable.");
if (operation == Operation::Password) { if (operation == Operation::Password) {
emit passwordChangeFinished(false, message); emit passwordChangeFinished(false, message);
} else { } else {
@@ -285,85 +356,122 @@ void ProvisioningBackend::startHelper(Operation operation,
return; return;
} }
m_operation = operation;
setBusy(true);
m_process = new QProcess(this);
m_process->setProgram(helperPath);
m_process->setProcessChannelMode(QProcess::SeparateChannels);
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
environment.insert(QStringLiteral("LC_ALL"), QStringLiteral("C"));
environment.insert(QStringLiteral("LANG"), QStringLiteral("C"));
m_process->setProcessEnvironment(environment);
auto *timeout = new QTimer(m_process);
timeout->setSingleShot(true);
timeout->setInterval(kHelperTimeoutMs);
connect(timeout, &QTimer::timeout, m_process, [process = m_process]() {
if (process->state() != QProcess::NotRunning) {
process->kill();
}
});
QByteArray first = firstSecret.toUtf8(); QByteArray first = firstSecret.toUtf8();
QByteArray second = secondSecret.toUtf8(); QByteArray second = secondSecret.toUtf8();
QByteArray third = thirdSecret.toUtf8(); QByteArray third = thirdSecret.toUtf8();
connect(m_process, &QProcess::started, this, m_pendingPayload.clear();
[this, first = std::move(first), second = std::move(second), m_pendingPayload.reserve(first.size() + second.size() + third.size() + 3);
third = std::move(third), timeout]() mutable { m_pendingPayload += first;
QByteArray payload; m_pendingPayload += '\n';
payload.reserve(first.size() + second.size() + third.size() + 3); m_pendingPayload += second;
payload += first; m_pendingPayload += '\n';
payload += '\n'; m_pendingPayload += third;
payload += second; m_pendingPayload += '\n';
payload += '\n';
payload += third;
payload += '\n';
m_process->write(payload); secureClear(first);
m_process->closeWriteChannel(); secureClear(second);
secureClear(third);
// Réduit la durée de vie des copies explicites côté backend. m_helperTimedOut = false;
secureClear(first); setBusy(true);
secureClear(second);
secureClear(third); auto *process = new QProcess(this);
secureClear(payload); m_process = process;
timeout->start(); process->setProgram(helperPath);
process->setProcessChannelMode(QProcess::SeparateChannels);
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
environment.insert(QStringLiteral("LC_ALL"), QStringLiteral("C"));
environment.insert(QStringLiteral("LANG"), QStringLiteral("C"));
process->setProcessEnvironment(environment);
auto *timeout = new QTimer(process);
timeout->setSingleShot(true);
timeout->setInterval(kHelperTimeoutMs);
connect(timeout, &QTimer::timeout, process,
[this, process, operation]() {
if (m_process != process || process->state() == QProcess::NotRunning) {
return;
}
m_helperTimedOut = true;
appendLog(operationName(operation) + QStringLiteral(" timeout"));
process->kill();
}); });
connect(m_process, &QProcess::errorOccurred, this, connect(process, &QProcess::started, this,
[this](QProcess::ProcessError error) { [this, process, timeout, operation]() {
if (error != QProcess::FailedToStart) { if (m_process != process) {
return; return;
} }
const qint64 expected = m_pendingPayload.size();
const qint64 written = process->write(m_pendingPayload);
process->closeWriteChannel();
secureClear(m_pendingPayload);
if (written != expected) {
appendLog(operationName(operation)
+ QStringLiteral(" warning: incomplete helper input write"));
}
appendLog(operationName(operation) + QStringLiteral(" helper started"));
timeout->start();
});
connect(process, &QProcess::errorOccurred, this,
[this, process, timeout, operation](QProcess::ProcessError error) {
if (m_process != process || error != QProcess::FailedToStart) {
return;
}
timeout->stop();
secureClear(m_pendingPayload);
appendLog(operationName(operation)
+ QStringLiteral(" failed to start: ")
+ process->errorString());
m_process = nullptr;
process->deleteLater();
setBusy(false); setBusy(false);
const QString message = QStringLiteral("Impossible de démarrer le composant de configuration."); const QString message = QStringLiteral("Impossible de démarrer le composant de configuration.");
if (m_operation == Operation::Password) { if (operation == Operation::Password) {
emit passwordChangeFinished(false, message); emit passwordChangeFinished(false, message);
} else { } else {
emit pinChangeFinished(false, message); emit pinChangeFinished(false, message);
} }
}); });
connect(m_process, connect(process,
qOverload<int, QProcess::ExitStatus>(&QProcess::finished), qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
this, this,
[this, timeout](int exitCode, QProcess::ExitStatus exitStatus) { [this, process, timeout, operation](int exitCode, QProcess::ExitStatus exitStatus) {
timeout->stop(); if (m_process != process) {
return;
}
const QByteArray stderrData = m_process->readAllStandardError(); timeout->stop();
const QByteArray stdoutData = m_process->readAllStandardOutput(); secureClear(m_pendingPayload);
const bool success = exitStatus == QProcess::NormalExit && exitCode == 0;
const Operation operation = m_operation; QByteArray stderrData = process->readAllStandardError();
QByteArray stdoutData = process->readAllStandardOutput();
QByteArray combinedOutput;
combinedOutput.reserve(stderrData.size() + stdoutData.size() + 1);
combinedOutput += stderrData;
combinedOutput += '\n';
combinedOutput += stdoutData;
const bool timedOut = m_helperTimedOut;
const bool helperSucceeded = !timedOut
&& exitStatus == QProcess::NormalExit
&& exitCode == 0;
QString message; QString message;
bool markerCreated = false; bool markerCreated = false;
if (success) { if (helperSucceeded) {
if (operation == Operation::Password) { if (operation == Operation::Password) {
markerCreated = createMarker(passwordMarker()); markerCreated = createMarker(passwordMarker());
message = markerCreated message = markerCreated
@@ -376,15 +484,26 @@ void ProvisioningBackend::startHelper(Operation operation,
: QStringLiteral("Le PIN a été modifié, mais l'état local n'a pas pu être enregistré. Contactez le service informatique avant de fermer la session."); : QStringLiteral("Le PIN a été modifié, mais l'état local n'a pas pu être enregistré. Contactez le service informatique avant de fermer la session.");
} }
} else { } else {
message = safeMessageForFailure(operation, exitCode, stderrData + stdoutData); message = safeMessageForFailure(operation, exitCode, combinedOutput, timedOut);
} }
m_process->deleteLater(); appendLog(operationName(operation)
+ QStringLiteral(" helper finished exitCode=%1 normalExit=%2 timeout=%3 marker=%4")
.arg(exitCode)
.arg(exitStatus == QProcess::NormalExit ? QStringLiteral("yes") : QStringLiteral("no"))
.arg(timedOut ? QStringLiteral("yes") : QStringLiteral("no"))
.arg(markerCreated ? QStringLiteral("yes") : QStringLiteral("no")));
secureClear(stderrData);
secureClear(stdoutData);
secureClear(combinedOutput);
m_process = nullptr; m_process = nullptr;
process->deleteLater();
setBusy(false); setBusy(false);
refreshState(); refreshState();
const bool completed = success && markerCreated; const bool completed = helperSucceeded && markerCreated;
if (operation == Operation::Password) { if (operation == Operation::Password) {
emit passwordChangeFinished(completed, message); emit passwordChangeFinished(completed, message);
} else { } else {
@@ -392,31 +511,36 @@ void ProvisioningBackend::startHelper(Operation operation,
} }
}); });
m_process->start(); process->start();
} }
QString ProvisioningBackend::safeMessageForFailure(Operation operation, QString ProvisioningBackend::safeMessageForFailure(Operation operation,
int exitCode, int exitCode,
const QByteArray &stderrData) const const QByteArray &outputData,
bool timedOut) const
{ {
const QString output = QString::fromUtf8(stderrData).toLower(); const QString output = QString::fromUtf8(outputData).toLower();
if (exitCode == 124 || output.contains(QStringLiteral("timeout"))) { if (timedOut || exitCode == 124 || output.contains(QStringLiteral("timeout"))) {
return QStringLiteral("L'opération a expiré. Vérifiez le périphérique puis réessayez."); return QStringLiteral("L'opération a expiré. Vérifiez le périphérique puis réessayez.");
} }
if (operation == Operation::Password) { if (operation == Operation::Password) {
if (output.contains(QStringLiteral("current_rejected"))) { if (output.contains(QStringLiteral("current_rejected"))
return QStringLiteral("Le mot de passe temporaire actuel est incorrect."); || output.contains(QStringLiteral("current_prompt_missing"))) {
return QStringLiteral("Le mot de passe temporaire actuel est incorrect ou n'a pas pu être vérifié.");
} }
if (output.contains(QStringLiteral("new_rejected"))) { if (output.contains(QStringLiteral("new_rejected"))) {
return QStringLiteral("Le système a refusé le nouveau mot de passe. Choisissez-en un autre puis réessayez."); return QStringLiteral("Le système a refusé le nouveau mot de passe. Choisissez-en un autre puis réessayez.");
} }
if (output.contains(QStringLiteral("input_error"))) {
return QStringLiteral("Le composant de changement de mot de passe n'a pas reçu les données attendues.");
}
return QStringLiteral("Le mot de passe n'a pas été modifié. Vérifiez le mot de passe actuel puis réessayez."); return QStringLiteral("Le mot de passe n'a pas été modifié. Vérifiez le mot de passe actuel puis réessayez.");
} }
if (output.contains(QStringLiteral("wrong_pin"))) { if (output.contains(QStringLiteral("pin_not_configured"))) {
return QStringLiteral("Le PIN temporaire est incorrect. N'essayez pas au hasard : le nombre de tentatives FIDO2 est limité."); return QStringLiteral("Aucun PIN FIDO2 actuel n'a été détecté sur la YubiKey. Contactez le service informatique pour initialiser la clé.");
} }
if (output.contains(QStringLiteral("pin_auth_blocked"))) { if (output.contains(QStringLiteral("pin_auth_blocked"))) {
return QStringLiteral("Les tentatives de PIN sont temporairement bloquées. Débranchez puis rebranchez la YubiKey avant de réessayer avec le bon PIN."); return QStringLiteral("Les tentatives de PIN sont temporairement bloquées. Débranchez puis rebranchez la YubiKey avant de réessayer avec le bon PIN.");
@@ -424,12 +548,18 @@ QString ProvisioningBackend::safeMessageForFailure(Operation operation,
if (output.contains(QStringLiteral("pin_blocked"))) { if (output.contains(QStringLiteral("pin_blocked"))) {
return QStringLiteral("Le PIN FIDO2 de la YubiKey est bloqué. Contactez le service informatique ; ne réinitialisez pas la clé."); return QStringLiteral("Le PIN FIDO2 de la YubiKey est bloqué. Contactez le service informatique ; ne réinitialisez pas la clé.");
} }
if (output.contains(QStringLiteral("wrong_pin"))) {
return QStringLiteral("Le PIN temporaire est incorrect. N'essayez pas au hasard : le nombre de tentatives FIDO2 est limité.");
}
if (output.contains(QStringLiteral("no_yubikey"))) { if (output.contains(QStringLiteral("no_yubikey"))) {
return QStringLiteral("Aucune YubiKey compatible n'a été détectée. Branchez la clé puis réessayez."); return QStringLiteral("Aucune YubiKey compatible n'a été détectée ou le système n'a pas les droits d'accès nécessaires.");
} }
if (output.contains(QStringLiteral("pin_policy"))) { if (output.contains(QStringLiteral("pin_policy"))) {
return QStringLiteral("Le nouveau PIN ne respecte pas la politique configurée sur cette YubiKey."); return QStringLiteral("Le nouveau PIN ne respecte pas la politique configurée sur cette YubiKey.");
} }
if (output.contains(QStringLiteral("input_error"))) {
return QStringLiteral("Le composant de configuration de la YubiKey n'a pas reçu les données attendues.");
}
return QStringLiteral("Le PIN YubiKey n'a pas été modifié. Vérifiez que la clé est branchée et que le PIN actuel est correct."); return QStringLiteral("Le PIN YubiKey n'a pas été modifié. Vérifiez que la clé est branchée et que le PIN actuel est correct.");
} }
+17 -7
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QByteArray>
#include <QObject> #include <QObject>
#include <QProcess> #include <QProcess>
#include <QString> #include <QString>
@@ -17,7 +18,8 @@ class ProvisioningBackend final : public QObject
Q_PROPERTY(bool authorizedUser READ authorizedUser CONSTANT) Q_PROPERTY(bool authorizedUser READ authorizedUser CONSTANT)
public: public:
explicit ProvisioningBackend(QObject *parent = nullptr); explicit ProvisioningBackend(QString targetUser, QObject *parent = nullptr);
~ProvisioningBackend() override;
bool busy() const { return m_busy; } bool busy() const { return m_busy; }
bool passwordDone() const { return m_passwordDone; } bool passwordDone() const { return m_passwordDone; }
@@ -27,6 +29,13 @@ public:
QString targetUser() const { return m_targetUser; } QString targetUser() const { return m_targetUser; }
bool authorizedUser() const { return m_authorizedUser; } bool authorizedUser() const { return m_authorizedUser; }
QString stateDirectory() const;
QString diagnosticLogPath() const;
QString passwordMarker() const;
QString pinMarker() const;
static QString effectiveUserName();
Q_INVOKABLE void changePassword(const QString &currentPassword, Q_INVOKABLE void changePassword(const QString &currentPassword,
const QString &newPassword, const QString &newPassword,
const QString &confirmation); const QString &confirmation);
@@ -57,22 +66,23 @@ private:
void refreshState(); void refreshState();
bool ensureStateWritable(); bool ensureStateWritable();
bool createMarker(const QString &path); bool createMarker(const QString &path);
QString stateDirectory() const; void appendLog(const QString &message) const;
QString passwordMarker() const;
QString pinMarker() const;
QString safeMessageForFailure(Operation operation, QString safeMessageForFailure(Operation operation,
int exitCode, int exitCode,
const QByteArray &stderrData) const; const QByteArray &output,
bool timedOut) const;
static QString effectiveUserName();
static void secureClear(QByteArray &data); static void secureClear(QByteArray &data);
static QString operationName(Operation operation);
bool m_busy = false; bool m_busy = false;
bool m_passwordDone = false; bool m_passwordDone = false;
bool m_pinDone = false; bool m_pinDone = false;
bool m_authorizedUser = false; bool m_authorizedUser = false;
bool m_helperTimedOut = false;
QString m_currentUser; QString m_currentUser;
QString m_targetUser; QString m_targetUser;
QProcess *m_process = nullptr; QProcess *m_process = nullptr;
Operation m_operation = Operation::Password; QByteArray m_pendingPayload;
}; };