Fix SSO/LDAP user origin overwritten by set_password

When `create()` registers a user with `origin: Some("sso")`, it correctly
sets `userid_origin = "sso"` then calls `set_password()`. However,
`set_password()` unconditionally overwrites `userid_origin` to "password"
whenever the password hash succeeds — including for the sentinel password
"*" used by SSO and LDAP accounts.

This causes all SSO/LDAP users to have `origin = "password"` in the
database, which breaks the UIA SSO bypass check in `uiaa.rs` that gates
on `users.origin(sender_user) == "sso"`. As a result, SSO users cannot
delete devices or perform other UIA-protected operations because they
are prompted for a password they don't have, and the SSO bypass never
triggers.

Fix: skip the `userid_origin` overwrite when the password is the
sentinel value `"*"`, preserving the origin set by `create()`.
This commit is contained in:
Denys Bezmenov
2026-02-15 12:07:17 -08:00
parent 6c91aa1ddc
commit 6bed0d38f4

View File

@@ -236,13 +236,17 @@ impl Service {
}
}
let is_sentinel = password.is_some_and(|p| p == "*");
match password.map(utils::hash::password) {
| None => {
self.db.userid_password.insert(user_id, b"");
},
| Some(Ok(hash)) => {
self.db.userid_password.insert(user_id, hash);
self.db.userid_origin.insert(user_id, "password");
if !is_sentinel {
self.db.userid_origin.insert(user_id, "password");
}
},
| Some(Err(e)) => {
return Err!(Request(InvalidParam(