Téléverser les fichiers vers "workstation-setup/src"
This commit is contained in:
+428
-1049
File diff suppressed because it is too large
Load Diff
@@ -17,17 +17,20 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int kHelperTimeoutMs = 60000;
|
constexpr int kHelperTimeoutMs = 120000;
|
||||||
|
|
||||||
bool containsLineBreak(const QString &value)
|
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()
|
QString effectiveHomeDirectory()
|
||||||
{
|
{
|
||||||
if (passwd *entry = getpwuid(geteuid())) {
|
if (passwd *entry = getpwuid(geteuid())) {
|
||||||
return QString::fromLocal8Bit(entry->pw_dir);
|
const QString home = QString::fromLocal8Bit(entry->pw_dir);
|
||||||
|
if (!home.isEmpty() && home != QStringLiteral("/")) {
|
||||||
|
return home;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return QDir::homePath();
|
return QDir::homePath();
|
||||||
}
|
}
|
||||||
@@ -39,12 +42,13 @@ ProvisioningBackend::ProvisioningBackend(QString targetUser, QObject *parent)
|
|||||||
, m_targetUser(std::move(targetUser))
|
, m_targetUser(std::move(targetUser))
|
||||||
{
|
{
|
||||||
refreshState();
|
refreshState();
|
||||||
appendLog(QStringLiteral("START currentUser=%1 targetUser=%2 authorized=%3 passwordDone=%4 pinDone=%5")
|
appendLog(QStringLiteral("START currentUser=%1 targetUser=%2 authorized=%3 passwordDone=%4 pinDone=%5 fidoDone=%6")
|
||||||
.arg(m_currentUser,
|
.arg(m_currentUser,
|
||||||
m_targetUser,
|
m_targetUser,
|
||||||
authorizedUser() ? QStringLiteral("yes") : QStringLiteral("no"),
|
authorizedUser() ? QStringLiteral("yes") : QStringLiteral("no"),
|
||||||
m_passwordDone ? QStringLiteral("yes") : QStringLiteral("no"),
|
m_passwordDone ? QStringLiteral("yes") : QStringLiteral("no"),
|
||||||
m_pinDone ? QStringLiteral("yes") : QStringLiteral("no")));
|
m_pinDone ? QStringLiteral("yes") : QStringLiteral("no"),
|
||||||
|
m_fidoDone ? QStringLiteral("yes") : QStringLiteral("no")));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProvisioningBackend::~ProvisioningBackend()
|
ProvisioningBackend::~ProvisioningBackend()
|
||||||
@@ -58,25 +62,22 @@ ProvisioningBackend::~ProvisioningBackend()
|
|||||||
|
|
||||||
QString ProvisioningBackend::effectiveUserName()
|
QString ProvisioningBackend::effectiveUserName()
|
||||||
{
|
{
|
||||||
const uid_t uid = geteuid();
|
if (passwd *entry = getpwuid(geteuid())) {
|
||||||
if (passwd *entry = getpwuid(uid)) {
|
|
||||||
return QString::fromLocal8Bit(entry->pw_name);
|
return QString::fromLocal8Bit(entry->pw_name);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ProvisioningBackend::authorizedUser() const
|
bool ProvisioningBackend::authorizedUser() const
|
||||||
{
|
{
|
||||||
if (m_targetUser.isEmpty()) {
|
if (m_targetUser.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray targetName = m_targetUser.toLocal8Bit();
|
const QByteArray name = m_targetUser.toLocal8Bit();
|
||||||
if (passwd *entry = getpwnam(targetName.constData())) {
|
if (passwd *entry = getpwnam(name.constData())) {
|
||||||
return entry->pw_uid == geteuid();
|
return entry->pw_uid == geteuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,8 +90,7 @@ QString ProvisioningBackend::stateDirectory() const
|
|||||||
return QDir::cleanPath(candidate + QStringLiteral("/nixos-workstations"));
|
return QDir::cleanPath(candidate + QStringLiteral("/nixos-workstations"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return QDir::cleanPath(effectiveHomeDirectory()
|
||||||
return QDir::cleanPath(homeDirectoryForEffectiveUser()
|
|
||||||
+ QStringLiteral("/.local/state/nixos-workstations"));
|
+ QStringLiteral("/.local/state/nixos-workstations"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,15 +109,22 @@ QString ProvisioningBackend::pinMarker() const
|
|||||||
return stateDirectory() + QStringLiteral("/yubikey-pin-created");
|
return stateDirectory() + QStringLiteral("/yubikey-pin-created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ProvisioningBackend::fidoMarker() const
|
||||||
|
{
|
||||||
|
return stateDirectory() + QStringLiteral("/yubikey-fido-enrolled");
|
||||||
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::refreshState()
|
void ProvisioningBackend::refreshState()
|
||||||
{
|
{
|
||||||
const bool oldPassword = m_passwordDone;
|
const bool oldPassword = m_passwordDone;
|
||||||
const bool oldPin = m_pinDone;
|
const bool oldPin = m_pinDone;
|
||||||
|
const bool oldFido = m_fidoDone;
|
||||||
|
|
||||||
m_passwordDone = QFileInfo::exists(passwordMarker());
|
m_passwordDone = QFileInfo::exists(passwordMarker());
|
||||||
m_pinDone = QFileInfo::exists(pinMarker());
|
m_pinDone = QFileInfo::exists(pinMarker());
|
||||||
|
m_fidoDone = QFileInfo::exists(fidoMarker());
|
||||||
|
|
||||||
if (oldPassword != m_passwordDone || oldPin != m_pinDone) {
|
if (oldPassword != m_passwordDone || oldPin != m_pinDone || oldFido != m_fidoDone) {
|
||||||
emit stateChanged();
|
emit stateChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,11 +146,10 @@ bool ProvisioningBackend::ensureStateWritable()
|
|||||||
if (!probe.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
if (!probe.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const bool ok = probe.write("ok\n") == 3;
|
||||||
const bool writeOk = probe.write("ok\n") == 3;
|
|
||||||
probe.close();
|
probe.close();
|
||||||
probe.remove();
|
probe.remove();
|
||||||
return writeOk;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProvisioningBackend::createMarker(const QString &path)
|
bool ProvisioningBackend::createMarker(const QString &path)
|
||||||
@@ -157,8 +163,7 @@ bool ProvisioningBackend::createMarker(const QString &path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray content =
|
const QByteArray content = QByteArrayLiteral("completed=")
|
||||||
QByteArrayLiteral("completed=")
|
|
||||||
+ QDateTime::currentDateTimeUtc().toString(Qt::ISODate).toUtf8()
|
+ QDateTime::currentDateTimeUtc().toString(Qt::ISODate).toUtf8()
|
||||||
+ '\n';
|
+ '\n';
|
||||||
|
|
||||||
@@ -166,14 +171,12 @@ bool ProvisioningBackend::createMarker(const QString &path)
|
|||||||
marker.cancelWriting();
|
marker.cancelWriting();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!marker.commit()) {
|
if (!marker.commit()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QFile::setPermissions(path,
|
return QFile::setPermissions(path,
|
||||||
QFileDevice::ReadOwner
|
QFileDevice::ReadOwner | QFileDevice::WriteOwner);
|
||||||
| QFileDevice::WriteOwner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::appendLog(const QString &message) const
|
void ProvisioningBackend::appendLog(const QString &message) const
|
||||||
@@ -182,7 +185,6 @@ void ProvisioningBackend::appendLog(const QString &message) const
|
|||||||
if (!QDir().mkpath(dir)) {
|
if (!QDir().mkpath(dir)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile::setPermissions(dir,
|
QFile::setPermissions(dir,
|
||||||
QFileDevice::ReadOwner
|
QFileDevice::ReadOwner
|
||||||
| QFileDevice::WriteOwner
|
| QFileDevice::WriteOwner
|
||||||
@@ -193,17 +195,13 @@ void ProvisioningBackend::appendLog(const QString &message) const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray line =
|
log.write(QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs).toUtf8()
|
||||||
QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs).toUtf8()
|
+ QByteArrayLiteral(" ")
|
||||||
+ QByteArrayLiteral(" ")
|
+ message.toUtf8()
|
||||||
+ message.toUtf8()
|
+ '\n');
|
||||||
+ '\n';
|
|
||||||
|
|
||||||
log.write(line);
|
|
||||||
log.close();
|
log.close();
|
||||||
QFile::setPermissions(diagnosticLogPath(),
|
QFile::setPermissions(diagnosticLogPath(),
|
||||||
QFileDevice::ReadOwner
|
QFileDevice::ReadOwner | QFileDevice::WriteOwner);
|
||||||
| QFileDevice::WriteOwner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::setBusy(bool busy)
|
void ProvisioningBackend::setBusy(bool busy)
|
||||||
@@ -229,9 +227,30 @@ void ProvisioningBackend::secureClear(QByteArray &data)
|
|||||||
|
|
||||||
QString ProvisioningBackend::operationName(Operation operation)
|
QString ProvisioningBackend::operationName(Operation operation)
|
||||||
{
|
{
|
||||||
return operation == Operation::Password
|
switch (operation) {
|
||||||
? QStringLiteral("PASSWORD")
|
case Operation::Password:
|
||||||
: QStringLiteral("PIN");
|
return QStringLiteral("PASSWORD");
|
||||||
|
case Operation::Pin:
|
||||||
|
return QStringLiteral("PIN");
|
||||||
|
case Operation::Fido:
|
||||||
|
return QStringLiteral("FIDO");
|
||||||
|
}
|
||||||
|
return QStringLiteral("UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProvisioningBackend::emitResult(Operation operation, bool success, const QString &message)
|
||||||
|
{
|
||||||
|
switch (operation) {
|
||||||
|
case Operation::Password:
|
||||||
|
emit passwordChangeFinished(success, message);
|
||||||
|
break;
|
||||||
|
case Operation::Pin:
|
||||||
|
emit pinChangeFinished(success, message);
|
||||||
|
break;
|
||||||
|
case Operation::Fido:
|
||||||
|
emit fidoEnrollmentFinished(success, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::changePassword(const QString ¤tPassword,
|
void ProvisioningBackend::changePassword(const QString ¤tPassword,
|
||||||
@@ -239,47 +258,31 @@ void ProvisioningBackend::changePassword(const QString ¤tPassword,
|
|||||||
const QString &confirmation)
|
const QString &confirmation)
|
||||||
{
|
{
|
||||||
if (!authorizedUser()) {
|
if (!authorizedUser()) {
|
||||||
appendLog(QStringLiteral("PASSWORD refused: unauthorized user"));
|
emit passwordChangeFinished(false, QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
|
||||||
emit passwordChangeFinished(false,
|
|
||||||
QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_busy) {
|
if (m_busy) {
|
||||||
emit passwordChangeFinished(false,
|
emit passwordChangeFinished(false, QStringLiteral("Une opération de configuration est déjà en cours."));
|
||||||
QStringLiteral("Une opération de configuration est déjà en cours."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_passwordDone) {
|
if (m_passwordDone) {
|
||||||
emit passwordChangeFinished(true,
|
emit passwordChangeFinished(true, QStringLiteral("Le mot de passe a déjà été personnalisé."));
|
||||||
QStringLiteral("Le mot de passe a déjà été personnalisé."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPassword.isEmpty() || newPassword.isEmpty() || confirmation.isEmpty()) {
|
if (currentPassword.isEmpty() || newPassword.isEmpty() || confirmation.isEmpty()) {
|
||||||
emit passwordChangeFinished(false,
|
emit passwordChangeFinished(false, QStringLiteral("Tous les champs du mot de passe doivent être renseignés."));
|
||||||
QStringLiteral("Tous les champs du mot de passe doivent être renseignés."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPassword != confirmation) {
|
if (newPassword != confirmation) {
|
||||||
emit passwordChangeFinished(false,
|
emit passwordChangeFinished(false, QStringLiteral("Les deux nouveaux mots de passe ne correspondent pas."));
|
||||||
QStringLiteral("Les deux nouveaux mots de passe ne correspondent pas."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (containsLineBreak(currentPassword) || containsLineBreak(newPassword) || containsLineBreak(confirmation)) {
|
||||||
if (containsLineBreak(currentPassword) || containsLineBreak(newPassword)
|
emit passwordChangeFinished(false, QStringLiteral("Le mot de passe contient un caractère non pris en charge."));
|
||||||
|| containsLineBreak(confirmation)) {
|
|
||||||
emit passwordChangeFinished(false,
|
|
||||||
QStringLiteral("Le mot de passe contient un caractère non pris en charge."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ensureStateWritable()) {
|
if (!ensureStateWritable()) {
|
||||||
appendLog(QStringLiteral("PASSWORD refused: state directory is not writable"));
|
emit passwordChangeFinished(false, QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil."));
|
||||||
emit passwordChangeFinished(false,
|
|
||||||
QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,65 +294,75 @@ void ProvisioningBackend::changePassword(const QString ¤tPassword,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::initializePin(const QString &newPin,
|
void ProvisioningBackend::initializePin(const QString &newPin,
|
||||||
const QString &confirmation)
|
const QString &confirmation)
|
||||||
{
|
{
|
||||||
if (!authorizedUser()) {
|
if (!authorizedUser()) {
|
||||||
appendLog(QStringLiteral("PIN refused: unauthorized user"));
|
emit pinChangeFinished(false, QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
|
||||||
emit pinChangeFinished(false,
|
|
||||||
QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_busy) {
|
if (m_busy) {
|
||||||
emit pinChangeFinished(false,
|
emit pinChangeFinished(false, QStringLiteral("Une opération de configuration est déjà en cours."));
|
||||||
QStringLiteral("Une opération de configuration est déjà en cours."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_passwordDone) {
|
if (!m_passwordDone) {
|
||||||
emit pinChangeFinished(false,
|
emit pinChangeFinished(false, QStringLiteral("Personnalisez d'abord votre mot de passe."));
|
||||||
QStringLiteral("Le mot de passe doit être personnalisé avant d'initialiser la YubiKey."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pinDone) {
|
if (m_pinDone) {
|
||||||
emit pinChangeFinished(true,
|
emit pinChangeFinished(true, QStringLiteral("Le PIN FIDO2 a déjà été initialisé."));
|
||||||
QStringLiteral("Le PIN FIDO2 de la YubiKey a déjà été initialisé."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPin.size() < 4 || confirmation.size() < 4) {
|
if (newPin.size() < 4 || confirmation.size() < 4) {
|
||||||
emit pinChangeFinished(false,
|
emit pinChangeFinished(false, QStringLiteral("Le PIN doit contenir au moins 4 caractères."));
|
||||||
QStringLiteral("Le PIN doit contenir au moins 4 caractères."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPin != confirmation) {
|
if (newPin != confirmation) {
|
||||||
emit pinChangeFinished(false,
|
emit pinChangeFinished(false, QStringLiteral("Les deux PIN ne correspondent pas."));
|
||||||
QStringLiteral("Les deux PIN ne correspondent pas."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containsLineBreak(newPin) || containsLineBreak(confirmation)) {
|
if (containsLineBreak(newPin) || containsLineBreak(confirmation)) {
|
||||||
emit pinChangeFinished(false,
|
emit pinChangeFinished(false, QStringLiteral("Le PIN contient un caractère non pris en charge."));
|
||||||
QStringLiteral("Le PIN contient un caractère non pris en charge."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ensureStateWritable()) {
|
|
||||||
appendLog(QStringLiteral("PIN refused: state directory is not writable"));
|
|
||||||
emit pinChangeFinished(false,
|
|
||||||
QStringLiteral("Impossible d'enregistrer l'état de configuration dans votre profil. Contactez le service informatique."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Le helper Étape 1 lit uniquement les deux premières lignes :
|
|
||||||
// nouveau PIN puis confirmation. Aucun ancien PIN n'est transmis.
|
|
||||||
startHelper(Operation::Pin,
|
startHelper(Operation::Pin,
|
||||||
QString::fromUtf8(NIXOS_WORKSTATIONS_PIN_HELPER_PATH),
|
QString::fromUtf8(NIXOS_WORKSTATIONS_PIN_HELPER_PATH),
|
||||||
newPin,
|
newPin,
|
||||||
confirmation,
|
confirmation);
|
||||||
QString());
|
}
|
||||||
|
|
||||||
|
void ProvisioningBackend::enrollFido(const QString ¤tPassword,
|
||||||
|
const QString &pin)
|
||||||
|
{
|
||||||
|
if (!authorizedUser()) {
|
||||||
|
emit fidoEnrollmentFinished(false, QStringLiteral("Cette opération n'est pas autorisée pour cet utilisateur."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_busy) {
|
||||||
|
emit fidoEnrollmentFinished(false, QStringLiteral("Une opération de configuration est déjà en cours."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_passwordDone || !m_pinDone) {
|
||||||
|
emit fidoEnrollmentFinished(false, QStringLiteral("Le mot de passe et le PIN doivent être configurés avant l'association FIDO2."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_fidoDone) {
|
||||||
|
emit fidoEnrollmentFinished(true, QStringLiteral("La YubiKey est déjà associée au home chiffré."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentPassword.isEmpty() || pin.size() < 4) {
|
||||||
|
emit fidoEnrollmentFinished(false, QStringLiteral("Saisissez votre mot de passe actuel et le PIN de la YubiKey."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (containsLineBreak(currentPassword) || containsLineBreak(pin)) {
|
||||||
|
emit fidoEnrollmentFinished(false, QStringLiteral("Un des secrets contient un caractère non pris en charge."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
startHelper(Operation::Fido,
|
||||||
|
QString::fromUtf8(NIXOS_WORKSTATIONS_FIDO_HELPER_PATH),
|
||||||
|
currentPassword,
|
||||||
|
pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProvisioningBackend::startHelper(Operation operation,
|
void ProvisioningBackend::startHelper(Operation operation,
|
||||||
@@ -360,14 +373,8 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
{
|
{
|
||||||
const QFileInfo helperInfo(helperPath);
|
const QFileInfo helperInfo(helperPath);
|
||||||
if (!helperInfo.exists() || !helperInfo.isFile() || !helperInfo.isExecutable()) {
|
if (!helperInfo.exists() || !helperInfo.isFile() || !helperInfo.isExecutable()) {
|
||||||
appendLog(operationName(operation)
|
appendLog(operationName(operation) + QStringLiteral(" failed: helper unavailable"));
|
||||||
+ QStringLiteral(" failed: helper missing or not executable"));
|
emitResult(operation, false, QStringLiteral("Le composant système requis est introuvable ou inutilisable."));
|
||||||
const QString message = QStringLiteral("Le composant système requis est introuvable ou inutilisable.");
|
|
||||||
if (operation == Operation::Password) {
|
|
||||||
emit passwordChangeFinished(false, message);
|
|
||||||
} else {
|
|
||||||
emit pinChangeFinished(false, message);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,17 +403,16 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
process->setProgram(helperPath);
|
process->setProgram(helperPath);
|
||||||
process->setProcessChannelMode(QProcess::SeparateChannels);
|
process->setProcessChannelMode(QProcess::SeparateChannels);
|
||||||
|
|
||||||
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
environment.insert(QStringLiteral("LC_ALL"), QStringLiteral("C"));
|
env.insert(QStringLiteral("LC_ALL"), QStringLiteral("C"));
|
||||||
environment.insert(QStringLiteral("LANG"), QStringLiteral("C"));
|
env.insert(QStringLiteral("LANG"), QStringLiteral("C"));
|
||||||
process->setProcessEnvironment(environment);
|
process->setProcessEnvironment(env);
|
||||||
|
|
||||||
auto *timeout = new QTimer(process);
|
auto *timer = new QTimer(process);
|
||||||
timeout->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
timeout->setInterval(kHelperTimeoutMs);
|
timer->setInterval(kHelperTimeoutMs);
|
||||||
|
|
||||||
connect(timeout, &QTimer::timeout, process,
|
connect(timer, &QTimer::timeout, process, [this, process, operation]() {
|
||||||
[this, process, operation]() {
|
|
||||||
if (m_process != process || process->state() == QProcess::NotRunning) {
|
if (m_process != process || process->state() == QProcess::NotRunning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -415,125 +421,101 @@ void ProvisioningBackend::startHelper(Operation operation,
|
|||||||
process->kill();
|
process->kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(process, &QProcess::started, this,
|
connect(process, &QProcess::started, this, [this, process, timer, operation]() {
|
||||||
[this, process, timeout, operation]() {
|
|
||||||
if (m_process != process) {
|
if (m_process != process) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
process->write(m_pendingPayload);
|
||||||
const qint64 expected = m_pendingPayload.size();
|
|
||||||
const qint64 written = process->write(m_pendingPayload);
|
|
||||||
process->closeWriteChannel();
|
process->closeWriteChannel();
|
||||||
secureClear(m_pendingPayload);
|
secureClear(m_pendingPayload);
|
||||||
|
|
||||||
if (written != expected) {
|
|
||||||
appendLog(operationName(operation)
|
|
||||||
+ QStringLiteral(" warning: incomplete helper input write"));
|
|
||||||
}
|
|
||||||
|
|
||||||
appendLog(operationName(operation) + QStringLiteral(" helper started"));
|
appendLog(operationName(operation) + QStringLiteral(" helper started"));
|
||||||
timeout->start();
|
timer->start();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(process, &QProcess::errorOccurred, this,
|
connect(process, &QProcess::errorOccurred, this,
|
||||||
[this, process, timeout, operation](QProcess::ProcessError error) {
|
[this, process, timer, operation](QProcess::ProcessError error) {
|
||||||
if (m_process != process || error != QProcess::FailedToStart) {
|
if (m_process != process || error != QProcess::FailedToStart) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
timer->stop();
|
||||||
timeout->stop();
|
|
||||||
secureClear(m_pendingPayload);
|
secureClear(m_pendingPayload);
|
||||||
appendLog(operationName(operation)
|
|
||||||
+ QStringLiteral(" failed to start: ")
|
|
||||||
+ process->errorString());
|
|
||||||
|
|
||||||
m_process = nullptr;
|
m_process = nullptr;
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
|
appendLog(operationName(operation) + QStringLiteral(" failed to start"));
|
||||||
const QString message = QStringLiteral("Impossible de démarrer le composant de configuration.");
|
emitResult(operation, false, QStringLiteral("Impossible de démarrer le composant de configuration."));
|
||||||
if (operation == Operation::Password) {
|
|
||||||
emit passwordChangeFinished(false, message);
|
|
||||||
} else {
|
|
||||||
emit pinChangeFinished(false, message);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(process,
|
connect(process,
|
||||||
qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
|
qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
|
||||||
this,
|
this,
|
||||||
[this, process, timeout, operation](int exitCode, QProcess::ExitStatus exitStatus) {
|
[this, process, timer, operation](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||||
if (m_process != process) {
|
if (m_process != process) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout->stop();
|
timer->stop();
|
||||||
secureClear(m_pendingPayload);
|
secureClear(m_pendingPayload);
|
||||||
|
|
||||||
QByteArray stderrData = process->readAllStandardError();
|
QByteArray stderrData = process->readAllStandardError();
|
||||||
QByteArray stdoutData = process->readAllStandardOutput();
|
QByteArray stdoutData = process->readAllStandardOutput();
|
||||||
QByteArray combinedOutput;
|
QByteArray combined = stderrData + '\n' + stdoutData;
|
||||||
combinedOutput.reserve(stderrData.size() + stdoutData.size() + 1);
|
|
||||||
combinedOutput += stderrData;
|
|
||||||
combinedOutput += '\n';
|
|
||||||
combinedOutput += stdoutData;
|
|
||||||
|
|
||||||
const bool timedOut = m_helperTimedOut;
|
const bool timedOut = m_helperTimedOut;
|
||||||
const bool helperSucceeded = !timedOut
|
const bool helperSucceeded = !timedOut
|
||||||
&& exitStatus == QProcess::NormalExit
|
&& exitStatus == QProcess::NormalExit
|
||||||
&& exitCode == 0;
|
&& exitCode == 0;
|
||||||
|
|
||||||
QString message;
|
|
||||||
bool markerCreated = false;
|
bool markerCreated = false;
|
||||||
|
QString message;
|
||||||
|
|
||||||
if (helperSucceeded) {
|
if (helperSucceeded) {
|
||||||
if (operation == Operation::Password) {
|
switch (operation) {
|
||||||
|
case Operation::Password:
|
||||||
markerCreated = createMarker(passwordMarker());
|
markerCreated = createMarker(passwordMarker());
|
||||||
message = markerCreated
|
message = markerCreated
|
||||||
? QStringLiteral("Votre mot de passe personnel est maintenant actif.")
|
? QStringLiteral("Votre nouveau mot de passe protège maintenant votre home chiffré.")
|
||||||
: QStringLiteral("Le mot de passe a été modifié, mais l'état local n'a pas pu être enregistré. Contactez le service informatique avant de fermer la session.");
|
: QStringLiteral("Le mot de passe a été modifié mais l'état local n'a pas pu être enregistré.");
|
||||||
} else {
|
break;
|
||||||
|
case Operation::Pin:
|
||||||
markerCreated = createMarker(pinMarker());
|
markerCreated = createMarker(pinMarker());
|
||||||
message = markerCreated
|
message = markerCreated
|
||||||
? QStringLiteral("Le PIN FIDO2 de votre YubiKey est maintenant initialisé.")
|
? QStringLiteral("Le PIN FIDO2 de votre YubiKey est maintenant initialisé.")
|
||||||
: QStringLiteral("Le PIN a été initialisé, mais l'état local n'a pas pu être enregistré. Contactez le service informatique avant de fermer la session.");
|
: QStringLiteral("Le PIN a été créé mais l'état local n'a pas pu être enregistré.");
|
||||||
|
break;
|
||||||
|
case Operation::Fido:
|
||||||
|
markerCreated = createMarker(fidoMarker());
|
||||||
|
message = markerCreated
|
||||||
|
? QStringLiteral("Votre YubiKey peut maintenant déverrouiller votre home chiffré.")
|
||||||
|
: QStringLiteral("La YubiKey a été enrôlée mais l'état local n'a pas pu être enregistré.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message = safeMessageForFailure(operation, exitCode, combinedOutput, timedOut);
|
message = safeMessageForFailure(operation, exitCode, combined, timedOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString helperToken = QString::fromUtf8(combinedOutput).trimmed();
|
QString token = QString::fromUtf8(combined).trimmed();
|
||||||
helperToken.remove(QRegularExpression(QStringLiteral("[^A-Za-z0-9_\\-]")));
|
token.remove(QRegularExpression(QStringLiteral("[^A-Za-z0-9_\\-]")));
|
||||||
if (helperToken.size() > 80) {
|
if (token.size() > 80) token.truncate(80);
|
||||||
helperToken.truncate(80);
|
if (token.isEmpty()) token = QStringLiteral("none");
|
||||||
}
|
|
||||||
if (helperToken.isEmpty()) {
|
|
||||||
helperToken = QStringLiteral("none");
|
|
||||||
}
|
|
||||||
|
|
||||||
appendLog(operationName(operation)
|
appendLog(operationName(operation)
|
||||||
+ QStringLiteral(" helper finished exitCode=%1 normalExit=%2 timeout=%3 marker=%4 token=%5")
|
+ QStringLiteral(" helper finished exitCode=%1 timeout=%2 marker=%3 token=%4")
|
||||||
.arg(exitCode)
|
.arg(exitCode)
|
||||||
.arg(exitStatus == QProcess::NormalExit ? QStringLiteral("yes") : QStringLiteral("no"))
|
|
||||||
.arg(timedOut ? QStringLiteral("yes") : QStringLiteral("no"))
|
.arg(timedOut ? QStringLiteral("yes") : QStringLiteral("no"))
|
||||||
.arg(markerCreated ? QStringLiteral("yes") : QStringLiteral("no"))
|
.arg(markerCreated ? QStringLiteral("yes") : QStringLiteral("no"))
|
||||||
.arg(helperToken));
|
.arg(token));
|
||||||
|
|
||||||
secureClear(stderrData);
|
secureClear(stderrData);
|
||||||
secureClear(stdoutData);
|
secureClear(stdoutData);
|
||||||
secureClear(combinedOutput);
|
secureClear(combined);
|
||||||
|
|
||||||
m_process = nullptr;
|
m_process = nullptr;
|
||||||
process->deleteLater();
|
process->deleteLater();
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
refreshState();
|
refreshState();
|
||||||
|
|
||||||
const bool completed = helperSucceeded && markerCreated;
|
emitResult(operation, helperSucceeded && markerCreated, message);
|
||||||
if (operation == Operation::Password) {
|
|
||||||
emit passwordChangeFinished(completed, message);
|
|
||||||
} else {
|
|
||||||
emit pinChangeFinished(completed, message);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
process->start();
|
process->start();
|
||||||
@@ -547,70 +529,58 @@ QString ProvisioningBackend::safeMessageForFailure(Operation operation,
|
|||||||
const QString output = QString::fromUtf8(outputData).toLower();
|
const QString output = QString::fromUtf8(outputData).toLower();
|
||||||
|
|
||||||
if (timedOut || exitCode == 124 || output.contains(QStringLiteral("timeout"))) {
|
if (timedOut || exitCode == 124 || output.contains(QStringLiteral("timeout"))) {
|
||||||
if (operation == Operation::Password) {
|
if (operation == Operation::Fido) {
|
||||||
if (output.contains(QStringLiteral("timeout_current_prompt"))) {
|
return QStringLiteral("L'association FIDO2 a expiré. Laissez la YubiKey branchée et touchez-la lorsqu'elle clignote.");
|
||||||
return QStringLiteral("Le système n'a pas présenté l'invite d'authentification du mot de passe actuel.");
|
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("timeout_new_prompt"))) {
|
|
||||||
return QStringLiteral("Le mot de passe actuel a été envoyé, mais le système n'a pas demandé le nouveau mot de passe.");
|
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("timeout_confirm_prompt"))) {
|
|
||||||
return QStringLiteral("Le nouveau mot de passe a été envoyé, mais le système n'a pas demandé sa confirmation.");
|
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("timeout_finish"))) {
|
|
||||||
return QStringLiteral("Le système a reçu les mots de passe mais n'a pas terminé l'opération.");
|
|
||||||
}
|
|
||||||
return QStringLiteral("Le changement de mot de passe a expiré avant la fin de l'opération.");
|
|
||||||
}
|
}
|
||||||
return QStringLiteral("L'opération YubiKey a expiré. Vérifiez que la clé est connectée puis réessayez.");
|
return QStringLiteral("L'opération a expiré avant de pouvoir être terminée.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == Operation::Password) {
|
if (operation == Operation::Password) {
|
||||||
if (output.contains(QStringLiteral("current_rejected"))
|
if (output.contains(QStringLiteral("current_rejected"))) {
|
||||||
|| output.contains(QStringLiteral("current_prompt_missing"))
|
return QStringLiteral("Le mot de passe temporaire actuel est incorrect.");
|
||||||
|| output.contains(QStringLiteral("current_reprompt"))) {
|
|
||||||
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 nouveau mot de passe a été refusé par la politique de sécurité.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("input_error"))) {
|
return QStringLiteral("Le mot de passe n'a pas pu être modifié par systemd-homed.");
|
||||||
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.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.contains(QStringLiteral("pin_already_configured"))) {
|
if (operation == Operation::Pin) {
|
||||||
return QStringLiteral("Cette YubiKey possède déjà un PIN FIDO2. Pour l’étape 1, utilisez une clé vierge ou réinitialisée ; aucune tentative de PIN n’a été effectuée.");
|
if (output.contains(QStringLiteral("pin_already_configured"))) {
|
||||||
|
return QStringLiteral("Cette YubiKey possède déjà un PIN FIDO2. Utilisez une YubiKey vierge ou réinitialisée.");
|
||||||
|
}
|
||||||
|
if (output.contains(QStringLiteral("pin_auth_blocked"))) {
|
||||||
|
return QStringLiteral("Les opérations PIN sont temporairement bloquées. Débranchez puis rebranchez la YubiKey.");
|
||||||
|
}
|
||||||
|
if (output.contains(QStringLiteral("pin_blocked"))) {
|
||||||
|
return QStringLiteral("Le PIN FIDO2 est bloqué. La YubiKey doit être réinitialisée avant provisioning.");
|
||||||
|
}
|
||||||
|
if (output.contains(QStringLiteral("multiple_yubikey"))) {
|
||||||
|
return QStringLiteral("Plusieurs clés FIDO2 sont détectées. Ne laissez branchée que la YubiKey d'Alice.");
|
||||||
|
}
|
||||||
|
if (output.contains(QStringLiteral("no_yubikey"))) {
|
||||||
|
return QStringLiteral("Aucune YubiKey FIDO2 compatible n'a été détectée.");
|
||||||
|
}
|
||||||
|
if (output.contains(QStringLiteral("pin_policy"))) {
|
||||||
|
return QStringLiteral("Le PIN choisi ne respecte pas la politique FIDO2 de la YubiKey.");
|
||||||
|
}
|
||||||
|
return QStringLiteral("Le PIN FIDO2 n'a pas pu être initialisé.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("pin_auth_blocked"))) {
|
|
||||||
return QStringLiteral("Les opérations PIN sont temporairement bloquées. Débranchez puis rebranchez la YubiKey avant toute nouvelle opération.");
|
if (output.contains(QStringLiteral("fido_bad_password"))) {
|
||||||
|
return QStringLiteral("Le mot de passe personnel fourni est incorrect ou insuffisant pour mettre à jour le home.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("pin_blocked"))) {
|
if (output.contains(QStringLiteral("fido_bad_pin"))) {
|
||||||
return QStringLiteral("Le PIN FIDO2 de la YubiKey est bloqué. Cette clé n’est pas vierge et ne peut pas être initialisée par l’étape 1.");
|
return QStringLiteral("Le PIN de la YubiKey est incorrect. Ne réessayez pas plusieurs fois : vérifiez le PIN avant une nouvelle tentative.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("multiple_yubikey"))) {
|
if (output.contains(QStringLiteral("multiple_yubikey"))) {
|
||||||
return QStringLiteral("Plusieurs clés FIDO2 sont détectées. Ne laissez branchée que la YubiKey à initialiser puis réessayez.");
|
return QStringLiteral("Plusieurs clés FIDO2 sont détectées. Ne laissez branchée que la YubiKey d'Alice.");
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("no_fido2"))) {
|
|
||||||
return QStringLiteral("La clé détectée ne fournit pas l’interface FIDO2 nécessaire.");
|
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("no_yubikey"))) {
|
if (output.contains(QStringLiteral("no_yubikey"))) {
|
||||||
return QStringLiteral("Aucune YubiKey FIDO2 compatible n’a été détectée ou le système n’a pas les droits d’accès nécessaires.");
|
return QStringLiteral("Aucune YubiKey FIDO2 compatible n'a été détectée.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("pin_policy"))) {
|
if (output.contains(QStringLiteral("fido_enroll_failed"))) {
|
||||||
return QStringLiteral("Le PIN choisi ne respecte pas la politique FIDO2 de cette YubiKey.");
|
return QStringLiteral("La YubiKey n'a pas pu être associée au home. Vérifiez le mot de passe, le PIN et touchez la clé lorsqu'elle clignote.");
|
||||||
}
|
}
|
||||||
if (output.contains(QStringLiteral("pin_state_not_updated"))
|
return QStringLiteral("L'association FIDO2 au home chiffré a échoué.");
|
||||||
|| output.contains(QStringLiteral("pin_state_error"))) {
|
|
||||||
return QStringLiteral("La commande FIDO2 a été envoyée, mais l’état PIN retourné par la clé est incohérent. Ne réessayez pas avant vérification avec ykman fido info.");
|
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("input_error"))) {
|
|
||||||
return QStringLiteral("Le composant d’initialisation de la YubiKey n’a pas reçu les données attendues.");
|
|
||||||
}
|
|
||||||
if (output.contains(QStringLiteral("pin_helper_error"))) {
|
|
||||||
return QStringLiteral("Le composant FIDO2 a rencontré une erreur interne sans pouvoir confirmer l’initialisation du PIN.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return QStringLiteral("Le PIN FIDO2 n’a pas pu être initialisé. Vérifiez que la YubiKey est vierge, connectée et compatible FIDO2.");
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class ProvisioningBackend final : public QObject
|
|||||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||||
Q_PROPERTY(bool passwordDone READ passwordDone NOTIFY stateChanged)
|
Q_PROPERTY(bool passwordDone READ passwordDone NOTIFY stateChanged)
|
||||||
Q_PROPERTY(bool pinDone READ pinDone NOTIFY stateChanged)
|
Q_PROPERTY(bool pinDone READ pinDone NOTIFY stateChanged)
|
||||||
|
Q_PROPERTY(bool fidoDone READ fidoDone NOTIFY stateChanged)
|
||||||
Q_PROPERTY(bool complete READ complete NOTIFY stateChanged)
|
Q_PROPERTY(bool complete READ complete NOTIFY stateChanged)
|
||||||
Q_PROPERTY(QString currentUser READ currentUser CONSTANT)
|
Q_PROPERTY(QString currentUser READ currentUser CONSTANT)
|
||||||
Q_PROPERTY(QString targetUser READ targetUser CONSTANT)
|
Q_PROPERTY(QString targetUser READ targetUser CONSTANT)
|
||||||
@@ -24,60 +25,66 @@ public:
|
|||||||
bool busy() const { return m_busy; }
|
bool busy() const { return m_busy; }
|
||||||
bool passwordDone() const { return m_passwordDone; }
|
bool passwordDone() const { return m_passwordDone; }
|
||||||
bool pinDone() const { return m_pinDone; }
|
bool pinDone() const { return m_pinDone; }
|
||||||
bool complete() const { return m_passwordDone && m_pinDone; }
|
bool fidoDone() const { return m_fidoDone; }
|
||||||
|
bool complete() const { return m_passwordDone && m_pinDone && m_fidoDone; }
|
||||||
QString currentUser() const { return m_currentUser; }
|
QString currentUser() const { return m_currentUser; }
|
||||||
QString targetUser() const { return m_targetUser; }
|
QString targetUser() const { return m_targetUser; }
|
||||||
bool authorizedUser() const;
|
bool authorizedUser() const;
|
||||||
|
|
||||||
QString stateDirectory() const;
|
|
||||||
QString diagnosticLogPath() const;
|
|
||||||
QString passwordMarker() const;
|
|
||||||
QString pinMarker() const;
|
|
||||||
|
|
||||||
static QString effectiveUserName();
|
|
||||||
|
|
||||||
Q_INVOKABLE void changePassword(const QString ¤tPassword,
|
Q_INVOKABLE void changePassword(const QString ¤tPassword,
|
||||||
const QString &newPassword,
|
const QString &newPassword,
|
||||||
const QString &confirmation);
|
const QString &confirmation);
|
||||||
|
|
||||||
Q_INVOKABLE void initializePin(const QString &newPin,
|
Q_INVOKABLE void initializePin(const QString &newPin,
|
||||||
const QString &confirmation);
|
const QString &confirmation);
|
||||||
|
Q_INVOKABLE void enrollFido(const QString ¤tPassword,
|
||||||
|
const QString &pin);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void busyChanged();
|
void busyChanged();
|
||||||
void stateChanged();
|
void stateChanged();
|
||||||
void passwordChangeFinished(bool success, const QString &message);
|
void passwordChangeFinished(bool success, const QString &message);
|
||||||
void pinChangeFinished(bool success, const QString &message);
|
void pinChangeFinished(bool success, const QString &message);
|
||||||
|
void fidoEnrollmentFinished(bool success, const QString &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Operation {
|
enum class Operation {
|
||||||
Password,
|
Password,
|
||||||
Pin
|
Pin,
|
||||||
|
Fido
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QString stateDirectory() const;
|
||||||
|
QString diagnosticLogPath() const;
|
||||||
|
QString passwordMarker() const;
|
||||||
|
QString pinMarker() const;
|
||||||
|
QString fidoMarker() const;
|
||||||
|
|
||||||
|
static QString effectiveUserName();
|
||||||
|
static void secureClear(QByteArray &data);
|
||||||
|
static QString operationName(Operation operation);
|
||||||
|
|
||||||
|
void refreshState();
|
||||||
|
bool ensureStateWritable();
|
||||||
|
bool createMarker(const QString &path);
|
||||||
|
void appendLog(const QString &message) const;
|
||||||
|
void setBusy(bool busy);
|
||||||
|
|
||||||
void startHelper(Operation operation,
|
void startHelper(Operation operation,
|
||||||
const QString &helperPath,
|
const QString &helperPath,
|
||||||
const QString &firstSecret,
|
const QString &firstSecret,
|
||||||
const QString &secondSecret,
|
const QString &secondSecret,
|
||||||
const QString &thirdSecret);
|
const QString &thirdSecret = {});
|
||||||
|
|
||||||
void setBusy(bool busy);
|
|
||||||
void refreshState();
|
|
||||||
bool ensureStateWritable();
|
|
||||||
bool createMarker(const QString &path);
|
|
||||||
void appendLog(const QString &message) const;
|
|
||||||
|
|
||||||
|
void emitResult(Operation operation, bool success, const QString &message);
|
||||||
QString safeMessageForFailure(Operation operation,
|
QString safeMessageForFailure(Operation operation,
|
||||||
int exitCode,
|
int exitCode,
|
||||||
const QByteArray &output,
|
const QByteArray &output,
|
||||||
bool timedOut) const;
|
bool timedOut) const;
|
||||||
|
|
||||||
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_fidoDone = false;
|
||||||
bool m_helperTimedOut = false;
|
bool m_helperTimedOut = false;
|
||||||
QString m_currentUser;
|
QString m_currentUser;
|
||||||
QString m_targetUser;
|
QString m_targetUser;
|
||||||
|
|||||||
Reference in New Issue
Block a user