| 1400 | #define ACME_CHALLENGE_PREFIX WELL_KNOWN_PREFIX"acme-challenge/" |
| 1401 | |
| 1402 | static int md_http_challenge_pr(request_rec *r) |
| 1403 | { |
| 1404 | apr_bucket_brigade *bb; |
| 1405 | const md_srv_conf_t *sc; |
| 1406 | const char *name, *data; |
| 1407 | md_reg_t *reg; |
| 1408 | const md_t *md; |
| 1409 | apr_status_t rv; |
| 1410 | |
| 1411 | if (r->parsed_uri.path |
| 1412 | && !strncmp(ACME_CHALLENGE_PREFIX, r->parsed_uri.path, sizeof(ACME_CHALLENGE_PREFIX)-1)) { |
| 1413 | sc = ap_get_module_config(r->server->module_config, &md_module); |
| 1414 | if (sc && sc->mc) { |
| 1415 | ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, |
| 1416 | "access inside /.well-known/acme-challenge for %s%s", |
| 1417 | r->hostname, r->parsed_uri.path); |
| 1418 | md = md_get_by_domain(sc->mc->mds, r->hostname); |
| 1419 | name = r->parsed_uri.path + sizeof(ACME_CHALLENGE_PREFIX)-1; |
| 1420 | reg = sc && sc->mc? sc->mc->reg : NULL; |
| 1421 | |
| 1422 | if (md && md->ca_challenges |
| 1423 | && md_array_str_index(md->ca_challenges, MD_AUTHZ_CHA_HTTP_01, 0, 1) < 0) { |
| 1424 | /* The MD this challenge is for does not allow http-01 challanges, |
| 1425 | * we have to decline. See #279 for a setup example where this |
| 1426 | * is necessary. |
| 1427 | */ |
| 1428 | return DECLINED; |
| 1429 | } |
| 1430 | |
| 1431 | if (strlen(name) && !ap_strchr_c(name, '/') && reg) { |
| 1432 | md_store_t *store = md_reg_store_get(reg); |
| 1433 | |
| 1434 | rv = md_store_load(store, MD_SG_CHALLENGES, r->hostname, |
| 1435 | MD_FN_HTTP01, MD_SV_TEXT, (void**)&data, r->pool); |
| 1436 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, |
| 1437 | "loading challenge for %s (%s)", r->hostname, r->uri); |
| 1438 | if (APR_SUCCESS == rv) { |
| 1439 | apr_size_t len = strlen(data); |
| 1440 | |
| 1441 | if (r->method_number != M_GET) { |
| 1442 | return HTTP_NOT_IMPLEMENTED; |
| 1443 | } |
| 1444 | /* A GET on a challenge resource for a hostname we are |
| 1445 | * configured for. Let's send the content back */ |
| 1446 | r->status = HTTP_OK; |
| 1447 | apr_table_setn(r->headers_out, "Content-Length", apr_ltoa(r->pool, (long)len)); |
| 1448 | |
| 1449 | bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); |
| 1450 | apr_brigade_write(bb, NULL, NULL, data, len); |
| 1451 | ap_pass_brigade(r->output_filters, bb); |
| 1452 | apr_brigade_cleanup(bb); |
| 1453 | |
| 1454 | return DONE; |
| 1455 | } |
| 1456 | else if (!md || md->renew_mode == MD_RENEW_MANUAL |
| 1457 | || (md->cert_files && md->cert_files->nelts |
| 1458 | && md->renew_mode == MD_RENEW_AUTO)) { |
| 1459 | /* The request hostname is not for a domain - or at least not for |
nothing calls this directly
no test coverage detected