Skip to content

Commit

Permalink
Expose certificate end dates (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
willdurand committed Apr 11, 2024
1 parent bf3b545 commit ee08980
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
55 changes: 50 additions & 5 deletions src/xpi/signatures.rs
@@ -1,10 +1,11 @@
use super::cose_ish::CoseSign;
use cms::cert::{
x509,
x509::{
attr::AttributeTypeAndValue,
certificate::TbsCertificateInner,
der::{
asn1::{PrintableStringRef, TeletexStringRef, Utf8StringRef},
asn1::{GeneralizedTime, PrintableStringRef, TeletexStringRef, UtcTime, Utf8StringRef},
Decode, Encode, Tag, Tagged,
},
Certificate,
Expand All @@ -17,16 +18,57 @@ use const_oid::db::{
rfc4519::{COMMON_NAME, ORGANIZATIONAL_UNIT_NAME},
rfc5912::{ID_SHA_1, ID_SHA_256},
};
use serde::Serialize;
use serde::{Serialize, Serializer};
use std::convert::{From, TryInto};
use std::{fmt, io, io::Read};
use std::{fmt, io, io::Read, time::Duration};
use zip::ZipArchive;

#[derive(Debug, PartialEq)]
/// Represents a date in a certificate.
pub struct Date(x509::time::Time);

impl Date {
pub fn utc_time_from_duration(duration: Duration) -> Self {
Date(x509::time::Time::from(
UtcTime::from_unix_duration(duration).expect("failed to make UtcTime"),
))
}

pub fn generalized_time_from_duration(duration: Duration) -> Self {
Date(x509::time::Time::from(
GeneralizedTime::from_unix_duration(duration).expect("failed to make GeneralizedTime"),
))
}
}

impl Default for Date {
fn default() -> Self {
Date::generalized_time_from_duration(Duration::ZERO)
}
}

impl Serialize for Date {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}", self.0);
serializer.serialize_str(&s)
}
}

impl fmt::Display for Date {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

#[derive(Default, Serialize)]
/// Represents some of the information found in a certificate.
pub struct CertificateInfo {
pub common_name: String,
pub organizational_unit: String,
pub end_date: Date,
}

impl CertificateInfo {
Expand Down Expand Up @@ -73,6 +115,7 @@ impl From<&TbsCertificateInner> for CertificateInfo {
CertificateInfo {
common_name,
organizational_unit,
end_date: Date(tbs_cert.validity.not_after),
}
}
}
Expand All @@ -81,8 +124,10 @@ impl fmt::Display for CertificateInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Common Name (CN): {}\n Organizational Unit (OU): {}",
self.common_name, self.organizational_unit
"Common Name (CN): {}\n \
Organizational Unit (OU): {}\n \
End Date : {}",
self.common_name, self.organizational_unit, self.end_date
)
}
}
Expand Down
Binary file added tests/fixtures/line-staging-cas-cur.xpi
Binary file not shown.
56 changes: 55 additions & 1 deletion tests/xpi_test.rs
@@ -1,5 +1,6 @@
use std::io::Cursor;
use xpidump::{RecommendationState, Signature, SignatureKind, XPI};
use std::time::Duration;
use xpidump::{Date, RecommendationState, Signature, SignatureKind, XPI};
use zip::ZipArchive;

fn assert_signature(signature: &Signature, kind: SignatureKind, is_staging: bool, algorithm: &str) {
Expand Down Expand Up @@ -45,7 +46,16 @@ fn test_prod_regular_addon() {
false,
"SHA-1",
);
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(1743724800)),
xpi.signatures.pkcs7.certificates[0].end_date
);

assert_signature(&xpi.signatures.cose, SignatureKind::Regular, false, "ES256");
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(1743724800)),
xpi.signatures.cose.certificates[0].end_date
);
}

#[test]
Expand All @@ -72,6 +82,10 @@ fn test_prod_old_regular_addon() {
"{6AC85730-7D0F-4de0-B3FA-21142DD85326}",
xpi.signatures.pkcs7.certificates[1].common_name
);
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(1741996362)),
xpi.signatures.pkcs7.certificates[0].end_date
);
assert!(!xpi.signatures.cose.exists());
}

Expand Down Expand Up @@ -229,3 +243,43 @@ fn test_unsigned_addon() {
assert!(!xpi.is_recommended());
assert!(!xpi.signatures.has_signatures());
}

#[test]
fn test_staging_line_extension() {
let bytes = include_bytes!("fixtures/line-staging-cas-cur.xpi");
let reader = Cursor::new(bytes);
let mut archive = ZipArchive::new(reader).unwrap();

let xpi = XPI::new(&mut archive);

assert!(xpi.manifest.exists());
assert!(xpi.is_recommended());
assert_eq!(
"{0cdc308b-4c2a-497d-916a-164d602ed358}",
xpi.manifest.id.expect("expect add-on ID")
);
assert_eq!(
"109.2",
xpi.manifest.version.expect("expect add-on version")
);

assert_signature(&xpi.signatures.pkcs7, SignatureKind::Regular, true, "SHA-1");
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(1741910400)),
xpi.signatures.pkcs7.certificates[0].end_date
);
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(2026818980)),
xpi.signatures.pkcs7.certificates[1].end_date
);

assert_signature(&xpi.signatures.cose, SignatureKind::Regular, true, "ES256");
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(1741910400)),
xpi.signatures.cose.certificates[0].end_date
);
assert_eq!(
Date::utc_time_from_duration(Duration::from_secs(2026818980)),
xpi.signatures.cose.certificates[1].end_date
);
}

0 comments on commit ee08980

Please sign in to comment.