Don't fetch actor when verifying JSON signature on Delete(Person) activity

This commit is contained in:
silverpill 2022-12-08 16:05:14 +00:00
parent cd6968b15a
commit 999dd7e608
2 changed files with 37 additions and 31 deletions

View file

@ -69,6 +69,32 @@ fn key_id_to_actor_id(key_id: &str) -> Result<String, AuthenticationError> {
Ok(actor_id.to_string())
}
async fn get_signer(
config: &Config,
db_client: &impl GenericClient,
signer_id: &str,
no_fetch: bool,
) -> Result<DbActorProfile, AuthenticationError> {
let signer = if no_fetch {
// Avoid fetching (e.g. if signer was deleted)
get_profile_by_remote_actor_id(db_client, signer_id).await?
} else {
match get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&config.media_dir(),
signer_id,
).await {
Ok(profile) => profile,
Err(HandlerError::DatabaseError(error)) => return Err(error.into()),
Err(other_error) => {
return Err(AuthenticationError::ImportError(other_error.to_string()));
},
}
};
Ok(signer)
}
/// Verifies HTTP signature and returns signer
pub async fn verify_signed_request(
config: &Config,
@ -89,22 +115,7 @@ pub async fn verify_signed_request(
};
let signer_id = key_id_to_actor_id(&signature_data.key_id)?;
let signer = if no_fetch {
get_profile_by_remote_actor_id(db_client, &signer_id).await?
} else {
match get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&config.media_dir(),
&signer_id,
).await {
Ok(profile) => profile,
Err(HandlerError::DatabaseError(error)) => return Err(error.into()),
Err(other_error) => {
return Err(AuthenticationError::ImportError(other_error.to_string()));
},
}
};
let signer = get_signer(config, db_client, &signer_id, no_fetch).await?;
let signer_actor = signer.actor_json.as_ref()
.expect("request should be signed by remote actor");
let signer_key =
@ -120,26 +131,15 @@ pub async fn verify_signed_activity(
config: &Config,
db_client: &impl GenericClient,
activity: &Value,
no_fetch: bool,
) -> Result<DbActorProfile, AuthenticationError> {
// Signed activities must have `actor` property, to avoid situations
// where signer is identified by DID but there is no matching
// identity proof in the local database.
let actor_id = activity["actor"].as_str()
.ok_or(AuthenticationError::ActorError("unknown actor"))?;
let actor_profile = match get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&config.media_dir(),
actor_id,
).await {
Ok(profile) => profile,
Err(HandlerError::DatabaseError(error)) => {
return Err(error.into());
},
Err(other_error) => {
return Err(AuthenticationError::ImportError(other_error.to_string()));
},
};
let actor_profile = get_signer(config, db_client, actor_id, no_fetch).await?;
let signature_data = match get_json_signature(activity) {
Ok(signature_data) => signature_data,
Err(JsonSignatureError::NoProof) => {

View file

@ -186,7 +186,13 @@ pub async fn receive_activity(
};
// JSON signature is optional
match verify_signed_activity(config, db_client, activity_raw).await {
match verify_signed_activity(
config,
db_client,
activity_raw,
// Don't fetch actor if this is Delete(Person) activity
is_self_delete,
).await {
Ok(activity_signer) => {
if activity_signer.acct != signer.acct {
log::warn!(