From: William Lallemand Date: Wed, 23 Jul 2025 10:32:34 +0000 (+0200) Subject: BUG/MEDIUM: acme: use POST-as-GET instead of GET for resources X-Git-Tag: v3.3-dev4~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7139ebd67659748e4447613cb3f2e12fd0229c12;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: acme: use POST-as-GET instead of GET for resources The requests that checked the status of the challenge and the retrieval of the certificate were done using a GET. This is working with letsencrypt and other CA providers, but it might not work everywhere. RFC 8555 specifies that only the directory and newNonce resources MUST work with a GET requests, but everything else must use POST-as-GET. Must be backported to 3.2. --- diff --git a/src/acme.c b/src/acme.c index 92f58e4a5..147038ddc 100644 --- a/src/acme.c +++ b/src/acme.c @@ -1274,11 +1274,8 @@ out: return ret; } - -/* - * Get an Auth URL - */ -int acme_req_auth(struct task *task, struct acme_ctx *ctx, struct acme_auth *auth, char **errmsg) +/* generate a POST-as-GET request */ +int acme_post_as_get(struct task *task, struct acme_ctx *ctx, struct ist url, char **errmsg) { struct buffer *req_in = NULL; struct buffer *req_out = NULL; @@ -1289,25 +1286,45 @@ int acme_req_auth(struct task *task, struct acme_ctx *ctx, struct acme_auth *aut int ret = 1; if ((req_in = alloc_trash_chunk()) == NULL) - goto error; + goto error_alloc; if ((req_out = alloc_trash_chunk()) == NULL) - goto error; + goto error_alloc; /* empty payload */ - if (acme_jws_payload(req_in, ctx->nonce, auth->auth, ctx->cfg->account.pkey, ctx->kid, req_out, errmsg) != 0) - goto error; + if (acme_jws_payload(req_in, ctx->nonce, url, ctx->cfg->account.pkey, ctx->kid, req_out, errmsg) != 0) + goto error_jws; - if (acme_http_req(task, ctx, auth->auth, HTTP_METH_POST, hdrs, ist2(req_out->area, req_out->data))) - goto error; + if (acme_http_req(task, ctx, url, HTTP_METH_POST, hdrs, ist2(req_out->area, req_out->data))) + goto error_http; ret = 0; -error: - memprintf(errmsg, "couldn't generate the Authorizations request"); +error_jws: + memprintf(errmsg, "couldn't generate the JWS token: %s", errmsg ? *errmsg : ""); + goto end; + +error_http: + memprintf(errmsg, "couldn't generate the http request"); + goto end; + +error_alloc: + memprintf(errmsg, "couldn't allocate memory"); + goto end; + +end: free_trash_chunk(req_in); free_trash_chunk(req_out); return ret; +} + + +/* + * Get an Auth URL + */ +int acme_req_auth(struct task *task, struct acme_ctx *ctx, struct acme_auth *auth, char **errmsg) +{ + return acme_post_as_get(task, ctx, auth->auth, errmsg); } @@ -1922,7 +1939,7 @@ re: break; case ACME_CHKCHALLENGE: if (http_st == ACME_HTTP_REQ) { - if (acme_http_req(task, ctx, ctx->next_auth->chall, HTTP_METH_GET, NULL, IST_NULL) != 0) + if (acme_post_as_get(task, ctx, ctx->next_auth->chall, &errmsg) != 0) goto retry; } if (http_st == ACME_HTTP_RES) { @@ -1957,7 +1974,7 @@ re: break; case ACME_CHKORDER: if (http_st == ACME_HTTP_REQ) { - if (acme_http_req(task, ctx, ctx->order, HTTP_METH_GET, NULL, IST_NULL) != 0) + if (acme_post_as_get(task, ctx, ctx->order, &errmsg) != 0) goto retry; } if (http_st == ACME_HTTP_RES) { @@ -1970,7 +1987,7 @@ re: break; case ACME_CERTIFICATE: if (http_st == ACME_HTTP_REQ) { - if (acme_http_req(task, ctx, ctx->certificate, HTTP_METH_GET, NULL, IST_NULL) != 0) + if (acme_post_as_get(task, ctx, ctx->certificate, &errmsg) != 0) goto retry; } if (http_st == ACME_HTTP_RES) {