From 3460a2821e294cf565bb709928df63e84667f4b8 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Mon, 19 Jan 2026 12:37:35 +0100 Subject: [PATCH] dav: Check Host matching for MV,COPY --- crates/dav/src/resource/methods/copy.rs | 10 +++++++++- crates/dav/src/resource/methods/mv.rs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/dav/src/resource/methods/copy.rs b/crates/dav/src/resource/methods/copy.rs index bec1372..c0426c1 100644 --- a/crates/dav/src/resource/methods/copy.rs +++ b/crates/dav/src/resource/methods/copy.rs @@ -6,12 +6,15 @@ use axum::{ extract::{MatchedPath, Path, State}, response::{IntoResponse, Response}, }; +use axum_extra::TypedHeader; +use headers::Host; use http::{HeaderMap, StatusCode, Uri}; use matchit_serde::ParamsDeserializer; use serde::Deserialize; use tracing::instrument; #[instrument(skip(path, resource_service,))] +#[allow(clippy::too_many_arguments)] pub async fn axum_route_copy( Path(path): Path, State(resource_service): State, @@ -20,6 +23,7 @@ pub async fn axum_route_copy( Overwrite(overwrite): Overwrite, matched_path: MatchedPath, header_map: HeaderMap, + TypedHeader(host): TypedHeader, ) -> Result { let destination = header_map .get("Destination") @@ -27,7 +31,11 @@ pub async fn axum_route_copy( .to_str() .map_err(|_| crate::Error::Forbidden)?; let destination_uri: Uri = destination.parse().map_err(|_| crate::Error::Forbidden)?; - // TODO: Check that host also matches + if let Some(authority) = destination_uri.authority() + && host != authority.clone().into() + { + return Err(crate::Error::Forbidden.into()); + } let destination = destination_uri.path(); let mut router = matchit::Router::new(); diff --git a/crates/dav/src/resource/methods/mv.rs b/crates/dav/src/resource/methods/mv.rs index a10d5d8..8192565 100644 --- a/crates/dav/src/resource/methods/mv.rs +++ b/crates/dav/src/resource/methods/mv.rs @@ -6,12 +6,15 @@ use axum::{ extract::{MatchedPath, Path, State}, response::{IntoResponse, Response}, }; +use axum_extra::TypedHeader; +use headers::Host; use http::{HeaderMap, StatusCode, Uri}; use matchit_serde::ParamsDeserializer; use serde::Deserialize; use tracing::instrument; #[instrument(skip(path, resource_service,))] +#[allow(clippy::too_many_arguments)] pub async fn axum_route_move( Path(path): Path, State(resource_service): State, @@ -20,6 +23,7 @@ pub async fn axum_route_move( Overwrite(overwrite): Overwrite, matched_path: MatchedPath, header_map: HeaderMap, + TypedHeader(host): TypedHeader, ) -> Result { let destination = header_map .get("Destination") @@ -27,7 +31,11 @@ pub async fn axum_route_move( .to_str() .map_err(|_| crate::Error::Forbidden)?; let destination_uri: Uri = destination.parse().map_err(|_| crate::Error::Forbidden)?; - // TODO: Check that host also matches + if let Some(authority) = destination_uri.authority() + && host != authority.clone().into() + { + return Err(crate::Error::Forbidden.into()); + } let destination = destination_uri.path(); let mut router = matchit::Router::new();