| 336 | } |
| 337 | |
| 338 | static apr_status_t md_acme_req_send(md_acme_req_t *req, int get_as_post) |
| 339 | { |
| 340 | apr_status_t rv; |
| 341 | md_acme_t *acme = req->acme; |
| 342 | md_data_t *body = NULL; |
| 343 | md_result_t *result; |
| 344 | |
| 345 | assert(acme->url); |
| 346 | |
| 347 | md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, req->p, |
| 348 | "sending req: %s %s", req->method, req->url); |
| 349 | md_result_reset(req->acme->last); |
| 350 | result = md_result_make(req->p, APR_SUCCESS); |
| 351 | |
| 352 | /* Whom are we talking to? */ |
| 353 | if (acme->version == MD_ACME_VERSION_UNKNOWN) { |
| 354 | rv = md_acme_setup(acme, result); |
| 355 | if (APR_SUCCESS != rv) goto leave; |
| 356 | } |
| 357 | |
| 358 | if (get_as_post && !strcmp("GET", req->method) && !req->on_init && !req->req_json) { |
| 359 | /* See <https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.6.3> |
| 360 | * and <https://mailarchive.ietf.org/arch/msg/acme/sotffSQ0OWV-qQJodLwWYWcEVKI> |
| 361 | * and <https://community.letsencrypt.org/t/acme-v2-scheduled-deprecation-of-unauthenticated-resource-gets/74380> |
| 362 | * We implement this change in ACMEv2 and higher as keeping the md_acme_GET() methods, |
| 363 | * but switching them to POSTs with a empty, JWS signed, body when we call |
| 364 | * our HTTP client. */ |
| 365 | req->method = "POST"; |
| 366 | req->on_init = acmev2_GET_as_POST_init; |
| 367 | /*req->max_retries = 0; don't do retries on these "GET"s */ |
| 368 | } |
| 369 | |
| 370 | /* Besides GET/HEAD, we always need a fresh nonce */ |
| 371 | if (strcmp("GET", req->method) && strcmp("HEAD", req->method)) { |
| 372 | if (acme->version == MD_ACME_VERSION_UNKNOWN) { |
| 373 | rv = md_acme_setup(acme, result); |
| 374 | if (APR_SUCCESS != rv) goto leave; |
| 375 | } |
| 376 | if (!acme->nonce && (APR_SUCCESS != (rv = acme->new_nonce_fn(acme)))) { |
| 377 | md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, req->p, |
| 378 | "error retrieving new nonce from ACME server"); |
| 379 | goto leave; |
| 380 | } |
| 381 | |
| 382 | md_json_sets(acme->nonce, req->prot_fields, "nonce", NULL); |
| 383 | md_json_sets(req->url, req->prot_fields, "url", NULL); |
| 384 | acme->nonce = NULL; |
| 385 | } |
| 386 | |
| 387 | rv = req->on_init? req->on_init(req, req->baton) : APR_SUCCESS; |
| 388 | if (APR_SUCCESS != rv) goto leave; |
| 389 | |
| 390 | if (req->req_json) { |
| 391 | body = apr_pcalloc(req->p, sizeof(*body)); |
| 392 | body->data = md_json_writep(req->req_json, req->p, MD_JSON_FMT_INDENT); |
| 393 | body->len = strlen(body->data); |
| 394 | md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, req->p, |
| 395 | "sending JSON body: %s", body->data); |
no test coverage detected