Apache HTTPD
md_acme_authz.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <stdio.h>
19
20#include <apr_lib.h>
21#include <apr_buckets.h>
22#include <apr_file_info.h>
23#include <apr_file_io.h>
24#include <apr_fnmatch.h>
25#include <apr_hash.h>
26#include <apr_strings.h>
27#include <apr_tables.h>
28
29#include "md.h"
30#include "md_crypt.h"
31#include "md_json.h"
32#include "md_http.h"
33#include "md_log.h"
34#include "md_jws.h"
35#include "md_result.h"
36#include "md_store.h"
37#include "md_util.h"
38
39#include "md_acme.h"
40#include "md_acme_authz.h"
41
43{
44 md_acme_authz_t *authz;
45 authz = apr_pcalloc(p, sizeof(*authz));
46
47 return authz;
48}
49
50/**************************************************************************************************/
51/* Register a new authorization */
52
53typedef struct {
54 size_t index;
55 const char *type;
56 const char *uri;
57 const char *token;
58 const char *key_authz;
60
68
70 const char *domain, md_acme_authz_t *authz, apr_pool_t *p)
71{
72 memset(ctx, 0, sizeof(*ctx));
73 ctx->p = p;
74 ctx->acme = acme;
75 ctx->domain = domain;
76 ctx->authz = authz;
77}
78
79/**************************************************************************************************/
80/* Update an existing authorization */
81
84{
85 md_acme_authz_t *authz;
86 apr_status_t rv;
87
88 authz = apr_pcalloc(p, sizeof(*authz));
89 authz->url = apr_pstrdup(p, url);
90 rv = md_acme_authz_update(authz, acme, p);
91
92 *pauthz = (APR_SUCCESS == rv)? authz : NULL;
93 return rv;
94}
95
100
101static int copy_challenge_error(void *baton, size_t index, md_json_t *json)
102{
104
105 (void)index;
106 if (md_json_has_key(json, MD_KEY_ERROR, NULL)) {
108 ctx->authz->error_detail = md_json_dups(ctx->p, json, MD_KEY_ERROR, MD_KEY_DETAIL, NULL);
109 ctx->authz->error_subproblems = md_json_dupj(ctx->p, json, MD_KEY_ERROR, MD_KEY_SUBPROBLEMS, NULL);
110 }
111 return 1;
112}
113
115{
116 md_json_t *json;
117 const char *s, *err;
119 apr_status_t rv;
121
122 assert(acme);
123 assert(acme->http);
124 assert(authz);
125 assert(authz->url);
126
128 json = NULL;
129 authz->error_type = authz->error_detail = NULL;
130 authz->error_subproblems = NULL;
131 err = "unable to parse response";
133
134 if (APR_SUCCESS == (rv = md_acme_get_json(&json, acme, authz->url, p))
135 && (s = md_json_gets(json, MD_KEY_STATUS, NULL))) {
136
138 authz->resource = json;
139 if (!strcmp(s, "pending")) {
141 err = "challenge 'pending'";
143 }
144 else if (!strcmp(s, "valid")) {
146 err = "challenge 'valid'";
148 }
149 else if (!strcmp(s, "invalid")) {
150 ctx.p = p;
151 ctx.authz = authz;
154 err = "challenge 'invalid'";
155 }
156 }
157
158 if (json && authz->state == MD_ACME_AUTHZ_S_UNKNOWN) {
159 err = "unable to understand response";
160 rv = APR_EINVAL;
161 }
162
164 md_log_perror(MD_LOG_MARK, log_level, rv, p, "ACME server authz: %s for %s at %s. "
165 "Exact response was: %s", err, authz->domain, authz->url,
166 json? md_json_writep(json, p, MD_JSON_FMT_COMPACT) : "not available");
167 }
168
169 return rv;
170}
171
172/**************************************************************************************************/
173/* response to a challenge */
174
176{
178
179 cha = apr_pcalloc(p, sizeof(*cha));
180 cha->index = index;
181 cha->type = md_json_dups(p, json, MD_KEY_TYPE, NULL);
182 if (md_json_has_key(json, MD_KEY_URL, NULL)) { /* ACMEv2 */
183 cha->uri = md_json_dups(p, json, MD_KEY_URL, NULL);
184 }
185 else { /* ACMEv1 */
186 cha->uri = md_json_dups(p, json, MD_KEY_URI, NULL);
187 }
188 cha->token = md_json_dups(p, json, MD_KEY_TOKEN, NULL);
189 cha->key_authz = md_json_dups(p, json, MD_KEY_KEYAUTHZ, NULL);
190
191 return cha;
192}
193
195{
197
198 (void)baton;
199 jpayload = md_json_create(req->p);
200 return md_acme_req_body_init(req, jpayload);
201}
202
204 md_json_t *body, void *baton)
205{
207
208 (void)acme;
209 (void)p;
210 (void)hdrs;
211 (void)body;
212 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ctx->p, "updated authz %s", ctx->authz->url);
213 return APR_SUCCESS;
214}
215
217 md_acme_t *acme, apr_pool_t *p, int *pchanged)
218{
219 const char *thumb64, *key_authz;
220 apr_status_t rv;
221
222 (void)authz;
223 assert(cha);
224 assert(cha->token);
225
226 *pchanged = 0;
227 if (APR_SUCCESS == (rv = md_jws_pkey_thumb(&thumb64, p, acme->acct_key))) {
228 key_authz = apr_psprintf(p, "%s.%s", cha->token, thumb64);
229 if (cha->key_authz) {
230 if (strcmp(key_authz, cha->key_authz)) {
231 /* Hu? Did the account change key? */
232 cha->key_authz = NULL;
233 }
234 }
235 if (!cha->key_authz) {
236 cha->key_authz = key_authz;
237 *pchanged = 1;
238 }
239 }
240 return rv;
241}
242
244 md_acme_t *acme, md_store_t *store,
246 apr_array_header_t *acme_tls_1_domains, const md_t *md,
248 const char **psetup_token, apr_pool_t *p)
249{
250 const char *data;
251 apr_status_t rv;
252 int notify_server;
253
254 (void)key_specs;
255 (void)env;
256 (void)acme_tls_1_domains;
257 (void)md;
258
259 if (APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))) {
260 goto out;
261 }
262
264 MD_SV_TEXT, (void**)&data, p);
265 if ((APR_SUCCESS == rv && strcmp(cha->key_authz, data)) || APR_STATUS_IS_ENOENT(rv)) {
266 const char *content = apr_psprintf(p, "%s\n", cha->key_authz);
267 rv = md_store_save(store, p, MD_SG_CHALLENGES, authz->domain, MD_FN_HTTP01,
268 MD_SV_TEXT, (void*)content, 0);
269 notify_server = 1;
270 }
271
272 if (APR_SUCCESS == rv && notify_server) {
274 const char *event;
275
276 /* Raise event that challenge data has been set up before we tell the
277 ACME server. Clusters might want to distribute it. */
278 event = apr_psprintf(p, "challenge-setup:%s:%s", MD_AUTHZ_TYPE_HTTP01, authz->domain);
280 if (APR_SUCCESS != rv) {
282 "%s: event '%s' failed. aborting challenge setup",
283 authz->domain, event);
284 goto out;
285 }
286 /* challenge is setup or was changed from previous data, tell ACME server
287 * so it may (re)try verification */
288 authz_req_ctx_init(&ctx, acme, NULL, authz, p);
289 ctx.challenge = cha;
291 }
292out:
293 *psetup_token = (APR_SUCCESS == rv)?
294 apr_psprintf(p, "%s:%s", MD_AUTHZ_TYPE_HTTP01, authz->domain) : NULL;
295 return rv;
296}
297
299{
300 *keyfn = apr_pstrcat(p, "acme-tls-alpn-01-", md_pkey_filename(kspec, p), NULL);
301 *certfn = apr_pstrcat(p, "acme-tls-alpn-01-", md_chain_filename(kspec, p), NULL);
302}
303
305 md_acme_t *acme, md_store_t *store,
307 apr_array_header_t *acme_tls_1_domains, const md_t *md,
309 const char **psetup_token, apr_pool_t *p)
310{
311 const char *acme_id, *token;
312 apr_status_t rv;
313 int notify_server;
315 int i;
316
317 (void)env;
318 (void)md;
319 if (md_array_str_index(acme_tls_1_domains, authz->domain, 0, 0) < 0) {
320 rv = APR_ENOTIMPL;
321 if (acme_tls_1_domains->nelts) {
323 "%s: protocol 'acme-tls/1' seems not enabled for this domain, "
324 "but is enabled for other associated domains. "
325 "Continuing with fingers crossed.", authz->domain);
326 }
327 else {
329 "%s: protocol 'acme-tls/1' seems not enabled for this or "
330 "any other associated domain. Not attempting challenge "
331 "type tls-alpn-01.", authz->domain);
332 goto out;
333 }
334 }
335 if (APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))) {
336 goto out;
337 }
338
339 /* Create a "tls-alpn-01" certificate for the domain we want to authenticate.
340 * The server will need to answer a TLS connection with SNI == authz->domain
341 * and ALPN protocol "acme-tls/1" with this certificate.
342 */
343 md_data_init_str(&data, cha->key_authz);
344 rv = md_crypt_sha256_digest_hex(&token, p, &data);
345 if (APR_SUCCESS != rv) {
346 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create tls-alpn-01 validation token",
347 authz->domain);
348 goto out;
349 }
350 acme_id = apr_psprintf(p, "critical,DER:04:20:%s", token);
351
352 /* Each configured key type must be generated to ensure:
353 * that any fallback certs already given to mod_ssl are replaced.
354 * We expect that the validation client (at the CA) can deal with at
355 * least one of them.
356 */
357
358 for (i = 0; i < md_pkeys_spec_count(key_specs); ++i) {
359 char *kfn, *cfn;
363
366
367 rv = md_store_load(store, MD_SG_CHALLENGES, authz->domain, cfn,
368 MD_SV_CERT, (void**)&cha_cert, p);
369 if ((APR_SUCCESS == rv && !md_cert_covers_domain(cha_cert, authz->domain))
370 || APR_STATUS_IS_ENOENT(rv)) {
371 if (APR_SUCCESS != (rv = md_pkey_gen(&cha_key, p, key_spec))) {
372 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create tls-alpn-01 %s challenge key",
374 goto out;
375 }
376
379 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create tls-alpn-01 %s challenge cert",
381 goto out;
382 }
383
384 if (APR_SUCCESS == (rv = md_store_save(store, p, MD_SG_CHALLENGES, authz->domain, kfn,
385 MD_SV_PKEY, (void*)cha_key, 0))) {
386 rv = md_store_save(store, p, MD_SG_CHALLENGES, authz->domain, cfn,
387 MD_SV_CERT, (void*)cha_cert, 0);
388 }
390 }
391 }
392
393 if (APR_SUCCESS == rv && notify_server) {
395 const char *event;
396
397 /* Raise event that challenge data has been set up before we tell the
398 ACME server. Clusters might want to distribute it. */
399 event = apr_psprintf(p, "challenge-setup:%s:%s", MD_AUTHZ_TYPE_TLSALPN01, authz->domain);
401 if (APR_SUCCESS != rv) {
403 "%s: event '%s' failed. aborting challenge setup",
404 authz->domain, event);
405 goto out;
406 }
407 /* challenge is setup or was changed from previous data, tell ACME server
408 * so it may (re)try verification */
409 authz_req_ctx_init(&ctx, acme, NULL, authz, p);
410 ctx.challenge = cha;
412 }
413out:
414 *psetup_token = (APR_SUCCESS == rv)?
415 apr_psprintf(p, "%s:%s", MD_AUTHZ_TYPE_TLSALPN01, authz->domain) : NULL;
416 return rv;
417}
418
420 md_acme_t *acme, md_store_t *store,
422 apr_array_header_t *acme_tls_1_domains, const md_t *md,
424 const char **psetup_token, apr_pool_t *p)
425{
426 const char *token;
427 const char * const *argv;
428 const char *cmdline, *dns01_cmd;
429 apr_status_t rv;
433 const char *event;
434
435 (void)store;
436 (void)key_specs;
437 (void)acme_tls_1_domains;
438
439 dns01_cmd = md->dns01_cmd;
440 if (!dns01_cmd)
441 dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
442 if (!dns01_cmd) {
443 rv = APR_ENOTIMPL;
444 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: dns-01 command not set",
445 authz->domain);
446 goto out;
447 }
448
449 if (APR_SUCCESS != (rv = setup_key_authz(cha, authz, acme, p, &notify_server))) {
450 goto out;
451 }
452
453 md_data_init_str(&data, cha->key_authz);
454 rv = md_crypt_sha256_digest64(&token, p, &data);
455 if (APR_SUCCESS != rv) {
456 md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: create dns-01 token for %s",
457 md->name, authz->domain);
458 goto out;
459 }
460
461 cmdline = apr_psprintf(p, "%s setup %s %s", dns01_cmd, authz->domain, token);
463 "%s: dns-01 setup command: %s", authz->domain, cmdline);
464
465 apr_tokenize_to_argv(cmdline, (char***)&argv, p);
466 if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, &exit_code))) {
468 "%s: dns-01 setup command failed to execute for %s", md->name, authz->domain);
469 goto out;
470 }
471 if (exit_code) {
472 rv = APR_EGENERAL;
474 "%s: dns-01 setup command returns %d for %s", md->name, exit_code, authz->domain);
475 goto out;
476 }
477
478 /* Raise event that challenge data has been set up before we tell the
479 ACME server. Clusters might want to distribute it. */
480 event = apr_psprintf(p, "challenge-setup:%s:%s", MD_AUTHZ_TYPE_DNS01, authz->domain);
482 if (APR_SUCCESS != rv) {
484 "%s: event '%s' failed. aborting challenge setup",
485 authz->domain, event);
486 goto out;
487 }
488 /* challenge is setup, tell ACME server so it may (re)try verification */
489 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: dns-01 setup succeeded for %s",
490 md->name, authz->domain);
491 authz_req_ctx_init(&ctx, acme, NULL, authz, p);
492 ctx.challenge = cha;
494
495out:
496 *psetup_token = (APR_SUCCESS == rv)?
497 apr_psprintf(p, "%s:%s %s", MD_AUTHZ_TYPE_DNS01, authz->domain, token) : NULL;
498 return rv;
499}
500
501static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, const md_t *md,
503{
504 const char * const *argv;
505 const char *cmdline, *dns01_cmd, *dns01v;
506 char *tmp, *s;
507 apr_status_t rv;
508 int exit_code;
509
510 (void)store;
511
512 dns01_cmd = md->dns01_cmd;
513 if (!dns01_cmd)
514 dns01_cmd = apr_table_get(env, MD_KEY_CMD_DNS01);
515 if (!dns01_cmd) {
516 rv = APR_ENOTIMPL;
517 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "%s: dns-01 command not set for %s",
518 md->name, domain);
519 goto out;
520 }
522 if (!dns01v || strcmp(dns01v, "2")) {
523 /* use older version of teardown args with only domain, remove token */
524 tmp = apr_pstrdup(p, domain);
525 s = strchr(tmp, ' ');
526 if (s) {
527 *s = '\0';
528 domain = tmp;
529 }
530 }
531
532 cmdline = apr_psprintf(p, "%s teardown %s", dns01_cmd, domain);
533 apr_tokenize_to_argv(cmdline, (char***)&argv, p);
534 if (APR_SUCCESS != (rv = md_util_exec(p, argv[0], argv, &exit_code)) || exit_code) {
536 "%s: dns-01 teardown command failed (exit code=%d) for %s",
537 md->name, exit_code, domain);
538 }
539out:
540 return rv;
541}
542
543static apr_status_t cha_teardown_dir(md_store_t *store, const char *domain, const md_t *md,
545{
546 (void)md;
547 (void)env;
548 return md_store_purge(store, p, MD_SG_CHALLENGES, domain);
549}
550
552 md_acme_t *acme, md_store_t *store,
554 apr_array_header_t *acme_tls_1_domains, const md_t *md,
556 const char **psetup_token, apr_pool_t *p);
557
558typedef apr_status_t cha_teardown(md_store_t *store, const char *domain, const md_t *md,
560
561typedef struct {
562 const char *name;
565} cha_type;
566
572static const apr_size_t CHA_TYPES_LEN = (sizeof(CHA_TYPES)/sizeof(CHA_TYPES[0]));
573
580
581static apr_status_t collect_offered(void *baton, size_t index, md_json_t *json)
582{
584 const char *ctype;
585
586 (void)index;
587 if ((ctype = md_json_gets(json, MD_KEY_TYPE, NULL))) {
588 APR_ARRAY_PUSH(ctx->offered, const char*) = apr_pstrdup(ctx->p, ctype);
589 }
590 return 1;
591}
592
593static apr_status_t find_type(void *baton, size_t index, md_json_t *json)
594{
596
597 const char *ctype = md_json_gets(json, MD_KEY_TYPE, NULL);
598 if (ctype && !apr_strnatcasecmp(ctx->type, ctype)) {
599 ctx->accepted = cha_from_json(ctx->p, index, json);
600 return 0;
601 }
602 return 1;
603}
604
607 apr_array_header_t *acme_tls_1_domains, const md_t *md,
608 apr_table_t *env, apr_pool_t *p, const char **psetup_token,
610{
611 apr_status_t rv;
612 int i, j;
613 cha_find_ctx fctx;
614
615 assert(acme);
616 assert(authz);
617 assert(authz->resource);
618
619 fctx.p = p;
620 fctx.accepted = NULL;
621
622 /* Look in the order challenge types are defined:
623 * - if they are offered by the CA, try to set it up
624 * - if setup was successful, we are done and the CA will evaluate us
625 * - if setup failed, continue to look for another supported challenge type
626 * - if there is no overlap in types, tell the user that she has to configure
627 * either more types (dns, tls-alpn-01), make ports available or refrain
628 * from using wildcard domains when dns is not available. etc.
629 * - if there was an overlap, but no setup was successful, report that. We
630 * will retry this, maybe the failure is temporary (e.g. command to setup DNS
631 */
632 md_result_printf(result, 0, "%s: selecting suitable authorization challenge "
633 "type, this domain supports %s",
634 authz->domain, apr_array_pstrcat(p, challenges, ' '));
635 rv = APR_ENOTIMPL;
637 for (i = 0; i < challenges->nelts; ++i) {
638 fctx.type = APR_ARRAY_IDX(challenges, i, const char *);
639 fctx.accepted = NULL;
642 "%s: challenge type '%s' for %s: %s",
643 authz->domain, fctx.type, md->name,
644 fctx.accepted? "maybe acceptable" : "not applicable");
645
646 if (fctx.accepted) {
647 for (j = 0; j < (int)CHA_TYPES_LEN; ++j) {
648 if (!apr_strnatcasecmp(CHA_TYPES[j].name, fctx.accepted->type)) {
649 md_result_activity_printf(result, "Setting up challenge '%s' for domain %s",
650 fctx.accepted->type, authz->domain);
651 rv = CHA_TYPES[j].setup(fctx.accepted, authz, acme, store, key_specs,
652 acme_tls_1_domains, md, env, result,
653 psetup_token, p);
654 if (APR_SUCCESS == rv) {
656 "%s: set up challenge '%s' for %s",
657 authz->domain, fctx.accepted->type, md->name);
658 goto out;
659 }
660 md_result_printf(result, rv, "error setting up challenge '%s' for %s, "
661 "for domain %s, looking for other option",
662 fctx.accepted->type, authz->domain, md->name);
664 }
665 }
666 }
667 }
668
669out:
670 if (!fctx.accepted || APR_ENOTIMPL == rv) {
671 rv = APR_EINVAL;
672 fctx.offered = apr_array_make(p, 5, sizeof(const char*));
674 md_result_printf(result, rv, "None of offered challenge types for domain %s are supported. "
675 "The server offered '%s' and available are: '%s'.",
676 authz->domain,
677 apr_array_pstrcat(p, fctx.offered, ' '),
679 result->problem = "challenge-mismatch";
681 }
682 else if (APR_SUCCESS != rv) {
683 fctx.offered = apr_array_make(p, 5, sizeof(const char*));
685 md_result_printf(result, rv, "None of the offered challenge types %s offered "
686 "for domain %s could be setup successfully. Please check the "
687 "log for errors.", authz->domain,
688 apr_array_pstrcat(p, fctx.offered, ' '));
689 result->problem = "challenge-setup-failure";
691 }
692 return rv;
693}
694
695apr_status_t md_acme_authz_teardown(struct md_store_t *store, const char *token,
696 const md_t *md, apr_table_t *env, apr_pool_t *p)
697{
698 char *challenge, *domain;
699 int i;
700
701 if (strchr(token, ':')) {
702 challenge = apr_pstrdup(p, token);
703 domain = strchr(challenge, ':');
704 *domain = '\0'; domain++;
705 for (i = 0; i < (int)CHA_TYPES_LEN; ++i) {
706 if (!apr_strnatcasecmp(CHA_TYPES[i].name, challenge)) {
707 if (CHA_TYPES[i].teardown) {
708 return CHA_TYPES[i].teardown(store, domain, md, env, p);
709 }
710 break;
711 }
712 }
713 }
714 return APR_SUCCESS;
715}
716
APR-UTIL Buckets/Bucket Brigades.
APR File Information.
APR File I/O Handling.
APR FNMatch Functions.
APR Hash Tables.
APR general purpose library routines.
APR Strings library.
APR Table library.
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_brigade_flush void * ctx
const char * url
Definition apr_escape.h:120
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
apr_array_header_t ** result
char const *const char const *const ** env
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_int32_t apr_int32_t apr_int32_t err
#define apr_time_from_sec(sec)
Definition apr_time.h:78
#define MD_KEY_TOKEN
Definition md.h:201
#define MD_KEY_ERROR
Definition md.h:145
#define MD_KEY_URL
Definition md.h:207
#define MD_KEY_URI
Definition md.h:209
#define MD_KEY_TYPE
Definition md.h:204
#define MD_KEY_SUBPROBLEMS
Definition md.h:198
#define MD_KEY_CMD_DNS01
Definition md.h:129
#define MD_KEY_VALUE
Definition md.h:212
#define MD_KEY_STATUS
Definition md.h:196
#define MD_KEY_DNS01_VERSION
Definition md.h:130
#define MD_KEY_CHALLENGES
Definition md.h:128
#define MD_KEY_IDENTIFIER
Definition md.h:156
#define MD_KEY_DETAIL
Definition md.h:136
#define MD_KEY_KEYAUTHZ
Definition md.h:159
apr_status_t md_acme_get_json(struct md_json_t **pjson, md_acme_t *acme, const char *url, apr_pool_t *p)
Definition md_acme.c:509
apr_status_t md_acme_req_body_init(md_acme_req_t *req, md_json_t *payload)
Definition md_acme.c:250
apr_status_t md_acme_POST(md_acme_t *acme, const char *url, md_acme_req_init_cb *on_init, md_acme_req_json_cb *on_json, md_acme_req_res_cb *on_res, md_acme_req_err_cb *on_err, void *baton)
Definition md_acme.c:432
static apr_status_t authz_http_set(md_acme_t *acme, apr_pool_t *p, const apr_table_t *hdrs, md_json_t *body, void *baton)
apr_status_t md_acme_authz_retrieve(md_acme_t *acme, apr_pool_t *p, const char *url, md_acme_authz_t **pauthz)
apr_status_t md_acme_authz_teardown(struct md_store_t *store, const char *token, const md_t *md, apr_table_t *env, apr_pool_t *p)
static apr_status_t collect_offered(void *baton, size_t index, md_json_t *json)
void tls_alpn01_fnames(apr_pool_t *p, md_pkey_spec_t *kspec, char **keyfn, char **certfn)
static int copy_challenge_error(void *baton, size_t index, md_json_t *json)
md_acme_authz_t * md_acme_authz_create(apr_pool_t *p)
static apr_status_t cha_tls_alpn_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, apr_table_t *env, md_result_t *result, const char **psetup_token, apr_pool_t *p)
static apr_status_t on_init_authz_resp(md_acme_req_t *req, void *baton)
static void authz_req_ctx_init(authz_req_ctx *ctx, md_acme_t *acme, const char *domain, md_acme_authz_t *authz, apr_pool_t *p)
apr_status_t cha_teardown(md_store_t *store, const char *domain, const md_t *md, apr_table_t *env, apr_pool_t *p)
static const cha_type CHA_TYPES[]
static apr_status_t cha_dns_01_teardown(md_store_t *store, const char *domain, const md_t *md, apr_table_t *env, apr_pool_t *p)
static apr_status_t cha_dns_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, apr_table_t *env, md_result_t *result, const char **psetup_token, apr_pool_t *p)
apr_status_t md_acme_authz_respond(md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, apr_array_header_t *challenges, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, apr_table_t *env, apr_pool_t *p, const char **psetup_token, md_result_t *result)
static apr_status_t cha_http_01_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, apr_table_t *env, md_result_t *result, const char **psetup_token, apr_pool_t *p)
static apr_status_t setup_key_authz(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, apr_pool_t *p, int *pchanged)
static apr_status_t cha_teardown_dir(md_store_t *store, const char *domain, const md_t *md, apr_table_t *env, apr_pool_t *p)
apr_status_t md_acme_authz_update(md_acme_authz_t *authz, md_acme_t *acme, apr_pool_t *p)
static apr_status_t find_type(void *baton, size_t index, md_json_t *json)
static md_acme_authz_cha_t * cha_from_json(apr_pool_t *p, size_t index, md_json_t *json)
apr_status_t cha_setup(md_acme_authz_cha_t *cha, md_acme_authz_t *authz, md_acme_t *acme, md_store_t *store, md_pkeys_spec_t *key_specs, apr_array_header_t *acme_tls_1_domains, const md_t *md, apr_table_t *env, md_result_t *result, const char **psetup_token, apr_pool_t *p)
static const apr_size_t CHA_TYPES_LEN
@ MD_ACME_AUTHZ_S_PENDING
@ MD_ACME_AUTHZ_S_VALID
@ MD_ACME_AUTHZ_S_UNKNOWN
@ MD_ACME_AUTHZ_S_INVALID
#define MD_AUTHZ_TYPE_DNS01
#define MD_FN_HTTP01
#define MD_AUTHZ_TYPE_HTTP01
#define MD_AUTHZ_TYPE_TLSALPN01
md_pkey_spec_t * md_pkeys_spec_get(const md_pkeys_spec_t *pks, int index)
Definition md_crypt.c:562
const char * md_pkey_spec_name(const md_pkey_spec_t *spec)
Definition md_crypt.c:520
int md_pkeys_spec_count(const md_pkeys_spec_t *pks)
Definition md_crypt.c:555
apr_status_t md_pkey_gen(md_pkey_t **ppkey, apr_pool_t *p, md_pkey_spec_t *spec)
Definition md_crypt.c:933
apr_status_t md_cert_make_tls_alpn_01(md_cert_t **pcert, const char *domain, const char *acme_id, md_pkey_t *pkey, apr_interval_time_t valid_for, apr_pool_t *p)
Definition md_crypt.c:2000
apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, const md_data_t *d)
Definition md_crypt.c:1088
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p, const md_data_t *data)
Definition md_crypt.c:1103
int md_cert_covers_domain(md_cert_t *cert, const char *domain_name)
Definition md_crypt.c:1230
apr_pool_t * p
Definition md_event.c:32
md_json_t * md_json_create(apr_pool_t *pool)
Definition md_json.c:92
md_json_t * md_json_dupj(apr_pool_t *p, const md_json_t *json,...)
Definition md_json.c:492
const char * md_json_gets(const md_json_t *json,...)
Definition md_json.c:406
int md_json_has_key(const md_json_t *json,...)
Definition md_json.c:279
int md_json_itera(md_json_itera_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:809
const char * md_json_dups(apr_pool_t *p, const md_json_t *json,...)
Definition md_json.c:418
const char * md_json_writep(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt)
Definition md_json.c:992
@ MD_JSON_FMT_COMPACT
Definition md_json.h:43
apr_status_t md_jws_pkey_thumb(const char **pthumb, apr_pool_t *p, struct md_pkey_t *pkey)
Definition md_jws.c:93
void md_log_perror(const char *file, int line, md_log_level_t level, apr_status_t rv, apr_pool_t *p, const char *fmt,...)
Definition md_log.c:68
int md_log_is_level(apr_pool_t *p, md_log_level_t level)
Definition md_log.c:60
static md_log_level_cb * log_level
Definition md_log.c:50
#define MD_LOG_MARK
Definition md_log.h:39
md_log_level_t
Definition md_log.h:20
@ MD_LOG_TRACE1
Definition md_log.h:29
@ MD_LOG_ERR
Definition md_log.h:24
@ MD_LOG_WARNING
Definition md_log.h:25
@ MD_LOG_DEBUG
Definition md_log.h:28
@ MD_LOG_INFO
Definition md_log.h:27
void md_result_activity_printf(md_result_t *result, const char *fmt,...)
Definition md_result.c:82
apr_status_t md_result_raise(md_result_t *result, const char *event, apr_pool_t *p)
Definition md_result.c:264
void md_result_printf(md_result_t *result, apr_status_t status, const char *fmt,...)
Definition md_result.c:126
void md_result_log(md_result_t *result, unsigned int level)
Definition md_result.c:227
apr_status_t md_store_save(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, const char *aspect, md_store_vtype_t vtype, void *data, int create)
Definition md_store.c:78
const char * md_pkey_filename(md_pkey_spec_t *spec, apr_pool_t *p)
Definition md_store.c:271
const char * md_chain_filename(md_pkey_spec_t *spec, apr_pool_t *p)
Definition md_store.c:276
apr_status_t md_store_purge(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name)
Definition md_store.c:93
apr_status_t md_store_load(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, md_store_vtype_t vtype, void **pdata, apr_pool_t *p)
Definition md_store.c:70
@ MD_SG_CHALLENGES
Definition md_store.h:65
@ MD_SV_PKEY
Definition md_store.h:56
@ MD_SV_CERT
Definition md_store.h:55
@ MD_SV_TEXT
Definition md_store.h:53
#define MD_SECS_PER_DAY
Definition md_time.h:23
void md_data_init_str(md_data_t *d, const char *str)
Definition md_util.c:102
int md_array_str_index(const apr_array_header_t *array, const char *s, int start, int case_sensitive)
Definition md_util.c:250
apr_status_t md_util_exec(apr_pool_t *p, const char *cmd, const char *const *argv, int *exit_code)
Definition md_util.c:1084
static apr_file_t * out
Definition mod_info.c:85
const char * argv[3]
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
apr_pool_t * p
md_acme_t * acme
md_acme_authz_t * authz
const char * domain
md_acme_authz_cha_t * challenge
const char * type
apr_pool_t * p
md_acme_authz_cha_t * accepted
apr_array_header_t * offered
cha_setup * setup
cha_teardown * teardown
const char * name
apr_pool_t * p
md_acme_authz_t * authz
const char * key_authz
const char * error_type
const char * domain
const struct md_json_t * error_subproblems
struct md_json_t * resource
md_acme_authz_state_t state
const char * url
const char * error_detail
apr_pool_t * p
Definition md_acme.h:249
struct md_http_t * http
Definition md_acme.h:131
struct md_pkey_t * acct_key
Definition md_acme.h:104
Definition md.h:76
const char * name
Definition md.h:77
const char * dns01_cmd
Definition md.h:99
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray