diff --git a/plume-common/src/activity_pub/sign.rs b/plume-common/src/activity_pub/sign.rs index fa9252e..427f50f 100644 --- a/plume-common/src/activity_pub/sign.rs +++ b/plume-common/src/activity_pub/sign.rs @@ -97,46 +97,47 @@ impl SignatureValidity { } pub fn verify_http_headers(sender: &S, all_headers: HeaderMap, data: String) -> SignatureValidity{ - if let Some(sig_header) = all_headers.get_one("Signature") { - let mut _key_id = None; - let mut _algorithm = None; - let mut headers = None; - let mut signature = None; - for part in sig_header.split(',') { - match part { - part if part.starts_with("keyId=") => _key_id = Some(&part[7..part.len()-1]), - part if part.starts_with("algorithm=") => _algorithm = Some(&part[11..part.len()-1]), - part if part.starts_with("headers=") => headers = Some(&part[9..part.len()-1]), - part if part.starts_with("signature=") => signature = Some(&part[11..part.len()-1]), - _ => {}, - } - } - if signature.is_some() && headers.is_some() { - let headers = headers.unwrap().split_whitespace().collect::>(); - let signature = signature.unwrap(); - let h = headers.iter() - .map(|header| (header,all_headers.get_one(header))) - .map(|(header, value)| format!("{}: {}", header.to_lowercase(), value.unwrap_or(""))) - .collect::>().join("\n"); - if sender.verify(h, base64::decode(signature).unwrap_or(Vec::new())) { - if headers.contains(&"digest") { - let digest = all_headers.get_one("digest").unwrap_or(""); - let digest = request::Digest::from_header(digest); - if digest.map(|d| d.verify(data)).unwrap_or(false) { - SignatureValidity::Valid - } else { - SignatureValidity::Invalid - } - } else { - SignatureValidity::ValidNoDigest - } - } else { - SignatureValidity::Invalid - } - } else { - SignatureValidity::Invalid + let sig_header = all_headers.get_one("Signature"); + if sig_header.is_none() { + return SignatureValidity::Absent + } + let sig_header = sig_header.unwrap(); + + let mut _key_id = None; + let mut _algorithm = None; + let mut headers = None; + let mut signature = None; + for part in sig_header.split(',') { + match part { + part if part.starts_with("keyId=") => _key_id = Some(&part[7..part.len()-1]), + part if part.starts_with("algorithm=") => _algorithm = Some(&part[11..part.len()-1]), + part if part.starts_with("headers=") => headers = Some(&part[9..part.len()-1]), + part if part.starts_with("signature=") => signature = Some(&part[11..part.len()-1]), + _ => {}, } + } + + if signature.is_none() || headers.is_none() {//missing part of the header + return SignatureValidity::Invalid + } + let headers = headers.unwrap().split_whitespace().collect::>(); + let signature = signature.unwrap(); + let h = headers.iter() + .map(|header| (header,all_headers.get_one(header))) + .map(|(header, value)| format!("{}: {}", header.to_lowercase(), value.unwrap_or(""))) + .collect::>().join("\n"); + + if !sender.verify(h, base64::decode(signature).unwrap_or(Vec::new())) { + return SignatureValidity::Invalid + } + if !headers.contains(&"digest") {// signature is valid, but body content is not verified + return SignatureValidity::ValidNoDigest + } + let digest = all_headers.get_one("digest").unwrap_or(""); + let digest = request::Digest::from_header(digest); + if !digest.map(|d| d.verify(data)).unwrap_or(false) {// signature was valid, but body content does not match its digest + SignatureValidity::Invalid } else { - SignatureValidity::Absent + SignatureValidity::Valid// all check passed } }