From 5161ade8c28ce934cfaef3f62bfe46cfd2ba8a3c Mon Sep 17 00:00:00 2001 From: zhangsheng Date: Fri, 28 Aug 2026 13:25:08 +0800 Subject: [PATCH] fix: include share name in SMB keyring credentials MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Root cause: DNetworkMounter's keyring credential management (savePasswd/loginPasswd/smbSchema) did not include share name, so loginPasswd searched by {server, protocol} only and returned all saved credentials for the same server regardless of share 2. Fix: add "object" attribute to smbSchema for share name, extract share from URL path in savePasswd and loginPasswd, include it in both store and search operations to isolate credentials per share 3. Impact: credentials are now stored and searched per-share; old credentials without "object" attribute won't be matched, users need to re-enter password once per share after upgrade 4. 方案层级: 根因层修复(5-Why 在 Why 4 收敛,根因层与症状层一致) Log: fix SMB share only authenticating once across different users Influence: 1. Test accessing non-anonymous shares of different users on the same server, second share should prompt for authentication 2. Test re-accessing a saved share, credential should auto-fill 3. Test anonymous share access is unaffected 4. Test FTP/WebDAV mounting is unaffected fix: SMB共享凭证加入share name属性隔离 1. 根因:DNetworkMounter 的 keyring 凭证管理(savePasswd/loginPasswd/ smbSchema)未包含 share name 属性,loginPasswd 仅按 {server, protocol} 搜索,返回同一服务器所有共享的已保存凭证 2. 方案:在 smbSchema 中新增 "object" 属性用于 share name, savePasswd 和 loginPasswd 从 URL 提取 share name 并在存储和 查询时附带,实现凭证按共享级别隔离 3. 影响:凭证按共享级别存储和搜索,旧凭证不含 "object" 属性 无法命中,升级后用户需对每个已保存共享重新输入一次密码 4. 方案层级:根因层修复(5-Why 在 Why 4 收敛,根因层与症状层一致) Log: 修复访问不同用户不同密码的SMB共享时仅鉴权一次的问题 Influence: 1. 测试同一服务器不同用户的非匿名共享,访问第二个共享应弹出鉴权窗口 2. 测试重复访问已保存的共享,凭证应自动填充无需再次输入 3. 测试匿名共享访问不受影响 4. 测试 FTP/WebDAV 挂载不受影响 PMS: BUG-375291 --- src/dfm-mount/private/dnetworkmounter.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dfm-mount/private/dnetworkmounter.cpp b/src/dfm-mount/private/dnetworkmounter.cpp index 6ad2fca7..610a9df1 100644 --- a/src/dfm-mount/private/dnetworkmounter.cpp +++ b/src/dfm-mount/private/dnetworkmounter.cpp @@ -43,6 +43,7 @@ static constexpr char kSchemaUser[] { "user" }; static constexpr char kSchemaProtocol[] { "protocol" }; static constexpr char kSchemaDomain[] { "domain" }; static constexpr char kSchemaServer[] { "server" }; +static constexpr char kSchemaObject[] { "object" }; static constexpr char kLoginUser[] { "user" }; static constexpr char kLoginDomain[] { "domain" }; @@ -114,10 +115,12 @@ QList DNetworkMounter::loginPasswd(const QString &address) QUrl u(address); QString protocol = u.scheme(); QString host = u.host(); + QString share = u.path().remove("/"); GHashTable_autoptr query = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert(query, strdup(kSchemaServer), strdup(host.toStdString().c_str())); g_hash_table_insert(query, strdup(kSchemaProtocol), strdup(protocol.toStdString().c_str())); + g_hash_table_insert(query, strdup(kSchemaObject), strdup(share.toStdString().c_str())); QList passwds; GError_autoptr err { nullptr }; @@ -164,10 +167,11 @@ QList DNetworkMounter::loginPasswd(const QString &address) std::string domain = passwd.value(kSchemaDomain).toString().toStdString(); GError_autoptr err { nullptr }; + std::string object = passwd.value(kSchemaObject).toString().toStdString(); g_autofree char *pwd = secret_password_lookup_sync( smbSchema(), nullptr, &err, kSchemaServer, server.c_str(), kSchemaProtocol, protocol.c_str(), kSchemaUser, user.c_str(), kSchemaDomain, domain.c_str(), - nullptr); + kSchemaObject, object.c_str(), nullptr); if (err) qDebug() << "query password failed: " << passwd << err->message; else { @@ -182,6 +186,7 @@ void DNetworkMounter::savePasswd(const QString &address, const MountPassInfo &in QUrl u(address); QString protocol = u.scheme(); QString server = u.host(); + QString share = u.path().remove("/"); const char *collection = info.savePasswd == NetworkMountPasswdSaveMode::kSaveBeforeLogout ? SECRET_COLLECTION_SESSION : SECRET_COLLECTION_DEFAULT; @@ -196,7 +201,8 @@ void DNetworkMounter::savePasswd(const QString &address, const MountPassInfo &in info.domain.toStdString().c_str(), kSchemaProtocol, protocol.toStdString().c_str(), kSchemaServer, server.toStdString().c_str(), kSchemaUser, - info.userName.toStdString().c_str(), nullptr); + info.userName.toStdString().c_str(), kSchemaObject, + share.toStdString().c_str(), nullptr); if (err) qWarning() << "save passwd failed: " << err->message; } @@ -211,6 +217,7 @@ SecretSchema *DNetworkMounter::smbSchema() sche.attributes[1] = { kSchemaDomain, SECRET_SCHEMA_ATTRIBUTE_STRING }; sche.attributes[2] = { kSchemaServer, SECRET_SCHEMA_ATTRIBUTE_STRING }; sche.attributes[3] = { kSchemaProtocol, SECRET_SCHEMA_ATTRIBUTE_STRING }; + sche.attributes[4] = { kSchemaObject, SECRET_SCHEMA_ATTRIBUTE_STRING }; return &sche; }