Add more checks in inbox, plus some refactoring #76
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::{
|
apub::{
|
||||||
|
check_is_apub_id_valid,
|
||||||
community::do_announce,
|
community::do_announce,
|
||||||
extensions::signatures::sign,
|
extensions::signatures::sign,
|
||||||
insert_activity,
|
insert_activity,
|
||||||
is_apub_id_valid,
|
|
||||||
ActorType,
|
ActorType,
|
||||||
},
|
},
|
||||||
request::retry_custom,
|
request::retry_custom,
|
||||||
|
@ -50,10 +50,7 @@ pub async fn send_activity(
|
||||||
|
|
||||||
for t in to {
|
for t in to {
|
||||||
let to_url = Url::parse(&t)?;
|
let to_url = Url::parse(&t)?;
|
||||||
if !is_apub_id_valid(&to_url) {
|
check_is_apub_id_valid(&to_url)?;
|
||||||
debug!("Not sending activity to {} (invalid or blocklisted)", t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = retry_custom(|| async {
|
let res = retry_custom(|| async {
|
||||||
let request = client.post(&t).header("Content-Type", "application/json");
|
let request = client.post(&t).header("Content-Type", "application/json");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::site::SearchResponse,
|
api::site::SearchResponse,
|
||||||
apub::{
|
apub::{
|
||||||
is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
ActorType,
|
ActorType,
|
||||||
FromApub,
|
FromApub,
|
||||||
GroupExt,
|
GroupExt,
|
||||||
|
@ -66,9 +66,7 @@ pub async fn fetch_remote_object<Response>(
|
||||||
where
|
where
|
||||||
Response: for<'de> Deserialize<'de>,
|
Response: for<'de> Deserialize<'de>,
|
||||||
{
|
{
|
||||||
if !is_apub_id_valid(&url) {
|
check_is_apub_id_valid(&url)?;
|
||||||
return Err(anyhow!("Activitypub uri invalid or blocked: {}", url).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let timeout = Duration::from_secs(60);
|
let timeout = Duration::from_secs(60);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::{
|
apub::{
|
||||||
|
check_is_apub_id_valid,
|
||||||
community::do_announce,
|
community::do_announce,
|
||||||
extensions::signatures::verify,
|
extensions::signatures::verify,
|
||||||
fetcher::{
|
fetcher::{
|
||||||
|
@ -67,9 +68,13 @@ pub async fn shared_inbox(
|
||||||
debug!("Shared inbox received activity: {}", json);
|
debug!("Shared inbox received activity: {}", json);
|
||||||
|
|
||||||
let sender = &activity.actor()?.to_owned().single_xsd_any_uri().unwrap();
|
let sender = &activity.actor()?.to_owned().single_xsd_any_uri().unwrap();
|
||||||
|
|
||||||
// TODO: pass this actor in instead of using get_user_from_activity()
|
// TODO: pass this actor in instead of using get_user_from_activity()
|
||||||
let actor = get_or_fetch_and_upsert_actor(sender, &client, &pool).await?;
|
let actor = get_or_fetch_and_upsert_actor(sender, &client, &pool).await?;
|
||||||
|
|
||||||
|
let community = get_community_id_from_activity(&activity).await;
|
||||||
|
|
||||||
|
check_is_apub_id_valid(sender)?;
|
||||||
|
check_is_apub_id_valid(&community)?;
|
||||||
verify(&request, actor.as_ref())?;
|
verify(&request, actor.as_ref())?;
|
||||||
|
|
||||||
insert_activity(actor.user_id(), activity.clone(), false, &pool).await?;
|
insert_activity(actor.user_id(), activity.clone(), false, &pool).await?;
|
||||||
|
@ -112,6 +117,15 @@ where
|
||||||
get_or_fetch_and_upsert_user(&user_uri, client, pool).await
|
get_or_fetch_and_upsert_user(&user_uri, client, pool).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(in crate::apub::inbox) async fn get_community_id_from_activity<T, A>(activity: &T) -> Url
|
||||||
|
where
|
||||||
|
T: AsBase<A> + ActorAndObjectRef + AsObject<A>,
|
||||||
|
{
|
||||||
|
let cc = activity.cc().unwrap();
|
||||||
|
let cc = cc.as_many().unwrap();
|
||||||
|
cc.first().unwrap().as_xsd_any_uri().unwrap().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>(
|
pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>(
|
||||||
activity: T,
|
activity: T,
|
||||||
user: &User_,
|
user: &User_,
|
||||||
|
|
|
@ -63,11 +63,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the ID has a valid format, correct scheme, and is in the allowed instance list.
|
// Checks if the ID has a valid format, correct scheme, and is in the allowed instance list.
|
||||||
fn is_apub_id_valid(apub_id: &Url) -> bool {
|
fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
|
||||||
debug!("Checking {}", apub_id);
|
|
||||||
if apub_id.scheme() != get_apub_protocol_string() {
|
if apub_id.scheme() != get_apub_protocol_string() {
|
||||||
debug!("invalid scheme: {:?}", apub_id.scheme());
|
return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let allowed_instances: Vec<String> = Settings::get()
|
let allowed_instances: Vec<String> = Settings::get()
|
||||||
|
@ -81,15 +79,12 @@ fn is_apub_id_valid(apub_id: &Url) -> bool {
|
||||||
let contains = allowed_instances.contains(&d.to_owned());
|
let contains = allowed_instances.contains(&d.to_owned());
|
||||||
|
|
||||||
if !contains {
|
if !contains {
|
||||||
debug!("{} not in {:?}", d, allowed_instances);
|
return Err(anyhow!("{} not in federation allowlist", d).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
contains
|
Ok(())
|
||||||
}
|
|
||||||
None => {
|
|
||||||
debug!("missing domain");
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
None => Err(anyhow!("federation allowlist is empty").into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue