diff --git a/acme_common/Cargo.toml b/acme_common/Cargo.toml index 13f55a9..aa71234 100644 --- a/acme_common/Cargo.toml +++ b/acme_common/Cargo.toml @@ -23,6 +23,7 @@ daemonize = "0.4" env_logger = "0.7" glob = "0.3" handlebars = "3.0" +libc = "0.2" log = "0.4" native-tls = "0.2" openssl = { version = "0.10", optional = true } diff --git a/acme_common/src/crypto.rs b/acme_common/src/crypto.rs index 21f3ca0..64f0fa8 100644 --- a/acme_common/src/crypto.rs +++ b/acme_common/src/crypto.rs @@ -10,6 +10,7 @@ mod openssl_keys; pub const TLS_LIB_NAME: &str = env!("ACMED_TLS_LIB_NAME"); pub const TLS_LIB_VERSION: &str = env!("ACMED_TLS_LIB_VERSION"); +pub const CRT_NB_DAYS_VALIDITY: u32 = 7; #[derive(Clone, Copy, Debug, PartialEq)] pub enum BaseHashFunction { diff --git a/acme_common/src/crypto/openssl_certificate.rs b/acme_common/src/crypto/openssl_certificate.rs index 5d51717..6593b9d 100644 --- a/acme_common/src/crypto/openssl_certificate.rs +++ b/acme_common/src/crypto/openssl_certificate.rs @@ -16,7 +16,6 @@ const APP_ORG: &str = "ACMEd"; const APP_NAME: &str = "ACMEd"; const X509_VERSION: i32 = 0x02; const CRT_SERIAL_NB_BITS: i32 = 32; -const CRT_NB_DAYS_VALIDITY: u32 = 7; const INVALID_EXT_MSG: &str = "Invalid acmeIdentifier extension."; fn get_digest(digest: HashFunction, key_pair: &KeyPair) -> MessageDigest { @@ -107,7 +106,7 @@ impl X509Certificate { } pub fn expires_in(&self) -> Result { - let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64; + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as libc::time_t; let now = Asn1Time::from_unix(timestamp)?; let not_after = self.inner_cert.not_after(); let diff = now.diff(not_after)?; @@ -172,7 +171,7 @@ fn gen_certificate( builder.set_pubkey(&key_pair.inner_key)?; let not_before = Asn1Time::days_from_now(0)?; builder.set_not_before(¬_before)?; - let not_after = Asn1Time::days_from_now(CRT_NB_DAYS_VALIDITY)?; + let not_after = Asn1Time::days_from_now(super::CRT_NB_DAYS_VALIDITY)?; builder.set_not_after(¬_after)?; builder.append_extension(BasicConstraints::new().build()?)?; diff --git a/acme_common/src/tests/certificate.rs b/acme_common/src/tests/certificate.rs index d43bf5c..2feb950 100644 --- a/acme_common/src/tests/certificate.rs +++ b/acme_common/src/tests/certificate.rs @@ -1,4 +1,4 @@ -use crate::crypto::{HashFunction, KeyType, X509Certificate}; +use crate::crypto::{HashFunction, KeyType, X509Certificate, CRT_NB_DAYS_VALIDITY}; use std::collections::HashSet; use std::iter::FromIterator; @@ -52,6 +52,34 @@ eX1G4/Av0XE7RqJ3Frq8qa5EjjLJTw0iEaWS5NGtZxMqWEIetCgb0IDZNxNvbeAv mmH6qnF3xQPx5FkwP/Yw4d9T4KhSHNf2/tImIlbuk3SEsOglGbKNY1juor8uw+J2 5XsUZxD5QiDbCFd3dGmH58XmkiQHXs8hhIbhu9ZLgp+fNv0enVMHTTI1gGpZ5MPm -----END CERTIFICATE-----"#; +const CERTIFICATE_EXPIRED_PEM: &str = r#"-----BEGIN CERTIFICATE----- +MIIEsTCCA5mgAwIBAgISBApMImYflPdX7BYLjinQ+ErUMA0GCSqGSIb3DQEBCwUA +MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD +ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTExMzAxODQxNTZaFw0y +MDAyMjgxODQxNTZaMBExDzANBgNVBAMTBmJ6aC50ZjB2MBAGByqGSM49AgEGBSuB +BAAiA2IABLSEIYJpT2SM+F9mEzFypkqbBm64dgX0KnyZuYGB2qHHsBLIBBK5Ev9Y +vPvYb8lzX3uJFHPn0JwPpGR0YBzPHBspyvwrhedokt8pNFEDC1eE4BH9XVN35utt +EGP1ZT92mKOCAnYwggJyMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUOALpvHYbvHbQ +GcrtL0I4s/W/S58wHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo7KEwbwYI +KwYBBQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0 +c2VuY3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0 +c2VuY3J5cHQub3JnLzAtBgNVHREEJjAkggZiemgudGaCDm10YS1zdHMuYnpoLnRm +ggp3d3cuYnpoLnRmMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEB +MCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIIBAwYK +KwYBBAHWeQIEAgSB9ASB8QDvAHYAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2y +CJo32RMAAAFuvdWC7QAABAMARzBFAiBgCoazSI4unyx09P8KYxdIfMZsG/fMtzkF +ciBDB9gcJQIhAPZMsnjqr4IqpyHyvauqrWoGqlFBcBCmogZCuhQXAnv5AHUAB7dc +G+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohwAAAFuvdWC7gAABAMARjBEAiAO +z7sHUA42VEQkicrWb5A4WjNGWV7NxpSDdb2XQ2Q1OwIgRaiEMrHfyT797O7Fvbk2 +cL6rnnmDJOyxIAC4Dxe7NVwwDQYJKoZIhvcNAQELBQADggEBAFaNvfsGKqBuJ9m7 +qRNqVmC7UHzGym+TPBLiXncwFIaWt0ncRHb6qfGCCETeAplhPv8uoOrzQQwTKwr3 +eMDtdmK+9smnQZ4AjUsscsrbkGwMWOOmIRm/tCwQZ0dFnl1ySZDuaoCG7v/uRE4A +HXtNAeVOKuE7BOISvvssFajxLifmFixifWRwEnimTffjnIX6xqol+2bcxMuLWxt9 +HmjTgcY4JMMcOAiNk3roJK9ayMi7jn0Cd097BFnvx08+oWSMOZ29hFHMHp3KCSzT +bQg4DAU6E9VT+pvyGsc1NNyREKxOlDkam3CqfYc0oAowjn11MmDac2aKP8Pyt4pk +ehm+yKg= +-----END CERTIFICATE-----"#; #[test] fn test_san_domains() { @@ -132,3 +160,22 @@ fn generate_ed448_certificate() { .unwrap(); assert_eq!(kp.key_type, KeyType::Ed448); } + +#[test] +fn cert_expiration_date_future() { + let (_, crt) = + X509Certificate::from_acme_ext("example.org", "", KeyType::EcdsaP256, HashFunction::Sha256) + .unwrap(); + let duration = crt.expires_in().unwrap().as_secs(); + let validity_sec = CRT_NB_DAYS_VALIDITY as u64 * 24 * 60 * 60; + let delta = 60; + assert!(duration > validity_sec - delta); + assert!(duration < validity_sec + delta); +} + +#[test] +fn cert_expiration_date_past() { + let crt = X509Certificate::from_pem(CERTIFICATE_EXPIRED_PEM.as_bytes()).unwrap(); + let duration = crt.expires_in().unwrap().as_secs(); + assert_eq!(duration, 0); +}