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.
This commit is contained in:
William Lallemand 2025-07-23 12:32:34 +02:00
parent 054fa05e1f
commit 7139ebd676

View File

@ -1274,11 +1274,8 @@ out:
return ret; return ret;
} }
/* generate a POST-as-GET request */
/* int acme_post_as_get(struct task *task, struct acme_ctx *ctx, struct ist url, char **errmsg)
* Get an Auth URL
*/
int acme_req_auth(struct task *task, struct acme_ctx *ctx, struct acme_auth *auth, char **errmsg)
{ {
struct buffer *req_in = NULL; struct buffer *req_in = NULL;
struct buffer *req_out = 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; int ret = 1;
if ((req_in = alloc_trash_chunk()) == NULL) if ((req_in = alloc_trash_chunk()) == NULL)
goto error; goto error_alloc;
if ((req_out = alloc_trash_chunk()) == NULL) if ((req_out = alloc_trash_chunk()) == NULL)
goto error; goto error_alloc;
/* empty payload */ /* empty payload */
if (acme_jws_payload(req_in, ctx->nonce, auth->auth, ctx->cfg->account.pkey, ctx->kid, req_out, errmsg) != 0) if (acme_jws_payload(req_in, ctx->nonce, url, ctx->cfg->account.pkey, ctx->kid, req_out, errmsg) != 0)
goto error; goto error_jws;
if (acme_http_req(task, ctx, auth->auth, HTTP_METH_POST, hdrs, ist2(req_out->area, req_out->data))) if (acme_http_req(task, ctx, url, HTTP_METH_POST, hdrs, ist2(req_out->area, req_out->data)))
goto error; goto error_http;
ret = 0; 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_in);
free_trash_chunk(req_out); free_trash_chunk(req_out);
return ret; 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; break;
case ACME_CHKCHALLENGE: case ACME_CHKCHALLENGE:
if (http_st == ACME_HTTP_REQ) { 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; goto retry;
} }
if (http_st == ACME_HTTP_RES) { if (http_st == ACME_HTTP_RES) {
@ -1957,7 +1974,7 @@ re:
break; break;
case ACME_CHKORDER: case ACME_CHKORDER:
if (http_st == ACME_HTTP_REQ) { 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; goto retry;
} }
if (http_st == ACME_HTTP_RES) { if (http_st == ACME_HTTP_RES) {
@ -1970,7 +1987,7 @@ re:
break; break;
case ACME_CERTIFICATE: case ACME_CERTIFICATE:
if (http_st == ACME_HTTP_REQ) { 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; goto retry;
} }
if (http_st == ACME_HTTP_RES) { if (http_st == ACME_HTTP_RES) {