Skip to content

Commit

Permalink
verification: add test_verify_tz_aware (#10229)
Browse files Browse the repository at this point in the history
* verification: add test_verify_tz_aware

Signed-off-by: William Woodruff <william@trailofbits.com>

* py_to_datetime handles tzinfo, add test

Signed-off-by: William Woodruff <william@trailofbits.com>

* Update src/rust/src/x509/common.rs

Co-authored-by: Alex Gaynor <alex.gaynor@gmail.com>

* x509/common: coverage for the coverage god

Signed-off-by: William Woodruff <william@trailofbits.com>

---------

Signed-off-by: William Woodruff <william@trailofbits.com>
Co-authored-by: Alex Gaynor <alex.gaynor@gmail.com>
  • Loading branch information
woodruffw and alex committed Jan 22, 2024
1 parent 41daf2d commit 972a7b5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 6 deletions.
21 changes: 15 additions & 6 deletions src/rust/src/x509/common.rs
Expand Up @@ -503,13 +503,22 @@ pub(crate) fn py_to_datetime(
py: pyo3::Python<'_>,
val: &pyo3::PyAny,
) -> pyo3::PyResult<asn1::DateTime> {
// We treat naive datetimes as UTC times, while aware datetimes get
// normalized to UTC before conversion.
let val_utc = if val.getattr(pyo3::intern!(py, "tzinfo"))?.is_none() {
val
} else {
let utc = types::DATETIME_TIMEZONE_UTC.get(py)?;
val.call_method1(pyo3::intern!(py, "astimezone"), (utc,))?
};

Ok(asn1::DateTime::new(
val.getattr(pyo3::intern!(py, "year"))?.extract()?,
val.getattr(pyo3::intern!(py, "month"))?.extract()?,
val.getattr(pyo3::intern!(py, "day"))?.extract()?,
val.getattr(pyo3::intern!(py, "hour"))?.extract()?,
val.getattr(pyo3::intern!(py, "minute"))?.extract()?,
val.getattr(pyo3::intern!(py, "second"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "year"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "month"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "day"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "hour"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "minute"))?.extract()?,
val_utc.getattr(pyo3::intern!(py, "second"))?.extract()?,
)
.unwrap())
}
Expand Down
35 changes: 35 additions & 0 deletions tests/x509/verification/test_verification.py
Expand Up @@ -103,3 +103,38 @@ def test_store_rejects_empty_list(self):
def test_store_rejects_non_certificates(self):
with pytest.raises(TypeError):
Store(["not a cert"]) # type: ignore[list-item]


class TestServerVerifier:
@pytest.mark.parametrize(
("validation_time", "valid"),
[
# 03:15:02 UTC+2, or 1 second before expiry in UTC
("2018-11-16T03:15:02+02:00", True),
# 00:15:04 UTC-1, or 1 second after expiry in UTC
("2018-11-16T00:15:04-01:00", False),
],
)
def test_verify_tz_aware(self, validation_time, valid):
# expires 2018-11-16 01:15:03 UTC
leaf = _load_cert(
os.path.join("x509", "cryptography.io.pem"),
x509.load_pem_x509_certificate,
)

store = Store([leaf])

builder = PolicyBuilder().store(store)
builder = builder.time(
datetime.datetime.fromisoformat(validation_time)
)
verifier = builder.build_server_verifier(DNSName("cryptography.io"))

if valid:
assert verifier.verify(leaf, []) == [leaf]
else:
with pytest.raises(
x509.verification.VerificationError,
match="cert is not valid at validation time",
):
verifier.verify(leaf, [])

0 comments on commit 972a7b5

Please sign in to comment.