From 67433b43be54ec9c3f0b8c56e49440ef21a0153a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 13 Dec 2024 05:26:26 +0100 Subject: [PATCH 1/6] `rd`: Split `GetFetchFailures` into single-protocol and multi-prtocol variants --- acrate_rd/src/any.rs | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/acrate_rd/src/any.rs b/acrate_rd/src/any.rs index 99acb96..eca9ef5 100644 --- a/acrate_rd/src/any.rs +++ b/acrate_rd/src/any.rs @@ -262,25 +262,27 @@ pub enum GetError { Fetch(GetFetchFailures), } -/// Request errors occurred during [`ResourceDescriptor::discover`]. +/// Request errors occurred during [`ResourceDescriptor::discover_http`] or [`ResourceDescriptor::discover`]. #[derive(Debug, Error)] #[error("all attempts of fetching the resource descriptor document failed")] pub struct GetFetchFailures { - /// HTTPS XRD retrieval. - pub https_xrd: GetXRDError, + /// XRD retrieval. + pub xrd: GetXRDError, - /// HTTPS JRD retrieval. - pub https_jrd: GetJRDError, + /// JRD retrieval. + pub jrd: GetJRDError, - /// HTTPS JRD with .json extension retrieval. - pub https_jrdj: GetJRDError, - - /// HTTPS XRD retrieval. - pub http_xrd: GetXRDError, - - /// HTTP JRD retrieval. - pub http_jrd: GetJRDError, - - /// HTTP JRD with .json extension retrieval. - pub http_jrdj: GetJRDError, + /// JRD with .json extension retrieval. + pub jrdj: GetJRDError, +} + +/// Request errors occurred during [`ResourceDescriptor::discover`]. +#[derive(Debug, Error)] +#[error("all attempts of fetching the resource descriptor document failed with all protocols")] +pub struct GetFetchFailuresMultiprotocol { + /// HTTPS. + pub https: GetFetchFailures, + + /// HTTP. + pub http: GetFetchFailures, } From 64c3557327f056a7642e88c27ab9c71698ebf927 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 16 Dec 2024 01:36:15 +0100 Subject: [PATCH 2/6] `rd`: Remove `host-meta` mention --- acrate_rd/src/xrd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acrate_rd/src/xrd.rs b/acrate_rd/src/xrd.rs index a5f5703..0624374 100644 --- a/acrate_rd/src/xrd.rs +++ b/acrate_rd/src/xrd.rs @@ -181,7 +181,7 @@ impl ResourceDescriptorXRD { pub async fn get(client: &reqwest::Client, url: reqwest::Url) -> Result { use GetXRDError::*; - log::debug!("Getting host-meta XRD document at: {url}"); + log::debug!("Getting XRD document at: {url}"); log::trace!("Building request..."); let request = { From 69f5232ab98f24db93a5da056a9bcbb4995ee890 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 16 Dec 2024 01:56:18 +0100 Subject: [PATCH 3/6] `rd`: Only get resource descriptors via the specified protocol, without downgrading to HTTP --- acrate_rd/src/any.rs | 130 ++++++++----------------------------------- 1 file changed, 24 insertions(+), 106 deletions(-) diff --git a/acrate_rd/src/any.rs b/acrate_rd/src/any.rs index eca9ef5..d4e5ce0 100644 --- a/acrate_rd/src/any.rs +++ b/acrate_rd/src/any.rs @@ -15,17 +15,16 @@ impl ResourceDescriptor { /// /// In order, this method attempts: /// - /// 1. HTTPS [XRD](ResourceDescriptorJRD::get) - /// 2. HTTPS [JRD](ResourceDescriptorJRD::get) - /// 3. HTTPS [JRD](ResourceDescriptorJRD::get) with .json path suffix - /// 4. HTTP [XRD](ResourceDescriptorJRD::get) - /// 5. HTTP [JRD](ResourceDescriptorJRD::get) - /// 6. HTTP [JRD](ResourceDescriptorJRD::get) with .json path suffix + /// 1. [XRD](ResourceDescriptorJRD::get) + /// 2. [JRD](ResourceDescriptorJRD::get) + /// 3. [JRD](ResourceDescriptorJRD::get) with .json path suffix /// /// # Notes /// /// This follows redirects until the redirect chain is 10 hops; see [`reqwest::redirect`] for more info. /// + /// Only the protocol specified in the passed [`reqwest::Url`] is used to fetch the [`ResourceDescriptor`]; despite the specification allowing servers to use only one between HTTP and HTTPS, no implicit downgrade is ever performed to prevent MITM attacks. + /// /// # Examples /// /// ``` @@ -53,121 +52,51 @@ impl ResourceDescriptor { log::trace!("Unsetting URL fragment..."); url.set_fragment(None); - log::trace!("Setting URL scheme to HTTPS..."); - url.set_scheme("https") - .map_err(UrlManipulation)?; - - log::trace!("Cloning URL for HTTPS XRD retrieval..."); - let https_xrd_url = url.clone(); - - log::trace!("Attempting HTTPS XRD retrieval..."); - let https_xrd = match ResourceDescriptorXRD::get(client, https_xrd_url).await { + log::trace!("Attempting XRD retrieval..."); + let xrd = match ResourceDescriptorXRD::get(client, url.clone()).await { Ok(data) => { - log::trace!("HTTPS XRD retrieval was successful, returning..."); + log::trace!("XRD retrieval was successful, returning..."); return Ok(Self::XRD(data)) } Err(err) => { - log::warn!("HTTPS XRD retrieval failed."); + log::warn!("XRD retrieval failed."); err } }; - log::trace!("Cloning URL for HTTPS JRD retrieval..."); - let https_jrd_url = url.clone(); - - log::trace!("Attempting HTTPS JRD retrieval..."); - let https_jrd = match ResourceDescriptorJRD::get(client, https_jrd_url).await { + log::trace!("Attempting JRD retrieval..."); + let jrd = match ResourceDescriptorJRD::get(client, url.clone()).await { Ok(data) => { - log::trace!("HTTPS JRD retrieval was successful, returning..."); + log::trace!("JRD retrieval was successful, returning..."); return Ok(Self::JRD(data)) } Err(err) => { - log::warn!("HTTPS JRD retrieval failed."); + log::warn!("JRD retrieval failed."); err } }; - log::trace!("Cloning URL for HTTPS JRD .json retrieval..."); - let mut https_jrdj_url = url.clone(); - - log::trace!("Altering URL path for HTTPS JRD .json retrieval..."); - https_jrdj_url.set_path( - &format!("{}.json", https_jrdj_url.path()) + log::trace!("Altering URL path for JRD .json retrieval..."); + url.set_path( + &format!("{}.json", url.path()) ); - log::trace!("Attempting HTTPS JRD .json retrieval..."); - let https_jrdj = match ResourceDescriptorJRD::get(client, https_jrdj_url).await { + log::trace!("Attempting JRD .json retrieval..."); + let jrdj = match ResourceDescriptorJRD::get(client, url.clone()).await { Ok(data) => { - log::trace!("HTTPS JRD .json retrieval was successful, returning..."); + log::trace!("JRD .json retrieval was successful, returning..."); return Ok(Self::JRD(data)) } Err(err) => { - log::warn!("HTTPS JRD .json retrieval failed."); - err - } - }; - - log::trace!("Setting URL scheme to HTTP..."); - url.set_scheme("http") - .map_err(UrlManipulation)?; - - log::trace!("Cloning URL for HTTP XRD retrieval..."); - let http_xrd_url = url.clone(); - - log::trace!("Attempting HTTP XRD retrieval..."); - let http_xrd = match ResourceDescriptorXRD::get(client, http_xrd_url).await { - Ok(data) => { - log::trace!("HTTP XRD retrieval was successful, returning..."); - return Ok(Self::XRD(data)) - } - Err(err) => { - log::warn!("HTTP XRD retrieval failed."); - err - } - }; - - log::trace!("Cloning URL for HTTP JRD retrieval..."); - let http_jrd_url = url.clone(); - - log::trace!("Attempting HTTP JRD retrieval..."); - let http_jrd = match ResourceDescriptorJRD::get(client, http_jrd_url).await { - Ok(data) => { - log::trace!("HTTP JRD retrieval was successful, returning..."); - return Ok(Self::JRD(data)) - } - Err(err) => { - log::warn!("HTTP JRD retrieval failed."); - err - } - }; - - log::trace!("Cloning URL for HTTP JRD .json retrieval..."); - let mut http_jrdj_url = url.clone(); - - log::trace!("Altering URL path for HTTPS JRD .json retrieval..."); - http_jrdj_url.set_path( - &format!("{}.json", http_jrdj_url.path()) - ); - - log::trace!("Attempting HTTP JRD .json retrieval..."); - let http_jrdj = match ResourceDescriptorJRD::get(client, http_jrdj_url).await { - Ok(data) => { - log::trace!("HTTP JRD .json retrieval was successful, returning..."); - return Ok(Self::JRD(data)) - } - Err(err) => { - log::warn!("HTTP JRD .json retrieval failed."); + log::warn!("JRD .json retrieval failed."); err } }; Err(Fetch(GetFetchFailures { - https_xrd, - https_jrd, - https_jrdj, - http_xrd, - http_jrd, - http_jrdj, + xrd, + jrd, + jrdj, })) } @@ -262,7 +191,7 @@ pub enum GetError { Fetch(GetFetchFailures), } -/// Request errors occurred during [`ResourceDescriptor::discover_http`] or [`ResourceDescriptor::discover`]. +/// Request errors occurred during [`ResourceDescriptor::get`]. #[derive(Debug, Error)] #[error("all attempts of fetching the resource descriptor document failed")] pub struct GetFetchFailures { @@ -275,14 +204,3 @@ pub struct GetFetchFailures { /// JRD with .json extension retrieval. pub jrdj: GetJRDError, } - -/// Request errors occurred during [`ResourceDescriptor::discover`]. -#[derive(Debug, Error)] -#[error("all attempts of fetching the resource descriptor document failed with all protocols")] -pub struct GetFetchFailuresMultiprotocol { - /// HTTPS. - pub https: GetFetchFailures, - - /// HTTP. - pub http: GetFetchFailures, -} From ded9fe564e3786d732642783da122463c74051fa Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 16 Dec 2024 01:57:58 +0100 Subject: [PATCH 4/6] Tests: Replace ice.frieren.quest with meow.company --- acrate_nodeinfo/tests/integration_tests.rs | 2 +- acrate_rd/tests/integration_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/acrate_nodeinfo/tests/integration_tests.rs b/acrate_nodeinfo/tests/integration_tests.rs index e9e2fba..4ef8db6 100644 --- a/acrate_nodeinfo/tests/integration_tests.rs +++ b/acrate_nodeinfo/tests/integration_tests.rs @@ -62,7 +62,7 @@ macro_rules! test { test!(akkoma, "https://junimo.party", "2.1"); test!(mastodon, "https://mastodon.social", "2.0"); test!(misskey, "https://misskey.io", "2.1"); -test!(iceshrimpnet, "https://ice.frieren.quest", "2.1"); +test!(iceshrimpnet, "https://meow_company", "2.1"); test!(gotosocial, "https://alpha.polymaths.social", "2.0"); test!(bridgyfed, "https://fed.brid.gy", "2.1"); test!(threads, "https://threads.net", "", ignore = "does not support NodeInfo"); diff --git a/acrate_rd/tests/integration_tests.rs b/acrate_rd/tests/integration_tests.rs index e2b051e..45996f6 100644 --- a/acrate_rd/tests/integration_tests.rs +++ b/acrate_rd/tests/integration_tests.rs @@ -105,7 +105,7 @@ macro_rules! test_de_ser_xrd { test_discover_hostmeta!(test_discover_hostmeta_junimo_party, "https://junimo.party"); test_discover_hostmeta!(test_discover_hostmeta_mastodon_social, "https://mastodon.social"); test_discover_hostmeta!(test_discover_hostmeta_misskey_io, "https://misskey.io"); -test_discover_hostmeta!(test_discover_hostmeta_ice_frieren_quest, "https://ice.frieren.quest"); +test_discover_hostmeta!(test_discover_hostmeta_meow_company, "https://meow.company"); test_discover_hostmeta!(test_discover_hostmeta_alpha_polymaths_social, "https://alpha.polymaths.social"); test_discover_hostmeta!(test_discover_hostmeta_fed_brid_gy, "https://fed.brid.gy"); test_discover_hostmeta!(test_discover_hostmeta_threads_net, "https://threads.net", ignore = "does not support host-meta"); From 4bc776c3fda08e375a80a8158539ab0515dba9eb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 16 Dec 2024 01:58:22 +0100 Subject: [PATCH 5/6] `nodeinfo`: Rename `test!` macro to `test_version!` --- acrate_nodeinfo/tests/integration_tests.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/acrate_nodeinfo/tests/integration_tests.rs b/acrate_nodeinfo/tests/integration_tests.rs index 4ef8db6..c170185 100644 --- a/acrate_nodeinfo/tests/integration_tests.rs +++ b/acrate_nodeinfo/tests/integration_tests.rs @@ -24,9 +24,9 @@ fn make_client() -> reqwest::Client { } -macro_rules! test { +macro_rules! test_version { ($id:ident, $url:literal, $version:literal) => { - test!($id, $url, $version,); + test_version!($id, $url, $version,); }; ($id:ident, $url:literal, $version:literal, $($tag:meta),*) => { mod $id { @@ -59,12 +59,12 @@ macro_rules! test { }; } -test!(akkoma, "https://junimo.party", "2.1"); -test!(mastodon, "https://mastodon.social", "2.0"); -test!(misskey, "https://misskey.io", "2.1"); -test!(iceshrimpnet, "https://meow_company", "2.1"); -test!(gotosocial, "https://alpha.polymaths.social", "2.0"); -test!(bridgyfed, "https://fed.brid.gy", "2.1"); -test!(threads, "https://threads.net", "", ignore = "does not support NodeInfo"); -test!(snac, "https://ngoa.giao.loan", "2.0"); -test!(hollo, "https://hollo.social", "2.1"); +test_version!(akkoma, "https://junimo.party", "2.1"); +test_version!(mastodon, "https://mastodon.social", "2.0"); +test_version!(misskey, "https://misskey.io", "2.1"); +test_version!(iceshrimpnet, "https://meow_company", "2.1"); +test_version!(gotosocial, "https://alpha.polymaths.social", "2.0"); +test_version!(bridgyfed, "https://fed.brid.gy", "2.1"); +test_version!(threads, "https://threads.net", "", ignore = "does not support NodeInfo"); +test_version!(snac, "https://ngoa.giao.loan", "2.0"); +test_version!(hollo, "https://hollo.social", "2.1"); From 48c3b9911b33087074b9a3d6b0adeccaa48f6990 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 16 Dec 2024 01:59:59 +0100 Subject: [PATCH 6/6] `nodeinfo`: Fix typo in test --- acrate_nodeinfo/tests/integration_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acrate_nodeinfo/tests/integration_tests.rs b/acrate_nodeinfo/tests/integration_tests.rs index c170185..4372a95 100644 --- a/acrate_nodeinfo/tests/integration_tests.rs +++ b/acrate_nodeinfo/tests/integration_tests.rs @@ -62,7 +62,7 @@ macro_rules! test_version { test_version!(akkoma, "https://junimo.party", "2.1"); test_version!(mastodon, "https://mastodon.social", "2.0"); test_version!(misskey, "https://misskey.io", "2.1"); -test_version!(iceshrimpnet, "https://meow_company", "2.1"); +test_version!(iceshrimpnet, "https://meow.company", "2.1"); test_version!(gotosocial, "https://alpha.polymaths.social", "2.0"); test_version!(bridgyfed, "https://fed.brid.gy", "2.1"); test_version!(threads, "https://threads.net", "", ignore = "does not support NodeInfo");