mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 14:20:58 +00:00
Stop Logged-Out Login Polling from Hitting the System Keychain (#15979)
With stealth mode off the home page asks for the login status every 2 s, and while nobody is logged in that ends in clear_user_secret(), which opened the system keychain and deleted the OrcaSlicer/Auth entry on the UI thread every tick. A working keychain cost a D-Bus round trip per tick; a keychain that never answers blocked the UI for 25 s per tick. It also deleted a login another running instance had just saved, and ignored use_encrypted_token_file, so opting out of the keychain did not help. Remember whether this process read a secret from the store or wrote one, and only then touch the store when a logged-out poll asks for a logout. A logged-out instance never touches the keychain, and in encrypted-file mode the poll no longer opens the keychain at all. A secret this process cannot read, such as a token file encrypted for another OS user sharing the data directory, is left alone by the poll. An explicit logout still wipes both backends, so a token stranded by switching the token storage option cannot sign the account back in later.
This commit is contained in:
@@ -819,7 +819,9 @@ int OrcaCloudServiceAgent::user_logout(bool request)
|
||||
}
|
||||
}
|
||||
|
||||
clear_session();
|
||||
// An explicit logout also wipes the backend the token storage option is not using, so a token
|
||||
// stranded by switching that option cannot sign the account back in later.
|
||||
clear_session(/*all_backends=*/request);
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1604,7 +1606,9 @@ void OrcaCloudServiceAgent::persist_user_secret(const std::string& secret)
|
||||
}
|
||||
}
|
||||
|
||||
(void) stored;
|
||||
if (stored) {
|
||||
secret_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool OrcaCloudServiceAgent::load_user_secret(std::string& out_secret)
|
||||
@@ -1644,6 +1648,7 @@ bool OrcaCloudServiceAgent::load_user_secret(std::string& out_secret)
|
||||
}
|
||||
|
||||
if (integrity_ok && aes256gcm_decrypt(encoded_payload, key, plain) && !plain.empty()) {
|
||||
secret_stored = true;
|
||||
out_secret = plain;
|
||||
// Upgrade legacy payloads to signed format
|
||||
if (payload.rfind("v2:", 0) != 0) {
|
||||
@@ -1661,6 +1666,7 @@ bool OrcaCloudServiceAgent::load_user_secret(std::string& out_secret)
|
||||
if (store.Load(SECRET_STORE_SERVICE, username, secret) && secret.IsOk()) {
|
||||
out_secret.assign(static_cast<const char*>(secret.GetData()), secret.GetSize());
|
||||
if (!out_secret.empty()) {
|
||||
secret_stored = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1670,11 +1676,20 @@ bool OrcaCloudServiceAgent::load_user_secret(std::string& out_secret)
|
||||
return false;
|
||||
}
|
||||
|
||||
void OrcaCloudServiceAgent::clear_user_secret()
|
||||
void OrcaCloudServiceAgent::clear_user_secret(bool all_backends)
|
||||
{
|
||||
wxSecretStore store = wxSecretStore::GetDefault();
|
||||
if (store.IsOk()) {
|
||||
store.Delete(SECRET_STORE_SERVICE);
|
||||
// Nothing this process loaded or saved: leave the store alone. Deleting would only cost a
|
||||
// keychain round trip (or a hang while the keychain is unresponsive) and could remove a
|
||||
// login another instance just saved.
|
||||
if (!secret_stored.exchange(false) && !all_backends) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (all_backends || !m_use_encrypted_token_file) {
|
||||
wxSecretStore store = wxSecretStore::GetDefault();
|
||||
if (store.IsOk()) {
|
||||
store.Delete(SECRET_STORE_SERVICE);
|
||||
}
|
||||
}
|
||||
|
||||
compute_fallback_path();
|
||||
@@ -2023,13 +2038,13 @@ bool OrcaCloudServiceAgent::set_user_session(const json& session_json, bool noti
|
||||
return success;
|
||||
}
|
||||
|
||||
void OrcaCloudServiceAgent::clear_session()
|
||||
void OrcaCloudServiceAgent::clear_session(bool all_backends)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(session_mutex);
|
||||
session = SessionInfo{};
|
||||
}
|
||||
clear_user_secret();
|
||||
clear_user_secret(all_backends);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -326,7 +326,7 @@ public:
|
||||
|
||||
void persist_user_secret(const std::string& secret);
|
||||
bool load_user_secret(std::string& out_secret);
|
||||
void clear_user_secret();
|
||||
void clear_user_secret(bool all_backends = false);
|
||||
|
||||
// Token refresh helpers
|
||||
bool refresh_if_expiring(std::chrono::seconds skew, const std::string& reason);
|
||||
@@ -344,7 +344,7 @@ public:
|
||||
bool persist = true);
|
||||
// Accepts either nested Orca cloud / GoTrue session JSON or flat WebView token JSON.
|
||||
bool set_user_session(const nlohmann::json& session_json, bool notify_login = true);
|
||||
void clear_session();
|
||||
void clear_session(bool all_backends = false);
|
||||
|
||||
static std::string generate_uuid_for_setting_id(const std::string& name, const std::string& user_id = "");
|
||||
|
||||
@@ -413,6 +413,11 @@ private:
|
||||
// Member variables - auth state
|
||||
PkceBundle pkce_bundle;
|
||||
std::string secret_fallback_path;
|
||||
// Set once this process has read a secret from the store or written one. Unless the user logs
|
||||
// out explicitly, clear_user_secret() only touches the store while it is set, so a logged-out
|
||||
// instance (the GUI polls the login status every 2 s) makes no keychain calls and cannot wipe
|
||||
// a login another instance saved.
|
||||
std::atomic_bool secret_stored{false};
|
||||
SessionHandler session_handler;
|
||||
OnLoginCompleteHandler on_login_complete_handler;
|
||||
SessionInfo session;
|
||||
|
||||
Reference in New Issue
Block a user