WebDAV: Reduce quota excess risk with lower TOCTOU window

This commit is contained in:
mdecimus
2025-09-30 11:36:25 +02:00
parent 5fcf73f070
commit 2f6cfbb6e6
2 changed files with 40 additions and 40 deletions

View File

@@ -167,17 +167,6 @@ impl CalendarUpdateRequestHandler for Server {
return Ok(HttpResponse::new(StatusCode::NO_CONTENT)); return Ok(HttpResponse::new(StatusCode::NO_CONTENT));
} }
// Validate quota
let extra_bytes =
(bytes.len() as u64).saturating_sub(u32::from(event.inner.size) as u64);
if extra_bytes > 0 {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
extra_bytes,
)
.await?;
}
// Validate iCal // Validate iCal
if event.inner.data.event.uids().next().unwrap_or_default() != validate_ical(&ical)? { if event.inner.data.event.uids().next().unwrap_or_default() != validate_ical(&ical)? {
return Err(DavError::Condition(DavErrorCondition::new( return Err(DavError::Condition(DavErrorCondition::new(
@@ -278,6 +267,17 @@ impl CalendarUpdateRequestHandler for Server {
} }
let nudge_queue = next_email_alarm.is_some() || itip_messages.is_some(); let nudge_queue = next_email_alarm.is_some() || itip_messages.is_some();
// Validate quota
let extra_bytes =
(bytes.len() as u64).saturating_sub(u32::from(event.inner.size) as u64);
if extra_bytes > 0 {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
extra_bytes,
)
.await?;
}
// Prepare write batch // Prepare write batch
let mut batch = BatchBuilder::new(); let mut batch = BatchBuilder::new();
let schedule_tag = new_event.schedule_tag; let schedule_tag = new_event.schedule_tag;
@@ -338,15 +338,6 @@ impl CalendarUpdateRequestHandler for Server {
) )
.await?; .await?;
// Validate quota
if !bytes.is_empty() {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
bytes.len() as u64,
)
.await?;
}
// Validate ical object // Validate ical object
assert_is_unique_uid( assert_is_unique_uid(
self, self,
@@ -410,6 +401,15 @@ impl CalendarUpdateRequestHandler for Server {
} }
let nudge_queue = next_email_alarm.is_some() || itip_messages.is_some(); let nudge_queue = next_email_alarm.is_some() || itip_messages.is_some();
// Validate quota
if !bytes.is_empty() {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
bytes.len() as u64,
)
.await?;
}
// Prepare write batch // Prepare write batch
let mut batch = BatchBuilder::new(); let mut batch = BatchBuilder::new();
let document_id = self let document_id = self

View File

@@ -152,17 +152,6 @@ impl CardUpdateRequestHandler for Server {
Err(e) => return Err(e), Err(e) => return Err(e),
} }
// Validate quota
let extra_bytes =
(bytes.len() as u64).saturating_sub(u32::from(card.inner.size) as u64);
if extra_bytes > 0 {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
extra_bytes,
)
.await?;
}
// Validate UID // Validate UID
match (card.inner.card.uid(), vcard.uid()) { match (card.inner.card.uid(), vcard.uid()) {
(Some(old_uid), Some(new_uid)) if old_uid == new_uid => {} (Some(old_uid), Some(new_uid)) if old_uid == new_uid => {}
@@ -175,6 +164,17 @@ impl CardUpdateRequestHandler for Server {
} }
} }
// Validate quota
let extra_bytes =
(bytes.len() as u64).saturating_sub(u32::from(card.inner.size) as u64);
if extra_bytes > 0 {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
extra_bytes,
)
.await?;
}
// Build node // Build node
let mut new_card = card let mut new_card = card
.deserialize::<ContactCard>() .deserialize::<ContactCard>()
@@ -223,15 +223,6 @@ impl CardUpdateRequestHandler for Server {
) )
.await?; .await?;
// Validate quota
if !bytes.is_empty() {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
bytes.len() as u64,
)
.await?;
}
// Validate UID // Validate UID
assert_is_unique_uid( assert_is_unique_uid(
self, self,
@@ -242,6 +233,15 @@ impl CardUpdateRequestHandler for Server {
) )
.await?; .await?;
// Validate quota
if !bytes.is_empty() {
self.has_available_quota(
&self.get_resource_token(access_token, account_id).await?,
bytes.len() as u64,
)
.await?;
}
// Build node // Build node
let card = ContactCard { let card = ContactCard {
names: vec![DavName { names: vec![DavName {