//! datse server over HTTP
use super ::* ;
use futures ::{
future ::{
OptionFuture ,
FutureExt ,
} ,
stream ,
} ;
use warp ::{
Filter ,
hyper ::body ::Bytes ,
} ;
use std ::{
str ,
sync ::Arc ,
convert ::Infallible ,
} ;
use cryptohelpers ::{
sha256 ,
rsa ,
} ;
use state ::State ;
use uuid ::Uuid ;
use server ::state ::ServerState ;
use settings ::Settings ;
/// Web server config
#[ derive(Debug, Clone, PartialEq, Eq) ]
pub struct Config
{
}
pub mod settings ;
mod session ;
mod state ;
mod source ;
mod forwarded_list ;
mod auth ;
/// Main entry point for web server
pub async fn main ( state : ServerState , cfg : Settings ) -> eyre ::Result < ( ) >
{
let state = Arc ::new ( State ::new ( state , cfg . clone ( ) ) ) ;
let state = warp ::any ( ) . map ( move | | state . clone ( ) ) ;
// Extract the client IP or fail with custom rejection
let client_ip = warp ::addr ::remote ( )
. and ( warp ::header ( "X-Forwarded-For" ) )
. map ( source ::extract ( cfg . trust_x_forwarded_for ) )
. and_then ( | req : Result < std ::net ::IpAddr , _ > | async move { req . map_err ( warp ::reject ::custom ) } ) ;
// /auth/req - Request an auth ID and information about how to respond (data to sign / password salt / what is supported, etc)
// /auth/resp/<req_id>/pw/<passwd hash> - Respond to an auth ID with a hashed password, salted with the salt obtained from the req call.
// /auth/resp/<req_id>/si[/<num of sigs in body>] - Respond to an auth ID with one or more signatures of the data to be signed obtained in the auth request. If no number is provided, 1 is assumed.
let auth = {
let req = warp ::path ( "req" )
. and ( client_ip . clone ( ) ) . and ( state . clone ( ) )
. and_then ( auth ::auth_req ) ;
let resp = {
let resp_auth_with_state = warp ::post ( )
. and ( client_ip . clone ( ) ) . and ( state . clone ( ) )
. and ( warp ::path ::param ( ) . map ( | req_id : uuid ::Uuid | req_id ) ) ;
let resp_auth_key = resp_auth_with_state . clone ( )
. and ( warp ::path ( "si" )
. and ( warp ::path ::param ( ) . map ( | num : usize | std ::cmp ::min ( std ::cmp ::max ( 1 ,
num ) ,
cfg . max_key_sigs_per_auth_response ) )
. or ( warp ::path ::end ( ) . map ( | | 1 usize ) ) . unify ( ) ) )
. and ( warp ::body ::content_length_limit ( cfg . max_body_len . 0 ) )
. and ( warp ::body ::bytes ( ) )
. and_then ( auth ::auth_key ) ;
// -- Paths --
let resp_auth_pass = {
let pw_path = resp_auth_with_state
. and ( warp ::path ( "pw" ) ) ;
if cfg . allow_passwd_auth {
pw_path . and ( warp ::path ::param ( ) . map ( | hash : auth ::Sha256Hash | hash . 0 ) )
. and ( warp ::path ::end ( ) )
. and_then ( auth ::auth_pass ) . boxed ( )
} else {
pw_path . and_then ( | _addr , _state , _hash | async move { Err ( warp ::reject ::not_found ( ) ) } ) . boxed ( )
}
} ;
let resp = warp ::path ( "resp" )
. and ( resp_auth_key
. or ( resp_auth_pass ) ) ;
// /resp/<req_id>/pw/<passwd hash>
// /resp/<req_id>/si[/<num of sigs in body>]
resp
} ;
warp ::path ( "auth" )
. and ( req . or ( resp ) )
. recover ( auth ::AuthError ::recover )
} ;
todo! ( )
}