wala-rust

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit d4ec353a8f75f9710b92dfb40e3b05ec3f0888d5
parent b26b80c16ae2fa1317f41f2c30da47c695fcc5c9
Author: lash <dev@holbrook.no>
Date:   Fri, 24 Jun 2022 09:01:02 +0000

Swap request data to file to enable multiple reads

Diffstat:
Msrc/auth/pgp.rs | 53++++++++++++++++++++++++++++++++++++++++-------------
Msrc/main.rs | 70++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/record.rs | 4++--
Msrc/request.rs | 6++++--
4 files changed, 98 insertions(+), 35 deletions(-)

diff --git a/src/auth/pgp.rs b/src/auth/pgp.rs @@ -1,3 +1,4 @@ +use std::io::Read; use crate::auth::{ AuthSpec, AuthError, @@ -69,10 +70,10 @@ fn check_key_bundle(data: &Vec<u8>) -> Option<PublicKey> { // None } -fn check_sig_single(public_key: &PublicKey, signature_data: Vec<u8>, message: Vec<u8>) -> bool { +fn check_sig_single(public_key: &PublicKey, signature_data: Vec<u8>, mut message: impl Read, message_length: usize) -> bool { match Signature::from_slice(Version::Old, &signature_data) { Ok(v) => { - match v.verify(public_key, &message[..]) { + match v.verify(public_key, message) { Ok(v) => { return true; }, @@ -84,10 +85,12 @@ fn check_sig_single(public_key: &PublicKey, signature_data: Vec<u8>, message: Ve false } -fn check_sig_bundle(public_key: &PublicKey, signature_data: Vec<u8>, message: Vec<u8>) -> bool { +fn check_sig_bundle(public_key: &PublicKey, signature_data: Vec<u8>, mut message: impl Read, message_length: usize) -> bool { match StandaloneSignature::from_bytes(&signature_data[..]) { Ok(v) => { - match v.verify(public_key, &message[..]) { + let mut data: Vec<u8> = vec!(); + let r = message.read_to_end(&mut data); + match v.verify(public_key, &data) { Ok(v) => { return true; }, @@ -99,28 +102,47 @@ fn check_sig_bundle(public_key: &PublicKey, signature_data: Vec<u8>, message: Ve false } -pub fn auth_check(auth: &AuthSpec) -> Result<AuthResult, AuthError> { +pub fn auth_check(auth: &AuthSpec, data: impl Read, data_length: usize) -> Result<AuthResult, AuthError> { if auth.method != "pgp" { return Err(AuthError{}); } + let key_data = match base64::decode(&auth.key) { Ok(v) => { - debug!("found valid raw key"); v }, Err(e) => { return Err(AuthError{}); } }; + + let sig_data = match base64::decode(&auth.signature) { + Ok(v) => { + v + }, + Err(e) => { + return Err(AuthError{}); + } + }; + let key = match check_key_single(&key_data) { Some(v) => { + if !check_sig_single(&v, sig_data, data, data_length) { + error!("invalid raw signature for {:?}", hex::encode(&v.fingerprint())); + return Err(AuthError{}); + } + debug!("found valid raw key {:?}", hex::encode(&v.fingerprint())); v }, None => { let key = match check_key_bundle(&key_data) { Some(v) => { - debug!("found valid key bundle"); + if !check_sig_bundle(&v, sig_data, data, data_length) { + error!("invalid bundle signature for {:?}", hex::encode(&v.fingerprint())); + return Err(AuthError{}); + } + debug!("found valid key bundle {:?}", hex::encode(&v.fingerprint())); v }, None => { @@ -131,8 +153,6 @@ pub fn auth_check(auth: &AuthSpec) -> Result<AuthResult, AuthError> { }, }; - println!("key {:?}", key); - let res = AuthResult { identity: key.fingerprint(), @@ -169,9 +189,10 @@ mod tests { let auth_spec_str = format!("pgp:{}:{}", key_single_base64, sig_foo_single_base64); let auth_spec = AuthSpec::from_str(&auth_spec_str).unwrap(); + let data = b"foo"; let r = match check_key_single(&key_single) { Some(v) => { - if !check_sig_single(&v, sig_foo_single, b"foo".to_vec()) { + if !check_sig_single(&v, sig_foo_single, &data[..], 0) { panic!("invalid"); } }, @@ -194,9 +215,11 @@ mod tests { let sig_foo_bundle = hex::decode(&sig_foo_bundle_hex).unwrap(); let sig_foo_bundle_base64 = base64::encode(&sig_foo_bundle); + let data = b"foo"; + let r = match check_key_bundle(&key_bundle) { Some(v) => { - if !check_sig_bundle(&v, sig_foo_bundle, b"foo".to_vec()) { + if !check_sig_bundle(&v, sig_foo_bundle, &data[..], 0) { panic!("invalid"); } }, @@ -221,7 +244,9 @@ mod tests { let auth_spec_str = format!("pgp:{}:{}", key_single_base64, sig_foo_single_base64); let auth_spec = AuthSpec::from_str(&auth_spec_str).unwrap(); - match auth_check(&auth_spec) { + let data = b"foo"; + + match auth_check(&auth_spec, &data[..], 0) { Ok(v) => { }, Err(e) => { @@ -244,7 +269,9 @@ mod tests { let auth_spec_str = format!("pgp:{}:{}", key_bundle_base64, sig_foo_bundle_base64); let auth_spec = AuthSpec::from_str(&auth_spec_str).unwrap(); - match auth_check(&auth_spec) { + let data = b"foo"; + + match auth_check(&auth_spec, &data[..], 0) { Ok(v) => { }, Err(e) => { diff --git a/src/main.rs b/src/main.rs @@ -4,6 +4,8 @@ use tiny_http::{ Request, Response, StatusCode, + Header, + Method, }; use std::net::{Ipv4Addr, SocketAddrV4}; use std::str::FromStr; @@ -11,6 +13,12 @@ use std::path::{PathBuf, Path}; use std::fs::File; use std::error::Error; use std::fmt; +use std::io::{ + copy as io_copy, + Read, + Seek, + empty, +}; use env_logger; @@ -31,7 +39,7 @@ use request::process_method; use log::{debug, info, error}; -use tempfile::NamedTempFile; +use tempfile::tempfile; #[cfg(feature = "dev")] @@ -57,7 +65,7 @@ impl fmt::Display for NoAuthError { } -fn exec_response(mut req: Request, r: RequestResult) { +fn exec_response(req: Request, r: RequestResult) { let res_status: StatusCode; match r.typ { RequestResultType::Found => { @@ -108,9 +116,9 @@ fn exec_response(mut req: Request, r: RequestResult) { } -fn exec_auth(auth_spec: AuthSpec) -> Option<AuthResult> { +fn exec_auth(auth_spec: AuthSpec, data: impl Read, data_length: usize) -> Option<AuthResult> { #[cfg(feature = "dev")] - match mock_auth_check(&auth_spec) { + match mock_auth_check(&auth_spec, data, data_length) { Ok(v) => { return Some(v); }, @@ -119,7 +127,7 @@ fn exec_auth(auth_spec: AuthSpec) -> Option<AuthResult> { } #[cfg(feature = "pgpauth")] - match pgp_auth_check(&auth_spec) { + match pgp_auth_check(&auth_spec, data, data_length) { Ok(v) => { return Some(v); }, @@ -131,7 +139,7 @@ fn exec_auth(auth_spec: AuthSpec) -> Option<AuthResult> { } -fn process_auth(auth_spec: AuthSpec) -> Option<AuthResult> { +fn process_auth(auth_spec: AuthSpec, data: impl Read, data_length: usize) -> Option<AuthResult> { if !auth_spec.valid() { let r = AuthResult{ identity: vec!(), @@ -139,12 +147,12 @@ fn process_auth(auth_spec: AuthSpec) -> Option<AuthResult> { }; return Some(r); } - exec_auth(auth_spec) + exec_auth(auth_spec, data, data_length) } -fn auth_from_headers(req: &Request) -> Option<AuthSpec> { - for h in req.headers() { +fn auth_from_headers(headers: &[Header], method: &Method) -> Option<AuthSpec> { + for h in headers { let k = &h.field; if k.equiv("Authorization") { let v = &h.value; @@ -155,7 +163,6 @@ fn auth_from_headers(req: &Request) -> Option<AuthSpec> { }, Err(e) => { error!("malformed auth string: {}", &h.value); - let method = req.method(); let r = AuthSpec{ method: String::from(method.as_str()), key: String::new(), @@ -170,12 +177,15 @@ fn auth_from_headers(req: &Request) -> Option<AuthSpec> { } -fn process_request(mut req: &Request) -> AuthResult { +fn process_request(req: &mut Request, f: &File) -> AuthResult { + let headers = req.headers(); + let method = req.method(); + let r: Option<AuthResult>; - r = match auth_from_headers(req) { + r = match auth_from_headers(headers, method) { Some(v) => { - process_auth(v) + process_auth(v, f, 0) }, _ => { None @@ -196,6 +206,7 @@ fn process_request(mut req: &Request) -> AuthResult { } } + fn main() { env_logger::init(); @@ -221,9 +232,6 @@ fn main() { } }; - let res = process_request(&req); - - let mut path = base_path.clone(); let url = String::from(&req.url()[1..]); let method = req.method().clone(); @@ -236,9 +244,35 @@ fn main() { }, }; let f = req.as_reader(); + let mut path = base_path.clone(); + let mut res: AuthResult = AuthResult{ + identity: vec!(), + error: false, + }; + let rw: Option<File> = match tempfile() { + Ok(mut v) => { + io_copy(f, &mut v); + v.rewind(); + res = process_request(&mut req, &mut v); + v.rewind(); + Some(v) + }, + Err(e) => { + None + }, + }; + + let mut result: RequestResult; + match rw { + Some(v) => { + result = process_method(&method, url, v, expected_size, &path, res); + }, + None => { + let v = empty(); + result = process_method(&method, url, v, expected_size, &path, res); + }, + }; - let mut result = process_method(&method, url, f, expected_size, &path, res); - exec_response(req, result); } } diff --git a/src/record.rs b/src/record.rs @@ -174,10 +174,10 @@ pub fn put_immutable(path: &Path, mut f: impl Read, expected_size: usize) -> Res } pub fn put_mutable(pointer: Vec<u8>, path: &Path, mut f: impl Read, expected_size: usize) -> Result<Record, RequestResult> { - let record = put_immutable(path, f, expected_size); - let mutable_ref = hex::encode(&pointer); let link_path_buf = path.join(&mutable_ref); + + let record = put_immutable(path, f, expected_size); match record { Ok(v) => { symlink(&v.path, &link_path_buf); diff --git a/src/request.rs b/src/request.rs @@ -21,6 +21,7 @@ use std::io::Read; use log::{ debug, + error, }; pub fn process_method(method: &Method, url: String, mut f: impl Read, expected_size: usize, path: &Path, auth_result: AuthResult) -> RequestResult { @@ -36,7 +37,7 @@ pub fn process_method(method: &Method, url: String, mut f: impl Read, expected_s if auth_result.active() { let res: RequestResult; let rk = ResourceKey::from_str(url.as_str()).unwrap(); - debug!("authenticated as {:?} using mutable key {} -> {}", auth_result, &url, &rk); + debug!("mutable put, authenticated as {:?} using mutable key {} -> {}", auth_result, &url, &rk); let ptr = rk.pointer_for(&auth_result); match put_mutable(ptr, path, f, expected_size) { Ok(v) => { @@ -48,7 +49,8 @@ pub fn process_method(method: &Method, url: String, mut f: impl Read, expected_s }; }, Err(e) => { - let err_str = format!("{}", e); + let err_str = format!("{:?}", e); + error!("{}", err_str); res = RequestResult { typ: RequestResultType::RecordError, v: Some(String::from(err_str)),