Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package uacme for openSUSE:Factory checked 
in at 2025-01-05 15:28:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/uacme (Old)
 and      /work/SRC/openSUSE:Factory/.uacme.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "uacme"

Sun Jan  5 15:28:26 2025 rev:6 rq:1234576 version:1.7.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/uacme/uacme.changes      2024-02-21 
17:59:26.637872011 +0100
+++ /work/SRC/openSUSE:Factory/.uacme.new.1881/uacme.changes    2025-01-05 
15:28:30.794992652 +0100
@@ -1,0 +2,13 @@
+Mon Dec 30 10:21:59 UTC 2024 - Martin Hauke <mar...@gmx.de>
+
+- Update to version 1.7.6
+  * Fix OpenSSL 3.x deprecated APIs.
+  * Fix cross compilation.
+  * uacme: Add environment variables.
+  * uacme: Add support for ACME Renewal Information (ARI).
+  * uacme: Try obtaining new Reply-Nonce if server doesn't supply
+    one.
+  * uacme: Add hook environment variables.
+  * uacme: Allow matching alternative chain by Authority Key Id.
+
+-------------------------------------------------------------------

Old:
----
  uacme-1.7.5.tar.gz

New:
----
  uacme-1.7.6.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ uacme.spec ++++++
--- /var/tmp/diff_new_pack.5OSwVi/_old  2025-01-05 15:28:31.427018648 +0100
+++ /var/tmp/diff_new_pack.5OSwVi/_new  2025-01-05 15:28:31.427018648 +0100
@@ -18,7 +18,7 @@
 
 
 Name:           uacme
-Version:        1.7.5
+Version:        1.7.6
 Release:        0
 Summary:        A minimal ACMEv2 client
 License:        GPL-3.0-or-later

++++++ uacme-1.7.5.tar.gz -> uacme-1.7.6.tar.gz ++++++
++++ 1869 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/ChangeLog new/uacme-1.7.6/ChangeLog
--- old/uacme-1.7.5/ChangeLog   2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/ChangeLog   2024-12-29 17:27:26.000000000 +0100
@@ -1,3 +1,21 @@
+2024-12-29 Nicola Di Lieto <nicola.dili...@gmail.com>
+       * Release 1.7.6
+       - Fix OpenSSL 3.x deprecated APIs
+       - Fix cross compilation
+         Closes https://github.com/ndilieto/uacme/issues/79
+       - uacme: Add environment variables
+         Closes https://github.com/ndilieto/uacme/issues/63
+       - uacme: Add support for ACME Renewal Information (ARI)
+         Closes https://github.com/ndilieto/uacme/issues/67
+       - uacme: Try obtaining new Reply-Nonce if server doesn't supply one
+         Closes https://github.com/ndilieto/uacme/issues/82
+       - uacme: Add hook environment variables
+         Closes https://github.com/ndilieto/uacme/issues/83
+       - uacme: Allow matching alternative chain by Authority Key Id
+         Closes https://github.com/ndilieto/uacme/issues/85
+       - Documentation update
+       - Add link to linode api hook
+
 2024-01-28 Nicola Di Lieto <nicola.dili...@gmail.com>
        * Release 1.7.5
        - fix ualpn exit code in client mode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/NEWS new/uacme-1.7.6/NEWS
--- old/uacme-1.7.5/NEWS        2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/NEWS        2024-12-29 17:27:26.000000000 +0100
@@ -1,6 +1,24 @@
 uacme NEWS
 Copyright (C) 2019-2024 Nicola Di Lieto <nicola.dili...@gmail.com>
 
+## [1.7.6] - 2024-12-29
+### Changed
+- Fix OpenSSL 3.x deprecated APIs
+- Fix cross compilation
+  Closes https://github.com/ndilieto/uacme/issues/79
+- uacme: Add environment variables
+  Closes https://github.com/ndilieto/uacme/issues/63
+- uacme: Add support for ACME Renewal Information (ARI)
+  Closes https://github.com/ndilieto/uacme/issues/67
+- uacme: Try obtaining new Reply-Nonce if server doesn't supply one
+  Closes https://github.com/ndilieto/uacme/issues/82
+- uacme: Add hook environment variables
+  Closes https://github.com/ndilieto/uacme/issues/83
+- uacme: Allow matching alternative chain by Authority Key Id
+  Closes https://github.com/ndilieto/uacme/issues/85
+- Documentation update
+- Add link to linode api hook
+
 ## [1.7.5] - 2024-01-28
 ### Changed
 - fix ualpn exit code in client mode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/README.md new/uacme-1.7.6/README.md
--- old/uacme-1.7.5/README.md   2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/README.md   2024-12-29 17:27:26.000000000 +0100
@@ -167,6 +167,9 @@
 
 https://sr.ht/~jacksonchen666/uacme-desec-hook/ works with [deSEC.io][desec].
 
+https://gist.github.com/acamari/93db6e6d26c3d6f223840283f195d8be shows how to
+integrate with [Linode API][Linode]
+
 ## tls-alpn-01 challenge support
 
 [ualpn][ualpn] is a lightweight proxying [tls-alpn-01][RFC8737] challenge
@@ -267,3 +270,4 @@
 [splice]: https://en.wikipedia.org/wiki/Splice_%28system_call%29
 [proxy]: http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
 [desec]: https://desec.readthedocs.io/en/latest/
+[Linode]: https://techdocs.akamai.com/linode-api/reference/post-domain-record
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/configure.ac new/uacme-1.7.6/configure.ac
--- old/uacme-1.7.5/configure.ac        2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/configure.ac        2024-12-29 17:27:26.000000000 +0100
@@ -355,7 +355,8 @@
                 AC_DEFINE(HAVE_MAP_DEVZERO, 1, [if mmap("/dev/zero", 
MAP_SHARED) works])
                 AC_MSG_RESULT([yes]),
                 AC_MSG_RESULT([no])
-                AC_MSG_ERROR([ualpn requires MAP_ANON or mmap("/dev/zero", 
MAP_SHARED)])),
+                AC_MSG_ERROR([ualpn requires MAP_ANON or mmap("/dev/zero", 
MAP_SHARED)]))
+        ], [
             AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <sys/mman.h>
                              int main() {return mmap(0, 4096, 
PROT_READ|PROT_WRITE,
                                 MAP_ANON|MAP_SHARED, -1, 0) == MAP_FAILED;}])],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/crypto.c new/uacme-1.7.6/crypto.c
--- old/uacme-1.7.5/crypto.c    2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/crypto.c    2024-12-29 17:27:26.000000000 +0100
@@ -38,6 +38,7 @@
 #include "base64.h"
 #include "crypto.h"
 #include "curlwrap.h"
+#include "json.h"
 #include "msg.h"
 #if !defined(USE_OPENSSL)
 #include "read-file.h"
@@ -57,6 +58,9 @@
 #include <openssl/bio.h>
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/core_names.h>
+#endif
 #include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
@@ -173,29 +177,11 @@
 static bool openssl_hmac_fast(const EVP_MD *type, const void *key,
         size_t keylen, const void *input, size_t len, unsigned char *output)
 {
-    bool success = false;
-    HMAC_CTX *hmac = HMAC_CTX_new();
-    if (!hmac) {
-        openssl_error("openssl_hmac_fast");
-        goto out;
-    }
-    if (!HMAC_Init_ex(hmac, key, keylen, type, NULL)) {
-        openssl_error("openssl_hmac_fast");
-        goto out;
-    }
-    if (!HMAC_Update(hmac, input, len)) {
-        openssl_error("openssl_hmac_fast");
-        goto out;
-    }
-    if (!HMAC_Final(hmac, output, NULL)) {
+    if (HMAC(type, key, keylen, input, len, output, NULL) == NULL) {
         openssl_error("openssl_hmac_fast");
-        goto out;
+        return false;
     }
-    success = true;
-out:
-    if (hmac)
-        HMAC_CTX_free(hmac);
-    return success;
+    return true;
 }
 #elif defined(USE_MBEDTLS)
 #if MBEDTLS_VERSION_NUMBER < 0x02100000
@@ -269,6 +255,31 @@
 }
 #endif
 
+#if !HAVE_STRCASESTR
+char *strcasestr(const char *haystack, const char *needle)
+{
+    char *ret = NULL;
+    char *_haystack = strdup(haystack);
+    char *_needle = strdup(needle);
+
+    if (!_haystack || !_needle)
+        warn("strcasestr: strdup failed");
+    else {
+        char *p;
+        for (p = _haystack; *p; p++)
+            *p = tolower(*p);
+        for (p = _needle; *p; p++)
+            *p = tolower(*p);
+        ret = strstr(_haystack, _needle);
+        if (ret)
+            ret = (char *)haystack + (ret - _haystack);
+    }
+    free(_haystack);
+    free(_needle);
+    return ret;
+}
+#endif
+
 char *sha2_base64url(size_t bits, const char *format, ...)
 {
     char *input = NULL;
@@ -556,6 +567,18 @@
     }
 #elif defined(USE_OPENSSL)
     unsigned char *data = NULL;
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    BIGNUM *bm = NULL;
+    BIGNUM *be = NULL;
+    if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_N, &bm)) {
+        openssl_error("rsa_params");
+        goto out;
+    }
+    if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_E, &be)) {
+        openssl_error("rsa_params");
+        goto out;
+    }
+#else
     const BIGNUM *bm = NULL;
     const BIGNUM *be = NULL;
     RSA *rsa = EVP_PKEY_get0_RSA(key);
@@ -564,6 +587,7 @@
         goto out;
     }
     RSA_get0_key(rsa, &bm, &be, NULL);
+#endif
     r = BN_num_bytes(bm);
     data = calloc(1, r);
     if (!data) {
@@ -654,6 +678,12 @@
     free(exp.data);
 #elif defined(USE_OPENSSL)
     free(data);
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    if (bm)
+        BN_free(bm);
+    if (be)
+        BN_free(be);
+#endif
 #elif defined(USE_MBEDTLS)
     free(data);
     mbedtls_mpi_free(&mn);
@@ -728,6 +758,31 @@
         openssl_error("ec_params");
         goto out;
     }
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    char group[0x20];
+    if (!EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME,
+                group, sizeof(group), NULL)) {
+        openssl_error("ec_params");
+        goto out;
+    }
+    if (strcasecmp(group, "prime256v1") == 0)
+        bits = 256;
+    else if (strcasecmp(group, "secp384r1") == 0)
+        bits = 384;
+    else {
+        warnx("ec_params: only \"prime256v1\" and \"secp384r1\" "
+                "Elliptic Curves supported");
+        goto out;
+    }
+    if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &bx)) {
+        openssl_error("ec_params");
+        goto out;
+    }
+    if (!EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &by)) {
+        openssl_error("ec_params");
+        goto out;
+    }
+#else
     EC_KEY *ec = EVP_PKEY_get0_EC_KEY(key);
     if (!ec) {
         openssl_error("ec_params");
@@ -760,6 +815,7 @@
         openssl_error("ec_params");
         goto out;
     }
+#endif
     r = BN_num_bytes(bx);
     data = calloc(1, r);
     if (!data) {
@@ -3382,6 +3438,78 @@
     return ret;
 }
 
+#if defined(USE_MBEDTLS)
+static int mbedtls_crt_get_authority_key_id(mbedtls_x509_crt *crt,
+        unsigned char **akid, size_t *size)
+{
+    unsigned char *p = crt->v3_ext.p;
+    unsigned char *end = p + crt->v3_ext.len;
+    size_t len;
+    int r;
+
+    if (!p || p == end)
+        return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+    r = mbedtls_asn1_get_tag(&p, end, &len,
+            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (r)
+        return r;
+    if (p + len != end)
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+
+    while (p < end) {
+        unsigned char *end_ext;
+
+        r = mbedtls_asn1_get_tag(&p, end, &len,
+                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+        if (r)
+            return r;
+
+        end_ext = p + len;
+        r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OID);
+        if (r)
+            return r;
+
+        if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER) ||
+                memcmp(p, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, len)) {
+            p = end_ext;
+            continue;
+        }
+        p += len;
+
+        r = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_BOOLEAN);
+        if (r == 0) {
+            if (len != 1)
+                return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+            p++;
+        } else if (r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
+            return r;
+
+        r = mbedtls_asn1_get_tag(&p, end_ext, &len,
+                MBEDTLS_ASN1_OCTET_STRING);
+        if (r)
+            return r;
+        if (end_ext != p + len)
+            return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+
+        r = mbedtls_asn1_get_tag(&p, p + len, &len,
+                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+        if (r)
+            return r;
+
+        r = mbedtls_asn1_get_tag(&p, p + len, &len,
+                MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+        if (r)
+            return r;
+
+        *akid = p;
+        *size = len;
+        return 0;
+    }
+
+    return MBEDTLS_ERR_X509_UNKNOWN_OID;
+}
+#endif
+
 bool cert_match(const char *cert, unsigned char *fingerprint,
         size_t fingerprint_len)
 {
@@ -3400,12 +3528,26 @@
         return ret;
     }
     for (unsigned int i = 0; i < crt_size; i++) {
-        unsigned char fp[32];
-        size_t s = sizeof(fp);
-        r = gnutls_x509_crt_get_fingerprint(crt[i], GNUTLS_DIG_SHA256, fp, &s);
-        if (r == 0 && fingerprint_len <= s &&
-                memcmp(fp, fingerprint, fingerprint_len) == 0)
-            ret = true;
+        unsigned char fp[128];
+        if (!ret) {
+            size_t s = sizeof(fp);
+            r = gnutls_x509_crt_get_fingerprint(crt[i], GNUTLS_DIG_SHA256,
+                    fp, &s);
+            if (r == 0 && fingerprint_len <= s &&
+                    memcmp(fp, fingerprint, fingerprint_len) == 0) {
+                msg(1, "certificate matched by fingerprint");
+                ret = true;
+            }
+        }
+        if (!ret) {
+            size_t s = sizeof(fp);
+            r = gnutls_x509_crt_get_authority_key_id(crt[i], fp, &s, NULL);
+            if (r == 0 && fingerprint_len <= s &&
+                    memcmp(fp, fingerprint, fingerprint_len) == 0) {
+                msg(1, "certificate matched by Authority Key Id");
+                ret = true;
+            }
+        }
         gnutls_x509_crt_deinit(crt[i]);
     }
     gnutls_free(crt);
@@ -3423,8 +3565,23 @@
             break;
         if (X509_digest(crt, EVP_sha256(), fp, &s) &&
                 fingerprint_len <= s &&
-                memcmp(fp, fingerprint, fingerprint_len) == 0)
+                memcmp(fp, fingerprint, fingerprint_len) == 0) {
+            msg(1, "certificate matched by fingerprint");
             ret = true;
+        } else {
+            AUTHORITY_KEYID *akid = X509_get_ext_d2i(crt,
+                    NID_authority_key_identifier, NULL, NULL);
+            if (akid != NULL) {
+                if (akid->keyid != NULL && fingerprint_len <=
+                        (size_t)ASN1_STRING_length(akid->keyid) &&
+                        memcmp(ASN1_STRING_get0_data(akid->keyid),
+                            fingerprint, fingerprint_len) == 0) {
+                    msg(1, "certificate matched by Authority Key Id");
+                    ret = true;
+                }
+                AUTHORITY_KEYID_free(akid);
+            }
+        }
         X509_free(crt);
     }
     BIO_free(bio);
@@ -3445,15 +3602,115 @@
     }
     for (mbedtls_x509_crt *c = &crt; c; c = c->next) {
         unsigned char fp[32];
+        unsigned char *akid;
+        size_t akid_len;
         r = mbedtls_hash_fast(MBEDTLS_MD_SHA256, c->raw.p, c->raw.len, fp);
         if (r == 0 && fingerprint_len <= sizeof(fp) &&
-                memcmp(fp, fingerprint, fingerprint_len) == 0)
+                memcmp(fp, fingerprint, fingerprint_len) == 0) {
+            msg(1, "certificate matched by fingerprint");
             ret = true;
+            break;
+        }
+        r = mbedtls_crt_get_authority_key_id(c, &akid, &akid_len);
+        if (r == 0 && fingerprint_len <= akid_len &&
+                memcmp(akid, fingerprint, fingerprint_len) == 0) {
+            msg(1, "certificate matched by Authority Key Id");
+            ret = true;
+            break;
+        }
     }
     mbedtls_x509_crt_free(&crt);
 #endif
     return ret;
 }
+
+#if defined(USE_GNUTLS)
+static char *crt_ari_url(gnutls_x509_crt_t crt, const char *prefix)
+#elif defined(USE_OPENSSL)
+static char *crt_ari_url(X509 *crt, const char *prefix)
+#elif defined(USE_MBEDTLS)
+static char *crt_ari_url(mbedtls_x509_crt *crt, const char *prefix)
+#endif
+{
+    char *url = NULL;
+    unsigned char akid[128];
+    char akid_b64[base64_ENCODED_LEN(sizeof(akid),
+            base64_VARIANT_URLSAFE_NO_PADDING)];
+    unsigned char serial[128];
+    char serial_b64[base64_ENCODED_LEN(sizeof(akid),
+            base64_VARIANT_URLSAFE_NO_PADDING)];
+    size_t alen = sizeof(akid);
+    size_t slen = sizeof(serial);
+
+#if defined(USE_GNUTLS)
+    int r = gnutls_x509_crt_get_authority_key_id(crt, akid, &alen, NULL);
+    if (r)
+        return NULL;
+    r = gnutls_x509_crt_get_serial(crt, serial, &slen);
+    if (r)
+        return NULL;
+#elif defined(USE_OPENSSL)
+    AUTHORITY_KEYID *ak = X509_get_ext_d2i(crt,
+            NID_authority_key_identifier, NULL, NULL);
+    if (ak != NULL) {
+        if (ak->keyid == NULL ||
+                alen < (size_t)ASN1_STRING_length(ak->keyid))
+            alen = 0;
+        else {
+            alen = (size_t)ASN1_STRING_length(ak->keyid);
+            memcpy(akid, ASN1_STRING_get0_data(ak->keyid), alen);
+        }
+        AUTHORITY_KEYID_free(ak);
+        if (alen == 0)
+            return NULL;
+    } else
+        return NULL;
+    const ASN1_INTEGER *sn = X509_get0_serialNumber(crt);
+    if (!sn)
+        return NULL;
+    BIGNUM *bn = ASN1_INTEGER_to_BN(sn, NULL);
+    if (!bn) {
+        openssl_error("cert_ari_url");
+        return NULL;
+    }
+    if (slen < (size_t)BN_num_bytes(bn)) {
+        BN_free(bn);
+        return NULL;
+    } else {
+        slen = (size_t)BN_bn2bin(bn, serial);
+        BN_free(bn);
+    }
+#elif defined(USE_MBEDTLS)
+    unsigned char *ak;
+    size_t len;
+    int r = mbedtls_crt_get_authority_key_id(crt, &ak, &len);
+    if (r)
+        return NULL;
+    if (alen < len)
+        return NULL;
+    alen = len;
+    memcpy(akid, ak, alen);
+    if (!crt->serial.p || slen < crt->serial.len)
+        return NULL;
+    slen = crt->serial.len;
+    memcpy(serial, crt->serial.p, slen);
+#endif
+    if (!bin2base64(akid_b64, sizeof(akid_b64), akid, alen,
+                base64_VARIANT_URLSAFE_NO_PADDING) ||
+            !bin2base64(serial_b64, sizeof(serial_b64), serial, slen,
+                base64_VARIANT_URLSAFE_NO_PADDING)) {
+        warnx("crt_ari_url: bin2base64 failed");
+        return NULL;
+    }
+
+    if (asprintf(&url, "%s/%s.%s", prefix, akid_b64, serial_b64) < 0) {
+        warnx("crt_ari_url: asprintf failed");
+        url = NULL;
+    }
+
+    return url;
+}
+
 #if defined(USE_GNUTLS)
 static bool ocsp_check(gnutls_x509_crt_t *crt)
 {
@@ -4298,8 +4555,99 @@
 }
 #endif
 
-bool cert_valid(const char *certfile, char * const *names, int validity,
-        bool status_check)
+#if defined(USE_GNUTLS)
+int ari_check(gnutls_x509_crt_t crt, const char *ari_url)
+#elif defined(USE_OPENSSL)
+int ari_check(X509 *crt, const char *ari_url)
+#elif defined(USE_MBEDTLS)
+int ari_check(mbedtls_x509_crt *crt, const char *ari_url)
+#endif
+{
+    int ret = -1;
+    json_value_t *json = NULL;
+
+    if (!ari_url)
+        goto out;
+
+    char *url = crt_ari_url(crt, ari_url);
+    if (!url)
+        goto out;
+
+    msg(1, "checking certificate renewal info at %s", url);
+    curldata_t *c = curl_get(url);
+    free(url);
+    if (!c) {
+        warnx("ari_check: curl_get failed");
+        goto out;
+    }
+
+    if (c->headers)
+        msg(3, "ari_check: HTTP headers\n%s", c->headers);
+    if (c->body)
+        msg(3, "ari_check: HTTP body\n%s", c->body);
+
+    char *p = find_header(c->headers, "Content-Type");
+    if (p && strcasestr(p, "json"))
+        json = json_parse(c->body, c->body_len);
+    free(p);
+    curldata_free(c);
+
+    if (!json) {
+        warnx("ari_check: failed to parse");
+        goto out;
+    }
+
+    const json_value_t *window = json_find(json, "suggestedWindow");
+    if (!window) {
+        warnx("ari_check: missing suggestedWindow");
+        goto out;
+    }
+
+    const char *start = json_find_string(window, "start");
+    const char *end = json_find_string(window, "end");
+    if (!start || !end) {
+        warnx("ari_check: missing start or end");
+        goto out;
+    }
+    msg(1, "certificate renewal window: start=%s end=%s", start, end);
+    struct tm start_tm, end_tm;
+    p = strptime(start, "%Y-%m-%dT%T%z", &start_tm);
+    if (!p || *p) {
+        warnx("ari_check: failed to parse start");
+        goto out;
+    }
+    p = strptime(end, "%Y-%m-%dT%T%z", &end_tm);
+    if (!p || *p) {
+        warnx("ari_check: failed to parse end");
+        goto out;
+    }
+    time_t start_t = mktime(&start_tm);
+    if (start_t == (time_t)-1) {
+        warnx("ari_check: invalid start");
+        goto out;
+    }
+    time_t end_t = mktime(&end_tm);
+    if (end_t == (time_t)-1) {
+        warnx("ari_check: invalid end");
+        goto out;
+    }
+    if (start_t >= end_t) {
+        warnx("ari_check: invalid start/end");
+        goto out;
+    }
+
+    if (time(NULL) > start_t + (end_t - start_t) * ((float)rand()/RAND_MAX))
+        ret = 1;
+    else
+        ret = 0;
+
+out:
+    json_free(json);
+    return ret;
+}
+
+bool cert_valid(const char *certfile, char * const *names, const char *ari_url,
+        int validity, bool status_check)
 {
     bool valid = false;
 #if defined(USE_GNUTLS)
@@ -4316,7 +4664,10 @@
 
     int days_left = (expiration - time(NULL))/(24*3600);
     msg(1, "%s expires in %d days", certfile, days_left);
-    if (days_left < validity) {
+    int ari = -1;
+    if (days_left > 0)
+        ari = ari_check(crt[0], ari_url);
+    if (ari > 0 || (ari < 0 && days_left < validity)) {
         msg(1, "%s is due for renewal", certfile);
         goto out;
     }
@@ -4370,7 +4721,10 @@
         goto out;
     }
     msg(1, "%s expires in %d days", certfile, days_left);
-    if (days_left < validity) {
+    int ari = -1;
+    if (days_left > 0)
+        ari = ari_check(crt[0], ari_url);
+    if (ari > 0 || (ari < 0 && days_left < validity)) {
         msg(1, "%s is due for renewal", certfile);
         goto out;
     }
@@ -4496,7 +4850,10 @@
 
     int days_left = (expiration - time(NULL))/(24*3600);
     msg(1, "%s expires in %d days", certfile, days_left);
-    if (days_left < validity) {
+    int ari = -1;
+    if (days_left > 0)
+        ari = ari_check(crt, ari_url);
+    if (ari > 0 || (ari < 0 && days_left < validity)) {
         msg(1, "%s is due for renewal", certfile);
         goto out;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/crypto.h new/uacme-1.7.6/crypto.h
--- old/uacme-1.7.5/crypto.h    2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/crypto.h    2024-12-29 17:27:26.000000000 +0100
@@ -82,8 +82,12 @@
 char *csr_gen(char * const *, bool, privkey_t);
 char *csr_load(const char *, char ***);
 char *cert_der_base64url(const char *);
-bool cert_valid(const char *, char * const *, int, bool);
+bool cert_valid(const char *, char * const *, const char *, int, bool);
 bool cert_match(const char *, unsigned char *, size_t);
 
+#if !HAVE_STRCASESTR
+char *strcasestr(const char *haystack, const char *needle);
+#endif
+
 #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/curlwrap.c new/uacme-1.7.6/curlwrap.c
--- old/uacme-1.7.5/curlwrap.c  2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/curlwrap.c  2024-12-29 17:27:26.000000000 +0100
@@ -20,12 +20,14 @@
 
 #include "config.h"
 #include <err.h>
+#include <regex.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "curlwrap.h"
+#include "msg.h"
 
 curldata_t *curldata_calloc(void)
 {
@@ -89,6 +91,30 @@
     return size * n;
 }
 
+static void curl_env(CURL *curl)
+{
+    const char *cainfo = getenv("UACME_CAINFO");
+    const char *capath = getenv("UACME_CAPATH");
+    const char *dnssrv = getenv("UACME_DNS_SERVERS");
+    const char *iface = getenv("UACME_INTERFACE");
+    const char *proxy = getenv("UACME_PROXY");
+
+    curl_easy_setopt(curl, CURLOPT_USERAGENT,
+            "uacme/" VERSION " (https://github.com/ndilieto/uacme)");
+    if (g_loglevel > 3)
+        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+    if (cainfo)
+        curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo);
+    if (capath)
+        curl_easy_setopt(curl, CURLOPT_CAPATH, capath);
+    if (dnssrv)
+        curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, dnssrv);
+    if (iface)
+        curl_easy_setopt(curl, CURLOPT_INTERFACE, iface);
+    if (proxy)
+        curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
+}
+
 curldata_t *curl_get(const char *url)
 {
     curldata_t *c = NULL;
@@ -106,13 +132,12 @@
             curl_easy_cleanup(curl);
             return NULL;
         }
+        curl_env(curl);
         curl_easy_setopt(curl, CURLOPT_URL, url);
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_wcb);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, c);
         curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_hcb);
         curl_easy_setopt(curl, CURLOPT_HEADERDATA, c);
-        curl_easy_setopt(curl, CURLOPT_USERAGENT,
-                "uacme/" VERSION " (https://github.com/ndilieto/uacme)");
         res = curl_easy_perform(curl);
         if (res != CURLE_OK) {
             warnx("curl_get: GET %s failed: %s", url,
@@ -155,13 +180,12 @@
             curl_easy_cleanup(curl);
             return NULL;
         }
+        curl_env(curl);
         curl_easy_setopt(curl, CURLOPT_URL, url);
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_wcb);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, c);
         curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_hcb);
         curl_easy_setopt(curl, CURLOPT_HEADERDATA, c);
-        curl_easy_setopt(curl, CURLOPT_USERAGENT,
-                "uacme/" VERSION " (https://github.com/ndilieto/uacme)");
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_size);
         va_start(ap, header);
@@ -193,3 +217,27 @@
     }
     return c;
 }
+
+char *find_header(const char *headers, const char *name)
+{
+    char *regex = NULL;
+    if (asprintf(&regex, "^%s:[ \t]*(.*)\r\n", name) < 0) {
+        warnx("find_header: asprintf failed");
+        return NULL;
+    }
+    char *ret = NULL;
+    regex_t reg;
+    if (regcomp(&reg, regex, REG_EXTENDED | REG_ICASE | REG_NEWLINE)) {
+        warnx("find_header: regcomp failed");
+    } else {
+        regmatch_t m[2];
+        if (regexec(&reg, headers, 2, m, 0) == 0) {
+            ret = strndup(headers + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
+            if (!ret)
+                warn("find_header: strndup failed");
+        }
+    }
+    free(regex);
+    regfree(&reg);
+    return ret;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/curlwrap.h new/uacme-1.7.6/curlwrap.h
--- old/uacme-1.7.5/curlwrap.h  2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/curlwrap.h  2024-12-29 17:27:26.000000000 +0100
@@ -35,5 +35,6 @@
 curldata_t *curl_get(const char *url);
 curldata_t *curl_post(const char *url, void *post_data, size_t post_size,
         const char *header, ...);
+char *find_header(const char *headers, const char *name);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/docs/uacme.html new/uacme-1.7.6/docs/uacme.html
--- old/uacme-1.7.5/docs/uacme.html     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/docs/uacme.html     2024-12-29 17:27:26.000000000 +0100
@@ -748,10 +748,11 @@
 <div class="sectionbody">
 <div class="paragraph"><p><strong>uacme</strong> 
[<strong>-a</strong>|<strong>--acme-url</strong> <em>URL</em>] 
[<strong>-b</strong>|<strong>--bits</strong> <em>BITS</em>]
     [<strong>-c</strong>|<strong>--confdir</strong> <em>DIR</em>] 
[<strong>-d</strong>|<strong>--days</strong> <em>DAYS</em>] 
[<strong>-e</strong>|<strong>--eab</strong> KEYID:KEY]
-    [<strong>-f</strong>|<strong>--force</strong>] 
[<strong>-h</strong>|<strong>--hook</strong> <em>PROGRAM</em>] 
[<strong>-l</strong>|<strong>--alternate</strong> <em>N</em> | <em>FP</em>]
-    [<strong>-m</strong>|<strong>--must-staple</strong>] 
[<strong>-n</strong>|<strong>--never-create</strong>] 
[<strong>-o</strong>|<strong>--no-ocsp</strong>]
-    [<strong>-r</strong>|<strong>--reason</strong> CODE] 
[<strong>-s</strong>|<strong>--staging</strong>] 
[<strong>-t</strong>|<strong>--type</strong> 
<strong>RSA</strong>|<strong>EC</strong>]
-    [<strong>-v</strong>|<strong>--verbose</strong> &#8230;] 
[<strong>-V</strong>|<strong>--version</strong>] 
[<strong>-y</strong>|<strong>--yes</strong>] 
[<strong>-?</strong>|<strong>--help</strong>]
+    [<strong>-f</strong>|<strong>--force</strong>] 
[<strong>-h</strong>|<strong>--hook</strong> <em>PROGRAM</em>] 
[<strong>-i</strong>|<strong>--no-ari</strong>]
+    [<strong>-l</strong>|<strong>--alternate</strong> <em>N</em> | 
<em>FP</em>] [<strong>-m</strong>|<strong>--must-staple</strong>]
+    [<strong>-n</strong>|<strong>--never-create</strong>] 
[<strong>-o</strong>|<strong>--no-ocsp</strong>] 
[<strong>-r</strong>|<strong>--reason</strong> CODE]
+    [<strong>-s</strong>|<strong>--staging</strong>] 
[<strong>-t</strong>|<strong>--type</strong> 
<strong>RSA</strong>|<strong>EC</strong>] 
[<strong>-v</strong>|<strong>--verbose</strong> &#8230;]
+    [<strong>-V</strong>|<strong>--version</strong>] 
[<strong>-y</strong>|<strong>--yes</strong>] 
[<strong>-?</strong>|<strong>--help</strong>]
     <strong>new</strong> [<em>EMAIL</em>] | <strong>update</strong> 
[<em>EMAIL</em>] | <strong>deactivate</strong> | <strong>newkey</strong> |
     <strong>issue</strong> <em>IDENTIFIER</em> [<em>ALTNAME</em> &#8230;]] | 
<strong>issue</strong> <em>CSRFILE</em> |
     <strong>revoke</strong> <em>CERTFILE</em> [<em>CERTKEYFILE</em>]</p></div>
@@ -854,7 +855,9 @@
 <dd>
 <p>
     Do not reissue certificates that are still valid for longer
-    than <em>DAYS</em> (default 30). See also <strong>-o, --no-ocsp</strong>.
+    than <em>DAYS</em> (default 30). This only applies as a fallback
+    if no server renewal information is available. See also
+    <strong>-i, --no-ari</strong> and <strong>-o, --no-ocsp</strong>.
 </p>
 </dd>
 <dt class="hdlist1">
@@ -874,7 +877,8 @@
 </dt>
 <dd>
 <p>
-    Force certificate reissuance regardless of expiration date.
+    Force certificate reissuance regardless of expiration date and
+    renewal information from the server.
 </p>
 </dd>
 <dt class="hdlist1">
@@ -964,6 +968,16 @@
 </dl></div>
 </dd>
 <dt class="hdlist1">
+<strong>-i, --no-ari</strong>
+</dt>
+<dd>
+<p>
+    Do not query or use the server&#8217;s certificate renewal information 
window
+    to decide whether to reissue an existing certificate. See also
+    <strong>-d, --days</strong> and <strong>-o, --no-ocsp</strong>.
+</p>
+</dd>
+<dt class="hdlist1">
 <strong>-l, --alternate</strong> <em>N</em> | <em>FP</em>
 </dt>
 <dd>
@@ -975,9 +989,11 @@
     in one of two ways. A positive integer <em>N</em> makes 
<strong>uacme</strong> select the Nth
     alternative chain in the order presented by the server.
     A colon (<em>:</em>) separated list of two or more 2-digit hexadecimal 
numbers
-    <em>FP</em> makes <strong>uacme</strong> select the first alternative 
chain containing a
-    certificate whose SHA256 fingerprint begins with <em>FP</em>.
-    In both cases <strong>uacme</strong> falls back to the main certificate 
URL if it cannot
+    <em>FP</em> makes <strong>uacme</strong> select the first alternative 
chain containing either a
+    certificate whose SHA256 fingerprint begins with <em>FP</em>, or a 
certificate
+    in which the Authority Key Identifier extension contains a keyIdentifier
+    field beginning with <em>FP</em>.
+    In all cases <strong>uacme</strong> falls back to the main certificate URL 
if it cannot
     match an alternative chain or the download thereof fails.
 </p>
 </dd>
@@ -1202,6 +1218,126 @@
 </div>
 </div>
 <div class="sect1">
+<h2 id="_environment">ENVIRONMENT</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong>UACME_CAINFO</strong>
+</dt>
+<dd>
+<p>
+    String naming a file holding one or more CA certificates to verify
+    the ACME server with.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_CAPATH</strong>
+</dt>
+<dd>
+<p>
+    String naming a directory holding multiple CA certificates to verify
+    the ACME server with. If libcurl is built against OpenSSL, the certificate
+    directory must be prepared using the OpenSSL c_rehash utility.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_DNS_SERVERS</strong>
+</dt>
+<dd>
+<p>
+    Comma separated list of DNS servers to be used instead of the system
+    default. The format of the dns servers option is
+    <em>host[:port][,host[:port]]&#8230;</em>
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_INTERFACE</strong>
+</dt>
+<dd>
+<p>
+    String setting the interface name to use as outgoing network interface.
+    The name can be an interface name, an IP address, or a hostname.
+    If you prefer one of these, you can use the following special prefixes:
+</p>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<em>if!&lt;name&gt;</em>
+</dt>
+<dd>
+<p>
+Interface name
+</p>
+</dd>
+<dt class="hdlist1">
+<em>host!&lt;name&gt;</em>
+</dt>
+<dd>
+<p>
+IP address or hostname
+</p>
+</dd>
+<dt class="hdlist1">
+<em>ifhost!&lt;interface&gt;!&lt;host&gt;</em>
+</dt>
+<dd>
+<p>
+Interface name and IP address or hostname
+</p>
+</dd>
+</dl></div>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_PROXY</strong>
+</dt>
+<dd>
+<p>
+    String holding the proxy hostname or dotted numerical IP address.
+    A numerical IPv6 address must be written within [brackets].
+    To specify port number in this string, append :[port] to the end of
+    the host name. If not specified, default to using port 1080.
+    The proxy string may be prefixed with [scheme]:// to specify which
+    kind of proxy is used (http://, https://, socks4://, socks4a://,
+    socks5://, socks5h://).
+    The proxy can also be specified with its associated credentials like
+    for ordinary URLs in the style: 
<em>scheme://username:password@hostname</em>
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_hook_environment">HOOK ENVIRONMENT</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The following environment variables are exported for 
use by the hook program:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong>UACME_CONFDIR</strong>
+</dt>
+<dd>
+<p>
+    Path to <em>CONFDIR</em>, see <strong>-c, --confdir</strong>
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_VERBOSE</strong>
+</dt>
+<dd>
+<p>
+    Verbosity, see <strong>-v, --verbose</strong>
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>UACME_METHOD</strong>, <strong>UACME_TYPE</strong>, 
<strong>UACME_IDENT</strong>, <strong>UACME_TOKEN</strong>, 
<strong>UACME_AUTH</strong>
+</dt>
+<dd>
+<p>
+    Copies of the hook program arguments, see <strong>-h, --hook</strong>
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
 <h2 id="_exit_status">EXIT STATUS</h2>
 <div class="sectionbody">
 <div class="dlist"><dl>
@@ -1336,9 +1472,9 @@
 <div id="footnotes"><hr></div>
 <div id="footer">
 <div id="footer-text">
-Version 1.7.5<br>
+Version 1.7.6<br>
 Last updated
- 2024-01-28 20:29:11 CET
+ 2024-12-29 17:25:16 CET
 </div>
 </div>
 </body>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/docs/ualpn.html new/uacme-1.7.6/docs/ualpn.html
--- old/uacme-1.7.5/docs/ualpn.html     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/docs/ualpn.html     2024-12-29 17:27:26.000000000 +0100
@@ -1188,9 +1188,9 @@
 <div id="footnotes"><hr></div>
 <div id="footer">
 <div id="footer-text">
-Version 1.7.5<br>
+Version 1.7.6<br>
 Last updated
- 2024-01-20 20:29:11 CET
+ 2024-12-29 17:25:21 CET
 </div>
 </div>
 </body>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/uacme.1 new/uacme-1.7.6/uacme.1
--- old/uacme-1.7.5/uacme.1     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/uacme.1     2024-12-29 17:27:26.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: uacme
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\"      Date: 01/28/2024
+.\"      Date: 12/29/2024
 .\"    Manual: User Commands
-.\"    Source: uacme 1.7.5
+.\"    Source: uacme 1.7.6
 .\"  Language: English
 .\"
-.TH "UACME" "1" "01/28/2024" "uacme 1\&.7\&.5" "User Commands"
+.TH "UACME" "1" "12/29/2024" "uacme 1\&.7\&.6" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -31,7 +31,7 @@
 uacme \- ACMEv2 client written in plain C with minimal dependencies
 .SH "SYNOPSIS"
 .sp
-\fBuacme\fR [\fB\-a\fR|\fB\-\-acme\-url\fR \fIURL\fR] 
[\fB\-b\fR|\fB\-\-bits\fR \fIBITS\fR] [\fB\-c\fR|\fB\-\-confdir\fR \fIDIR\fR] 
[\fB\-d\fR|\fB\-\-days\fR \fIDAYS\fR] [\fB\-e\fR|\fB\-\-eab\fR KEYID:KEY] 
[\fB\-f\fR|\fB\-\-force\fR] [\fB\-h\fR|\fB\-\-hook\fR \fIPROGRAM\fR] 
[\fB\-l\fR|\fB\-\-alternate\fR \fIN\fR | \fIFP\fR] 
[\fB\-m\fR|\fB\-\-must\-staple\fR] [\fB\-n\fR|\fB\-\-never\-create\fR] 
[\fB\-o\fR|\fB\-\-no\-ocsp\fR] [\fB\-r\fR|\fB\-\-reason\fR CODE] 
[\fB\-s\fR|\fB\-\-staging\fR] [\fB\-t\fR|\fB\-\-type\fR \fBRSA\fR|\fBEC\fR] 
[\fB\-v\fR|\fB\-\-verbose\fR \&...] [\fB\-V\fR|\fB\-\-version\fR] 
[\fB\-y\fR|\fB\-\-yes\fR] [\fB\-?\fR|\fB\-\-help\fR] \fBnew\fR [\fIEMAIL\fR] | 
\fBupdate\fR [\fIEMAIL\fR] | \fBdeactivate\fR | \fBnewkey\fR | \fBissue\fR 
\fIIDENTIFIER\fR [\fIALTNAME\fR \&...]] | \fBissue\fR \fICSRFILE\fR | 
\fBrevoke\fR \fICERTFILE\fR [\fICERTKEYFILE\fR]
+\fBuacme\fR [\fB\-a\fR|\fB\-\-acme\-url\fR \fIURL\fR] 
[\fB\-b\fR|\fB\-\-bits\fR \fIBITS\fR] [\fB\-c\fR|\fB\-\-confdir\fR \fIDIR\fR] 
[\fB\-d\fR|\fB\-\-days\fR \fIDAYS\fR] [\fB\-e\fR|\fB\-\-eab\fR KEYID:KEY] 
[\fB\-f\fR|\fB\-\-force\fR] [\fB\-h\fR|\fB\-\-hook\fR \fIPROGRAM\fR] 
[\fB\-i\fR|\fB\-\-no\-ari\fR] [\fB\-l\fR|\fB\-\-alternate\fR \fIN\fR | 
\fIFP\fR] [\fB\-m\fR|\fB\-\-must\-staple\fR] 
[\fB\-n\fR|\fB\-\-never\-create\fR] [\fB\-o\fR|\fB\-\-no\-ocsp\fR] 
[\fB\-r\fR|\fB\-\-reason\fR CODE] [\fB\-s\fR|\fB\-\-staging\fR] 
[\fB\-t\fR|\fB\-\-type\fR \fBRSA\fR|\fBEC\fR] [\fB\-v\fR|\fB\-\-verbose\fR 
\&...] [\fB\-V\fR|\fB\-\-version\fR] [\fB\-y\fR|\fB\-\-yes\fR] 
[\fB\-?\fR|\fB\-\-help\fR] \fBnew\fR [\fIEMAIL\fR] | \fBupdate\fR [\fIEMAIL\fR] 
| \fBdeactivate\fR | \fBnewkey\fR | \fBissue\fR \fIIDENTIFIER\fR [\fIALTNAME\fR 
\&...]] | \fBissue\fR \fICSRFILE\fR | \fBrevoke\fR \fICERTFILE\fR 
[\fICERTKEYFILE\fR]
 .SH "DESCRIPTION"
 .sp
 \fBuacme\fR is a client for the ACMEv2 protocol described in RFC8555, written 
in plain C with minimal dependencies (libcurl and one of GnuTLS, OpenSSL or 
mbedTLS)\&. The ACMEv2 protocol allows a Certificate Authority 
(https://letsencrypt\&.org is a popular one) and an applicant to automate the 
process of verification and certificate issuance\&. The protocol also provides 
facilities for other certificate management functions, such as certificate 
revocation\&. For more information see https://tools\&.ietf\&.org/html/rfc8555
@@ -95,7 +95,9 @@
 .RS 4
 Do not reissue certificates that are still valid for longer than
 \fIDAYS\fR
-(default 30)\&. See also
+(default 30)\&. This only applies as a fallback if no server renewal 
information is available\&. See also
+\fB\-i, \-\-no\-ari\fR
+and
 \fB\-o, \-\-no\-ocsp\fR\&.
 .RE
 .PP
@@ -111,7 +113,7 @@
 .PP
 \fB\-f, \-\-force\fR
 .RS 4
-Force certificate reissuance regardless of expiration date\&.
+Force certificate reissuance regardless of expiration date and renewal 
information from the server\&.
 .RE
 .PP
 \fB\-h, \-\-hook\fR \fIPROGRAM\fR
@@ -182,6 +184,14 @@
 .RE
 .RE
 .PP
+\fB\-i, \-\-no\-ari\fR
+.RS 4
+Do not query or use the server\(cqs certificate renewal information window to 
decide whether to reissue an existing certificate\&. See also
+\fB\-d, \-\-days\fR
+and
+\fB\-o, \-\-no\-ocsp\fR\&.
+.RE
+.PP
 \fB\-l, \-\-alternate\fR \fIN\fR | \fIFP\fR
 .RS 4
 According to
@@ -194,8 +204,9 @@
 \fIFP\fR
 makes
 \fBuacme\fR
-select the first alternative chain containing a certificate whose SHA256 
fingerprint begins with
-\fIFP\fR\&. In both cases
+select the first alternative chain containing either a certificate whose 
SHA256 fingerprint begins with
+\fIFP\fR, or a certificate in which the Authority Key Identifier extension 
contains a keyIdentifier field beginning with
+\fIFP\fR\&. In all cases
 \fBuacme\fR
 falls back to the main certificate URL if it cannot match an alternative chain 
or the download thereof fails\&.
 .RE
@@ -396,6 +407,71 @@
 \fIrevoked\-TIMESTAMP\&.pem\fR\&. The reason code in the revocation request 
defaults to 0 but it can be specified by the user with
 \fB\-r, \-\-reason\fR\&.
 .RE
+.SH "ENVIRONMENT"
+.PP
+\fBUACME_CAINFO\fR
+.RS 4
+String naming a file holding one or more CA certificates to verify the ACME 
server with\&.
+.RE
+.PP
+\fBUACME_CAPATH\fR
+.RS 4
+String naming a directory holding multiple CA certificates to verify the ACME 
server with\&. If libcurl is built against OpenSSL, the certificate directory 
must be prepared using the OpenSSL c_rehash utility\&.
+.RE
+.PP
+\fBUACME_DNS_SERVERS\fR
+.RS 4
+Comma separated list of DNS servers to be used instead of the system 
default\&. The format of the dns servers option is
+\fIhost[:port][,host[:port]]\&...\fR
+.RE
+.PP
+\fBUACME_INTERFACE\fR
+.RS 4
+String setting the interface name to use as outgoing network interface\&. The 
name can be an interface name, an IP address, or a hostname\&. If you prefer 
one of these, you can use the following special prefixes:
+.PP
+\fIif!<name>\fR
+.RS 4
+Interface name
+.RE
+.PP
+\fIhost!<name>\fR
+.RS 4
+IP address or hostname
+.RE
+.PP
+\fIifhost!<interface>!<host>\fR
+.RS 4
+Interface name and IP address or hostname
+.RE
+.RE
+.PP
+\fBUACME_PROXY\fR
+.RS 4
+String holding the proxy hostname or dotted numerical IP address\&. A 
numerical IPv6 address must be written within [brackets]\&. To specify port 
number in this string, append :[port] to the end of the host name\&. If not 
specified, default to using port 1080\&. The proxy string may be prefixed with 
[scheme]:// to specify which kind of proxy is used (http://, https://, 
socks4://, socks4a://, socks5://, socks5h://)\&. The proxy can also be 
specified with its associated credentials like for ordinary URLs in the style:
+\fIscheme://username:password@hostname\fR
+.RE
+.SH "HOOK ENVIRONMENT"
+.sp
+The following environment variables are exported for use by the hook program:
+.PP
+\fBUACME_CONFDIR\fR
+.RS 4
+Path to
+\fICONFDIR\fR, see
+\fB\-c, \-\-confdir\fR
+.RE
+.PP
+\fBUACME_VERBOSE\fR
+.RS 4
+Verbosity, see
+\fB\-v, \-\-verbose\fR
+.RE
+.PP
+\fBUACME_METHOD\fR, \fBUACME_TYPE\fR, \fBUACME_IDENT\fR, \fBUACME_TOKEN\fR, 
\fBUACME_AUTH\fR
+.RS 4
+Copies of the hook program arguments, see
+\fB\-h, \-\-hook\fR
+.RE
 .SH "EXIT STATUS"
 .PP
 \fB0\fR
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/uacme.1.txt new/uacme-1.7.6/uacme.1.txt
--- old/uacme-1.7.5/uacme.1.txt 2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/uacme.1.txt 2024-12-29 17:27:26.000000000 +0100
@@ -15,10 +15,11 @@
 --------
 *uacme* [*-a*|*--acme-url* 'URL'] [*-b*|*--bits* 'BITS']
     [*-c*|*--confdir* 'DIR'] [*-d*|*--days* 'DAYS'] [*-e*|*--eab* KEYID:KEY]
-    [*-f*|*--force*] [*-h*|*--hook* 'PROGRAM'] [*-l*|*--alternate* 'N' | 'FP']
-    [*-m*|*--must-staple*] [*-n*|*--never-create*] [*-o*|*--no-ocsp*]
-    [*-r*|*--reason* CODE] [*-s*|*--staging*] [*-t*|*--type* *RSA*|*EC*]
-    [*-v*|*--verbose* ...] [*-V*|*--version*] [*-y*|*--yes*] [*-?*|*--help*]
+    [*-f*|*--force*] [*-h*|*--hook* 'PROGRAM'] [*-i*|*--no-ari*]
+    [*-l*|*--alternate* 'N' | 'FP'] [*-m*|*--must-staple*]
+    [*-n*|*--never-create*] [*-o*|*--no-ocsp*] [*-r*|*--reason* CODE]
+    [*-s*|*--staging*] [*-t*|*--type* *RSA*|*EC*] [*-v*|*--verbose* ...]
+    [*-V*|*--version*] [*-y*|*--yes*] [*-?*|*--help*]
     *new* ['EMAIL'] | *update* ['EMAIL'] | *deactivate* | *newkey* |
     *issue* 'IDENTIFIER' ['ALTNAME' ...]] | *issue* 'CSRFILE' |
     *revoke* 'CERTFILE' ['CERTKEYFILE']
@@ -61,7 +62,9 @@
 
 *-d, --days* 'DAYS'::
     Do not reissue certificates that are still valid for longer
-    than 'DAYS' (default 30). See also *-o, --no-ocsp*.
+    than 'DAYS' (default 30). This only applies as a fallback
+    if no server renewal information is available. See also
+    *-i, --no-ari* and *-o, --no-ocsp*.
 
 *-e, --eab* 'KEYID:KEY'::
     Specify RFC8555 External Account Binding credentials according
@@ -71,7 +74,8 @@
     'KEYID' must be an ASCII string. 'KEY' must be base64url-encoded.
 
 *-f, --force*::
-    Force certificate reissuance regardless of expiration date.
+    Force certificate reissuance regardless of expiration date and
+    renewal information from the server.
 
 *-h, --hook* 'PROGRAM'::
     Challenge hook program. If not specified *uacme* interacts with
@@ -94,6 +98,11 @@
         'AUTH'::: The key authorization (for *dns-01* and *tls-alpn-01*
            already converted to the base64url-encoded SHA256 digest format)
 
+*-i, --no-ari*::
+    Do not query or use the server's certificate renewal information window
+    to decide whether to reissue an existing certificate. See also
+    *-d, --days* and *-o, --no-ocsp*.
+
 *-l, --alternate* 'N' | 'FP'::
     According to <https://tools.ietf.org/html/rfc8555#section-7.4.2>
     the server MAY provide one or more additional certificate download URLs,
@@ -102,9 +111,11 @@
     in one of two ways. A positive integer 'N' makes *uacme* select the Nth
     alternative chain in the order presented by the server.
     A colon (':') separated list of two or more 2-digit hexadecimal numbers
-    'FP' makes *uacme* select the first alternative chain containing a
-    certificate whose SHA256 fingerprint begins with 'FP'.
-    In both cases *uacme* falls back to the main certificate URL if it cannot
+    'FP' makes *uacme* select the first alternative chain containing either a
+    certificate whose SHA256 fingerprint begins with 'FP', or a certificate
+    in which the Authority Key Identifier extension contains a keyIdentifier
+    field beginning with 'FP'.
+    In all cases *uacme* falls back to the main certificate URL if it cannot
     match an alternative chain or the download thereof fails.
 
 *-m, --must-staple*::
@@ -237,6 +248,57 @@
     can be specified by the user with *-r, --reason*.
 
 
+ENVIRONMENT
+-----------
+*UACME_CAINFO*::
+    String naming a file holding one or more CA certificates to verify
+    the ACME server with.
+
+*UACME_CAPATH*::
+    String naming a directory holding multiple CA certificates to verify
+    the ACME server with. If libcurl is built against OpenSSL, the certificate
+    directory must be prepared using the OpenSSL c_rehash utility.
+
+*UACME_DNS_SERVERS*::
+    Comma separated list of DNS servers to be used instead of the system
+    default. The format of the dns servers option is
+    'host[:port][,host[:port]]...'
+
+*UACME_INTERFACE*::
+    String setting the interface name to use as outgoing network interface.
+    The name can be an interface name, an IP address, or a hostname.
+    If you prefer one of these, you can use the following special prefixes:
+
+    'if!<name>'::: Interface name
+    'host!<name>'::: IP address or hostname
+    'ifhost!<interface>!<host>'::: Interface name and IP address or hostname 
+
+*UACME_PROXY*::
+    String holding the proxy hostname or dotted numerical IP address.
+    A numerical IPv6 address must be written within [brackets].
+    To specify port number in this string, append :[port] to the end of
+    the host name. If not specified, default to using port 1080.
+    The proxy string may be prefixed with [scheme]:// to specify which
+    kind of proxy is used (http://, https://, socks4://, socks4a://,
+    socks5://, socks5h://).
+    The proxy can also be specified with its associated credentials like
+    for ordinary URLs in the style: 'scheme://username:password@hostname'
+
+
+HOOK ENVIRONMENT
+----------------
+The following environment variables are exported for use by the hook program:
+
+*UACME_CONFDIR*::
+    Path to 'CONFDIR', see *-c, --confdir*
+
+*UACME_VERBOSE*::
+    Verbosity, see *-v, --verbose*
+
+*UACME_METHOD*, *UACME_TYPE*, *UACME_IDENT*, *UACME_TOKEN*, *UACME_AUTH*::
+    Copies of the hook program arguments, see *-h, --hook*
+
+
 EXIT STATUS
 -----------
 *0*::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/uacme.c new/uacme-1.7.6/uacme.c
--- old/uacme-1.7.5/uacme.c     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/uacme.c     2024-12-29 17:27:26.000000000 +0100
@@ -71,55 +71,6 @@
     char *certprefix;
 } acme_t;
 
-#if !HAVE_STRCASESTR
-char *strcasestr(const char *haystack, const char *needle)
-{
-    char *ret = NULL;
-    char *_haystack = strdup(haystack);
-    char *_needle = strdup(needle);
-
-    if (!_haystack || !_needle)
-        warn("strcasestr: strdup failed");
-    else {
-        char *p;
-        for (p = _haystack; *p; p++)
-            *p = tolower(*p);
-        for (p = _needle; *p; p++)
-            *p = tolower(*p);
-        ret = strstr(_haystack, _needle);
-        if (ret)
-            ret = (char *)haystack + (ret - _haystack);
-    }
-    free(_haystack);
-    free(_needle);
-    return ret;
-}
-#endif
-
-char *find_header(const char *headers, const char *name)
-{
-    char *regex = NULL;
-    if (asprintf(&regex, "^%s:[ \t]*(.*)\r\n", name) < 0) {
-        warnx("find_header: asprintf failed");
-        return NULL;
-    }
-    char *ret = NULL;
-    regex_t reg;
-    if (regcomp(&reg, regex, REG_EXTENDED | REG_ICASE | REG_NEWLINE)) {
-        warnx("find_header: regcomp failed");
-    } else {
-        regmatch_t m[2];
-        if (regexec(&reg, headers, 2, m, 0) == 0) {
-            ret = strndup(headers + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
-            if (!ret)
-                warn("find_header: strndup failed");
-        }
-    }
-    free(regex);
-    regfree(&reg);
-    return ret;
-}
-
 int acme_get(acme_t *a, const char *url)
 {
     int ret = 0;
@@ -178,6 +129,50 @@
     return ret;
 }
 
+bool acme_error(acme_t *a)
+{
+    if (!a->json) return false;
+
+    if (a->type && strcasestr(a->type, "application/problem+json")) {
+        warnx("the server reported the following error:");
+        json_dump(stderr, a->json);
+        return true;
+    }
+
+    const json_value_t *e = json_find(a->json, "error");
+    if (e && e->type == JSON_OBJECT) {
+        warnx("the server reported the following error:");
+        json_dump(stderr, e);
+        return true;
+    }
+
+    return false;
+}
+
+bool acme_nonce(acme_t *a)
+{
+    const char *url = json_find_string(a->dir, "newNonce");
+    if (!url)
+    {
+        warnx("failed to find newNonce URL in directory");
+        return false;
+    }
+
+    msg(2, "fetching new nonce at %s", url);
+    if (acme_get(a, url) != 204) {
+        warnx("failed to fetch new nonce at %s", url);
+        acme_error(a);
+        return false;
+    } else if (acme_error(a))
+        return false;
+    else if (!a->nonce) {
+        warnx("failed to find nonce in newNonce resource");
+        return false;
+    }
+
+    return true;
+}
+
 int acme_post(acme_t *a, const char *url, const char *format, ...)
 {
     int ret = 0;
@@ -190,8 +185,8 @@
         return 0;
     }
 
-    if (!a->nonce) {
-        warnx("acme_post: need a nonce first");
+    if (!a->nonce && !acme_nonce(a)) {
+        warnx("acme_post: no nonce available");
         return 0;
     }
 
@@ -300,6 +295,11 @@
         else
             warnx("hook_run: %s terminated abnormally", prog);
     } else { // child
+        setenv("UACME_METHOD", method, 1);
+        setenv("UACME_TYPE", type, 1);
+        setenv("UACME_IDENT", ident, 1);
+        setenv("UACME_TOKEN", token, 1);
+        setenv("UACME_AUTH", auth, 1);
         if (execl(prog, prog, method, type, ident, token, auth,
                     (char *)NULL) < 0) {
             warn("hook_run: failed to execute %s", prog);
@@ -377,26 +377,6 @@
     return ids;
 }
 
-bool acme_error(acme_t *a)
-{
-    if (!a->json) return false;
-
-    if (a->type && strcasestr(a->type, "application/problem+json")) {
-        warnx("the server reported the following error:");
-        json_dump(stderr, a->json);
-        return true;
-    }
-
-    const json_value_t *e = json_find(a->json, "error");
-    if (e && e->type == JSON_OBJECT) {
-        warnx("the server reported the following error:");
-        json_dump(stderr, e);
-        return true;
-    }
-
-    return false;
-}
-
 bool acme_bootstrap(acme_t *a)
 {
     msg(1, "fetching directory at %s", a->directory);
@@ -410,21 +390,6 @@
     a->dir = a->json;
     a->json = NULL;
 
-    const char *url = json_find_string(a->dir, "newNonce");
-    if (!url)
-    {
-        warnx("failed to find newNonce URL in directory");
-        return false;
-    }
-
-    msg(2, "fetching new nonce at %s", url);
-    if (acme_get(a, url) != 204) {
-        warnx("failed to fetch new nonce at %s", url);
-        acme_error(a);
-        return false;
-    } else if (acme_error(a))
-        return false;
-
     return true;
 }
 
@@ -1379,10 +1344,10 @@
     fprintf(stderr,
         "usage: %s [-a|--acme-url URL] [-b|--bits BITS] [-c|--confdir DIR]\n"
         "\t[-d|--days DAYS] [-e|--eab KEYID:KEY] [-f|--force] [-h|--hook 
PROG]\n"
-        "\t[-l|--alternate [N | SHA256]] [-m|--must-staple] 
[-n|--never-create]\n"
-        "\t[-o|--no-ocsp] [-r|--reason CODE] [-s|--staging] [-t|--type RSA | 
EC]\n"
-        "\t[-v|--verbose ...] [-V|--version] [-y|--yes] [-?|--help]\n"
-        "\tnew [EMAIL] | update [EMAIL] | deactivate | newkey |\n"
+        "\t[-i|--no-ari] [-l|--alternate [N | SHA256]] [-m|--must-staple]\n"
+        "\t[-n|--never-create] [-o|--no-ocsp] [-r|--reason CODE] 
[-s|--staging]\n"
+        "\t[-t|--type RSA | EC] [-v|--verbose ...] [-V|--version] [-y|--yes]\n"
+        "\t[-?|--help] new [EMAIL] | update [EMAIL] | deactivate | newkey |\n"
         "\tissue IDENTIFIER [ALTNAME ...]] | issue CSRFILE |\n"
         "\trevoke CERTFILE [CERTKEYFILE]\n", progname);
 }
@@ -1413,6 +1378,7 @@
         {"force",        no_argument,       NULL, 'f'},
         {"help",         no_argument,       NULL, '?'},
         {"hook",         required_argument, NULL, 'h'},
+        {"no-ari",       no_argument,       NULL, 'i'},
         {"alternate",    required_argument, NULL, 'l'},
         {"must-staple",  no_argument,       NULL, 'm'},
         {"never-create", no_argument,       NULL, 'n'},
@@ -1434,6 +1400,7 @@
     bool custom_directory = false;
     bool status_req = false;
     bool status_check = true;
+    bool ari_check = true;
     int days = 30;
     int bits = 0;
     int reason = 0;
@@ -1454,6 +1421,8 @@
         return ret;
     }
 
+    srand(getpid() ^ time(NULL));
+
 #if LIBCURL_VERSION_NUM < 0x072600
 #error libcurl version 7.38.0 or later is required
 #endif
@@ -1477,7 +1446,7 @@
     while (1) {
         char *endptr;
         int option_index;
-        int c = getopt_long(argc, argv, "a:b:c:d:e:f?h:l:mnor:st:vVy",
+        int c = getopt_long(argc, argv, "a:b:c:d:e:f?h:il:mnor:st:vVy",
                 options, &option_index);
         if (c == -1) break;
         switch (c) {
@@ -1523,6 +1492,10 @@
                 a.hook = optarg;
                 break;
 
+            case 'i':
+                ari_check = false;
+                break;
+
             case 'l':
                 if (!alt_parse(&a, optarg))
                     goto out;
@@ -1728,6 +1701,10 @@
     } else
         msg(1, "version " PACKAGE_VERSION " starting on %s", buf);
 
+    snprintf(buf, sizeof(buf), "%d", g_loglevel);
+    setenv("UACME_VERBOSE", buf, 1);
+    setenv("UACME_CONFDIR", confdir, 1);
+
     if (a.hook && access(a.hook, R_OK | X_OK) < 0) {
         warn("%s", a.hook);
         goto out;
@@ -1823,8 +1800,13 @@
             goto out;
         }
 
+        if (!acme_bootstrap(&a))
+            goto out;
+        const char *ari_url = ari_check ?
+            json_find_string(a.dir, "renewalInfo") : NULL;
+
         msg(1, "checking existence and expiration of %s", filename);
-        if (cert_valid(filename, names, days, status_check)) {
+        if (cert_valid(filename, names, ari_url, days, status_check)) {
             if (force)
                 msg(1, "forcing reissue of %s", filename);
             else {
@@ -1843,8 +1825,7 @@
             }
         }
 
-        if (acme_bootstrap(&a) && account_retrieve(&a)
-                && cert_issue(&a, names, csr))
+        if (account_retrieve(&a) && cert_issue(&a, names, csr))
             ret = 0;
     } else if (strcmp(action, "revoke") == 0) {
         if (acme_bootstrap(&a) && (!a.keyprefix || account_retrieve(&a)) &&
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/ualpn.1 new/uacme-1.7.6/ualpn.1
--- old/uacme-1.7.5/ualpn.1     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/ualpn.1     2024-12-29 17:27:26.000000000 +0100
@@ -2,12 +2,12 @@
 .\"     Title: ualpn
 .\"    Author: [see the "AUTHOR" section]
 .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\"      Date: 01/28/2024
+.\"      Date: 12/29/2024
 .\"    Manual: User Commands
-.\"    Source: ualpn 1.7.5
+.\"    Source: ualpn 1.7.6
 .\"  Language: English
 .\"
-.TH "UALPN" "1" "01/28/2024" "ualpn 1\&.7\&.5" "User Commands"
+.TH "UALPN" "1" "12/29/2024" "ualpn 1\&.7\&.6" "User Commands"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/uacme-1.7.5/ualpn.c new/uacme-1.7.6/ualpn.c
--- old/uacme-1.7.5/ualpn.c     2024-01-28 21:03:31.000000000 +0100
+++ new/uacme-1.7.6/ualpn.c     2024-12-29 17:27:26.000000000 +0100
@@ -833,7 +833,7 @@
     }
 
     bn = BN_new();
-    if (!bn || !BN_pseudo_rand(bn, 127, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
+    if (!bn || !BN_rand(bn, 127, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
         openssl_error("auth_crt");
         goto out;
     }

Reply via email to