From 4cd243e545486b1332f6784fcf00586f77b7b8f4 Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Thu, 23 Apr 2020 12:24:53 +0100 Subject: [PATCH] Fix bug where digest was required even for GET requests Rouille returns `Some(empty body)` for GET requests, rather than the `None` we were expecting, so allow the digest to be omitted when the body is present but empty. --- Cargo.toml | 2 +- README.md | 9 ++++++--- src/rouille_impls.rs | 29 ++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1d73ae2..f1fb26f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "http-sig" description = "Implementation of the IETF draft 'Signing HTTP Messages'" -version = "0.3.0" +version = "0.3.1" authors = ["Jack Cargill ", "Diggory Blake"] edition = "2018" readme = "README.md" diff --git a/README.md b/README.md index 8027877..6734c6e 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,18 @@ features. | [reqwest](https://crates.io/crates/reqwest) | Client | Supports blocking and non-blocking requests.1 | | [rouille](https://crates.io/crates/rouille) | Server | | -1. Due to limitations of the reqwest API, digests can only be calculated automatically for non-blocking non-streaming requests. For - blocking or streaming requests, the user must add the digest manually before signing the request, or else the `Digest` header will - not be included in the signature. +1. Due to limitations of the reqwest API, digests cannot be calculated automatically for non-blocking, streaming requests. For + these requests, the user must add the digest manually before signing the request, or else the `Digest` header will + not be included in the signature. Automatic digests for streaming requests *are* supported via the blocking API. ### Supported signature algorithms: Algorithm registry: https://tools.ietf.org/id/draft-cavage-http-signatures-12.html#hsa-registry - `hmac-sha256` +- `hmac-sha512` +- `rsa-sha256` +- `rsa-sha512` ### Supported digest algorithms: diff --git a/src/rouille_impls.rs b/src/rouille_impls.rs index 355704e..9a18ac8 100644 --- a/src/rouille_impls.rs +++ b/src/rouille_impls.rs @@ -58,6 +58,8 @@ impl<'a> ServerRequestLike for &'a rouille::Request { let mut result = Vec::new(); if let Err(e) = body.read_to_end(&mut result) { (None, Some(RouilleBody(RouilleBodyInner::Digested(Err(e))))) + } else if result.is_empty() { + (None, None) } else { let computed_digest = digest.http_digest(&result); ( @@ -87,7 +89,7 @@ mod tests { use super::*; #[test] - fn it_works() { + fn can_verify_post_request() { let key_provider = SimpleKeyProvider::new(vec![( "test_key", Arc::new(DefaultSignatureAlgorithm::new("abcdefgh".as_bytes())) @@ -113,4 +115,29 @@ mod tests { request.verify(&config).unwrap(); } + + #[test] + fn can_verify_get_request() { + let key_provider = SimpleKeyProvider::new(vec![( + "test_key", + Arc::new(DefaultSignatureAlgorithm::new("abcdefgh".as_bytes())) + as Arc, + )]); + let config = VerifyingConfig::new(key_provider).with_validate_date(false); + + let request = rouille::Request::fake_http( + "GET", + "/foo/bar", + vec![ + ("Date".into(), Utc.ymd(2014, 7, 8) + .and_hms(9, 10, 11) + .format("%a, %d %b %Y %T GMT") + .to_string()), + ("Authorization".into(), "Signature keyId=\"test_key\",algorithm=\"hmac-sha256\",signature=\"sGQ3hA9KB40CU1pHbRLXLvLdUWYn+c3fcfL+Sw8kIZE=\",headers=\"(request-target) date".into()), + ], + Vec::new() + ); + + request.verify(&config).unwrap(); + } }