Browse Source

Fix the OpenSSL time parsing

ACMEd was not able to parse some possible time representation, which
could cause a certificate not being renewed at all. This commit support
all current known outputs.

https://github.com/openssl/openssl/blob/master/crypto/asn1/a_time.c
pull/5/head
Rodolphe Breard 6 years ago
parent
commit
cd391ffdaf
  1. 3
      CHANGELOG.md
  2. 44
      acmed/src/certificate.rs

3
CHANGELOG.md

@ -28,6 +28,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed ### Removed
- In challenge hooks, the `algorithm` template variable has been removed. - In challenge hooks, the `algorithm` template variable has been removed.
### Fixed
- In some cases, ACMEd was unable to parse a certificate's expiration date.
## [0.3.0] - 2019-04-30 ## [0.3.0] - 2019-04-30

44
acmed/src/certificate.rs

@ -3,18 +3,35 @@ use crate::config::{Account, HookType};
use crate::hooks::{self, ChallengeHookData, Hook, PostOperationHookData}; use crate::hooks::{self, ChallengeHookData, Hook, PostOperationHookData};
use crate::storage::{certificate_files_exists, get_certificate}; use crate::storage::{certificate_files_exists, get_certificate};
use acme_common::error::Error; use acme_common::error::Error;
use log::debug;
use log::{debug, trace};
use openssl::x509::X509; use openssl::x509::X509;
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt; use std::fmt;
use time::{strptime, Duration}; use time::{strptime, Duration};
// OpenSSL ASN1_TIME_print madness
// The real fix would be to add Asn1TimeRef access in the openssl crate.
//
// https://github.com/sfackler/rust-openssl/issues/687
// https://github.com/sfackler/rust-openssl/pull/673
fn parse_openssl_time_string(time: &str) -> Result<time::Tm, Error> { fn parse_openssl_time_string(time: &str) -> Result<time::Tm, Error> {
let formats = ["%b %d %T %Y", "%b %d %T %Y", "%b %d %T %Y"];
debug!("Parsing OpenSSL time: \"{}\"", time);
let formats = [
"%b %d %T %Y %Z",
"%b %d %T %Y %Z",
"%b %d %T %Y",
"%b %d %T %Y",
"%b %d %T.%f %Y %Z",
"%b %d %T.%f %Y %Z",
"%b %d %T.%f %Y",
"%b %d %T.%f %Y",
];
for fmt in formats.iter() { for fmt in formats.iter() {
if let Ok(t) = strptime(time, fmt) { if let Ok(t) = strptime(time, fmt) {
trace!("Format \"{}\" matches", fmt);
return Ok(t); return Ok(t);
} }
trace!("Format \"{}\" does not match", fmt);
} }
let msg = format!("invalid time string: {}", time); let msg = format!("invalid time string: {}", time);
Err(msg.into()) Err(msg.into())
@ -223,3 +240,26 @@ impl Certificate {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use super::parse_openssl_time_string;
#[test]
fn test_parse_openssl_time() {
let time_str_lst = [
"May 7 18:34:07 2024",
"May 7 18:34:07 2024 GMT",
"May 17 18:34:07 2024",
"May 17 18:34:07 2024 GMT",
"May 7 18:34:07.922661874 2024",
"May 7 18:34:07.922661874 2024 GMT",
"May 17 18:34:07.922661874 2024",
"May 17 18:34:07.922661874 2024 GMT",
];
for time_str in time_str_lst.iter() {
let time_res = parse_openssl_time_string(time_str);
assert!(time_res.is_ok());
}
}
}
Loading…
Cancel
Save