1
0
Fork 0
mirror of https://github.com/dani-garcia/vaultwarden.git synced 2025-07-14 08:14:59 +00:00

Add some extra access checks for attachments and groups

This commit is contained in:
Daniel García 2023-07-03 19:58:14 +02:00
parent e7f083dee9
commit 60964c07e6
No known key found for this signature in database
GPG key ID: FC8A7D14C3CD543A
7 changed files with 101 additions and 28 deletions

View file

@ -934,6 +934,15 @@ async fn share_cipher_by_uuid(
/// redirects to the same location as before the v2 API.
#[get("/ciphers/<uuid>/attachment/<attachment_id>")]
async fn get_attachment(uuid: &str, attachment_id: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
let cipher = match Cipher::find_by_uuid(uuid, &mut conn).await {
Some(cipher) => cipher,
None => err!("Cipher doesn't exist"),
};
if !cipher.is_accessible_to_user(&headers.user.uuid, &mut conn).await {
err!("Cipher is not accessible")
}
match Attachment::find_by_id(attachment_id, &mut conn).await {
Some(attachment) if uuid == attachment.cipher_uuid => Ok(Json(attachment.to_json(&headers.host))),
Some(_) => err!("Attachment doesn't belong to cipher"),

View file

@ -2578,11 +2578,15 @@ async fn put_user_groups(
err!("Group support is disabled");
}
match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
let user_org = match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
Some(uo) => uo,
_ => err!("User could not be found!"),
};
if user_org.org_uuid != org_id {
err!("Group doesn't belong to organization");
}
GroupUser::delete_all_by_user(org_user_id, &mut conn).await?;
let assigned_group_ids = data.into_inner().data;
@ -2628,16 +2632,24 @@ async fn delete_group_user(
err!("Group support is disabled");
}
match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
let user_org = match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
Some(uo) => uo,
_ => err!("User could not be found!"),
};
match Group::find_by_uuid(group_id, &mut conn).await {
Some(_) => { /* Do nothing */ }
if user_org.org_uuid != org_id {
err!("User doesn't belong to organization");
}
let group = match Group::find_by_uuid(group_id, &mut conn).await {
Some(g) => g,
_ => err!("Group could not be found!"),
};
if group.organizations_uuid != org_id {
err!("Group doesn't belong to organization");
}
log_event(
EventType::OrganizationUserUpdatedGroups as i32,
org_user_id,

View file

@ -340,27 +340,30 @@ async fn post_send_file_v2_data(
let mut data = data.into_inner();
if let Some(send) = Send::find_by_uuid(send_uuid, &mut conn).await {
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_uuid);
let file_path = folder_path.join(file_id);
tokio::fs::create_dir_all(&folder_path).await?;
let Some(send) = Send::find_by_uuid(send_uuid, &mut conn).await else { err!("Send not found. Unable to save the file.") };
if let Err(_err) = data.data.persist_to(&file_path).await {
data.data.move_copy_to(file_path).await?
}
nt.send_send_update(
UpdateType::SyncSendCreate,
&send,
&send.update_users_revision(&mut conn).await,
&headers.device.uuid,
&mut conn,
)
.await;
} else {
err!("Send not found. Unable to save the file.");
let Some(send_user_id) = &send.user_uuid else {err!("Sends are only supported for users at the moment")};
if send_user_id != &headers.user.uuid {
err!("Send doesn't belong to user");
}
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_uuid);
let file_path = folder_path.join(file_id);
tokio::fs::create_dir_all(&folder_path).await?;
if let Err(_err) = data.data.persist_to(&file_path).await {
data.data.move_copy_to(file_path).await?
}
nt.send_send_update(
UpdateType::SyncSendCreate,
&send,
&send.update_users_revision(&mut conn).await,
&headers.device.uuid,
&mut conn,
)
.await;
Ok(())
}

View file

@ -5,6 +5,7 @@ use serde_json::Value;
use crate::{
api::{core::now, ApiResult, EmptyResult},
auth::decode_file_download,
error::Error,
util::{Cached, SafeString},
CONFIG,
@ -91,8 +92,13 @@ async fn web_files(p: PathBuf) -> Cached<Option<NamedFile>> {
Cached::long(NamedFile::open(Path::new(&CONFIG.web_vault_folder()).join(p)).await.ok(), true)
}
#[get("/attachments/<uuid>/<file_id>")]
async fn attachments(uuid: SafeString, file_id: SafeString) -> Option<NamedFile> {
#[get("/attachments/<uuid>/<file_id>?<token>")]
async fn attachments(uuid: SafeString, file_id: SafeString, token: String) -> Option<NamedFile> {
let Ok(claims) = dbg!(decode_file_download(&token)) else { return None };
if claims.sub != *uuid || claims.file_id != *file_id {
return None;
}
NamedFile::open(Path::new(&CONFIG.attachments_folder()).join(uuid).join(file_id)).await.ok()
}