@@ -37,10 +37,7 @@ fn extract_amz_content_sha256<'a>(hs: &'_ OrderedHeaders<'a>) -> S3Result<Option
3737 Ok ( x) => Ok ( Some ( x) ) ,
3838 Err ( e) => {
3939 // https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-troubleshooting.html
40- let mut err = S3Error :: new ( S3ErrorCode :: SignatureDoesNotMatch ) ;
41- err. set_message ( "invalid header: x-amz-content-sha256" ) ;
42- err. set_source ( Box :: new ( e) ) ;
43- Err ( err)
40+ Err ( s3_error ! ( e, SignatureDoesNotMatch , "invalid header: x-amz-content-sha256" ) )
4441 }
4542 }
4643}
@@ -271,6 +268,11 @@ impl SignatureContext<'_> {
271268 // Per AWS SigV4 spec, the signed POST policy must contain eq conditions
272269 // for x-amz-date, x-amz-credential, and x-amz-algorithm that match the
273270 // submitted form fields exactly.
271+ //
272+ // TODO: the policy is parsed again later in `prepare` via
273+ // `PostPolicy::from_base64` + `validate_conditions_only`. Consider
274+ // caching the parsed `PostPolicy` here and reusing it downstream to
275+ // avoid the double base64-decode + JSON-parse.
274276 {
275277 let policy = PostPolicy :: from_base64 ( info. policy ) . map_err ( |e| s3_error ! ( e, InvalidPolicyDocument ) ) ?;
276278
@@ -292,9 +294,7 @@ impl SignatureContext<'_> {
292294
293295 // Per AWS SigV4 spec, the credential scope date must match the x-amz-date date.
294296 if credential. date != amz_date. fmt_date ( ) . as_str ( ) {
295- let mut err = S3Error :: new ( S3ErrorCode :: SignatureDoesNotMatch ) ;
296- err. set_message ( "credential scope date does not match x-amz-date" ) ;
297- return Err ( err) ;
297+ return Err ( s3_error ! ( SignatureDoesNotMatch , "credential scope date does not match x-amz-date" ) ) ;
298298 }
299299
300300 validate_sig_v4_clock_skew ( & amz_date, time:: OffsetDateTime :: now_utc ( ) , & self . config . snapshot ( ) ) ?;
@@ -348,9 +348,7 @@ impl SignatureContext<'_> {
348348
349349 // Per AWS SigV4 spec, the credential scope date must match the x-amz-date date.
350350 if presigned_url. credential . date != presigned_url. amz_date . fmt_date ( ) . as_str ( ) {
351- let mut err = S3Error :: new ( S3ErrorCode :: SignatureDoesNotMatch ) ;
352- err. set_message ( "credential scope date does not match x-amz-date" ) ;
353- return Err ( err) ;
351+ return Err ( s3_error ! ( SignatureDoesNotMatch , "credential scope date does not match x-amz-date" ) ) ;
354352 }
355353
356354 // ASK: how to use it?
@@ -456,6 +454,16 @@ impl SignatureContext<'_> {
456454
457455 let auth = require_auth ( self . auth ) ?;
458456
457+ // Reject stale requests before doing I/O work (secret key lookup).
458+ let amz_date = extract_amz_date ( & self . hs ) ?. ok_or_else ( || invalid_request ! ( "missing header: x-amz-date" ) ) ?;
459+
460+ // Per AWS SigV4 spec, the credential scope date must match the x-amz-date date.
461+ if authorization. credential . date != amz_date. fmt_date ( ) . as_str ( ) {
462+ return Err ( s3_error ! ( SignatureDoesNotMatch , "credential scope date does not match x-amz-date" ) ) ;
463+ }
464+
465+ validate_sig_v4_clock_skew ( & amz_date, time:: OffsetDateTime :: now_utc ( ) , & self . config . snapshot ( ) ) ?;
466+
459467 let amz_content_sha256 = extract_amz_content_sha256 ( & self . hs ) ?;
460468
461469 if service == "s3" && amz_content_sha256. is_none ( ) {
@@ -465,17 +473,6 @@ impl SignatureContext<'_> {
465473 let access_key = authorization. credential . access_key_id ;
466474 let secret_key = auth. get_secret_key ( access_key) . await ?;
467475
468- let amz_date = extract_amz_date ( & self . hs ) ?. ok_or_else ( || invalid_request ! ( "missing header: x-amz-date" ) ) ?;
469-
470- // Per AWS SigV4 spec, the credential scope date must match the x-amz-date date.
471- if authorization. credential . date != amz_date. fmt_date ( ) . as_str ( ) {
472- let mut err = S3Error :: new ( S3ErrorCode :: SignatureDoesNotMatch ) ;
473- err. set_message ( "credential scope date does not match x-amz-date" ) ;
474- return Err ( err) ;
475- }
476-
477- validate_sig_v4_clock_skew ( & amz_date, time:: OffsetDateTime :: now_utc ( ) , & self . config . snapshot ( ) ) ?;
478-
479476 let is_stream = amz_content_sha256. is_some_and ( |v| v. is_streaming ( ) ) ;
480477
481478 let expected_signature = authorization. signature ;
0 commit comments