]> Untitled Git - lemmy.git/commitdiff
Implement instance whitelist
authorFelix <me@nutomic.com>
Fri, 17 Apr 2020 17:34:18 +0000 (19:34 +0200)
committerFelix <me@nutomic.com>
Fri, 17 Apr 2020 17:34:18 +0000 (19:34 +0200)
docker/federation/docker-compose.yml
server/config/defaults.hjson
server/src/apub/activities.rs
server/src/apub/community_inbox.rs
server/src/apub/fetcher.rs
server/src/apub/mod.rs
server/src/apub/user_inbox.rs
server/src/settings.rs

index 61db932cc44f2f765a7458de3015685503ee5031..b7aec47baba5945fe31c98f1fc6fee87ee2fade0 100644 (file)
@@ -25,6 +25,7 @@ services:
       - LEMMY_FRONT_END_DIR=/app/dist
       - LEMMY_FEDERATION__ENABLED=true
       - LEMMY_FEDERATION__TLS_ENABLED=false
+      - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_beta
       - LEMMY_PORT=8540
       - LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
       - LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@@ -58,6 +59,7 @@ services:
       - LEMMY_FRONT_END_DIR=/app/dist
       - LEMMY_FEDERATION__ENABLED=true
       - LEMMY_FEDERATION__TLS_ENABLED=false
+      - LEMMY_FEDERATION__INSTANCE_WHITELIST=lemmy_alpha
       - LEMMY_PORT=8550
       - LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
       - LEMMY_SETUP__ADMIN_PASSWORD=lemmy
index 509bef47d622547946578d0b71ea1aa5f33adcc5..09db4c020a7151f9aa3910541b295543cdfdb8c1 100644 (file)
@@ -56,6 +56,8 @@
     enabled: false
     # whether tls is required for activitypub. only disable this for debugging, never for producion.
     tls_enabled: true
+    # comma seperated list of instances with which federation is allowed
+    instance_whitelist: ""
   }
 #  # email sending configuration
 #  email: {
index f31be9db3087ddaea08abe8c0779d32ef361080a..d49008064916bd5d096d1a2507bce0b1f626a86a 100644 (file)
@@ -1,3 +1,4 @@
+use crate::apub::is_apub_id_valid;
 use crate::db::community::Community;
 use crate::db::community_view::CommunityFollowerView;
 use crate::db::post::Post;
@@ -36,9 +37,12 @@ where
   A: Serialize + Debug,
 {
   let json = serde_json::to_string(&activity)?;
-  debug!("Sending activitypub activity {}", json);
+  debug!("Sending activitypub activity {} to {:?}", json, to);
   for t in to {
-    debug!("Sending activity to: {}", t);
+    if is_apub_id_valid(&t) {
+      debug!("Not sending activity to {} (invalid or blacklisted)", t);
+      continue;
+    }
     let res = Request::post(t)
       .header("Content-Type", "application/json")
       .body(json.to_owned())?
index ea0d9105443f443e774279bc9a7670f359fb07af..65d7bec1ffaa313521d273aca1c0c086faf5ed29 100644 (file)
@@ -17,22 +17,18 @@ pub enum CommunityAcceptedObjects {
   Follow(Follow),
 }
 
-#[derive(Deserialize)]
-pub struct Params {
-  community_name: String,
-}
-
 /// Handler for all incoming activities to community inboxes.
 pub async fn community_inbox(
   input: web::Json<CommunityAcceptedObjects>,
-  params: web::Query<Params>,
+  path: web::Path<String>,
   db: web::Data<Pool<ConnectionManager<PgConnection>>>,
 ) -> Result<HttpResponse, Error> {
   let input = input.into_inner();
   let conn = &db.get().unwrap();
   debug!(
     "Community {} received activity {:?}",
-    &params.community_name, &input
+    &path.into_inner(),
+    &input
   );
   match input {
     CommunityAcceptedObjects::Follow(f) => handle_follow(&f, conn),
index 368aa4dc4d84116c6fdf1ccb9cbebbc3eee7093f..d44fdcb5ffd3f5905b51d89951d4e62b513651f6 100644 (file)
@@ -8,7 +8,6 @@ use crate::db::user::{UserForm, User_};
 use crate::db::user_view::UserView;
 use crate::db::{Crud, SearchType};
 use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
-use crate::settings::Settings;
 use activitystreams::collection::OrderedCollection;
 use activitystreams::object::Page;
 use activitystreams::BaseBox;
@@ -68,8 +67,8 @@ pub fn fetch_remote_object<Response>(url: &Url) -> Result<Response, Error>
 where
   Response: for<'de> Deserialize<'de>,
 {
-  if Settings::get().federation.tls_enabled && url.scheme() != "https" {
-    return Err(format_err!("Activitypub uri is insecure: {}", url));
+  if !is_apub_id_valid(&url.to_string()) {
+    return Err(format_err!("Activitypub uri invalid or blocked: {}", url));
   }
   // TODO: this function should return a future
   let timeout = Duration::from_secs(60);
@@ -86,7 +85,7 @@ where
 
 /// The types of ActivityPub objects that can be fetched directly by searching for their ID.
 #[serde(untagged)]
-#[derive(serde::Deserialize)]
+#[derive(serde::Deserialize, Debug)]
 pub enum SearchAcceptedObjects {
   Person(Box<PersonExt>),
   Group(Box<GroupExt>),
index a7f0668a35dcc6cbe527436f3402666fdb79cd1c..634f351010ea1213f879265564678107aa9d6b01 100644 (file)
@@ -88,3 +88,26 @@ pub fn gen_keypair_str() -> (String, String) {
 fn vec_bytes_to_str(bytes: Vec<u8>) -> String {
   String::from_utf8_lossy(&bytes).into_owned()
 }
+
+// Checks if the ID has a valid format, correct scheme, and is in the whitelist.
+fn is_apub_id_valid(apub_id: &str) -> bool {
+  let url = match Url::parse(apub_id) {
+    Ok(u) => u,
+    Err(_) => return false,
+  };
+
+  if url.scheme() != get_apub_protocol_string() {
+    return false;
+  }
+
+  let whitelist: Vec<String> = Settings::get()
+    .federation
+    .instance_whitelist
+    .split(',')
+    .map(|d| d.to_string())
+    .collect();
+  match url.domain() {
+    Some(d) => whitelist.contains(&d.to_owned()),
+    None => false,
+  }
+}
index 7d1463083ef2fe86e82440604938dd958772d0c5..75cd4e4790e77a12fb4596e89ac1cdc9b3360dfd 100644 (file)
@@ -17,20 +17,19 @@ pub enum UserAcceptedObjects {
   Accept(Accept),
 }
 
-#[derive(Deserialize)]
-pub struct Params {
-  user_name: String,
-}
-
 /// Handler for all incoming activities to user inboxes.
 pub async fn user_inbox(
   input: web::Json<UserAcceptedObjects>,
-  params: web::Query<Params>,
+  path: web::Path<String>,
   db: web::Data<Pool<ConnectionManager<PgConnection>>>,
 ) -> Result<HttpResponse, Error> {
   let input = input.into_inner();
   let conn = &db.get().unwrap();
-  debug!("User {} received activity: {:?}", &params.user_name, &input);
+  debug!(
+    "User {} received activity: {:?}",
+    &path.into_inner(),
+    &input
+  );
 
   match input {
     UserAcceptedObjects::Create(c) => handle_create(&c, conn),
index a82e478601bd8fded283e5b76ee3148c403060dd..c19cb717520b2a43c398a69234a2ed16aaabe382 100644 (file)
@@ -64,6 +64,7 @@ pub struct Database {
 pub struct Federation {
   pub enabled: bool,
   pub tls_enabled: bool,
+  pub instance_whitelist: String,
 }
 
 lazy_static! {