From: Lloyd Subject: Re: acme-client(8): Adapt renewal calculation for shortlived certificates. To: Florian Obser Cc: tech Date: Tue, 16 Sep 2025 16:59:26 +0000 This is a good idea. I have been improving a patch for IP address certificates and those are currently issued with 6-day validity. One of the issues was the fixed setting of 30 days for renewal. Regards Lloyd Florian Obser wrote: > If the lifetime is more than 10 days, renew if less than 1/3 of the > lifetime is left. Otherwise renew after 1/2 of the remaining lifetime. > > Since we suggest to run the cronjob daily, this is capped at 3 days > remaining lifetime to have the opportunity to run the cronjob at least > twice. > > I would like to commit this as soon as the tree unlocks again after > 7.8. OK? > > diff --git revokeproc.c revokeproc.c > index 0f1bf32678b..6790211e40b 100644 > --- revokeproc.c > +++ revokeproc.c > @@ -32,13 +32,11 @@ > > #include "extern.h" > > -#define RENEW_ALLOW (30 * 24 * 60 * 60) > - > /* > - * Convert the X509's expiration time into a time_t value. > + * Convert the X509's notAfter time into a time_t value. > */ > static time_t > -X509expires(X509 *x) > +X509notafter(X509 *x) > { > ASN1_TIME *atim; > struct tm t; > @@ -58,6 +56,30 @@ X509expires(X509 x) > return timegm(&t); > } > > +/ > + * Convert the X509's notBefore time into a time_t value. > + */ > +static time_t > +X509notbefore(X509 *x) > +{ > + ASN1_TIME *atim; > + struct tm t; > + > + if ((atim = X509_getm_notBefore(x)) == NULL) { > + warnx("missing notBefore"); > + return -1; > + } > + > + memset(&t, 0, sizeof(t)); > + > + if (!ASN1_TIME_to_tm(atim, &t)) { > + warnx("invalid ASN1_TIME"); > + return -1; > + } > + > + return timegm(&t); > +} > + > int > revokeproc(int fd, const char *certfile, int force, > int revocate, const char *const *alts, size_t altsz) > @@ -70,7 +92,8 @@ revokeproc(int fd, const char *certfile, int force, > X509 x = NULL; > long lval; > enum revokeop op, rop; > - time_t t; > + time_t notafter, notbefore, cert_validity; > + time_t remaining_validity, renew_allow; > size_t j; > > / > @@ -125,8 +148,13 @@ revokeproc(int fd, const char certfile, int force, > > / Read out the expiration date. */ > > - if ((t = X509expires(x)) == -1) { > - warnx("X509expires"); > + if ((notafter = X509notafter(x)) == -1) { > + warnx("X509notafter"); > + goto out; > + } > + > + if ((notbefore = X509notbefore(x)) == -1) { > + warnx("X509notbefore"); > goto out; > } > > @@ -252,14 +280,35 @@ revokeproc(int fd, const char *certfile, int force, > goto out; > } > > - rop = time(NULL) >= (t - RENEW_ALLOW) ? REVOKE_EXP : REVOKE_OK; > > + cert_validity = notafter - notbefore; > + > + if (cert_validity < 0) { > + warnx("Invalid cert, expire time before inception time"); > + rc = -1; > + goto out; > + } > + if (cert_validity > 10 * 24 * 60 * 60) > > + renew_allow = cert_validity / 3; > + else > + renew_allow = cert_validity / 2; > + > + /* We suggest to run renewals daily. Make sure we have 2 chances. */ > + if (renew_allow < 3 * 24 * 60 *60) > + renew_allow = 3 * 24 * 60 *60; > + > + remaining_validity = notafter - time(NULL); > + > + if (remaining_validity < renew_allow) > + rop = REVOKE_EXP; > + else > + rop = REVOKE_OK; > > if (rop == REVOKE_EXP) > dodbg("%s: certificate renewable: %lld days left", > - certfile, (long long)(t - time(NULL)) / 24 / 60 / 60); > + certfile, (long long)(remaining_validity / 24 / 60 / 60)); > else > dodbg("%s: certificate valid: %lld days left", > - certfile, (long long)(t - time(NULL)) / 24 / 60 / 60); > + certfile, (long long)(remaining_validity / 24 / 60 / 60)); > > if (rop == REVOKE_OK && force) { > warnx("%s: %sforcing renewal", certfile, > > -- > In my defence, I have been left unsupervised.