From 8cb0a0c53d392c3abf2bb6ccbf9ac1d90f77db24 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 26 May 2026 08:36:36 +0200 Subject: [PATCH] BUG/MEDIUM: acme: protect against risk of null-deref on connection failure 7 ACME state handlers iterate over hc->res.hdrs, but they can be called after an error was detected, and the HTTP client will leave res.hdrs NULL on connection errors before headers are received. Let's check this inside the loop, like the chkorder handler already does. Most of them, if not all, need to be backported to 3.2. --- src/acme.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/acme.c b/src/acme.c index 6b4dcd2af..7875f11e8 100644 --- a/src/acme.c +++ b/src/acme.c @@ -1532,7 +1532,7 @@ int acme_res_certificate(struct task *task, struct acme_ctx *ctx, char **errmsg) hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v); @@ -1745,7 +1745,7 @@ int acme_res_finalize(struct task *task, struct acme_ctx *ctx, char **errmsg) hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v); @@ -1846,7 +1846,7 @@ enum acme_ret acme_res_challenge(struct task *task, struct acme_ctx *ctx, struct TRACE_DATA(__FUNCTION__, ACME_EV_RES, ctx, NULL, &hc->res.buf); - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v); @@ -1973,7 +1973,7 @@ int acme_res_auth(struct task *task, struct acme_ctx *ctx, struct acme_auth *aut hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v); @@ -2289,7 +2289,7 @@ int acme_res_neworder(struct task *task, struct acme_ctx *ctx, char **errmsg) hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v); @@ -2468,7 +2468,7 @@ int acme_res_account(struct task *task, struct acme_ctx *ctx, int newaccount, ch hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Location"))) { istfree(&ctx->kid); ctx->kid = istdup(hdr->v); @@ -2535,7 +2535,7 @@ int acme_nonce(struct task *task, struct acme_ctx *ctx, char **errmsg) hdrs = hc->res.hdrs; - for (hdr = hdrs; isttest(hdr->v); hdr++) { + for (hdr = hdrs; hdrs && isttest(hdr->v); hdr++) { if (isteqi(hdr->n, ist("Replay-Nonce"))) { istfree(&ctx->nonce); ctx->nonce = istdup(hdr->v);