Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-11-23 05:20:28 +01:00
Fix conflict resolution logic for read_only
and hide_passwords
flags
For one of these flags to be in effect for a cipher, upstream requires all of (rather than any of) the collections the cipher is in to have that flag set. Also, some of the logic for loading access restrictions was wrong. I think that only malicious clients that also had knowledge of the UUIDs of ciphers they didn't have access to would have been able to take advantage of that.
Dieser Commit ist enthalten in:
Ursprung
a2316ca091
Commit
6cbb724069
1 geänderte Dateien mit 24 neuen und 21 gelöschten Zeilen
|
@ -343,36 +343,39 @@ impl Cipher {
|
||||||
db_run! {conn: {
|
db_run! {conn: {
|
||||||
// Check whether this cipher is in any collections accessible to the
|
// Check whether this cipher is in any collections accessible to the
|
||||||
// user. If so, retrieve the access flags for each collection.
|
// user. If so, retrieve the access flags for each collection.
|
||||||
let query = ciphers::table
|
let rows = ciphers::table
|
||||||
.filter(ciphers::uuid.eq(&self.uuid))
|
.filter(ciphers::uuid.eq(&self.uuid))
|
||||||
.inner_join(ciphers_collections::table.on(
|
.inner_join(ciphers_collections::table.on(
|
||||||
ciphers::uuid.eq(ciphers_collections::cipher_uuid)))
|
ciphers::uuid.eq(ciphers_collections::cipher_uuid)))
|
||||||
.inner_join(users_collections::table.on(
|
.inner_join(users_collections::table.on(
|
||||||
ciphers_collections::collection_uuid.eq(users_collections::collection_uuid)
|
ciphers_collections::collection_uuid.eq(users_collections::collection_uuid)
|
||||||
.and(users_collections::user_uuid.eq(user_uuid))))
|
.and(users_collections::user_uuid.eq(user_uuid))))
|
||||||
.select((users_collections::read_only, users_collections::hide_passwords));
|
.select((users_collections::read_only, users_collections::hide_passwords))
|
||||||
|
.load::<(bool, bool)>(conn)
|
||||||
|
.expect("Error getting access restrictions");
|
||||||
|
|
||||||
// There's an edge case where a cipher can be in multiple collections
|
if rows.is_empty() {
|
||||||
// with inconsistent access flags. For example, a cipher could be in
|
// This cipher isn't in any collections accessible to the user.
|
||||||
// one collection where the user has read-only access, but also in
|
return None;
|
||||||
// another collection where the user has read/write access. To handle
|
}
|
||||||
// this, we do a boolean OR of all values in each of the `read_only`
|
|
||||||
// and `hide_passwords` columns. This could ideally be done as part
|
// A cipher can be in multiple collections with inconsistent access flags.
|
||||||
// of the query, but Diesel doesn't support a max() or bool_or()
|
// For example, a cipher could be in one collection where the user has
|
||||||
// function on booleans and this behavior isn't portable anyway.
|
// read-only access, but also in another collection where the user has
|
||||||
if let Ok(vec) = query.load::<(bool, bool)>(conn) {
|
// read/write access. For a flag to be in effect for a cipher, upstream
|
||||||
let mut read_only = false;
|
// requires all collections the cipher is in to have that flag set.
|
||||||
let mut hide_passwords = false;
|
// Therefore, we do a boolean AND of all values in each of the `read_only`
|
||||||
for (ro, hp) in vec.iter() {
|
// and `hide_passwords` columns. This could ideally be done as part of the
|
||||||
read_only |= ro;
|
// query, but Diesel doesn't support a min() or bool_and() function on
|
||||||
hide_passwords |= hp;
|
// booleans and this behavior isn't portable anyway.
|
||||||
|
let mut read_only = true;
|
||||||
|
let mut hide_passwords = true;
|
||||||
|
for (ro, hp) in rows.iter() {
|
||||||
|
read_only &= ro;
|
||||||
|
hide_passwords &= hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((read_only, hide_passwords))
|
Some((read_only, hide_passwords))
|
||||||
} else {
|
|
||||||
// This cipher isn't in any collections accessible to the user.
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Laden …
In neuem Issue referenzieren