Include (request-target) and Host header to HTTP Signature
This commit is contained in:
		
							parent
							
								
									76f7b5e7ac
								
							
						
					
					
						commit
						bd1caaf5da
					
				| @ -1,6 +1,6 @@ | ||||
| use activitypub::{Activity, Link, Object}; | ||||
| use array_tool::vec::Uniq; | ||||
| use reqwest::r#async::ClientBuilder; | ||||
| use reqwest::{header::HeaderValue, r#async::ClientBuilder, Url}; | ||||
| use rocket::{ | ||||
|     http::Status, | ||||
|     request::{FromRequest, Request}, | ||||
| @ -143,6 +143,20 @@ where | ||||
|     for inbox in boxes { | ||||
|         let body = signed.to_string(); | ||||
|         let mut headers = request::headers(); | ||||
|         let url = Url::parse(&inbox); | ||||
|         if url.is_err() { | ||||
|             warn!("Inbox is invalid URL: {:?}", &inbox); | ||||
|             continue; | ||||
|         } | ||||
|         let url = url.unwrap(); | ||||
|         if !url.has_host() { | ||||
|             warn!("Inbox doesn't have host: {:?}", &inbox); | ||||
|             continue; | ||||
|         }; | ||||
|         headers.insert( | ||||
|             "Host", | ||||
|             HeaderValue::from_str(&url.host_str().unwrap()).unwrap(), | ||||
|         ); | ||||
|         headers.insert("Digest", request::Digest::digest(&body)); | ||||
|         rt.spawn( | ||||
|             client | ||||
| @ -150,7 +164,7 @@ where | ||||
|                 .headers(headers.clone()) | ||||
|                 .header( | ||||
|                     "Signature", | ||||
|                     request::signature(sender, &headers) | ||||
|                     request::signature(sender, &headers, "post", url.path(), url.query()) | ||||
|                         .expect("activity_pub::broadcast: request signature error"), | ||||
|                 ) | ||||
|                 .body(body) | ||||
|  | ||||
| @ -112,25 +112,46 @@ pub fn headers() -> HeaderMap { | ||||
|     headers | ||||
| } | ||||
| 
 | ||||
| pub fn signature<S: Signer>(signer: &S, headers: &HeaderMap) -> Result<HeaderValue, Error> { | ||||
|     let signed_string = headers | ||||
| type Method<'a> = &'a str; | ||||
| type Path<'a> = &'a str; | ||||
| type Query<'a> = &'a str; | ||||
| 
 | ||||
| pub fn signature<S: Signer>( | ||||
|     signer: &S, | ||||
|     headers: &HeaderMap, | ||||
|     method: Method, | ||||
|     path: Path, | ||||
|     query: Option<Query>, | ||||
| ) -> Result<HeaderValue, Error> { | ||||
|     let origin_form = if let Some(query) = query { | ||||
|         format!("{}?{}", path, query) | ||||
|     } else { | ||||
|         path.to_string() | ||||
|     }; | ||||
| 
 | ||||
|     let mut headers = headers | ||||
|         .iter() | ||||
|         .map(|(h, v)| { | ||||
|             format!( | ||||
|                 "{}: {}", | ||||
|             ( | ||||
|                 h.as_str().to_lowercase(), | ||||
|                 v.to_str() | ||||
|                     .expect("request::signature: invalid header error") | ||||
|                     .expect("request::signature: invalid header error"), | ||||
|             ) | ||||
|         }) | ||||
|         .collect::<Vec<(String, &str)>>(); | ||||
|     let request_target = format!("{} {}", method.to_lowercase(), origin_form); | ||||
|     headers.push(("(request-target)".to_string(), &request_target)); | ||||
| 
 | ||||
|     let signed_string = headers | ||||
|         .iter() | ||||
|         .map(|(h, v)| format!("{}: {}", h, v)) | ||||
|         .collect::<Vec<String>>() | ||||
|         .join("\n"); | ||||
|     let signed_headers = headers | ||||
|         .iter() | ||||
|         .map(|(h, _)| h.as_str()) | ||||
|         .map(|(h, _)| h.as_ref()) | ||||
|         .collect::<Vec<&str>>() | ||||
|         .join(" ") | ||||
|         .to_lowercase(); | ||||
|         .join(" "); | ||||
| 
 | ||||
|     let data = signer.sign(&signed_string).map_err(|_| Error())?; | ||||
|     let sign = base64::encode(&data); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user