Unverified Commit 613da266 authored by Nugine's avatar Nugine
Browse files

s3s: ops: sig_v4: check expiration

parent ffbd65c0
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -385,10 +385,26 @@ impl SignatureContext<'_> {
        // ASK: how to use it?
        let _content_sha256: Option<AmzContentSha256<'_>> = extract_amz_content_sha256(&self.headers)?;

        // FIXME: check expiration
        {
            // check expiration
            let now = time::OffsetDateTime::now_utc();

        let auth = require_auth(self.auth)?;
            let date = presigned_url
                .amz_date
                .to_time()
                .ok_or_else(|| invalid_request!("invalid amz date"))?;

            let duration = now - date;
            if duration.is_positive().not() {
                return Err(invalid_request!("invalid presigned url date"))?;
            }

            if duration > presigned_url.expires {
                return Err(s3_error!(AccessDenied, "Request has expired"));
            }
        }

        let auth = require_auth(self.auth)?;
        let secret_key = auth.get_secret_key(presigned_url.credential.access_key_id).await?;

        let signature = {
+14 −2
Original line number Diff line number Diff line
@@ -79,7 +79,8 @@ impl AmzDate {

    /// `{YYYY}{MM}{DD}T{HH}{MM}{SS}Z`
    #[must_use]
    pub fn to_iso8601(&self) -> String {
    pub fn fmt_iso8601(&self) -> String {
        // TODO: small string
        format!(
            "{:04}{:02}{:02}T{:02}{:02}{:02}Z",
            self.year, self.month, self.day, self.hour, self.minute, self.second
@@ -88,7 +89,18 @@ impl AmzDate {

    /// `{YYYY}{MM}{DD}`
    #[must_use]
    pub fn to_date(&self) -> String {
    pub fn fmt_date(&self) -> String {
        // TODO: small string
        format!("{:04}{:02}{:02}", self.year, self.month, self.day,)
    }

    pub fn to_time(&self) -> Option<time::OffsetDateTime> {
        let y = self.year as i32;
        let m: time::Month = self.month.try_into().ok()?;
        let d = self.day;

        let t = time::Date::from_calendar_date(y, m, d).ok()?;
        let t = t.with_hms(self.hour, self.minute, self.second).ok()?;
        Some(t.assume_utc())
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -216,13 +216,13 @@ pub fn create_string_to_sign(canonical_request: &str, amz_date: &AmzDate, region

    {
        // <RequestDateTime>\n
        ans.push_str(&amz_date.to_iso8601());
        ans.push_str(&amz_date.fmt_iso8601());
        ans.push('\n');
    }

    {
        // <CredentialScope>\n
        ans.push_str(&amz_date.to_date());
        ans.push_str(&amz_date.fmt_date());
        ans.push('/');
        ans.push_str(region); // TODO: use a `Region` type
        ans.push_str("/s3/aws4_request\n");
@@ -244,11 +244,11 @@ pub fn create_chunk_string_to_sign(amz_date: &AmzDate, region: &str, prev_signat
        ans.push_str("AWS4-HMAC-SHA256-PAYLOAD\n");
    }
    {
        ans.push_str(&amz_date.to_iso8601());
        ans.push_str(&amz_date.fmt_iso8601());
        ans.push('\n');
    }
    {
        ans.push_str(&amz_date.to_date());
        ans.push_str(&amz_date.fmt_date());
        ans.push('/');
        ans.push_str(region); // TODO: use a `Region` type
        ans.push_str("/s3/aws4_request\n");
@@ -283,7 +283,7 @@ pub fn calculate_signature(string_to_sign: &str, secret_key: &str, amz_date: &Am
    };

    // DateKey
    let date = amz_date.to_date();
    let date = amz_date.fmt_date();
    let date_key = hmac_sha256(secret, date);

    // DateRegionKey
+7 −2
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ pub struct PresignedUrlV4<'a> {
    /// amz date
    pub amz_date: AmzDate,
    /// expires
    pub expires: u32,
    pub expires: time::Duration,
    /// signed headers
    pub signed_headers: SmallVec<[&'a str; 16]>,
    /// signature
@@ -79,7 +79,7 @@ impl<'a> PresignedUrlV4<'a> {

        let amz_date = AmzDate::parse(info.x_amz_date).map_err(|_e| err())?;

        let expires: u32 = info.x_amz_expires.parse().map_err(|_e| err())?;
        let expires = parse_expires(info.x_amz_expires).ok_or_else(err)?;

        if !info.x_amz_signed_headers.is_ascii() {
            return Err(err());
@@ -101,3 +101,8 @@ impl<'a> PresignedUrlV4<'a> {
        })
    }
}

fn parse_expires(s: &str) -> Option<time::Duration> {
    let x = s.parse::<u32>().ok().filter(|&x| x > 0)?;
    Some(time::Duration::new(x as i64, 0))
}