diff options
Diffstat (limited to 'crates/sellershut/src/server/middleware/sign_request.rs')
-rw-r--r-- | crates/sellershut/src/server/middleware/sign_request.rs | 124 |
1 files changed, 100 insertions, 24 deletions
diff --git a/crates/sellershut/src/server/middleware/sign_request.rs b/crates/sellershut/src/server/middleware/sign_request.rs index 889984f..4eb3bd3 100644 --- a/crates/sellershut/src/server/middleware/sign_request.rs +++ b/crates/sellershut/src/server/middleware/sign_request.rs @@ -1,20 +1,21 @@ mod signature; -use activitypub_federation::config::FederationConfig; +use activitypub_federation::{config::FederationConfig, traits::Object}; use axum::{ body::Body, extract::Request, - http::HeaderValue, + http::{HeaderValue, StatusCode}, response::Response, }; use futures_util::future::BoxFuture; -use std::{ - task::{Context, Poll}, -}; +use std::task::{Context, Poll}; use tower::{Layer, Service}; +use tracing::trace; -use crate::{server::middleware::sign_request::signature::Signature, state::AppHandle}; - +use crate::{ + server::{middleware::sign_request::signature::Signature, routes::users::get_user::read_user}, + state::AppHandle, +}; #[derive(Clone)] pub struct SignRequestLayer { @@ -62,30 +63,105 @@ where fn call(&mut self, request: Request) -> Self::Future { let mut inner = self.inner.clone(); + let uri = request.uri().clone(); let (parts, body) = request.into_parts(); + let state = self.state.to_request_data(); + let domain = self.state.domain().to_owned(); Box::pin(async move { - let bytes = axum::body::to_bytes(body, usize::MAX).await.unwrap(); - - let signature = Signature::create( - "" - .as_bytes(), - bytes, - ) - .unwrap(); + let ok_500 = || { + let mut response = axum::response::Response::default(); + *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + Ok(response) + }; + let bytes = match axum::body::to_bytes(body, usize::MAX).await { + Ok(b) => b, + Err(e) => { + trace!("could not decode response body: {e:?}"); + return ok_500(); + } + }; + + // Get user + let user = match read_user("sellershut", &state).await { + Ok(Some(u)) => u, + Ok(None) => { + trace!("user not found"); + return ok_500(); + } + Err(e) => { + trace!("failed to read user: {e:?}"); + return ok_500(); + } + }; + + let pk = user.private_key.clone().unwrap_or_default(); + + let json_user = match user.into_json(&state).await { + Ok(j) => j, + Err(e) => { + trace!("failed to serialise user: {e:?}"); + return ok_500(); + } + }; + + // Sign the body + let signature = match Signature::new(pk.as_bytes(), bytes, uri, &domain) { + Ok(sig) => sig, + Err(e) => { + trace!("signature creation failed: {e:?}"); + return ok_500(); + } + }; let mut new_request = Request::from_parts(parts, Body::from(signature.body)); let head = new_request.headers_mut(); - let header = format!( - "keyId=\"http://localhost/users/sellershut#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"{}\"", - signature.signature, - ); - println!("{header}"); - head.insert("Host", HeaderValue::from_str(&signature.host).unwrap()); - head.insert("Date", HeaderValue::from_str(&signature.date).unwrap()); - head.insert("Digest", HeaderValue::from_str(&signature.digest).unwrap()); - head.insert("Signature", HeaderValue::from_str(&header).unwrap()); + + let header = [ + format!("keyId=\"{}\"", json_user.public_id()), + "algorithm=rsa-sha256".to_string(), + "headers=\"(request-target) host date digest\"".to_string(), + format!("signature=\"{}\"", signature.signature), + ] + .join(","); + + let host = match HeaderValue::from_str(&signature.host) { + Ok(value) => value, + Err(e) => { + trace!(name = "host",value = ?signature.host, "header creation failed: {e:?}"); + return ok_500(); + } + }; + + let date = match HeaderValue::from_str(&signature.date) { + Ok(value) => value, + Err(e) => { + trace!(name = "date",value = ?signature.date, "header creation failed: {e:?}"); + return ok_500(); + } + }; + + let digest = match HeaderValue::from_str(&signature.digest) { + Ok(value) => value, + Err(e) => { + trace!(name = "digest",value = ?signature.digest, "header creation failed: {e:?}"); + return ok_500(); + } + }; + + let signature = match HeaderValue::from_str(&header) { + Ok(value) => value, + Err(e) => { + trace!(name = "signature", "header creation failed: {e:?}"); + return ok_500(); + } + }; + + head.insert("Host", host); + head.insert("Date", date); + head.insert("Digest", digest); + head.insert("Signature", signature); inner.call(new_request).await }) |