Apache HTTPD
md_acme_order.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#include "md_acme_order.h"
42
43
45{
47
48 order = apr_pcalloc(p, sizeof(*order));
49 order->p = p;
50 order->authz_urls = apr_array_make(p, 5, sizeof(const char *));
51 order->challenge_setups = apr_array_make(p, 5, sizeof(const char *));
52
53 return order;
54}
55
56/**************************************************************************************************/
57/* order conversion */
58
59#define MD_KEY_CHALLENGE_SETUPS "challenge-setups"
60
62{
63 if (s) {
64 if (!strcmp("valid", s)) {
66 }
67 else if (!strcmp("invalid", s)) {
69 }
70 else if (!strcmp("ready", s)) {
72 }
73 else if (!strcmp("pending", s)) {
75 }
76 else if (!strcmp("processing", s)) {
78 }
79 }
81}
82
84{
85 switch (status) {
87 return "pending";
89 return "ready";
91 return "processing";
93 return "valid";
95 return "invalid";
96 default:
97 return "invalid";
98 }
99}
100
102{
103 md_json_t *json = md_json_create(p);
104
105 if (order->url) {
106 md_json_sets(order->url, json, MD_KEY_URL, NULL);
107 }
109 md_json_setsa(order->authz_urls, json, MD_KEY_AUTHORIZATIONS, NULL);
110 md_json_setsa(order->challenge_setups, json, MD_KEY_CHALLENGE_SETUPS, NULL);
111 if (order->finalize) {
112 md_json_sets(order->finalize, json, MD_KEY_FINALIZE, NULL);
113 }
114 if (order->certificate) {
115 md_json_sets(order->certificate, json, MD_KEY_CERTIFICATE, NULL);
116 }
117 return json;
118}
119
121{
122 if (!order->url && md_json_has_key(json, MD_KEY_URL, NULL)) {
123 order->url = md_json_dups(p, json, MD_KEY_URL, NULL);
124 }
127 md_json_dupsa(order->authz_urls, p, json, MD_KEY_AUTHORIZATIONS, NULL);
128 }
130 md_json_dupsa(order->challenge_setups, p, json, MD_KEY_CHALLENGE_SETUPS, NULL);
131 }
133 order->finalize = md_json_dups(p, json, MD_KEY_FINALIZE, NULL);
134 }
136 order->certificate = md_json_dups(p, json, MD_KEY_CERTIFICATE, NULL);
137 }
138}
139
147
149{
151 if (md_array_str_index(order->authz_urls, authz_url, 0, 1) < 0) {
152 APR_ARRAY_PUSH(order->authz_urls, const char*) = apr_pstrdup(order->p, authz_url);
153 }
154 return APR_SUCCESS;
155}
156
158{
159 int i;
160
162 i = md_array_str_index(order->authz_urls, authz_url, 0, 1);
163 if (i >= 0) {
164 order->authz_urls = md_array_str_remove(order->p, order->authz_urls, authz_url, 1);
165 return APR_SUCCESS;
166 }
167 return APR_ENOENT;
168}
169
171{
172 if (md_array_str_index(order->challenge_setups, token, 0, 1) < 0) {
173 APR_ARRAY_PUSH(order->challenge_setups, const char*) = apr_pstrdup(order->p, token);
174 }
175 return APR_SUCCESS;
176}
177
178/**************************************************************************************************/
179/* persistence */
180
182 const char *md_name, md_acme_order_t **pauthz_set,
183 apr_pool_t *p)
184{
185 apr_status_t rv;
186 md_json_t *json;
188
189 rv = md_store_load_json(store, group, md_name, MD_FN_ORDER, &json, p);
190 if (APR_SUCCESS == rv) {
192 }
193 *pauthz_set = (APR_SUCCESS == rv)? authz_set : NULL;
194 return rv;
195}
196
198{
199 md_store_t *store = baton;
200 md_json_t *json;
201 md_store_group_t group;
202 md_acme_order_t *set;
203 const char *md_name;
204 int create;
205
206 (void)p;
207 group = (md_store_group_t)va_arg(ap, int);
208 md_name = va_arg(ap, const char *);
209 set = va_arg(ap, md_acme_order_t *);
210 create = va_arg(ap, int);
211
212 json = md_acme_order_to_json(set, ptemp);
213 assert(json);
214 return md_store_save_json(store, ptemp, group, md_name, MD_FN_ORDER, json, create);
215}
216
218 md_store_group_t group, const char *md_name,
219 md_acme_order_t *authz_set, int create)
220{
221 return md_util_pool_vdo(p_save, store, p, group, md_name, authz_set, create, NULL);
222}
223
225{
226 md_store_t *store = baton;
228 md_store_group_t group;
229 const md_t *md;
230 const char *setup_token;
232 int i;
233
234 group = (md_store_group_t)va_arg(ap, int);
235 md = va_arg(ap, const md_t *);
236 env = va_arg(ap, apr_table_t *);
237
238 if (APR_SUCCESS == md_acme_order_load(store, group, md->name, &order, p)) {
239 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "order loaded for %s", md->name);
240 for (i = 0; i < order->challenge_setups->nelts; ++i) {
241 setup_token = APR_ARRAY_IDX(order->challenge_setups, i, const char*);
242 if (setup_token) {
244 "order teardown setup %s", setup_token);
246 }
247 }
248 }
249 return md_store_remove(store, group, md->name, MD_FN_ORDER, ptemp, 1);
250}
251
253 const md_t *md, apr_table_t *env)
254{
255 return md_util_pool_vdo(p_purge, store, p, group, md, env, NULL);
256}
257
258/**************************************************************************************************/
259/* ACMEv2 order requests */
260
269
270#define ORDER_CTX_INIT(ctx, p, o, a, n, d, r) \
271 (ctx)->p = (p); (ctx)->order = (o); (ctx)->acme = (a); \
272 (ctx)->name = (n); (ctx)->domains = d; (ctx)->result = r
273
275{
276 md_json_t *jid;
277
278 (void)baton;
280 md_json_sets("dns", jid, "type", NULL);
281 md_json_sets(value, jid, "value", NULL);
282 return md_json_setj(jid, json, NULL);
283}
284
286{
289
290 jpayload = md_json_create(req->p);
291 md_json_seta(ctx->domains, identifier_to_json, NULL, jpayload, "identifiers", NULL);
292
293 return md_acme_req_body_init(req, jpayload);
294}
295
297 md_json_t *body, void *baton)
298{
300 const char *location = apr_table_get(hdrs, "location");
302
303 (void)acme;
304 (void)p;
305 if (!ctx->order) {
306 if (location) {
307 ctx->order = md_acme_order_create(ctx->p);
308 ctx->order->url = apr_pstrdup(ctx->p, location);
309 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, ctx->p, "new order at %s", location);
310 }
311 else {
312 rv = APR_EINVAL;
313 md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, ctx->p, "new order, no location header");
314 goto out;
315 }
316 }
317
318 order_update_from_json(ctx->order, body, ctx->p);
319out:
320 return rv;
321}
322
324 const char *name, apr_array_header_t *domains)
325{
327 apr_status_t rv;
328
330 ORDER_CTX_INIT(&ctx, p, NULL, acme, name, domains, NULL);
332 *porder = (APR_SUCCESS == rv)? ctx.order : NULL;
333 return rv;
334}
335
338{
340 apr_status_t rv;
341
343 ORDER_CTX_INIT(&ctx, p, order, acme, NULL, NULL, result);
344 rv = md_acme_GET(acme, order->url, NULL, on_order_upd, NULL, NULL, &ctx);
345 if (APR_SUCCESS != rv && APR_SUCCESS != acme->last->status) {
346 md_result_dup(result, acme->last);
347 }
348 return rv;
349}
350
351static apr_status_t await_ready(void *baton, int attempt)
352{
355
356 (void)attempt;
357 if (APR_SUCCESS != (rv = md_acme_order_update(ctx->order, ctx->acme,
358 ctx->result, ctx->p))) goto out;
359 switch (ctx->order->status) {
363 break;
365 rv = APR_EAGAIN;
366 break;
367 default:
368 rv = APR_EINVAL;
369 break;
370 }
371out:
372 return rv;
373}
374
376 const md_t *md, apr_interval_time_t timeout,
378{
380 apr_status_t rv;
381
383 ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
384
385 md_result_activity_setn(result, "Waiting for order to become ready");
386 rv = md_util_try(await_ready, &ctx, 0, timeout, 0, 0, 1);
388 return rv;
389}
390
391static apr_status_t await_valid(void *baton, int attempt)
392{
395
396 (void)attempt;
397 if (APR_SUCCESS != (rv = md_acme_order_update(ctx->order, ctx->acme,
398 ctx->result, ctx->p))) goto out;
399 switch (ctx->order->status) {
401 md_result_set(ctx->result, APR_EINVAL, "ACME server order status is 'valid'.");
402 break;
404 rv = APR_EAGAIN;
405 break;
407 md_result_set(ctx->result, APR_EINVAL, "ACME server order status is 'invalid'.");
408 rv = APR_EINVAL;
409 break;
410 default:
411 rv = APR_EINVAL;
412 break;
413 }
414out:
415 return rv;
416}
417
419 const md_t *md, apr_interval_time_t timeout,
421{
423 apr_status_t rv;
424
426 ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
427
428 md_result_activity_setn(result, "Waiting for finalized order to become valid");
429 rv = md_util_try(await_valid, &ctx, 0, timeout, 0, 0, 1);
431 return rv;
432}
433
434/**************************************************************************************************/
435/* processing */
436
439 md_store_t *store, const md_t *md,
441 apr_pool_t *p)
442{
444 md_acme_authz_t *authz;
445 const char *url, *setup_token;
446 int i;
447
448 md_result_activity_printf(result, "Starting challenges for domains");
449 for (i = 0; i < order->authz_urls->nelts; ++i) {
450 url = APR_ARRAY_IDX(order->authz_urls, i, const char*);
451 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: check AUTHZ at %s", md->name, url);
452
453 if (APR_SUCCESS != (rv = md_acme_authz_retrieve(acme, p, url, &authz))) {
454 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: check authz for %s",
455 md->name, authz->domain);
456 goto leave;
457 }
458
459 switch (authz->state) {
461 break;
462
465 "%s: authorization pending for %s",
466 md->name, authz->domain);
467 rv = md_acme_authz_respond(authz, acme, store, challenge_types,
468 md->pks,
469 md->acme_tls_1_domains, md,
470 env, p, &setup_token, result);
471 if (APR_SUCCESS != rv) {
472 goto leave;
473 }
475 md_acme_order_save(store, p, MD_SG_STAGING, md->name, order, 0);
476 break;
477
479 rv = APR_EINVAL;
480 if (authz->error_type) {
482 goto leave;
483 }
484 /* fall through */
485 default:
486 rv = APR_EINVAL;
487 md_result_printf(result, rv, "unexpected AUTHZ state %d for domain %s",
488 authz->state, authz->domain);
490 goto leave;
491 }
492 }
493leave:
494 return rv;
495}
496
497static apr_status_t check_challenges(void *baton, int attempt)
498{
500 const char *url;
501 md_acme_authz_t *authz;
503 int i;
504
505 for (i = 0; i < ctx->order->authz_urls->nelts; ++i) {
506 url = APR_ARRAY_IDX(ctx->order->authz_urls, i, const char*);
507 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ctx->p, "%s: check AUTHZ at %s (attempt %d)",
508 ctx->name, url, attempt);
509
510 rv = md_acme_authz_retrieve(ctx->acme, ctx->p, url, &authz);
511 if (APR_SUCCESS == rv) {
512 switch (authz->state) {
514 md_result_printf(ctx->result, rv,
515 "domain authorization for %s is valid", authz->domain);
516 break;
518 rv = APR_EAGAIN;
520 "%s: status pending at %s", authz->domain, authz->url);
521 goto leave;
523 rv = APR_EINVAL;
524 md_result_printf(ctx->result, rv,
525 "domain authorization for %s failed, CA considers "
526 "answer to challenge invalid%s.",
527 authz->domain, authz->error_type? "" : ", no error given");
528 md_result_log(ctx->result, MD_LOG_ERR);
529 goto leave;
530 default:
531 rv = APR_EINVAL;
532 md_result_printf(ctx->result, rv,
533 "domain authorization for %s failed with state %d",
534 authz->domain, authz->state);
535 md_result_log(ctx->result, MD_LOG_ERR);
536 goto leave;
537 }
538 }
539 else {
540 md_result_printf(ctx->result, rv, "authorization retrieval failed for %s on <%s>",
541 ctx->name, url);
542 }
543 }
544leave:
545 return rv;
546}
547
549 const md_t *md, apr_interval_time_t timeout,
551{
553 apr_status_t rv;
554
555 ORDER_CTX_INIT(&ctx, p, order, acme, md->name, NULL, result);
556
557 md_result_activity_printf(result, "Monitoring challenge status for %s", md->name);
558 rv = md_util_try(check_challenges, &ctx, 0, timeout, 0, 0, 1);
559 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "%s: checked authorizations", md->name);
560 return rv;
561}
562
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_EAGAIN
Definition apr_errno.h:730
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
apr_brigade_flush void * ctx
const char * url
Definition apr_escape.h:120
apr_size_t size
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_array_header_t ** result
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
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
int int status
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
#define MD_KEY_URL
Definition md.h:207
#define MD_KEY_FINALIZE
Definition md.h:148
#define MD_KEY_STATUS
Definition md.h:196
#define MD_KEY_CERTIFICATE
Definition md.h:126
#define MD_KEY_AUTHORIZATIONS
Definition md.h:120
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_GET(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:455
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
#define MD_ACME_VERSION_MAJOR(i)
Definition md_acme.h:42
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)
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)
@ MD_ACME_AUTHZ_S_PENDING
@ MD_ACME_AUTHZ_S_VALID
@ MD_ACME_AUTHZ_S_INVALID
static apr_status_t on_init_order_register(md_acme_req_t *req, void *baton)
apr_status_t md_acme_order_save(struct md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *md_name, md_acme_order_t *authz_set, int create)
static md_acme_order_st order_st_from_str(const char *s)
static apr_status_t check_challenges(void *baton, int attempt)
static apr_status_t p_purge(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
apr_status_t md_acme_order_load(struct md_store_t *store, md_store_group_t group, const char *md_name, md_acme_order_t **pauthz_set, apr_pool_t *p)
static apr_status_t await_valid(void *baton, int attempt)
#define ORDER_CTX_INIT(ctx, p, o, a, n, d, r)
static apr_status_t identifier_to_json(void *value, md_json_t *json, apr_pool_t *p, void *baton)
static apr_status_t add_setup_token(md_acme_order_t *order, const char *token)
apr_status_t md_acme_order_update(md_acme_order_t *order, md_acme_t *acme, md_result_t *result, apr_pool_t *p)
static apr_status_t await_ready(void *baton, int attempt)
apr_status_t md_acme_order_remove(md_acme_order_t *order, const char *authz_url)
apr_status_t md_acme_order_start_challenges(md_acme_order_t *order, md_acme_t *acme, apr_array_header_t *challenge_types, md_store_t *store, const md_t *md, apr_table_t *env, md_result_t *result, apr_pool_t *p)
#define MD_KEY_CHALLENGE_SETUPS
md_acme_order_t * md_acme_order_from_json(md_json_t *json, apr_pool_t *p)
static const char * order_st_to_str(md_acme_order_st status)
apr_status_t md_acme_order_purge(md_store_t *store, apr_pool_t *p, md_store_group_t group, const md_t *md, apr_table_t *env)
apr_status_t md_acme_order_await_ready(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
md_json_t * md_acme_order_to_json(md_acme_order_t *order, apr_pool_t *p)
apr_status_t md_acme_order_monitor_authzs(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
md_acme_order_t * md_acme_order_create(apr_pool_t *p)
static apr_status_t p_save(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
static void order_update_from_json(md_acme_order_t *order, md_json_t *json, apr_pool_t *p)
apr_status_t md_acme_order_register(md_acme_order_t **porder, md_acme_t *acme, apr_pool_t *p, const char *name, apr_array_header_t *domains)
apr_status_t md_acme_order_await_valid(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
static apr_status_t on_order_upd(md_acme_t *acme, apr_pool_t *p, const apr_table_t *hdrs, md_json_t *body, void *baton)
apr_status_t md_acme_order_add(md_acme_order_t *order, const char *authz_url)
#define MD_FN_ORDER
md_acme_order_st
@ MD_ACME_ORDER_ST_VALID
@ MD_ACME_ORDER_ST_PENDING
@ MD_ACME_ORDER_ST_INVALID
@ MD_ACME_ORDER_ST_READY
@ MD_ACME_ORDER_ST_PROCESSING
apr_pool_t * p
Definition md_event.c:32
md_json_t * md_json_create(apr_pool_t *pool)
Definition md_json.c:92
apr_status_t md_json_sets(const char *value, md_json_t *json,...)
Definition md_json.c:430
const char * md_json_gets(const md_json_t *json,...)
Definition md_json.c:406
apr_status_t md_json_seta(apr_array_header_t *a, md_json_to_cb *cb, void *baton, md_json_t *json,...)
Definition md_json.c:767
apr_status_t md_json_dupsa(apr_array_header_t *a, apr_pool_t *p, md_json_t *json,...)
Definition md_json.c:887
apr_status_t md_json_setj(const md_json_t *value, md_json_t *json,...)
Definition md_json.c:527
int md_json_has_key(const md_json_t *json,...)
Definition md_json.c:279
const char * md_json_dups(apr_pool_t *p, const md_json_t *json,...)
Definition md_json.c:418
apr_status_t md_json_setsa(apr_array_header_t *a, md_json_t *json,...)
Definition md_json.c:911
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
#define MD_LOG_MARK
Definition md_log.h:39
@ 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
void md_result_activity_printf(md_result_t *result, const char *fmt,...)
Definition md_result.c:82
void md_result_activity_setn(md_result_t *result, const char *activity)
Definition md_result.c:74
void md_result_dup(md_result_t *dest, const md_result_t *src)
Definition md_result.c:216
void md_result_printf(md_result_t *result, apr_status_t status, const char *fmt,...)
Definition md_result.c:126
void md_result_problem_set(md_result_t *result, apr_status_t status, const char *problem, const char *detail, const md_json_t *subproblems)
Definition md_result.c:100
void md_result_log(md_result_t *result, unsigned int level)
Definition md_result.c:227
void md_result_set(md_result_t *result, apr_status_t status, const char *detail)
Definition md_result.c:91
apr_status_t md_store_save_json(md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *name, const char *aspect, struct md_json_t *data, int create)
Definition md_store.c:113
apr_status_t md_store_remove(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, apr_pool_t *p, int force)
Definition md_store.c:86
apr_status_t md_store_load_json(md_store_t *store, md_store_group_t group, const char *name, const char *aspect, struct md_json_t **pdata, apr_pool_t *p)
Definition md_store.c:106
md_store_group_t
Definition md_store.h:62
@ MD_SG_STAGING
Definition md_store.h:67
apr_status_t md_util_try(md_util_try_fn *fn, void *baton, int ignore_errs, apr_interval_time_t timeout, apr_interval_time_t start_delay, apr_interval_time_t max_delay, int backoff)
Definition md_util.c:1040
apr_status_t md_util_pool_vdo(md_util_vaction *cb, void *baton, apr_pool_t *p,...)
Definition md_util.c:65
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_array_header_t * md_array_str_remove(apr_pool_t *p, apr_array_header_t *src, const char *exclude, int case_sensitive)
Definition md_util.c:318
static const char * order(cmd_parms *cmd, void *dv, const char *arg)
static apr_file_t * out
Definition mod_info.c:85
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
const char * error_type
const char * domain
md_acme_authz_state_t state
const char * url
const char * error_detail
apr_pool_t * p
Definition md_acme.h:249
struct md_result_t * last
Definition md_acme.h:135
int version
Definition md_acme.h:106
struct md_acme_t::@21::@23 v2
union md_acme_t::@21 api
const char * new_order
Definition md_acme.h:117
const char * url
Definition md_acme.h:95
apr_pool_t * p
Definition md_json.c:57
apr_status_t status
Definition md_result.h:32
Definition md.h:76
const char * name
Definition md.h:77
struct apr_array_header_t * acme_tls_1_domains
Definition md.h:98
struct md_pkeys_spec_t * pks
Definition md.h:81
md_acme_t * acme
const char * name
apr_pool_t * p
md_acme_order_t * order
md_result_t * result
apr_array_header_t * domains
IN ULONG IN INT timeout