From a828a0f3a94af3a252dfd5f32616df7b2abadf12 Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Tue, 28 Oct 2025 21:33:37 +0800 Subject: [PATCH 1/3] refactor: enhance disk encryption credential transmission security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed disk encryption D-Bus methods to use file descriptors instead of direct variant maps for credential transmission Added secure pipe-based credential transmission mechanism between client and service Implemented QDataStream serialization for reliable credential data transfer Ensured immediate pipe closure after use to minimize credential exposure Modified DBus interface definitions to reflect new credential transmission method The changes improve security by ensuring sensitive credentials like passphrases are transmitted securely over D-Bus through file descriptors rather than potentially exposed in memory via QVariantMap. This reduces the risk of credential sniffing attacks during transmission. Influence: 1. Test all disk encryption operations (encrypt/decrypt/change passphrase) 2. Verify credentials are properly transmitted and received 3. Check error handling when pipes fail 4. Test with multiple simultaneous encryption operations 5. Verify compatibility with existing encrypted disks refactor: 增强磁盘加密凭证传输安全性 1. 修改磁盘加密D-Bus方法,使用文件描述符而非直接传输variant map来传递 凭证 2. 添加基于管道的安全凭证传输机制 3. 实现QDataStream序列化确保可靠的凭证数据传输 4. 确保使用后立即关闭管道最小化凭证暴露风险 5. 修改DBus接口定义以反映新的凭证传输方式 这些改动通过文件描述符安全传输敏感凭证而非使用QVariantMap内存传输,降低 了传输过程中凭证被窃取的风险。 Influence: 1. 测试所有磁盘加密操作(加密/解密/修改密码) 2. 验证凭证是否正确传输和接收 3. 检查管道失败时的错误处理 4. 测试多个并发加密操作 5. 验证与现有加密磁盘的兼容性 --- .../org.deepin.Filemanager.DiskEncrypt.xml | 9 +- .../menu/diskencryptmenuscene.cpp | 115 ++++++++++++++++-- .../diskencrypt/dbus/diskencryptsetup.cpp | 109 ++++++++++++++--- .../diskencrypt/dbus/diskencryptsetup.h | 7 +- .../diskencrypt/dbus/diskencryptsetup_p.h | 5 + 5 files changed, 206 insertions(+), 39 deletions(-) diff --git a/assets/dbus/org.deepin.Filemanager.DiskEncrypt.xml b/assets/dbus/org.deepin.Filemanager.DiskEncrypt.xml index b8558aaa66..540dbdc2de 100644 --- a/assets/dbus/org.deepin.Filemanager.DiskEncrypt.xml +++ b/assets/dbus/org.deepin.Filemanager.DiskEncrypt.xml @@ -43,17 +43,14 @@ - - + - - + - - + diff --git a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp index 7b2f025951..f21cd97d47 100644 --- a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp +++ b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp @@ -26,11 +26,14 @@ #include #include #include +#include +#include #include #include #include +#include DFMBASE_USE_NAMESPACE using namespace dfmplugin_diskenc; @@ -396,20 +399,48 @@ void DiskEncryptMenuScene::doReencryptDevice(const DeviceEncryptParam ¶m) kDaemonBusIface, QDBusConnection::systemBus()); if (iface.isValid()) { + // Create anonymous pipe for secure credential transmission + int pipefd[2]; + if (pipe(pipefd) == -1) { + fmCritical() << "Failed to create anonymous pipe for credentials"; + return; + } + + // Prepare credentials data using QDataStream for reliable serialization + QByteArray credentials; + QDataStream stream(&credentials, QIODevice::WriteOnly); QVariantMap params { { encrypt_param_keys::kKeyDevice, param.devDesc }, { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) }, { encrypt_param_keys::kKeyExportToPath, param.exportPath }, }; if (!tpmToken.isEmpty()) params.insert(encrypt_param_keys::kKeyTPMToken, tpmToken); + stream << params; - fmDebug() << "Starting device re-encryption"; - QDBusReply ret = iface.call("SetupAuthArgs", params); - if (ret.value()) { - QApplication::setOverrideCursor(Qt::WaitCursor); - } else { - fmCritical() << "Re-encryption setup failed"; + // Write credentials to pipe and close write end immediately + ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); + close(pipefd[1]); // Close write end immediately after writing + + if (written != credentials.size()) { + fmCritical() << "Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); + close(pipefd[0]); + return; + } + + // Create file descriptor for D-Bus transmission + QDBusUnixFileDescriptor fd(pipefd[0]); + if (!fd.isValid()) { + fmCritical() << "Failed to create valid file descriptor from pipe"; + close(pipefd[0]); + return; } + + fmDebug() << "Starting device re-encryption via fd"; + iface.asyncCall("SetupAuthArgs", QVariant::fromValue(fd)); + QApplication::setOverrideCursor(Qt::WaitCursor); + + // Close read end (D-Bus service will have its own copy) + close(pipefd[0]); } else { fmCritical() << "Failed to create D-Bus interface for re-encryption"; } @@ -422,21 +453,53 @@ void DiskEncryptMenuScene::doDecryptDevice(const DeviceEncryptParam ¶m) kDaemonBusIface, QDBusConnection::systemBus()); if (iface.isValid()) { + // Create anonymous pipe for secure credential transmission + int pipefd[2]; + if (pipe(pipefd) == -1) { + fmCritical() << "Failed to create anonymous pipe for credentials"; + return; + } + + // Prepare credentials data using QDataStream for reliable serialization + QByteArray credentials; + QDataStream stream(&credentials, QIODevice::WriteOnly); QVariantMap params { { encrypt_param_keys::kKeyJobType, param.jobType }, { encrypt_param_keys::kKeyDevice, param.devDesc }, { encrypt_param_keys::kKeyDeviceName, param.deviceDisplayName }, { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) } }; + stream << params; - fmDebug() << "Calling Decryption D-Bus method"; - QDBusReply ret = iface.call("Decryption", params); + // Write credentials to pipe and close write end immediately + ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); + close(pipefd[1]); // Close write end immediately after writing + + if (written != credentials.size()) { + fmCritical() << "Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); + close(pipefd[0]); + return; + } + + // Create file descriptor for D-Bus transmission + QDBusUnixFileDescriptor fd(pipefd[0]); + if (!fd.isValid()) { + fmCritical() << "Failed to create valid file descriptor from pipe"; + close(pipefd[0]); + return; + } + + fmDebug() << "Calling Decryption D-Bus method via fd"; + QDBusReply ret = iface.call("Decryption", QVariant::fromValue(fd)); if (ret.value()) { QApplication::setOverrideCursor(Qt::WaitCursor); } else { fmCritical() << "Decryption failed to start"; } + // Close read end (D-Bus service will have its own copy) + close(pipefd[0]); + EventsHandler::instance()->autoStartDFM(); } else { fmCritical() << "Failed to create D-Bus interface for decryption"; @@ -474,6 +537,16 @@ void DiskEncryptMenuScene::doChangePassphrase(const DeviceEncryptParam ¶m) kDaemonBusIface, QDBusConnection::systemBus()); if (iface.isValid()) { + // Create anonymous pipe for secure credential transmission + int pipefd[2]; + if (pipe(pipefd) == -1) { + fmCritical() << "Failed to create anonymous pipe for credentials"; + return; + } + + // Prepare credentials data using QDataStream for reliable serialization + QByteArray credentials; + QDataStream stream(&credentials, QIODevice::WriteOnly); QVariantMap params { { encrypt_param_keys::kKeyDevice, param.devDesc }, { encrypt_param_keys::kKeyPassphrase, toBase64(param.newKey) }, @@ -482,14 +555,36 @@ void DiskEncryptMenuScene::doChangePassphrase(const DeviceEncryptParam ¶m) { encrypt_param_keys::kKeyTPMToken, token }, { encrypt_param_keys::kKeyDeviceName, param.deviceDisplayName } }; + stream << params; - fmDebug() << "Calling ChangePassphrase D-Bus method"; - QDBusReply ret = iface.call("ChangePassphrase", params); + // Write credentials to pipe and close write end immediately + ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); + close(pipefd[1]); // Close write end immediately after writing + + if (written != credentials.size()) { + fmCritical() << "Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); + close(pipefd[0]); + return; + } + + // Create file descriptor for D-Bus transmission + QDBusUnixFileDescriptor fd(pipefd[0]); + if (!fd.isValid()) { + fmCritical() << "Failed to create valid file descriptor from pipe"; + close(pipefd[0]); + return; + } + + fmDebug() << "Calling ChangePassphrase D-Bus method via fd"; + QDBusReply ret = iface.call("ChangePassphrase", QVariant::fromValue(fd)); if (ret.value()) { QApplication::setOverrideCursor(Qt::WaitCursor); } else { fmCritical() << "Passphrase change failed to start"; } + + // Close read end (D-Bus service will have its own copy) + close(pipefd[0]); } else { fmCritical() << "Failed to create D-Bus interface for passphrase change"; } diff --git a/src/services/diskencrypt/dbus/diskencryptsetup.cpp b/src/services/diskencrypt/dbus/diskencryptsetup.cpp index 36b8dabac4..9290ea101a 100644 --- a/src/services/diskencrypt/dbus/diskencryptsetup.cpp +++ b/src/services/diskencrypt/dbus/diskencryptsetup.cpp @@ -17,9 +17,12 @@ #include #include +#include #include +#include + static constexpr char kActionEncrypt[] { "org.deepin.Filemanager.DiskEncrypt.Encrypt" }; static constexpr char kActionDecrypt[] { "org.deepin.Filemanager.DiskEncrypt.Decrypt" }; static constexpr char kActionChgPwd[] { "org.deepin.Filemanager.DiskEncrypt.ChangePassphrase" }; @@ -47,7 +50,7 @@ DiskEncryptSetup::DiskEncryptSetup(QObject *parent) bool DiskEncryptSetup::InitEncryption(const QVariantMap &args) { qInfo() << "[DiskEncryptSetup::InitEncryption] Encryption initialization request received"; - + if (m_dptr->jobRunning) { qWarning() << "[DiskEncryptSetup::InitEncryption] Job already running, cannot create new job"; return false; @@ -65,13 +68,13 @@ bool DiskEncryptSetup::InitEncryption(const QVariantMap &args) auto type = args.value(disk_encrypt::encrypt_param_keys::kKeyJobType).toString(); qInfo() << "[DiskEncryptSetup::InitEncryption] Creating encryption worker for job type:" << type; - + auto worker = m_dptr->createInitWorker(type, args); if (!worker) { qCritical() << "[DiskEncryptSetup::InitEncryption] Failed to create encryption worker for type:" << type; return false; } - + m_dptr->initThreadConnection(worker); connect(worker, &QThread::finished, m_dptr, &DiskEncryptSetupPrivate::onInitEncryptFinished); @@ -83,7 +86,7 @@ bool DiskEncryptSetup::InitEncryption(const QVariantMap &args) bool DiskEncryptSetup::ResumeEncryption(const QVariantMap &args) { qInfo() << "[DiskEncryptSetup::ResumeEncryption] Encryption resume request received"; - + if (m_dptr->jobRunning) { qWarning() << "[DiskEncryptSetup::ResumeEncryption] Job already running, cannot resume encryption"; return false; @@ -93,16 +96,16 @@ bool DiskEncryptSetup::ResumeEncryption(const QVariantMap &args) qCritical() << "[DiskEncryptSetup::ResumeEncryption] Invalid resume arguments provided:" << args; return false; } - + qInfo() << "[DiskEncryptSetup::ResumeEncryption] Resuming encryption with validated arguments"; m_dptr->resumeEncryption(args); return true; } -bool DiskEncryptSetup::Decryption(const QVariantMap &args) +bool DiskEncryptSetup::Decryption(const QDBusUnixFileDescriptor &credentialsFd) { - qInfo() << "[DiskEncryptSetup::Decryption] Decryption request received"; - + qInfo() << "[DiskEncryptSetup::Decryption] Decryption request received via fd"; + if (m_dptr->jobRunning) { qWarning() << "[DiskEncryptSetup::Decryption] Job already running, cannot start decryption"; return false; @@ -113,6 +116,13 @@ bool DiskEncryptSetup::Decryption(const QVariantMap &args) return false; } + // Parse credentials from fd using common method + QVariantMap args; + if (!m_dptr->parseCredentialsFromFd(credentialsFd, &args)) { + qCritical() << "[DiskEncryptSetup::Decryption] Failed to parse credentials from fd"; + return false; + } + if (!m_dptr->validateDecryptArgs(args)) { qCritical() << "[DiskEncryptSetup::Decryption] Invalid decryption arguments provided:" << args; return false; @@ -120,13 +130,13 @@ bool DiskEncryptSetup::Decryption(const QVariantMap &args) auto type = args.value(disk_encrypt::encrypt_param_keys::kKeyJobType).toString(); qInfo() << "[DiskEncryptSetup::Decryption] Creating decryption worker for job type:" << type; - + auto worker = m_dptr->createDecryptWorker(type, args); if (!worker) { qCritical() << "[DiskEncryptSetup::Decryption] Failed to create decryption worker for type:" << type; return false; } - + m_dptr->initThreadConnection(worker); connect(worker, &QThread::finished, m_dptr, &DiskEncryptSetupPrivate::onDecryptFinished); @@ -135,15 +145,22 @@ bool DiskEncryptSetup::Decryption(const QVariantMap &args) return true; } -bool DiskEncryptSetup::ChangePassphrase(const QVariantMap &args) +bool DiskEncryptSetup::ChangePassphrase(const QDBusUnixFileDescriptor &credentialsFd) { - qInfo() << "[DiskEncryptSetup::ChangePassphrase] Passphrase change request received"; - + qInfo() << "[DiskEncryptSetup::ChangePassphrase] Passphrase change request received via fd"; + if (!m_dptr->checkAuth(kActionChgPwd)) { qWarning() << "[DiskEncryptSetup::ChangePassphrase] Authentication failed for passphrase change action"; return false; } + // Parse credentials from fd using common method + QVariantMap args; + if (!m_dptr->parseCredentialsFromFd(credentialsFd, &args)) { + qCritical() << "[DiskEncryptSetup::ChangePassphrase] Failed to parse credentials from fd"; + return false; + } + if (!m_dptr->validateChgPwdArgs(args)) { qCritical() << "[DiskEncryptSetup::ChangePassphrase] Invalid passphrase change arguments provided:" << args; return false; @@ -158,9 +175,18 @@ bool DiskEncryptSetup::ChangePassphrase(const QVariantMap &args) return true; } -void DiskEncryptSetup::SetupAuthArgs(const QVariantMap &args) +void DiskEncryptSetup::SetupAuthArgs(const QDBusUnixFileDescriptor &credentialsFd) { - qInfo() << "[DiskEncryptSetup::SetupAuthArgs] Setting up authentication arguments"; + qInfo() << "[DiskEncryptSetup::SetupAuthArgs] Setting up authentication arguments via fd"; + + // Parse credentials from fd using common method + QVariantMap args; + if (!m_dptr->parseCredentialsFromFd(credentialsFd, &args)) { + qCritical() << "[DiskEncryptSetup::SetupAuthArgs] Failed to parse credentials from fd"; + return; + } + + qInfo() << "[DiskEncryptSetup::SetupAuthArgs] Successfully parsed authentication arguments from fd"; Q_EMIT NotificationHelper::instance()->replyAuthArgs(args); } @@ -173,7 +199,7 @@ void DiskEncryptSetup::IgnoreAuthSetup() QString DiskEncryptSetup::TpmToken(const QString &dev) { qInfo() << "[DiskEncryptSetup::TpmToken] Retrieving TPM token for device:" << dev; - + QString token; crypt_setup_helper::getToken(dev, &token); if (token.isEmpty()) { @@ -186,14 +212,14 @@ QString DiskEncryptSetup::TpmToken(const QString &dev) } else { qInfo() << "[DiskEncryptSetup::TpmToken] TPM token found for device:" << dev; } - + return token; } int DiskEncryptSetup::DeviceStatus(const QString &dev) { qInfo() << "[DiskEncryptSetup::DeviceStatus] Checking encryption status for device:" << dev; - + // check status of device itself. auto status = crypt_setup_helper::encryptStatus(dev); if (status != disk_encrypt::kStatusNotEncrypted) { @@ -231,7 +257,7 @@ bool DiskEncryptSetup::IsTaskRunning() QString DiskEncryptSetup::PendingDecryptionDevice() { qInfo() << "[DiskEncryptSetup::PendingDecryptionDevice] Checking for pending decryption devices"; - + QDir d(kUSecBootRoot); auto files = d.entryList(QDir::AllEntries | QDir::NoDotAndDotDot); for (auto f : files) { @@ -247,7 +273,8 @@ QString DiskEncryptSetup::PendingDecryptionDevice() DiskEncryptSetupPrivate::DiskEncryptSetupPrivate(DiskEncryptSetup *parent) : QObject(parent), - qptr(parent) { + qptr(parent) +{ qInfo() << "[DiskEncryptSetupPrivate] Initializing private implementation"; } @@ -377,6 +404,48 @@ BaseEncryptWorker *DiskEncryptSetupPrivate::createDecryptWorker(const QString &t return nullptr; } +bool DiskEncryptSetupPrivate::parseCredentialsFromFd(const QDBusUnixFileDescriptor &credentialsFd, QVariantMap *args) +{ + Q_ASSERT(args); + // Validate file descriptor + if (!credentialsFd.isValid()) { + qWarning() << "[DiskEncryptSetupPrivate::parseCredentialsFromFd] Invalid file descriptor provided"; + return false; + } + + int fd = credentialsFd.fileDescriptor(); + if (fd < 0) { + qWarning() << "[DiskEncryptSetupPrivate::parseCredentialsFromFd] Invalid file descriptor value:" << fd; + return false; + } + + // Read all data from pipe into buffer + QByteArray buffer; + char readBuffer[1024]; + ssize_t bytesRead; + + while ((bytesRead = read(fd, readBuffer, sizeof(readBuffer))) > 0) { + buffer.append(readBuffer, bytesRead); + } + + if (buffer.isEmpty()) { + qWarning() << "[DiskEncryptSetupPrivate::parseCredentialsFromFd] No data received from pipe"; + return false; + } + + // Parse credentials using QDataStream + QDataStream stream(&buffer, QIODevice::ReadOnly); + stream >> *args; + + if (stream.status() != QDataStream::Ok) { + qWarning() << "[DiskEncryptSetupPrivate::parseCredentialsFromFd] Failed to parse credentials from pipe data, stream status:" << stream.status(); + return false; + } + + qInfo() << "[DiskEncryptSetupPrivate::parseCredentialsFromFd] Successfully parsed credentials from fd"; + return true; +} + void DiskEncryptSetupPrivate::initThreadConnection(const QThread *thread) { connect(thread, &QThread::started, this, &DiskEncryptSetupPrivate::onLongTimeJobStarted); diff --git a/src/services/diskencrypt/dbus/diskencryptsetup.h b/src/services/diskencrypt/dbus/diskencryptsetup.h index 23c5a181d3..e5760a9b6c 100644 --- a/src/services/diskencrypt/dbus/diskencryptsetup.h +++ b/src/services/diskencrypt/dbus/diskencryptsetup.h @@ -7,6 +7,7 @@ #include #include +#include #include @@ -24,9 +25,9 @@ class DiskEncryptSetup : public QDBusService, public QDBusContext public Q_SLOTS: bool InitEncryption(const QVariantMap &args); bool ResumeEncryption(const QVariantMap &args); - bool Decryption(const QVariantMap &args); - bool ChangePassphrase(const QVariantMap &args); - void SetupAuthArgs(const QVariantMap &args); + bool Decryption(const QDBusUnixFileDescriptor &credentialsFd); + bool ChangePassphrase(const QDBusUnixFileDescriptor &credentialsFd); + void SetupAuthArgs(const QDBusUnixFileDescriptor &credentialsFd); void IgnoreAuthSetup(); QString TpmToken(const QString &dev); diff --git a/src/services/diskencrypt/dbus/diskencryptsetup_p.h b/src/services/diskencrypt/dbus/diskencryptsetup_p.h index f9513dc327..0660050272 100644 --- a/src/services/diskencrypt/dbus/diskencryptsetup_p.h +++ b/src/services/diskencrypt/dbus/diskencryptsetup_p.h @@ -8,6 +8,8 @@ #include "workers/baseencryptworker.h" #include +#include +#include class DiskEncryptSetup; class DiskEncryptSetupPrivate : public QObject @@ -26,6 +28,9 @@ class DiskEncryptSetupPrivate : public QObject bool validateDecryptArgs(const QVariantMap &args); bool validateChgPwdArgs(const QVariantMap &args); + // Parse credentials from file descriptor + bool parseCredentialsFromFd(const QDBusUnixFileDescriptor &credentialsFd, QVariantMap *args); + QString resolveDeviceByDetachHeaderName(const QString &fileName); FILE_ENCRYPT_NS::BaseEncryptWorker *createInitWorker(const QString &type, const QVariantMap &args); From ab5b545391968fe94eebf77cfd501928e078085b Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Wed, 29 Oct 2025 10:29:18 +0800 Subject: [PATCH 2/3] refactor: improve credential transmission security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes refactor the credential transmission logic for disk encryption/decryption operations to use a common helper function. Previously each operation (re-encryption and decryption) had duplicate pipe creation and credential serialization code. Now this logic is centralized in sendCredentialsViaFd() which handles: 1. Pipe creation for secure credentials transfer 2. Credentials serialization using QDataStream 3. FD creation and cleanup 4. Synchronous/asynchronous D-Bus calls Benefits include: 1. Reduced code duplication 2. More consistent error handling 3. Improved log messages with method context 4. Proper pipe cleanup in all cases 5. Better separation of concerns Log: Improved security message when transmitting encryption credentials Influence: 1. Verify disk encryption still works with valid credentials 2. Test with invalid credentials to check error handling 3. Verify decryption works for encrypted devices 4. Check logs for credential transmission errors 5. Test cancellation during credential transmission refactor: 改进凭据传输安全性 该提交重构了磁盘加密/解密操作的凭据传输逻辑,改用通用辅助函数。之前每个 操作(重新加密和解密)都有重复的管道创建和凭据序列化代码。现在这些逻辑集 中在sendCredentialsViaFd()中,处理: 1. 用于安全凭据传输的管道创建 2. 使用QDataStream进行凭据序列化 3. 文件描述符创建和清理 4. 同步/异步D-Bus调用 优点包括: 1. 减少代码重复 2. 更一致的错误处理 3. 改进的带方法上下文的日志消息 4. 所有情况下正确的管道清理 5. 更好的关注点分离 Log: 改进传输加密凭据时的安全消息显示 Influence: 1. 验证使用有效凭据时磁盘加密仍能工作 2. 使用无效凭据测试错误处理 3. 验证对加密设备的解密功能 4. 检查凭据传输错误的日志 5. 测试凭据传输期间的取消操作 --- .../menu/diskencryptmenuscene.cpp | 168 ++++++++---------- .../menu/diskencryptmenuscene.h | 5 + 2 files changed, 84 insertions(+), 89 deletions(-) diff --git a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp index f21cd97d47..7a9fa7323a 100644 --- a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp +++ b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.cpp @@ -398,51 +398,24 @@ void DiskEncryptMenuScene::doReencryptDevice(const DeviceEncryptParam ¶m) kDaemonBusPath, kDaemonBusIface, QDBusConnection::systemBus()); - if (iface.isValid()) { - // Create anonymous pipe for secure credential transmission - int pipefd[2]; - if (pipe(pipefd) == -1) { - fmCritical() << "Failed to create anonymous pipe for credentials"; - return; - } - - // Prepare credentials data using QDataStream for reliable serialization - QByteArray credentials; - QDataStream stream(&credentials, QIODevice::WriteOnly); - QVariantMap params { - { encrypt_param_keys::kKeyDevice, param.devDesc }, - { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) }, - { encrypt_param_keys::kKeyExportToPath, param.exportPath }, - }; - if (!tpmToken.isEmpty()) params.insert(encrypt_param_keys::kKeyTPMToken, tpmToken); - stream << params; - - // Write credentials to pipe and close write end immediately - ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); - close(pipefd[1]); // Close write end immediately after writing - - if (written != credentials.size()) { - fmCritical() << "Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); - close(pipefd[0]); - return; - } + if (!iface.isValid()) { + fmCritical() << "Failed to create D-Bus interface for re-encryption"; + return; + } - // Create file descriptor for D-Bus transmission - QDBusUnixFileDescriptor fd(pipefd[0]); - if (!fd.isValid()) { - fmCritical() << "Failed to create valid file descriptor from pipe"; - close(pipefd[0]); - return; - } + // Prepare credentials data + QVariantMap params { + { encrypt_param_keys::kKeyDevice, param.devDesc }, + { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) }, + { encrypt_param_keys::kKeyExportToPath, param.exportPath }, + }; + if (!tpmToken.isEmpty()) + params.insert(encrypt_param_keys::kKeyTPMToken, tpmToken); - fmDebug() << "Starting device re-encryption via fd"; - iface.asyncCall("SetupAuthArgs", QVariant::fromValue(fd)); + // Send credentials via fd + fmDebug() << "Starting device re-encryption via fd"; + if (sendCredentialsViaFd(iface, "SetupAuthArgs", params, true)) { QApplication::setOverrideCursor(Qt::WaitCursor); - - // Close read end (D-Bus service will have its own copy) - close(pipefd[0]); - } else { - fmCritical() << "Failed to create D-Bus interface for re-encryption"; } } @@ -452,57 +425,26 @@ void DiskEncryptMenuScene::doDecryptDevice(const DeviceEncryptParam ¶m) kDaemonBusPath, kDaemonBusIface, QDBusConnection::systemBus()); - if (iface.isValid()) { - // Create anonymous pipe for secure credential transmission - int pipefd[2]; - if (pipe(pipefd) == -1) { - fmCritical() << "Failed to create anonymous pipe for credentials"; - return; - } - - // Prepare credentials data using QDataStream for reliable serialization - QByteArray credentials; - QDataStream stream(&credentials, QIODevice::WriteOnly); - QVariantMap params { - { encrypt_param_keys::kKeyJobType, param.jobType }, - { encrypt_param_keys::kKeyDevice, param.devDesc }, - { encrypt_param_keys::kKeyDeviceName, param.deviceDisplayName }, - { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) } - }; - stream << params; - - // Write credentials to pipe and close write end immediately - ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); - close(pipefd[1]); // Close write end immediately after writing - - if (written != credentials.size()) { - fmCritical() << "Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); - close(pipefd[0]); - return; - } - - // Create file descriptor for D-Bus transmission - QDBusUnixFileDescriptor fd(pipefd[0]); - if (!fd.isValid()) { - fmCritical() << "Failed to create valid file descriptor from pipe"; - close(pipefd[0]); - return; - } - - fmDebug() << "Calling Decryption D-Bus method via fd"; - QDBusReply ret = iface.call("Decryption", QVariant::fromValue(fd)); - if (ret.value()) { - QApplication::setOverrideCursor(Qt::WaitCursor); - } else { - fmCritical() << "Decryption failed to start"; - } + if (!iface.isValid()) { + fmCritical() << "Failed to create D-Bus interface for decryption"; + return; + } - // Close read end (D-Bus service will have its own copy) - close(pipefd[0]); + // Prepare credentials data + QVariantMap params { + { encrypt_param_keys::kKeyJobType, param.jobType }, + { encrypt_param_keys::kKeyDevice, param.devDesc }, + { encrypt_param_keys::kKeyDeviceName, param.deviceDisplayName }, + { encrypt_param_keys::kKeyPassphrase, toBase64(param.key) } + }; + // Send credentials via fd + fmDebug() << "Calling Decryption D-Bus method via fd"; + if (sendCredentialsViaFd(iface, "Decryption", params, false)) { + QApplication::setOverrideCursor(Qt::WaitCursor); EventsHandler::instance()->autoStartDFM(); } else { - fmCritical() << "Failed to create D-Bus interface for decryption"; + fmCritical() << "Decryption failed to start"; } } @@ -658,6 +600,54 @@ QString DiskEncryptMenuScene::getBase64Of(const QString &fileName) return QString(contents.toBase64()); } +bool DiskEncryptMenuScene::sendCredentialsViaFd(QDBusInterface &iface, const QString &method, + const QVariantMap ¶ms, bool asyncCall) +{ + // Create anonymous pipe for secure credential transmission + int pipefd[2]; + if (pipe(pipefd) == -1) { + fmCritical() << "[sendCredentialsViaFd] Failed to create anonymous pipe for credentials"; + return false; + } + + // Prepare credentials data using QDataStream for reliable serialization + QByteArray credentials; + QDataStream stream(&credentials, QIODevice::WriteOnly); + stream << params; + + // Write credentials to pipe and close write end immediately + ssize_t written = write(pipefd[1], credentials.constData(), credentials.size()); + close(pipefd[1]); // Close write end immediately after writing + + if (written != credentials.size()) { + fmCritical() << "[sendCredentialsViaFd] Failed to write credentials to pipe, written:" << written << "expected:" << credentials.size(); + close(pipefd[0]); + return false; + } + + // Create file descriptor for D-Bus transmission + QDBusUnixFileDescriptor fd(pipefd[0]); + if (!fd.isValid()) { + fmCritical() << "[sendCredentialsViaFd] Failed to create valid file descriptor from pipe"; + close(pipefd[0]); + return false; + } + + // Call D-Bus method with file descriptor + fmDebug() << "[sendCredentialsViaFd] Calling D-Bus method:" << method << "via fd"; + if (asyncCall) { + iface.asyncCall(method, QVariant::fromValue(fd)); + } else { + QDBusReply reply = iface.call(method, QVariant::fromValue(fd)); + close(pipefd[0]); + return reply.value(); + } + + // Close read end (D-Bus service will have its own copy) + close(pipefd[0]); + return true; +} + void DiskEncryptMenuScene::onUnlocked(bool ok, dfmmount::OperationErrorInfo info, QString clearDev) { QApplication::restoreOverrideCursor(); diff --git a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.h b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.h index 38a14a6eba..71f5e1d6a0 100644 --- a/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.h +++ b/src/plugins/filemanager/dfmplugin-disk-encrypt-entry/menu/diskencryptmenuscene.h @@ -13,6 +13,7 @@ #include #include +#include class QAction; @@ -60,6 +61,10 @@ class DiskEncryptMenuScene : public dfmbase::AbstractMenuScene static QString generateTPMToken(const QString &device, bool pin); static QString getBase64Of(const QString &fileName); + // Send credentials via file descriptor for secure D-Bus transmission + static bool sendCredentialsViaFd(QDBusInterface &iface, const QString &method, + const QVariantMap ¶ms, bool asyncCall = false); + static void onUnlocked(bool ok, dfmmount::OperationErrorInfo, QString); static void onMounted(bool ok, dfmmount::OperationErrorInfo, QString); From ad798633a5fb7f8fe2c165a306ad442c05201551 Mon Sep 17 00:00:00 2001 From: Zhang Sheng Date: Wed, 29 Oct 2025 10:54:59 +0800 Subject: [PATCH 3/3] refactor: migrate from pkla to polkit rules format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed disk encryption authentication from deprecated PKLA format to modern Polkit JavaScript rules format. Updated CMake installation configuration to install rules in new standard location (/usr/ share/polkit-1/rules.d) instead of old location (/etc/polkit-1/ localauthority/10-vendor.d). Removed old pkla file completely. This change was made because PKLA format has been deprecated in favor of JavaScript rules format which provides more flexibility and is the current standard for Polkit authentication rules. The new format follows modern Linux security practices and maintains better compatibility with newer Polkit versions. Influence: 1. Verify disk encryption functionality still works properly 2. Test authentication prompts appear/disappear as expected 3. Check system logs for any Polkit-related errors 4. Confirm rules file exists in correct location (/usr/share/polkit- 1/rules.d) 5. Test with different user permissions scenarios refactor: 从 pkla 迁移到 polkit 规则格式 将磁盘加密认证从已废弃的 PKLA 格式改为现代的 Polkit JavaScript 规则格 式。更新了 CMake 安装配置,将规则安装到新的标准位置(/usr/share/polkit-1/ rules.d)而非旧位置(/etc/polkit-1/localauthority/10-vendor.d)。完全移除了 旧的 pkla 文件。 进行此更改是因为 PKLA 格式已被废弃,转而支持 JavaScript 规则格式,后者提 供了更大的灵活性且是当前 Polkit 认证规则的标准。新格式遵循现代 Linux 安 全实践,并与较新的 Polkit 版本保持更好的兼容性。 Influence: 1. 验证磁盘加密功能仍正常工作 2. 测试认证提示是否按预期出现/消失 3. 检查系统日志是否有 Polkit 相关错误 4. 确认规则文件存在于正确位置(/usr/share/polkit-1/rules.d) 5. 使用不同用户权限场景进行测试 --- .../dde-file-manager-services-plugins.install | 2 +- src/services/diskencrypt/CMakeLists.txt | 8 ++++-- .../rules/99-dde-file-manager-encrypt.pkla | 13 ---------- .../rules/99-dde-file-manager-encrypt.rules | 26 +++++++++++++++++++ 4 files changed, 33 insertions(+), 16 deletions(-) delete mode 100644 src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.pkla create mode 100644 src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.rules diff --git a/debian/dde-file-manager-services-plugins.install b/debian/dde-file-manager-services-plugins.install index 75b27a000f..8cf1da26ef 100644 --- a/debian/dde-file-manager-services-plugins.install +++ b/debian/dde-file-manager-services-plugins.install @@ -7,5 +7,5 @@ usr/share/dbus-1/system-services/*.service usr/share/dbus-1/system.d/org.deepin.filemanager.diskencrypt.conf usr/share/dbus-1/services/org.deepin.Filemanager.TextIndex.service etc/systemd/system/deepin-service-group@.service.d/* -etc/polkit-1/localauthority/10-vendor.d/99-dde-file-manager-encrypt.pkla +usr/share/polkit-1/rules.d/99-dde-file-manager-encrypt.rules etc/udev/rules.d/*.rules diff --git a/src/services/diskencrypt/CMakeLists.txt b/src/services/diskencrypt/CMakeLists.txt index b340ec17b6..9cf063fa87 100644 --- a/src/services/diskencrypt/CMakeLists.txt +++ b/src/services/diskencrypt/CMakeLists.txt @@ -27,7 +27,11 @@ install(FILES org.deepin.Filemanager.DiskEncrypt.service DESTINATION share/dbus- install(FILES ${CMAKE_SOURCE_DIR}/assets/rules/99-dfm-encrypt.rules DESTINATION /etc/udev/rules.d) set(PolicyDir "${CMAKE_INSTALL_PREFIX}/share/polkit-1/actions") +set(RulesDir "${CMAKE_INSTALL_PREFIX}/share/polkit-1/rules.d") + install(FILES polkit/policy/org.deepin.filemanager.diskencrypt.policy DESTINATION ${PolicyDir}) -install(FILES polkit/rules/99-dde-file-manager-encrypt.pkla - DESTINATION /etc/polkit-1/localauthority/10-vendor.d) + +# Install polkit rules (JavaScript format, replaces deprecated .pkla) +install(FILES polkit/rules/99-dde-file-manager-encrypt.rules + DESTINATION ${RulesDir}) diff --git a/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.pkla b/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.pkla deleted file mode 100644 index b0abc0a06e..0000000000 --- a/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.pkla +++ /dev/null @@ -1,13 +0,0 @@ -[Skip auth when unlock system devices] -Identity=unix-group:* -Action=org.freedesktop.udisks2.encrypted-unlock-system -ResultAny=no -ResultInactive=no -ResultActive=yes - -[Skip auth when unlock devices] -Identity=unix-group:* -Action=org.freedesktop.udisks2.encrypted-unlock -ResultAny=no -ResultInactive=no -ResultActive=yes diff --git a/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.rules b/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.rules new file mode 100644 index 0000000000..1641696868 --- /dev/null +++ b/src/services/diskencrypt/polkit/rules/99-dde-file-manager-encrypt.rules @@ -0,0 +1,26 @@ +// Polkit rules for DDE File Manager disk encryption +// This file replaces the deprecated .pkla configuration +// +// Location: /etc/polkit-1/rules.d/99-dde-file-manager-encrypt.rules +// or /usr/share/polkit-1/rules.d/99-dde-file-manager-encrypt.rules +// +// Priority: 99 ensures these rules are evaluated late, allowing +// other rules to override if needed. + +// Skip authentication when unlocking system encrypted devices +polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.udisks2.encrypted-unlock-system" && + subject.isInGroup("*") && + subject.active) { + return polkit.Result.YES; + } +}); + +// Skip authentication when unlocking regular encrypted devices +polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.udisks2.encrypted-unlock" && + subject.isInGroup("*") && + subject.active) { + return polkit.Result.YES; + } +});