Refactor and verify http signature on personnal inbox
Verify signature on personnal inbox Reduce code duplication Put Headers in plume-models
This commit is contained in:
		
							parent
							
								
									0a5d435249
								
							
						
					
					
						commit
						62c94ed463
					
				| @ -128,6 +128,15 @@ pub enum SignatureValidity { | ||||
|     Absent, | ||||
| } | ||||
| 
 | ||||
| impl SignatureValidity { | ||||
|     pub fn is_secure(&self) -> bool { | ||||
|         match self { | ||||
|             SignatureValidity::Valid => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn verify_http_headers<S: sign::Signer+::std::fmt::Debug>(sender: &S, all_headers: HeaderMap, data: String) -> SignatureValidity{ | ||||
|     if let Some(sig_header) = all_headers.get_one("Signature") { | ||||
|         let mut _key_id = None; | ||||
|  | ||||
							
								
								
									
										17
									
								
								plume-models/src/headers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								plume-models/src/headers.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| use rocket::request::{self, FromRequest, Request}; | ||||
| use rocket::{http::HeaderMap, Outcome}; | ||||
| 
 | ||||
| 
 | ||||
| pub struct Headers<'r>(pub HeaderMap<'r>); | ||||
| 
 | ||||
| impl<'a, 'r> FromRequest<'a, 'r> for Headers<'r> { | ||||
|     type Error = (); | ||||
| 
 | ||||
|     fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> { | ||||
|         let mut headers = HeaderMap::new(); | ||||
|         for header in request.headers().clone().into_iter() { | ||||
|             headers.add(header); | ||||
|         } | ||||
|         Outcome::Success(Headers(headers)) | ||||
|     } | ||||
| } | ||||
| @ -110,6 +110,7 @@ pub mod blogs; | ||||
| pub mod comments; | ||||
| pub mod db_conn; | ||||
| pub mod follows; | ||||
| pub mod headers; | ||||
| pub mod instance; | ||||
| pub mod likes; | ||||
| pub mod medias; | ||||
|  | ||||
| @ -1,16 +1,15 @@ | ||||
| use gettextrs::gettext; | ||||
| use rocket::{http::HeaderMap, Outcome, | ||||
|     request::{self, FromRequest, LenientForm, Request}, | ||||
|     response::Redirect}; | ||||
| use rocket::{request::LenientForm, response::Redirect}; | ||||
| use rocket_contrib::{Json, Template}; | ||||
| use serde_json; | ||||
| use validator::{Validate}; | ||||
| 
 | ||||
| use plume_common::activity_pub::{verify_http_headers, SignatureValidity}; | ||||
| use plume_common::activity_pub::verify_http_headers; | ||||
| use plume_models::{ | ||||
|     admin::Admin, | ||||
|     comments::Comment, | ||||
|     db_conn::DbConn, | ||||
|     headers::Headers, | ||||
|     posts::Post, | ||||
|     users::User, | ||||
|     safe_string::SafeString, | ||||
| @ -191,22 +190,6 @@ fn ban(_admin: Admin, conn: DbConn, id: i32) -> Redirect { | ||||
|     Redirect::to(uri!(admin_users)) | ||||
| } | ||||
| 
 | ||||
| struct Headers<'r> { | ||||
|     headers: HeaderMap<'r>, | ||||
| } | ||||
| 
 | ||||
| impl<'a, 'r> FromRequest<'a, 'r> for Headers<'r> { | ||||
|     type Error = (); | ||||
| 
 | ||||
|     fn from_request(request: &'a Request<'r>) ->request::Outcome<Self, ()> { | ||||
|         let mut headers = HeaderMap::new(); | ||||
|         for header in request.headers().clone().into_iter() { | ||||
|             headers.add(header); | ||||
|         } | ||||
|         Outcome::Success(Headers{headers}) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[post("/inbox", data = "<data>")] | ||||
| fn shared_inbox(conn: DbConn, data: String, headers: Headers) -> String { | ||||
|     let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap(); | ||||
| @ -215,14 +198,9 @@ fn shared_inbox(conn: DbConn, data: String, headers: Headers) -> String { | ||||
|     let actor_id = activity["actor"].as_str() | ||||
|         .unwrap_or_else(|| activity["actor"]["id"].as_str().expect("No actor ID for incoming activity, blocks by panicking")); | ||||
| 
 | ||||
|     let sig = match verify_http_headers(&User::from_url(&conn, actor_id.to_owned()).unwrap(), headers.headers, data) { | ||||
|         SignatureValidity::Valid => true, | ||||
|         _ => { | ||||
|             // TODO verify json signature
 | ||||
|             false | ||||
|         } | ||||
|     }; | ||||
|     let sig = verify_http_headers(&User::from_url(&conn, actor_id.to_owned()).unwrap(), headers.0, data).is_secure(); | ||||
|     if !sig { | ||||
|         // TODO check for valid json-ld signature
 | ||||
|         return "invalid signature".to_owned(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -16,13 +16,14 @@ use workerpool::thunk::*; | ||||
| 
 | ||||
| use plume_common::activity_pub::{ | ||||
|     ActivityStream, broadcast, Id, IntoId, ApRequest, | ||||
|     inbox::{FromActivity, Notify, Deletable} | ||||
|     verify_http_headers, inbox::{FromActivity, Notify, Deletable} | ||||
| }; | ||||
| use plume_common::utils; | ||||
| use plume_models::{ | ||||
|     blogs::Blog, | ||||
|     db_conn::DbConn, | ||||
|     follows, | ||||
|     headers::Headers, | ||||
|     instance::Instance, | ||||
|     posts::Post, | ||||
|     reshares::Reshare, | ||||
| @ -295,13 +296,20 @@ fn outbox(name: String, conn: DbConn) -> ActivityStream<OrderedCollection> { | ||||
| } | ||||
| 
 | ||||
| #[post("/@/<name>/inbox", data = "<data>")] | ||||
| fn inbox(name: String, conn: DbConn, data: String) -> String { | ||||
| fn inbox(name: String, conn: DbConn, data: String, headers: Headers) -> String { | ||||
|     let user = User::find_local(&*conn, name).unwrap(); | ||||
|     let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap(); | ||||
| 
 | ||||
|     let activity = act.clone(); | ||||
|     let actor_id = activity["actor"].as_str() | ||||
|         .unwrap_or_else(|| activity["actor"]["id"].as_str().expect("User: No actor ID for incoming activity, blocks by panicking")); | ||||
| 
 | ||||
|     let sig = verify_http_headers(&User::from_url(&conn, actor_id.to_owned()).unwrap(), headers.0, data).is_secure(); | ||||
|     if !sig { | ||||
|         // TODO check for json-ld signature
 | ||||
|         return "invalid signature".to_owned(); | ||||
|     } | ||||
| 
 | ||||
|     if Instance::is_blocked(&*conn, actor_id.to_string()) { | ||||
|         return String::new(); | ||||
|     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user