From e894b6512df2ed567cb540a304ce85614c773953 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Wed, 6 Dec 2023 14:24:59 +0000 Subject: [PATCH] node: prevent fetch response if no repo policy If a node had removed a seeding policy and another node fetched from it, then it would perform the fetch. Instead, check the policy during the authorization step and prevent the fetch is the resulting policy is `Block`. Note that the policy will be `Block` iff the `Block` policy was specifically set or the `Block` is the default policy for the node. Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- radicle-node/src/tests/e2e.rs | 29 +++++++++++++++++++++++++++++ radicle-node/src/worker.rs | 11 ++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/radicle-node/src/tests/e2e.rs b/radicle-node/src/tests/e2e.rs index 0fc9461d..a9c20dbc 100644 --- a/radicle-node/src/tests/e2e.rs +++ b/radicle-node/src/tests/e2e.rs @@ -596,6 +596,35 @@ fn test_fetch_up_to_date() { ); } +#[test] +fn test_fetch_unseeded() { + logger::init(log::Level::Debug); + + let tmp = tempfile::tempdir().unwrap(); + let alice = Node::init(tmp.path(), Config::test(Alias::new("alice"))); + let mut bob = Node::init(tmp.path(), Config::test(Alias::new("bob"))); + let acme = bob.project("acme", ""); + + let mut alice = alice.spawn(); + let mut bob = bob.spawn(); + + alice.connect(&bob); + converge([&alice, &bob]); + + transport::local::register(alice.storage.clone()); + + let _ = alice.handle.seed(acme, Scope::All).unwrap(); + let result = alice.handle.fetch(acme, bob.id, DEFAULT_TIMEOUT).unwrap(); + assert!(result.is_success()); + + // Bob stops seeding the repository + assert!(bob.handle.unseed(acme).unwrap()); + + // Alice attempts to fetch but is unauthorized + let result = alice.handle.fetch(acme, bob.id, DEFAULT_TIMEOUT).unwrap(); + assert_matches!(result, FetchResult::Failed { .. }); +} + #[test] fn test_large_fetch() { logger::init(log::Level::Debug); diff --git a/radicle-node/src/worker.rs b/radicle-node/src/worker.rs index eb26c72b..14c7da8b 100644 --- a/radicle-node/src/worker.rs +++ b/radicle-node/src/worker.rs @@ -79,6 +79,8 @@ pub enum UploadError { Identity(#[from] radicle::identity::DocError), #[error(transparent)] Repository(#[from] radicle::storage::RepositoryError), + #[error(transparent)] + PolicyStore(#[from] radicle::node::policy::store::Error), } impl UploadError { @@ -259,9 +261,16 @@ impl Worker { } fn is_authorized(&self, remote: NodeId, rid: Id) -> Result<(), UploadError> { + let policy = { + let policy = self.fetch_config.policy; + let scope = self.fetch_config.scope; + let db = &self.fetch_config.policies_db; + let policies = policy::Config::new(policy, scope, policy::Store::reader(db)?); + policies.repo_policy(&rid)?.policy + }; let repo = self.storage.repository(rid)?; let doc = repo.canonical_identity_doc()?; - if !doc.is_visible_to(&remote) { + if !doc.is_visible_to(&remote) || policy == Policy::Block { Err(UploadError::Unauthorized(remote, rid)) } else { Ok(())