Apache HTTPD
mod_md.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 <apr_optional.h>
19#include <apr_strings.h>
20
21#include <mpm_common.h>
22#include <httpd.h>
23#include <http_core.h>
24#include <http_protocol.h>
25#include <http_request.h>
26#include <http_ssl.h>
27#include <http_log.h>
28#include <http_vhost.h>
29#include <ap_listen.h>
30
31#include "mod_status.h"
32
33#include "md.h"
34#include "md_curl.h"
35#include "md_crypt.h"
36#include "md_event.h"
37#include "md_http.h"
38#include "md_json.h"
39#include "md_store.h"
40#include "md_store_fs.h"
41#include "md_log.h"
42#include "md_ocsp.h"
43#include "md_result.h"
44#include "md_reg.h"
45#include "md_status.h"
46#include "md_util.h"
47#include "md_version.h"
48#include "md_acme.h"
49#include "md_acme_authz.h"
50
51#include "mod_md.h"
52#include "mod_md_config.h"
53#include "mod_md_drive.h"
54#include "mod_md_ocsp.h"
55#include "mod_md_os.h"
56#include "mod_md_status.h"
57
58static void md_hooks(apr_pool_t *pool);
59
62 NULL, /* func to create per dir config */
63 NULL, /* func to merge per dir config */
64 md_config_create_svr, /* func to create per server config */
65 md_config_merge_svr, /* func to merge per server config */
66 md_cmds, /* command handlers */
68#if defined(AP_MODULE_FLAG_NONE)
70#endif
71};
72
73/**************************************************************************************************/
74/* logging setup */
75
77
78static int log_is_level(void *baton, apr_pool_t *p, md_log_level_t level)
79{
80 (void)baton;
81 (void)p;
82 if (log_server) {
83 return APLOG_IS_LEVEL(log_server, (int)level);
84 }
85 return level <= MD_LOG_INFO;
86}
87
88#define LOG_BUF_LEN 16*1024
89
90static void log_print(const char *file, int line, md_log_level_t level,
91 apr_status_t rv, void *baton, apr_pool_t *p, const char *fmt, va_list ap)
92{
93 if (log_is_level(baton, p, level)) {
94 char buffer[LOG_BUF_LEN];
95
96 memset(buffer, 0, sizeof(buffer));
98 buffer[LOG_BUF_LEN-1] = '\0';
99
100 if (log_server) {
101 ap_log_error(file, line, APLOG_MODULE_INDEX, (int)level, rv, log_server, "%s", buffer);
102 }
103 else {
104 ap_log_perror(file, line, APLOG_MODULE_INDEX, (int)level, rv, p, "%s", buffer);
105 }
106 }
107}
108
109/**************************************************************************************************/
110/* mod_ssl interface */
111
112static void init_ssl(void)
113{
114 /* nop */
115}
116
117/**************************************************************************************************/
118/* lifecycle */
119
121{
122 (void)dummy;
124 return APR_SUCCESS;
125}
126
127static void init_setups(apr_pool_t *p, server_rec *base_server)
128{
129 log_server = base_server;
131}
132
133/**************************************************************************************************/
134/* notification handling */
135
136typedef struct {
137 const char *reason; /* what the notification is about */
138 apr_time_t min_interim; /* minimum time between notifying for this reason */
140
142 { "renewing", apr_time_from_sec(MD_SECS_PER_HOUR) }, /* once per hour */
143 { "renewed", apr_time_from_sec(MD_SECS_PER_DAY) }, /* once per day */
144 { "installed", apr_time_from_sec(MD_SECS_PER_DAY) }, /* once per day */
145 { "expiring", apr_time_from_sec(MD_SECS_PER_DAY) }, /* once per day */
146 { "errored", apr_time_from_sec(MD_SECS_PER_HOUR) }, /* once per hour */
147 { "ocsp-renewed", apr_time_from_sec(MD_SECS_PER_DAY) }, /* once per day */
148 { "ocsp-errored", apr_time_from_sec(MD_SECS_PER_HOUR) }, /* once per hour */
149};
150
151static apr_status_t notify(md_job_t *job, const char *reason,
153{
155 const char * const *argv;
156 const char *cmdline;
157 int exit_code;
159 apr_time_t min_interim = 0;
161 const char *log_msg_reason;
162 int i;
163
164 log_msg_reason = apr_psprintf(p, "message-%s", reason);
165 for (i = 0; i < (int)(sizeof(notify_rates)/sizeof(notify_rates[0])); ++i) {
167 min_interim = notify_rates[i].min_interim;
168 }
169 }
170 if (min_interim > 0) {
172 since_last.end = apr_time_now();
173 if (since_last.start > 0 && md_timeperiod_length(&since_last) < min_interim) {
174 /* not enough time has passed since we sent the last notification
175 * for this reason. */
177 "%s: rate limiting notification about '%s'", job->mdomain, reason);
178 return APR_SUCCESS;
179 }
180 }
181
182 if (!strcmp("renewed", reason)) {
183 if (mc->notify_cmd) {
184 cmdline = apr_psprintf(p, "%s %s", mc->notify_cmd, job->mdomain);
185 apr_tokenize_to_argv(cmdline, (char***)&argv, p);
186 rv = md_util_exec(p, argv[0], argv, &exit_code);
187
188 if (APR_SUCCESS == rv && exit_code) rv = APR_EGENERAL;
189 if (APR_SUCCESS != rv) {
191 "MDNotifyCmd %s failed with exit code %d.",
192 mc->notify_cmd, exit_code);
194 md_job_log_append(job, "notify-error", result->problem, result->detail);
195 return rv;
196 }
197 }
199 "The Managed Domain %s has been setup and changes "
200 "will be activated on next (graceful) server restart.", job->mdomain);
201 }
202 if (mc->message_cmd) {
203 cmdline = apr_psprintf(p, "%s %s %s", mc->message_cmd, reason, job->mdomain);
204 apr_tokenize_to_argv(cmdline, (char***)&argv, p);
205 rv = md_util_exec(p, argv[0], argv, &exit_code);
206
207 if (APR_SUCCESS == rv && exit_code) rv = APR_EGENERAL;
208 if (APR_SUCCESS != rv) {
210 "MDMessageCmd %s failed with exit code %d.",
211 mc->message_cmd, exit_code);
213 md_job_log_append(job, "message-error", reason, result->detail);
214 return rv;
215 }
216 }
217
219 return APR_SUCCESS;
220}
221
222static apr_status_t on_event(const char *event, const char *mdomain, void *baton,
224{
225 (void)mdomain;
226 return notify(job, event, result, p, baton);
227}
228
229/**************************************************************************************************/
230/* store setup */
231
232static apr_status_t store_file_ev(void *baton, struct md_store_t *store,
233 md_store_fs_ev_t ev, unsigned int group,
234 const char *fname, apr_filetype_e ftype,
235 apr_pool_t *p)
236{
237 server_rec *s = baton;
238 apr_status_t rv;
239
240 (void)store;
241 ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s, "store event=%d on %s %s (group %d)",
242 ev, (ftype == APR_DIR)? "dir" : "file", fname, group);
243
244 /* Directories in group CHALLENGES, STAGING and OCSP are written to
245 * under a different user. Give her ownership.
246 */
247 if (ftype == APR_DIR) {
248 switch (group) {
249 case MD_SG_CHALLENGES:
250 case MD_SG_STAGING:
251 case MD_SG_OCSP:
253 if (APR_ENOTIMPL != rv) {
254 return rv;
255 }
256 break;
257 default:
258 break;
259 }
260 }
261 return APR_SUCCESS;
262}
263
266{
267 const char *dir;
268 apr_status_t rv;
269
270 if (APR_SUCCESS == (rv = md_store_get_fname(&dir, store, group, NULL, NULL, p))
272 rv = store_file_ev(s, store, MD_S_FS_EV_CREATED, group, dir, APR_DIR, p);
273 }
274 return rv;
275}
276
279{
280 const char *base_dir;
281 apr_status_t rv;
282
283 base_dir = ap_server_root_relative(p, mc->base_dir);
284
285 if (APR_SUCCESS != (rv = md_store_fs_init(pstore, p, base_dir))) {
286 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10046)"setup store for %s", base_dir);
287 goto leave;
288 }
289
295 ) {
297 "setup challenges directory");
298 goto leave;
299 }
300
301leave:
302 return rv;
303}
304
305/**************************************************************************************************/
306/* post config handling */
307
309{
310 const char *contact;
311
312 if (!md->sc) {
313 md->sc = base_sc;
314 }
315
316 if (!md->ca_urls && md->sc->ca_urls) {
317 md->ca_urls = apr_array_copy(p, md->sc->ca_urls);
318 }
319 if (!md->ca_proto) {
321 }
322 if (!md->ca_agreement) {
324 }
326 if (md->contacts && md->contacts->nelts > 0) {
327 /* set explicitly */
328 }
329 else if (contact && contact[0]) {
331 APR_ARRAY_PUSH(md->contacts, const char *) =
332 md_util_schemify(p, contact, "mailto");
333 }
334 else if( md->sc->s->server_admin && strcmp(DEFAULT_ADMIN, md->sc->s->server_admin)) {
336 APR_ARRAY_PUSH(md->contacts, const char *) =
337 md_util_schemify(p, md->sc->s->server_admin, "mailto");
338 }
339 if (md->renew_mode == MD_RENEW_DEFAULT) {
341 }
344 if (md->transitive < 0) {
346 }
347 if (!md->ca_challenges && md->sc->ca_challenges) {
349 }
350 if (md_pkeys_spec_is_empty(md->pks)) {
351 md->pks = md->sc->pks;
352 }
353 if (md->require_https < 0) {
355 }
356 if (!md->ca_eab_kid) {
357 md->ca_eab_kid = md->sc->ca_eab_kid;
358 md->ca_eab_hmac = md->sc->ca_eab_hmac;
359 }
360 if (md->must_staple < 0) {
362 }
363 if (md->stapling < 0) {
365 }
366}
367
368static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s,
369 int *pupdates, apr_pool_t *p)
370{
371 if (md_contains(md, domain, 0)) {
372 return APR_SUCCESS;
373 }
374 else if (md->transitive) {
375 APR_ARRAY_PUSH(md->domains, const char*) = apr_pstrdup(p, domain);
377 return APR_SUCCESS;
378 }
379 else {
381 "Virtual Host %s:%d matches Managed Domain '%s', but the "
382 "name/alias %s itself is not managed. A requested MD certificate "
383 "will not match ServerName.",
384 s->server_hostname, s->port, md->name, domain);
385 return APR_SUCCESS;
386 }
387}
388
390{
391 apr_status_t rv;
392 const char *name;
393 int i;
394
395 if (APR_SUCCESS == (rv = check_coverage(md, s->server_hostname, s, pupdates, p))) {
397 "md[%s]: auto add, covers name %s", md->name, s->server_hostname);
398 for (i = 0; s->names && i < s->names->nelts; ++i) {
399 name = APR_ARRAY_IDX(s->names, i, const char*);
400 if (APR_SUCCESS != (rv = check_coverage(md, name, s, pupdates, p))) {
401 break;
402 }
404 "md[%s]: auto add, covers alias %s", md->name, name);
405 }
406 }
407 return rv;
408}
409
410static int uses_port(server_rec *s, int port)
411{
413 int match = 0;
414 for (sa = s->addrs; sa; sa = sa->next) {
415 if (sa->host_port == port) {
416 /* host_addr might be general (0.0.0.0) or specific, we count this as match */
417 match = 1;
418 }
419 else {
420 /* uses other port/wildcard */
421 return 0;
422 }
423 }
424 return match;
425}
426
428 apr_pool_t *p, int log_level)
429{
432 int can_http, can_https;
433
434 if (mc->can_http >= 0 && mc->can_https >= 0) goto set_and_leave;
435
436 can_http = can_https = 0;
437 for (lr = ap_listeners; lr; lr = lr->next) {
438 for (sa = lr->bind_addr; sa; sa = sa->next) {
439 if (sa->port == mc->local_80
440 && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
441 can_http = 1;
442 }
443 else if (sa->port == mc->local_443
444 && (!lr->protocol || !strncmp("http", lr->protocol, 4))) {
445 can_https = 1;
446 }
447 }
448 }
449 if (mc->can_http < 0) mc->can_http = can_http;
450 if (mc->can_https < 0) mc->can_https = can_https;
452 "server seems%s reachable via http: and%s reachable via https:",
453 mc->can_http? "" : " not", mc->can_https? "" : " not");
455 return md_reg_set_props(mc->reg, p, mc->can_http, mc->can_https);
456}
457
458static server_rec *get_public_https_server(md_t *md, const char *domain, server_rec *base_server)
459{
460 md_srv_conf_t *sc;
462 server_rec *s;
465 int i;
466 int check_port = 1;
467
468 sc = md_config_get(base_server);
469 mc = sc->mc;
470 memset(&r, 0, sizeof(r));
471
472 if (md->ca_challenges && md->ca_challenges->nelts > 0) {
473 /* skip the port check if "tls-alpn-01" is pre-configured */
475 }
476
477 if (check_port && !mc->can_https) return NULL;
478
479 /* find an ssl server matching domain from MD */
480 for (s = base_server; s; s = s->next) {
481 sc = md_config_get(s);
482 if (!sc || !sc->is_ssl || !sc->assigned) continue;
483 if (base_server == s && !mc->manage_base_server) continue;
484 if (base_server != s && check_port && mc->local_443 > 0 && !uses_port(s, mc->local_443)) continue;
485 for (i = 0; i < sc->assigned->nelts; ++i) {
486 if (md == APR_ARRAY_IDX(sc->assigned, i, md_t*)) {
487 r.server = s;
488 if (ap_matches_request_vhost(&r, domain, s->port)) {
489 if (check_port) {
490 return s;
491 }
492 else {
493 /* there may be multiple matching servers because we ignore the port.
494 if possible, choose a server that supports the acme-tls/1 protocol */
496 return s;
497 }
498 res = s;
499 }
500 }
501 }
502 }
503 }
504 return res;
505}
506
508{
509 md_srv_conf_t *sc;
510 server_rec *s;
512 int updates;
513
514 /* Ad all domain names used in SSL VirtualHosts, if not already there */
515 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, base_server,
516 "md[%s]: auto add domains", md->name);
517 updates = 0;
518 for (s = base_server; s; s = s->next) {
519 sc = md_config_get(s);
520 if (!sc || !sc->is_ssl || !sc->assigned || sc->assigned->nelts != 1) continue;
521 if (md != APR_ARRAY_IDX(sc->assigned, 0, md_t*)) continue;
522 if (APR_SUCCESS != (rv = md_cover_server(md, s, &updates, p))) {
523 return rv;
524 }
525 }
526 return rv;
527}
528
529static void init_acme_tls_1_domains(md_t *md, server_rec *base_server)
530{
531 md_srv_conf_t *sc;
533 server_rec *s;
534 int i;
535 const char *domain;
536
537 /* Collect those domains that support the "acme-tls/1" protocol. This
538 * is part of the MD (and not tested dynamically), since challenge selection
539 * may be done outside the server, e.g. in the a2md command. */
540 sc = md_config_get(base_server);
541 mc = sc->mc;
543 for (i = 0; i < md->domains->nelts; ++i) {
544 domain = APR_ARRAY_IDX(md->domains, i, const char*);
545 s = get_public_https_server(md, domain, base_server);
546 /* If we did not find a specific virtualhost for md and manage
547 * the base_server, that one is inspected */
548 if (NULL == s && mc->manage_base_server) s = base_server;
549 if (NULL == s) {
550 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10168)
551 "%s: no https server_rec found for %s", md->name, domain);
552 continue;
553 }
555 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10169)
556 "%s: https server_rec for %s does not have protocol %s enabled",
557 md->name, domain, PROTO_ACME_TLS_1);
558 continue;
559 }
560 APR_ARRAY_PUSH(md->acme_tls_1_domains, const char*) = domain;
561 }
562}
563
565 apr_pool_t *p)
566{
567 server_rec *s;
569 md_srv_conf_t *sc;
570 int i;
571 const char *domain, *uri;
572
573 sc = md_config_get(base_server);
574
575 /* Assign the MD to all server_rec configs that it matches. If there already
576 * is an assigned MD not equal this one, the configuration is in error.
577 */
578 memset(&r, 0, sizeof(r));
579 for (s = base_server; s; s = s->next) {
580 if (!mc->manage_base_server && s == base_server) {
581 /* we shall not assign ourselves to the base server */
582 continue;
583 }
584
585 r.server = s;
586 for (i = 0; i < md->domains->nelts; ++i) {
587 domain = APR_ARRAY_IDX(md->domains, i, const char*);
588
589 if ((mc->match_mode == MD_MATCH_ALL &&
590 ap_matches_request_vhost(&r, domain, s->port))
591 || (((mc->match_mode == MD_MATCH_SERVERNAMES) || md_dns_is_wildcard(p, domain)) &&
592 md_dns_matches(domain, s->server_hostname))) {
593 /* Create a unique md_srv_conf_t record for this server, if there is none yet */
594 sc = md_config_get_unique(s, p);
595 if (!sc->assigned) sc->assigned = apr_array_make(p, 2, sizeof(md_t*));
596 if (sc->assigned->nelts == 1 && mc->match_mode == MD_MATCH_SERVERNAMES) {
597 /* there is already an MD assigned for this server. But in
598 * this match mode, wildcard matches are pre-empted by non-wildcards */
600 APR_ARRAY_IDX(sc->assigned, 0, const md_t*)->domains,
601 s->server_hostname);
602 if (!existing_wild && md_dns_is_wildcard(p, domain))
603 continue; /* do not add */
604 if (existing_wild && !md_dns_is_wildcard(p, domain))
605 sc->assigned->nelts = 0; /* overwrite existing */
606 }
607 APR_ARRAY_PUSH(sc->assigned, md_t*) = md;
608 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10041)
609 "Server %s:%d matches md %s (config %s, match-mode=%d) "
610 "for domain %s, has now %d MDs",
611 s->server_hostname, s->port, md->name, sc->name,
612 mc->match_mode, domain, (int)sc->assigned->nelts);
613
614 if (md->contacts && md->contacts->nelts > 0) {
615 /* set explicitly */
616 }
617 else if (sc->ca_contact && sc->ca_contact[0]) {
618 uri = md_util_schemify(p, sc->ca_contact, "mailto");
619 if (md_array_str_index(md->contacts, uri, 0, 0) < 0) {
620 APR_ARRAY_PUSH(md->contacts, const char *) = uri;
621 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10044)
622 "%s: added contact %s", md->name, uri);
623 }
624 }
625 else if (s->server_admin && strcmp(DEFAULT_ADMIN, s->server_admin)) {
626 uri = md_util_schemify(p, s->server_admin, "mailto");
627 if (md_array_str_index(md->contacts, uri, 0, 0) < 0) {
628 APR_ARRAY_PUSH(md->contacts, const char *) = uri;
629 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, base_server, APLOGNO(10237)
630 "%s: added contact %s", md->name, uri);
631 }
632 }
633 break;
634 }
635 }
636 }
637 return APR_SUCCESS;
638}
639
641{
642 int i;
643 md_t *md;
645
646 apr_array_clear(mc->unused_names);
647 for (i = 0; i < mc->mds->nelts; ++i) {
648 md = APR_ARRAY_IDX(mc->mds, i, md_t*);
649 if (APR_SUCCESS != (rv = link_md_to_servers(mc, md, s, p))) {
650 goto leave;
651 }
652 }
653leave:
654 return rv;
655}
656
658 server_rec *base_server, int log_level)
659{
661 md_t *md, *omd;
662 const char *domain;
663 md_timeslice_t *ts;
665 int i, j;
666
667 /* The global module configuration 'mc' keeps a list of all configured MDomains
668 * in the server. This list is collected during configuration processing and,
669 * in the post config phase, get updated from all merged server configurations
670 * before the server starts processing.
671 */
672 base_conf = md_config_get(base_server);
674 if (ts) md_reg_set_renew_window_default(mc->reg, ts);
676 if (ts) md_reg_set_warn_window_default(mc->reg, ts);
677
678 /* Complete the properties of the MDs, now that we have the complete, merged
679 * server configurations.
680 */
681 for (i = 0; i < mc->mds->nelts; ++i) {
682 md = APR_ARRAY_IDX(mc->mds, i, md_t*);
684
685 if (mc->match_mode == MD_MATCH_ALL) {
686 /* Check that we have no overlap with the MDs already completed */
687 for (j = 0; j < i; ++j) {
688 omd = APR_ARRAY_IDX(mc->mds, j, md_t*);
689 if ((domain = md_common_name(md, omd)) != NULL) {
690 ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10038)
691 "two Managed Domains have an overlap in domain '%s'"
692 ", first definition in %s(line %d), second in %s(line %d)",
693 domain, md->defn_name, md->defn_line_number,
694 omd->defn_name, omd->defn_line_number);
695 return APR_EINVAL;
696 }
697 }
698 }
699
700 if (md->cert_files && md->cert_files->nelts) {
701 if (!md->pkey_files || (md->cert_files->nelts != md->pkey_files->nelts)) {
702 ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10170)
703 "The Managed Domain '%s' "
704 "needs one MDCertificateKeyFile for each MDCertificateFile.",
705 md->name);
706 return APR_EINVAL;
707 }
708 }
709 else if (md->pkey_files && md->pkey_files->nelts
710 && (!md->cert_files || !md->cert_files->nelts)) {
711 ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10171)
712 "The Managed Domain '%s' "
713 "has MDCertificateKeyFile(s) but no MDCertificateFile.",
714 md->name);
715 return APR_EINVAL;
716 }
717
718 if (APLOG_IS_LEVEL(base_server, log_level)) {
719 ap_log_error(APLOG_MARK, log_level, 0, base_server, APLOGNO(10039)
720 "Completed MD[%s, CA=%s, Proto=%s, Agreement=%s, renew-mode=%d "
721 "renew_window=%s, warn_window=%s",
722 md->name, md->ca_effective, md->ca_proto, md->ca_agreement, md->renew_mode,
723 md->renew_window? md_timeslice_format(md->renew_window, p) : "unset",
724 md->warn_window? md_timeslice_format(md->warn_window, p) : "unset");
725 }
726 }
727 return rv;
728}
729
731{
732 server_rec *s;
733 md_srv_conf_t *sc;
734
735 ap_log_error( APLOG_MARK, APLOG_TRACE1, 0, base_server,
736 "checking duplicate ssl assignments");
737 for (s = base_server; s; s = s->next) {
738 sc = md_config_get(s);
739 if (!sc || !sc->assigned) continue;
740
741 if (sc->assigned->nelts > 1 && sc->is_ssl) {
742 /* duplicate assignment to SSL VirtualHost, not allowed */
743 ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server, APLOGNO(10042)
744 "conflict: %d MDs match to SSL VirtualHost %s, there can at most be one.",
745 (int)sc->assigned->nelts, s->server_hostname);
746 return APR_EINVAL;
747 }
748 }
749 return APR_SUCCESS;
750}
751
753 apr_pool_t *p, apr_pool_t *ptemp)
754{
755 server_rec *s;
756 md_srv_conf_t *sc;
758 int i, has_ssl;
759 apr_array_header_t *servers;
760
761 (void)p;
762 servers = apr_array_make(ptemp, 5, sizeof(server_rec*));
763 has_ssl = 0;
764 for (s = base_server; s; s = s->next) {
765 sc = md_config_get(s);
766 if (!sc || !sc->assigned) continue;
767 for (i = 0; i < sc->assigned->nelts; ++i) {
768 if (md == APR_ARRAY_IDX(sc->assigned, i, md_t*)) {
769 APR_ARRAY_PUSH(servers, server_rec*) = s;
770 if (sc->is_ssl) has_ssl = 1;
771 }
772 }
773 }
774
775 if (!has_ssl && md->require_https > MD_REQUIRE_OFF) {
776 /* We require https for this MD, but do we have a SSL vhost? */
777 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(10105)
778 "MD %s does not match any VirtualHost with 'SSLEngine on', "
779 "but is configured to require https. This cannot work.", md->name);
780 }
781 if (apr_is_empty_array(servers)) {
782 if (md->renew_mode != MD_RENEW_ALWAYS) {
783 /* Not an error, but looks suspicious */
784 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(10045)
785 "No VirtualHost matches Managed Domain %s", md->name);
786 APR_ARRAY_PUSH(mc->unused_names, const char*) = md->name;
787 }
788 }
789 return rv;
790}
791
793{
794 md_t *md;
796 int i, count;
797
798 /* Calculate the list of MD names which we need to watch:
799 * - all MDs that are used somewhere
800 * - all MDs in drive mode 'AUTO' that are not in 'unused_names'
801 */
802 count = 0;
804 for (i = 0; i < mc->mds->nelts; ++i) {
805 md = APR_ARRAY_IDX(mc->mds, i, md_t*);
807 md->watched = 0;
808 if (md->state == MD_S_ERROR) {
810 "in error state, unable to drive forward. This "
811 "indicates an incomplete or inconsistent configuration. "
812 "Please check the log for warnings in this regard.");
813 continue;
814 }
815
816 if (md->renew_mode == MD_RENEW_AUTO
817 && md_array_str_index(mc->unused_names, md->name, 0, 0) >= 0) {
818 /* This MD is not used in any virtualhost, do not watch */
819 continue;
820 }
821
822 if (md_will_renew_cert(md)) {
823 /* make a test init to detect early errors. */
824 md_reg_test_init(mc->reg, md, mc->env, result, p);
825 if (APR_SUCCESS != result->status && result->detail) {
826 apr_hash_set(mc->init_errors, md->name, APR_HASH_KEY_STRING, apr_pstrdup(p, result->detail));
828 "md[%s]: %s", md->name, result->detail);
829 }
830 }
831
832 md->watched = 1;
833 ++count;
834 }
835 return count;
836}
837
839 apr_pool_t *ptemp, server_rec *s)
840{
841 void *data = NULL;
842 const char *mod_md_init_key = "mod_md_init_counter";
843 md_srv_conf_t *sc;
846 int dry_run = 0, log_level = APLOG_DEBUG;
847 md_store_t *store;
848
849 apr_pool_userdata_get(&data, mod_md_init_key, s->process->pool);
850 if (data == NULL) {
851 /* At the first start, httpd makes a config check dry run. It
852 * runs all config hooks to check if it can. If so, it does
853 * this all again and starts serving requests.
854 *
855 * On a dry run, we therefore do all the cheap config things we
856 * need to do to find out if the settings are ok. More expensive
857 * things we delay to the real run.
858 */
859 dry_run = 1;
862 "initializing post config dry run");
863 apr_pool_userdata_set((const void *)1, mod_md_init_key,
864 apr_pool_cleanup_null, s->process->pool);
865 }
866 else {
868 "mod_md (v%s), initializing...", MOD_MD_VERSION);
869 }
870
871 (void)plog;
872 init_setups(p, s);
874
876 sc = md_config_get(s);
877 mc = sc->mc;
878 mc->dry_run = dry_run;
879
882
883 rv = setup_store(&store, mc, p, s);
884 if (APR_SUCCESS != rv) goto leave;
885
886 rv = md_reg_create(&mc->reg, p, store, mc->proxy_url, mc->ca_certs,
887 mc->min_delay, mc->retry_failover,
888 mc->use_store_locks, mc->lock_wait_timeout);
889 if (APR_SUCCESS != rv) {
890 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10072) "setup md registry");
891 goto leave;
892 }
893
894 /* renew on 30% remaining /*/
895 rv = md_ocsp_reg_make(&mc->ocsp, p, store, mc->ocsp_renew_window,
896 AP_SERVER_BASEVERSION, mc->proxy_url,
897 mc->min_delay);
898 if (APR_SUCCESS != rv) {
899 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10196) "setup ocsp registry");
900 goto leave;
901 }
902
903 init_ssl();
904
905 /* How to bootstrap this module:
906 * 1. find out if we know if http: and/or https: requests will arrive
907 * 2. apply the now complete configuration settings to the MDs
908 * 3. Link MDs to the server_recs they are used in. Detect unused MDs.
909 * 4. Update the store with the MDs. Change domain names, create new MDs, etc.
910 * Basically all MD properties that are configured directly.
911 * WARNING: this may change the name of an MD. If an MD loses the first
912 * of its domain names, it first gets the new first one as name. The
913 * store will find the old settings and "recover" the previous name.
914 * 5. Load any staged data from previous driving.
915 * 6. on a dry run, this is all we do
916 * 7. Read back the MD properties that reflect the existence and aspect of
917 * credentials that are in the store (or missing there).
918 * Expiry times, MD state, etc.
919 * 8. Determine the list of MDs that need driving/supervision.
920 * 9. Cleanup any left-overs in registry/store that are no longer needed for
921 * the list of MDs as we know it now.
922 * 10. If this list is non-empty, setup a watchdog to run.
923 */
924 /*1*/
926 /*2*/
927 if (APR_SUCCESS != (rv = merge_mds_with_conf(mc, p, s, log_level))) goto leave;
928 /*3*/
929 if (APR_SUCCESS != (rv = link_mds_to_servers(mc, s, p))) goto leave;
930 /*4*/
931 if (APR_SUCCESS != (rv = md_reg_lock_global(mc->reg, ptemp))) {
933 "unable to obtain global registry lock, "
934 "renewed certificates may remain inactive on "
935 "this httpd instance!");
936 /* FIXME: or should we fail the server start/reload here? */
937 rv = APR_SUCCESS;
938 goto leave;
939 }
940 if (APR_SUCCESS != (rv = md_reg_sync_start(mc->reg, mc->mds, ptemp))) {
942 "syncing %d mds to registry", mc->mds->nelts);
943 goto leave;
944 }
945 /*5*/
946 md_reg_load_stagings(mc->reg, mc->mds, mc->env, p);
947leave:
948 md_reg_unlock_global(mc->reg, ptemp);
949 return rv;
950}
951
953 apr_pool_t *ptemp, server_rec *s)
954{
955 md_srv_conf_t *sc;
958 int watched, i;
959 md_t *md;
960
961 (void)ptemp;
962 (void)plog;
963 sc = md_config_get(s);
964
965 /*6*/
966 if (!sc || !sc->mc || sc->mc->dry_run) goto leave;
967 mc = sc->mc;
968
969 /*7*/
970 if (APR_SUCCESS != (rv = check_invalid_duplicates(s))) {
971 goto leave;
972 }
973 apr_array_clear(mc->unused_names);
974 for (i = 0; i < mc->mds->nelts; ++i) {
975 md = APR_ARRAY_IDX(mc->mds, i, md_t *);
976
977 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "md{%s}: auto_add", md->name);
978 if (APR_SUCCESS != (rv = auto_add_domains(md, s, p))) {
979 goto leave;
980 }
982 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "md{%s}: check_usage", md->name);
983 if (APR_SUCCESS != (rv = check_usage(mc, md, s, p, ptemp))) {
984 goto leave;
985 }
986 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "md{%s}: sync_finish", md->name);
987 if (APR_SUCCESS != (rv = md_reg_sync_finish(mc->reg, md, p, ptemp))) {
989 "md[%s]: error syncing to store", md->name);
990 goto leave;
991 }
992 }
993 /*8*/
994 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "init_cert_watch");
995 watched = init_cert_watch_status(mc, p, ptemp, s);
996 /*9*/
997 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "cleanup challenges");
998 md_reg_cleanup_challenges(mc->reg, p, ptemp, mc->mds);
999
1000 /* From here on, the domains in the registry are readonly
1001 * and only staging/challenges may be manipulated */
1002 md_reg_freeze_domains(mc->reg, mc->mds);
1003
1004 if (watched) {
1005 /*10*/
1007 "%d out of %d mds need watching", watched, mc->mds->nelts);
1008
1010 rv = md_renew_start_watching(mc, s, p);
1011 }
1012 else {
1013 ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(10075) "no mds to supervise");
1014 }
1015
1016 if (!mc->ocsp || md_ocsp_count(mc->ocsp) == 0) {
1017 ap_log_error( APLOG_MARK, APLOG_TRACE1, 0, s, "no ocsp to manage");
1018 goto leave;
1019 }
1020
1022 rv = md_ocsp_start_watching(mc, s, p);
1023
1024leave:
1025 ap_log_error( APLOG_MARK, APLOG_TRACE2, rv, s, "post_config done");
1026 return rv;
1027}
1028
1029/**************************************************************************************************/
1030/* connection context */
1031
1032typedef struct {
1033 const char *protocol;
1034} md_conn_ctx;
1035
1036static const char *md_protocol_get(const conn_rec *c)
1037{
1039
1040 ctx = (md_conn_ctx*)ap_get_module_config(c->conn_config, &md_module);
1041 return ctx? ctx->protocol : NULL;
1042}
1043
1044/**************************************************************************************************/
1045/* ALPN handling */
1046
1048 server_rec *s,
1051{
1052 (void)s;
1053 if (!r && offers && ap_ssl_conn_is_ssl(c)
1056 "proposing protocol '%s'", PROTO_ACME_TLS_1);
1058 return OK;
1059 }
1060 return DECLINED;
1061}
1062
1064 const char *protocol)
1065{
1067
1068 (void)s;
1071 "switching protocol '%s'", PROTO_ACME_TLS_1);
1072 ctx = apr_pcalloc(c->pool, sizeof(*ctx));
1073 ctx->protocol = PROTO_ACME_TLS_1;
1074 ap_set_module_config(c->conn_config, &md_module, ctx);
1075
1076 c->keepalive = AP_CONN_CLOSE;
1077 return OK;
1078 }
1079 return DECLINED;
1080}
1081
1082
1083/**************************************************************************************************/
1084/* Access API to other httpd components */
1085
1087{
1088 *keyfn = apr_pstrcat(p, "fallback-", md_pkey_filename(kspec, p), NULL);
1089 *certfn = apr_pstrcat(p, "fallback-", md_chain_filename(kspec, p), NULL);
1090}
1091
1093 server_rec *s, apr_pool_t *p, char *keyfn, char *crtfn)
1094{
1095 md_pkey_t *pkey;
1096 md_cert_t *cert;
1097 apr_status_t rv;
1098
1099 if (APR_SUCCESS != (rv = md_pkey_gen(&pkey, p, kspec))
1100 || APR_SUCCESS != (rv = md_store_save(store, p, MD_SG_DOMAINS, md->name,
1101 keyfn, MD_SV_PKEY, (void*)pkey, 0))
1102 || APR_SUCCESS != (rv = md_cert_self_sign(&cert, "Apache Managed Domain Fallback",
1104 || APR_SUCCESS != (rv = md_store_save(store, p, MD_SG_DOMAINS, md->name,
1105 crtfn, MD_SV_CERT, (void*)cert, 0))) {
1107 "%s: make fallback %s certificate", md->name, md_pkey_spec_name(kspec));
1108 }
1109 return rv;
1110}
1111
1114 apr_array_header_t **pkey_files)
1115{
1117 md_srv_conf_t *sc;
1118 md_reg_t *reg;
1119 md_store_t *store;
1120 const md_t *md;
1121 apr_array_header_t *key_files, *chain_files;
1122 const char *keyfile, *chainfile;
1123 int i;
1124
1125 *pkey_files = *pcert_files = NULL;
1126 key_files = apr_array_make(p, 5, sizeof(const char*));
1127 chain_files = apr_array_make(p, 5, sizeof(const char*));
1128
1130 "get_certificates called for vhost %s.", s->server_hostname);
1131
1132 sc = md_config_get(s);
1133 if (!sc) {
1135 "asked for certificate of server %s which has no md config",
1136 s->server_hostname);
1137 return APR_ENOENT;
1138 }
1139
1140 assert(sc->mc);
1141 reg = sc->mc->reg;
1142 assert(reg);
1143
1144 sc->is_ssl = 1;
1145
1146 if (!sc->assigned) {
1147 /* With the new hooks in mod_ssl, we are invoked for all server_rec. It is
1148 * therefore normal, when we have nothing to add here. */
1149 return APR_ENOENT;
1150 }
1151 else if (sc->assigned->nelts != 1) {
1152 if (!fallback) {
1154 "conflict: %d MDs match Virtualhost %s which uses SSL, however "
1155 "there can be at most 1.",
1156 (int)sc->assigned->nelts, s->server_hostname);
1157 }
1158 return APR_EINVAL;
1159 }
1160 md = APR_ARRAY_IDX(sc->assigned, 0, const md_t*);
1161
1162 if (md->cert_files && md->cert_files->nelts) {
1164 apr_array_cat(key_files, md->pkey_files);
1165 rv = APR_SUCCESS;
1166 }
1167 else {
1168 md_pkey_spec_t *spec;
1169
1170 for (i = 0; i < md_cert_count(md); ++i) {
1171 spec = md_pkeys_spec_get(md->pks, i);
1172 rv = md_reg_get_cred_files(&keyfile, &chainfile, reg, MD_SG_DOMAINS, md, spec, p);
1173 if (APR_SUCCESS == rv) {
1174 APR_ARRAY_PUSH(key_files, const char*) = keyfile;
1175 APR_ARRAY_PUSH(chain_files, const char*) = chainfile;
1176 }
1177 else if (APR_STATUS_IS_ENOENT(rv)) {
1178 /* certificate for this pkey is not available, others might
1179 * if pkeys have been added for a running mdomain.
1180 * see issue #260 */
1181 rv = APR_SUCCESS;
1182 }
1183 else if (!APR_STATUS_IS_ENOENT(rv)) {
1185 "retrieving credentials for MD %s (%s)",
1186 md->name, md_pkey_spec_name(spec));
1187 return rv;
1188 }
1189 }
1190
1191 if (md_array_is_empty(key_files)) {
1192 if (fallback) {
1193 /* Provide temporary, self-signed certificate as fallback, so that
1194 * clients do not get obscure TLS handshake errors or will see a fallback
1195 * virtual host that is not intended to be served here. */
1196 char *kfn, *cfn;
1197
1198 store = md_reg_store_get(reg);
1199 assert(store);
1200
1201 for (i = 0; i < md_cert_count(md); ++i) {
1202 spec = md_pkeys_spec_get(md->pks, i);
1203 fallback_fnames(p, spec, &kfn, &cfn);
1204
1208 if (APR_SUCCESS != (rv = make_fallback_cert(store, md, spec, s, p, kfn, cfn))) {
1209 return rv;
1210 }
1211 }
1213 "%s: providing %s fallback certificate for server %s",
1214 md->name, md_pkey_spec_name(spec), s->server_hostname);
1215 APR_ARRAY_PUSH(key_files, const char*) = keyfile;
1216 APR_ARRAY_PUSH(chain_files, const char*) = chainfile;
1217 }
1218 rv = APR_EAGAIN;
1219 goto leave;
1220 }
1221 }
1222 }
1224 "%s[state=%d]: providing certificates for server %s",
1225 md->name, md->state, s->server_hostname);
1226leave:
1227 if (!md_array_is_empty(key_files) && !md_array_is_empty(chain_files)) {
1228 *pkey_files = key_files;
1230 }
1231 else if (APR_SUCCESS == rv) {
1232 rv = APR_ENOENT;
1233 }
1234 return rv;
1235}
1236
1238 apr_array_header_t *cert_files,
1239 apr_array_header_t *key_files)
1240{
1243 apr_status_t rv;
1244
1245 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "hook ssl_add_cert_files for %s",
1246 s->server_hostname);
1248 if (APR_SUCCESS == rv) {
1249 if (!apr_is_empty_array(cert_files)) {
1250 /* downgraded fromm WARNING to DEBUG, since installing separate certificates
1251 * may be a valid use case. */
1253 "host '%s' is covered by a Managed Domain, but "
1254 "certificate/key files are already configured "
1255 "for it (most likely via SSLCertificateFile).",
1256 s->server_hostname);
1257 }
1259 "host '%s' is covered by a Managed Domaina and "
1260 "is being provided with %d key/certificate files.",
1261 s->server_hostname, md_cert_files->nelts);
1262 apr_array_cat(cert_files, md_cert_files);
1263 apr_array_cat(key_files, md_key_files);
1264 return DONE;
1265 }
1266 return DECLINED;
1267}
1268
1270 apr_array_header_t *cert_files,
1271 apr_array_header_t *key_files)
1272{
1275 apr_status_t rv;
1276
1277 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "hook ssl_add_fallback_cert_files for %s",
1278 s->server_hostname);
1280 if (APR_EAGAIN == rv) {
1281 apr_array_cat(cert_files, md_cert_files);
1282 apr_array_cat(key_files, md_key_files);
1283 return DONE;
1284 }
1285 return DECLINED;
1286}
1287
1288static int md_answer_challenge(conn_rec *c, const char *servername,
1289 const char **pcert_pem, const char **pkey_pem)
1290{
1291 const char *protocol;
1292 int hook_rv = DECLINED;
1294 md_srv_conf_t *sc;
1295 md_store_t *store;
1296 char *cert_name, *pkey_name;
1297 const char *cert_pem, *key_pem;
1298 int i;
1299
1300 if (!servername
1301 || !(protocol = md_protocol_get(c))
1303 goto cleanup;
1304 }
1305 sc = md_config_get(c->base_server);
1306 if (!sc || !sc->mc->reg) goto cleanup;
1307
1309 "Answer challenge[tls-alpn-01] for %s", servername);
1310 store = md_reg_store_get(sc->mc->reg);
1311
1312 for (i = 0; i < md_pkeys_spec_count( sc->pks ); i++) {
1314 &pkey_name, &cert_name);
1315
1317 (void**)&cert_pem, c->pool);
1318 if (APR_STATUS_IS_ENOENT(rv)) continue;
1319 if (APR_SUCCESS != rv) goto cleanup;
1320
1322 (void**)&key_pem, c->pool);
1323 if (APR_STATUS_IS_ENOENT(rv)) continue;
1324 if (APR_SUCCESS != rv) goto cleanup;
1325
1327 "Found challenge cert %s, key %s for %s",
1329 *pcert_pem = cert_pem;
1330 *pkey_pem = key_pem;
1331 hook_rv = OK;
1332 break;
1333 }
1334
1335 if (DECLINED == hook_rv) {
1337 "%s: unknown tls-alpn-01 challenge host", servername);
1338 }
1339
1340cleanup:
1341 return hook_rv;
1342}
1343
1344
1345/**************************************************************************************************/
1346/* ACME 'http-01' challenge responses */
1347
1348#define WELL_KNOWN_PREFIX "/.well-known/"
1349#define ACME_CHALLENGE_PREFIX WELL_KNOWN_PREFIX"acme-challenge/"
1350
1352{
1354 const md_srv_conf_t *sc;
1355 const char *name, *data;
1356 md_reg_t *reg;
1357 const md_t *md;
1358 apr_status_t rv;
1359
1360 if (r->parsed_uri.path
1362 sc = ap_get_module_config(r->server->module_config, &md_module);
1363 if (sc && sc->mc) {
1365 "access inside /.well-known/acme-challenge for %s%s",
1367 md = md_get_by_domain(sc->mc->mds, r->hostname);
1369 reg = sc && sc->mc? sc->mc->reg : NULL;
1370
1371 if (md && md->ca_challenges
1373 /* The MD this challenge is for does not allow http-01 challanges,
1374 * we have to decline. See #279 for a setup example where this
1375 * is necessary.
1376 */
1377 return DECLINED;
1378 }
1379
1380 if (strlen(name) && !ap_strchr_c(name, '/') && reg) {
1381 md_store_t *store = md_reg_store_get(reg);
1382
1384 MD_FN_HTTP01, MD_SV_TEXT, (void**)&data, r->pool);
1386 "loading challenge for %s (%s)", r->hostname, r->uri);
1387 if (APR_SUCCESS == rv) {
1388 apr_size_t len = strlen(data);
1389
1390 if (r->method_number != M_GET) {
1391 return HTTP_NOT_IMPLEMENTED;
1392 }
1393 /* A GET on a challenge resource for a hostname we are
1394 * configured for. Let's send the content back */
1395 r->status = HTTP_OK;
1396 apr_table_setn(r->headers_out, "Content-Length", apr_ltoa(r->pool, (long)len));
1397
1402
1403 return DONE;
1404 }
1405 else if (!md || md->renew_mode == MD_RENEW_MANUAL
1406 || (md->cert_files && md->cert_files->nelts
1407 && md->renew_mode == MD_RENEW_AUTO)) {
1408 /* The request hostname is not for a domain - or at least not for
1409 * a domain that we renew ourselves. We are not
1410 * the sole authority here for /.well-known/acme-challenge (see PR62189).
1411 * So, we decline to handle this and give others a chance to provide
1412 * the answer.
1413 */
1414 return DECLINED;
1415 }
1416 else if (APR_STATUS_IS_ENOENT(rv)) {
1417 return HTTP_NOT_FOUND;
1418 }
1420 "loading challenge %s from store", name);
1422 }
1423 }
1424 }
1425 return DECLINED;
1426}
1427
1428/**************************************************************************************************/
1429/* Require Https hook */
1430
1432{
1433 const md_srv_conf_t *sc;
1434 apr_uri_t uri;
1435 const char *s, *host;
1436 const md_t *md;
1437 int status;
1438
1439 /* Requests outside the /.well-known path are subject to possible
1440 * https: redirects or HSTS header additions.
1441 */
1442 sc = ap_get_module_config(r->server->module_config, &md_module);
1443 if (!sc || !sc->assigned || !sc->assigned->nelts || !r->parsed_uri.path
1445 goto declined;
1446 }
1447
1450 if (!md) goto declined;
1451
1453 /* Using https:
1454 * if 'permanent' and no one else set a HSTS header already, do it */
1458 }
1459 }
1460 else {
1461 if (md->require_https > MD_REQUIRE_OFF) {
1462 /* Not using https:, but require it. Redirect. */
1463 if (r->method_number == M_GET) {
1464 /* safe to use the old-fashioned codes */
1467 }
1468 else {
1469 /* these should keep the method unchanged on retry */
1472 }
1473
1474 s = ap_construct_url(r->pool, r->uri, r);
1475 if (APR_SUCCESS == apr_uri_parse(r->pool, s, &uri)) {
1476 uri.scheme = (char*)"https";
1477 uri.port = 443;
1478 uri.port_str = (char*)"443";
1479 uri.query = r->parsed_uri.query;
1480 uri.fragment = r->parsed_uri.fragment;
1482 if (s && *s) {
1483 apr_table_setn(r->headers_out, "Location", s);
1484 return status;
1485 }
1486 }
1487 }
1488 }
1489declined:
1490 return DECLINED;
1491}
1492
1493/* Runs once per created child process. Perform any process
1494 * related initialization here.
1495 */
1497{
1498 (void)pool;
1499 (void)s;
1500}
1501
1502/* Install this module into the apache2 infrastructure.
1503 */
1505{
1506 static const char *const mod_ssl[] = { "mod_ssl.c", "mod_tls.c", NULL};
1507 static const char *const mod_wd[] = { "mod_watchdog.c", NULL};
1508
1509 /* Leave the ssl initialization to mod_ssl or friends. */
1511
1512 ap_log_perror(APLOG_MARK, APLOG_TRACE1, 0, pool, "installing hooks");
1513
1514 /* Run once after configuration is set, before mod_ssl.
1515 * Run again after mod_ssl is done.
1516 */
1519
1520 /* Run once after a child process has been created.
1521 */
1523
1524 /* answer challenges *very* early, before any configured authentication may strike */
1527
1531
1532 /* Status request handlers and contributors */
1537
1541
1542#if AP_MODULE_MAGIC_AT_LEAST(20120211, 105)
1545#else
1546#error "This version of mod_md requires Apache httpd 2.4.48 or newer."
1547#endif /* AP_MODULE_MAGIC_AT_LEAST() */
1548}
1549
Apache Listeners Library.
int int const char ** match
Definition ap_regex.h:279
const char apr_size_t len
Definition ap_regex.h:187
#define AP_SERVER_BASEVERSION
Definition ap_release.h:75
APR-UTIL registration of functions exported by modules.
APR Strings library.
apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm, apr_pool_t *pool)
#define AP_MODULE_FLAG_ALWAYS_MERGE
#define ap_get_module_config(v, m)
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
#define AP_DECLARE_MODULE(foo)
char * ap_server_root_relative(apr_pool_t *p, const char *fname)
Definition config.c:1594
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:170
#define ap_set_module_config(v, m, val)
request_rec * r
void ap_hook_child_init(ap_HOOK_child_init_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:167
#define DECLINED
Definition httpd.h:457
#define DEFAULT_ADMIN
Definition httpd.h:123
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
char * ap_construct_url(apr_pool_t *p, const char *uri, request_rec *r)
Definition core.c:1246
const char * ap_get_server_name_for_url(request_rec *r)
Definition core.c:1187
ap_listen_rec * ap_listeners
Definition listen.c:42
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_INFO
Definition http_log.h:70
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_TRACE3
Definition http_log.h:74
#define ap_log_error
Definition http_log.h:370
#define ap_log_cerror
Definition http_log.h:498
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_IS_LEVEL(s, level)
Definition http_log.h:223
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_TRACE2
Definition http_log.h:73
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_DEBUG
Definition http_log.h:71
#define APLOG_MODULE_INDEX
Definition http_log.h:168
void ap_hook_ssl_answer_challenge(ap_HOOK_ssl_answer_challenge_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition ssl.c:276
void ap_hook_protocol_get(ap_HOOK_protocol_get_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2605
void ap_hook_protocol_propose(ap_HOOK_protocol_propose_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2599
void ap_hook_ssl_ocsp_prime_hook(ap_HOOK_ssl_ocsp_prime_hook_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition ssl.c:279
void ap_hook_protocol_switch(ap_HOOK_protocol_switch_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2603
void ap_hook_post_read_request(ap_HOOK_post_read_request_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2585
void ap_hook_ssl_add_fallback_cert_files(ap_HOOK_ssl_add_fallback_cert_files_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition ssl.c:273
void ap_hook_ssl_add_cert_files(ap_HOOK_ssl_add_cert_files_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition ssl.c:269
int ap_is_allowed_protocol(conn_rec *c, request_rec *r, server_rec *s, const char *protocol)
Definition protocol.c:2564
void ap_hook_ssl_ocsp_get_resp_hook(ap_HOOK_ssl_ocsp_get_resp_hook_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition ssl.c:283
int ap_ssl_conn_is_ssl(conn_rec *c)
Definition ssl.c:90
const char apr_port_t port
Definition http_vhost.h:125
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
void * dummy
Definition http_vhost.h:62
const char * host
Definition http_vhost.h:124
#define APR_EAGAIN
Definition apr_errno.h:730
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_ENOENT
Definition apr_errno.h:662
#define APR_EINVAL
Definition apr_errno.h:711
unsigned int count
Definition apr_md5.h:152
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_brigade_flush void * ctx
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
apr_datum_t * pkey
Definition apr_dbm.h:158
#define APR_HOOK_LAST
Definition apr_hooks.h:305
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
apr_memcache_t * mc
#define APR_OPTIONAL_HOOK(ns, name, pfn, aszPre, aszSucc, nOrder)
const char * uri
Definition apr_uri.h:159
#define APR_URI_UNP_OMITUSERINFO
Definition apr_uri.h:70
#define HTTP_OK
Definition httpd.h:490
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define HTTP_MOVED_TEMPORARILY
Definition httpd.h:502
#define HTTP_PERMANENT_REDIRECT
Definition httpd.h:507
#define HTTP_MOVED_PERMANENTLY
Definition httpd.h:501
#define HTTP_NOT_FOUND
Definition httpd.h:512
#define HTTP_NOT_IMPLEMENTED
Definition httpd.h:536
#define HTTP_TEMPORARY_REDIRECT
Definition httpd.h:506
#define M_GET
Definition httpd.h:592
#define STANDARD20_MODULE_STUFF
#define ap_strchr_c(s, c)
Definition httpd.h:2353
int ap_array_str_contains(const apr_array_header_t *array, const char *s)
Definition util.c:3446
@ AP_CONN_CLOSE
Definition httpd.h:1145
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_filetype_e
@ APR_DIR
void * data
const char apr_file_t * file
void const char apr_status_t(* cleanup)(void *))
char * buffer
const char * fname
apr_array_header_t ** result
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_vformatter_buff_t const char * fmt
Definition apr_lib.h:175
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_sockaddr_t * sa
int int int protocol
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
apr_dir_t * dir
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 reason
int int status
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
static const char *const mod_ssl[]
Definition h2_c1.c:305
CORE HTTP Daemon.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
SSL protocol handling.
Virtual Host package.
HTTP Daemon routines.
int md_cert_count(const md_t *md)
Definition md_core.c:187
@ MD_S_ERROR
Definition md.h:57
const char * md_common_name(const md_t *md1, const md_t *md2)
Definition md_core.c:43
md_t * md_get_by_domain(struct apr_array_header_t *mds, const char *domain)
Definition md_core.c:163
#define MD_HSTS_HEADER
Definition md.h:40
#define PROTO_ACME_TLS_1
Definition md.h:43
@ MD_RENEW_DEFAULT
Definition md.h:69
@ MD_RENEW_AUTO
Definition md.h:71
@ MD_RENEW_MANUAL
Definition md.h:70
@ MD_RENEW_ALWAYS
Definition md.h:72
@ MD_REQUIRE_OFF
Definition md.h:63
@ MD_REQUIRE_PERMANENT
Definition md.h:65
int md_contains(const md_t *md, const char *domain, int case_sensitive)
Definition md_core.c:35
apr_status_t md_acme_init(apr_pool_t *p, const char *base, int init_ssl)
Definition md_acme.c:163
#define MD_AUTHZ_CHA_HTTP_01
Definition md_acme.h:35
void tls_alpn01_fnames(apr_pool_t *p, md_pkey_spec_t *kspec, char **keyfn, char **certfn)
#define MD_FN_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
apr_status_t md_cert_self_sign(md_cert_t **pcert, const char *cn, apr_array_header_t *domains, md_pkey_t *pkey, apr_interval_time_t valid_for, apr_pool_t *p)
Definition md_crypt.c:1942
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
int md_pkeys_spec_is_empty(const md_pkeys_spec_t *pks)
Definition md_crypt.c:533
md_http_impl_t * md_curl_get_impl(apr_pool_t *p)
Definition md_curl.c:647
void md_event_subscribe(md_event_cb *cb, void *baton)
Definition md_event.c:50
apr_pool_t * p
Definition md_event.c:32
void md_event_init(apr_pool_t *p)
Definition md_event.c:43
void md_http_use_implementation(md_http_impl_t *impl)
Definition md_http.c:44
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
void md_log_set(md_log_level_cb *level_cb, md_log_print_cb *print_cb, void *baton)
Definition md_log.c:53
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_NOTICE
Definition md_log.h:26
@ MD_LOG_ERR
Definition md_log.h:24
@ MD_LOG_DEBUG
Definition md_log.h:28
@ MD_LOG_INFO
Definition md_log.h:27
apr_size_t md_ocsp_count(md_ocsp_reg_t *reg)
Definition md_ocsp.c:491
apr_status_t md_ocsp_reg_make(md_ocsp_reg_t **preg, apr_pool_t *p, md_store_t *store, const md_timeslice_t *renew_window, const char *user_agent, const char *proxy_url, apr_time_t min_delay)
Definition md_ocsp.c:274
apr_status_t md_reg_cleanup_challenges(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp, apr_array_header_t *mds)
Definition md_reg.c:1032
apr_status_t md_reg_sync_start(md_reg_t *reg, apr_array_header_t *master_mds, apr_pool_t *p)
Definition md_reg.c:834
void md_reg_set_warn_window_default(md_reg_t *reg, md_timeslice_t *warn_window)
Definition md_reg.c:1316
apr_status_t md_reg_freeze_domains(md_reg_t *reg, apr_array_header_t *mds)
Definition md_reg.c:1290
apr_status_t md_reg_set_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https)
Definition md_reg.c:750
void md_reg_unlock_global(md_reg_t *reg, apr_pool_t *p)
Definition md_reg.c:1283
apr_status_t md_reg_lock_global(md_reg_t *reg, apr_pool_t *p)
Definition md_reg.c:1269
apr_status_t md_reg_create(md_reg_t **preg, apr_pool_t *p, struct md_store_t *store, const char *proxy_url, const char *ca_file, apr_time_t min_delay, int retry_failover, int use_store_locks, apr_time_t lock_wait_timeout)
Definition md_reg.c:87
apr_status_t md_reg_get_cred_files(const char **pkeyfile, const char **pcertfile, md_reg_t *reg, md_store_group_t group, const md_t *md, md_pkey_spec_t *spec, apr_pool_t *p)
Definition md_reg.c:635
apr_status_t md_reg_load_stagings(md_reg_t *reg, apr_array_header_t *mds, apr_table_t *env, apr_pool_t *p)
Definition md_reg.c:1244
void md_reg_set_renew_window_default(md_reg_t *reg, md_timeslice_t *renew_window)
Definition md_reg.c:1311
apr_status_t md_reg_test_init(md_reg_t *reg, const md_t *md, struct apr_table_t *env, md_result_t *result, apr_pool_t *p)
Definition md_reg.c:1133
apr_status_t md_reg_sync_finish(md_reg_t *reg, md_t *md, apr_pool_t *p, apr_pool_t *ptemp)
Definition md_reg.c:918
struct md_store_t * md_reg_store_get(md_reg_t *reg)
Definition md_reg.c:122
#define MD_UPD_DOMAINS
Definition md_reg.h:95
md_result_t * md_result_make(apr_pool_t *p, apr_status_t status)
Definition md_result.c:39
void md_result_log(md_result_t *result, unsigned int level)
Definition md_result.c:227
void md_result_problem_printf(md_result_t *result, apr_status_t status, const char *problem, const char *fmt,...)
Definition md_result.c:111
void md_result_set(md_result_t *result, apr_status_t status, const char *detail)
Definition md_result.c:91
#define MD_RESULT_LOG_ID(logno)
Definition md_result.h:61
apr_time_t md_job_log_get_time_of_latest(md_job_t *job, const char *type)
Definition md_status.c:433
void md_job_log_append(md_job_t *job, const char *type, const char *status, const char *detail)
Definition md_status.c:382
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
apr_status_t md_store_get_fname(const char **pfname, md_store_t *store, md_store_group_t group, const char *name, const char *aspect, apr_pool_t *p)
Definition md_store.c:127
const char * md_chain_filename(md_pkey_spec_t *spec, apr_pool_t *p)
Definition md_store.c:276
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_store_group_t
Definition md_store.h:62
@ MD_SG_ACCOUNTS
Definition md_store.h:64
@ MD_SG_STAGING
Definition md_store.h:67
@ MD_SG_OCSP
Definition md_store.h:70
@ MD_SG_CHALLENGES
Definition md_store.h:65
@ MD_SG_DOMAINS
Definition md_store.h:66
@ MD_SV_PKEY
Definition md_store.h:56
@ MD_SV_CERT
Definition md_store.h:55
@ MD_SV_TEXT
Definition md_store.h:53
apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *path)
apr_status_t md_store_fs_set_event_cb(struct md_store_t *store, md_store_fs_cb *cb, void *baton)
md_store_fs_ev_t
Definition md_store_fs.h:53
@ MD_S_FS_EV_CREATED
Definition md_store_fs.h:54
#define MD_FPROT_D_UALL_GREAD
Definition md_store_fs.h:33
const char * md_timeslice_format(const md_timeslice_t *ts, apr_pool_t *p)
Definition md_time.c:277
apr_time_t md_timeperiod_length(const md_timeperiod_t *period)
Definition md_time.c:26
#define MD_SECS_PER_HOUR
Definition md_time.h:22
#define MD_SECS_PER_DAY
Definition md_time.h:23
int md_dns_is_wildcard(apr_pool_t *p, const char *domain)
Definition md_util.c:852
int md_array_is_empty(const struct apr_array_header_t *array)
Definition md_util.c:235
int md_is_wild_match(const apr_array_header_t *domains, const char *name)
Definition md_util.c:919
const char * md_util_schemify(apr_pool_t *p, const char *s, const char *def_scheme)
Definition md_util.c:932
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
int md_file_exists(const char *fname, apr_pool_t *p)
Definition md_util.c:411
int md_dns_matches(const char *pattern, const char *domain)
Definition md_util.c:858
#define MOD_MD_VERSION
Definition md_version.h:30
#define WELL_KNOWN_PREFIX
Definition mod_md.c:1348
static apr_status_t check_group_dir(md_store_t *store, md_store_group_t group, apr_pool_t *p, server_rec *s)
Definition mod_md.c:264
static apr_status_t check_invalid_duplicates(server_rec *base_server)
Definition mod_md.c:730
static int init_cert_watch_status(md_mod_conf_t *mc, apr_pool_t *p, apr_pool_t *ptemp, server_rec *s)
Definition mod_md.c:792
static void init_acme_tls_1_domains(md_t *md, server_rec *base_server)
Definition mod_md.c:529
static void merge_srv_config(md_t *md, md_srv_conf_t *base_sc, apr_pool_t *p)
Definition mod_md.c:308
static void md_hooks(apr_pool_t *pool)
Definition mod_md.c:1504
static int md_require_https_maybe(request_rec *r)
Definition mod_md.c:1431
#define LOG_BUF_LEN
Definition mod_md.c:88
static apr_status_t setup_store(md_store_t **pstore, md_mod_conf_t *mc, apr_pool_t *p, server_rec *s)
Definition mod_md.c:277
static int log_is_level(void *baton, apr_pool_t *p, md_log_level_t level)
Definition mod_md.c:78
static apr_status_t auto_add_domains(md_t *md, server_rec *base_server, apr_pool_t *p)
Definition mod_md.c:507
static apr_status_t notify(md_job_t *job, const char *reason, md_result_t *result, apr_pool_t *p, void *baton)
Definition mod_md.c:151
static apr_status_t get_certificates(server_rec *s, apr_pool_t *p, int fallback, apr_array_header_t **pcert_files, apr_array_header_t **pkey_files)
Definition mod_md.c:1112
static apr_status_t cleanup_setups(void *dummy)
Definition mod_md.c:120
static server_rec * log_server
Definition mod_md.c:76
static void init_ssl(void)
Definition mod_md.c:112
static notify_rate notify_rates[]
Definition mod_md.c:141
static int md_protocol_switch(conn_rec *c, request_rec *r, server_rec *s, const char *protocol)
Definition mod_md.c:1063
static int md_protocol_propose(conn_rec *c, request_rec *r, server_rec *s, const apr_array_header_t *offers, apr_array_header_t *proposals)
Definition mod_md.c:1047
static apr_status_t merge_mds_with_conf(md_mod_conf_t *mc, apr_pool_t *p, server_rec *base_server, int log_level)
Definition mod_md.c:657
static int md_http_challenge_pr(request_rec *r)
Definition mod_md.c:1351
static apr_status_t detect_supported_protocols(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p, int log_level)
Definition mod_md.c:427
static apr_status_t md_post_config_before_ssl(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition mod_md.c:838
static const char * md_protocol_get(const conn_rec *c)
Definition mod_md.c:1036
#define ACME_CHALLENGE_PREFIX
Definition mod_md.c:1349
static int md_answer_challenge(conn_rec *c, const char *servername, const char **pcert_pem, const char **pkey_pem)
Definition mod_md.c:1288
static void log_print(const char *file, int line, md_log_level_t level, apr_status_t rv, void *baton, apr_pool_t *p, const char *fmt, va_list ap)
Definition mod_md.c:90
static int uses_port(server_rec *s, int port)
Definition mod_md.c:410
static apr_status_t md_cover_server(md_t *md, server_rec *s, int *pupdates, apr_pool_t *p)
Definition mod_md.c:389
static int md_add_fallback_cert_files(server_rec *s, apr_pool_t *p, apr_array_header_t *cert_files, apr_array_header_t *key_files)
Definition mod_md.c:1269
static apr_status_t on_event(const char *event, const char *mdomain, void *baton, md_job_t *job, md_result_t *result, apr_pool_t *p)
Definition mod_md.c:222
static void fallback_fnames(apr_pool_t *p, md_pkey_spec_t *kspec, char **keyfn, char **certfn)
Definition mod_md.c:1086
static apr_status_t link_mds_to_servers(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p)
Definition mod_md.c:640
static void md_child_init(apr_pool_t *pool, server_rec *s)
Definition mod_md.c:1496
static int md_add_cert_files(server_rec *s, apr_pool_t *p, apr_array_header_t *cert_files, apr_array_header_t *key_files)
Definition mod_md.c:1237
static void init_setups(apr_pool_t *p, server_rec *base_server)
Definition mod_md.c:127
static server_rec * get_public_https_server(md_t *md, const char *domain, server_rec *base_server)
Definition mod_md.c:458
static apr_status_t check_usage(md_mod_conf_t *mc, md_t *md, server_rec *base_server, apr_pool_t *p, apr_pool_t *ptemp)
Definition mod_md.c:752
static apr_status_t store_file_ev(void *baton, struct md_store_t *store, md_store_fs_ev_t ev, unsigned int group, const char *fname, apr_filetype_e ftype, apr_pool_t *p)
Definition mod_md.c:232
static apr_status_t link_md_to_servers(md_mod_conf_t *mc, md_t *md, server_rec *base_server, apr_pool_t *p)
Definition mod_md.c:564
static apr_status_t make_fallback_cert(md_store_t *store, const md_t *md, md_pkey_spec_t *kspec, server_rec *s, apr_pool_t *p, char *keyfn, char *crtfn)
Definition mod_md.c:1092
static apr_status_t md_post_config_after_ssl(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition mod_md.c:952
static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s, int *pupdates, apr_pool_t *p)
Definition mod_md.c:368
md_srv_conf_t * md_config_get(server_rec *s)
const char * md_config_gets(const md_srv_conf_t *sc, md_config_var_t var)
const command_rec md_cmds[]
void md_config_get_timespan(md_timeslice_t **pspan, const md_srv_conf_t *sc, md_config_var_t var)
void * md_config_create_svr(apr_pool_t *pool, server_rec *s)
md_srv_conf_t * md_config_get_unique(server_rec *s, apr_pool_t *p)
apr_status_t md_config_post_config(server_rec *s, apr_pool_t *p)
const md_t * md_get_for_domain(server_rec *s, const char *domain)
void * md_config_merge_svr(apr_pool_t *pool, void *basev, void *addv)
int md_config_geti(const md_srv_conf_t *sc, md_config_var_t var)
@ MD_CONFIG_MUST_STAPLE
@ MD_CONFIG_CA_PROTO
@ MD_CONFIG_RENEW_WINDOW
@ MD_CONFIG_STAPLING
@ MD_CONFIG_CA_AGREEMENT
@ MD_CONFIG_REQUIRE_HTTPS
@ MD_CONFIG_CA_CONTACT
@ MD_CONFIG_TRANSITIVE
@ MD_CONFIG_DRIVE_MODE
@ MD_CONFIG_WARN_WINDOW
@ MD_MATCH_SERVERNAMES
@ MD_MATCH_ALL
int md_will_renew_cert(const md_t *md)
apr_status_t md_renew_start_watching(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p)
int md_ocsp_provide_status(server_rec *s, conn_rec *c, const char *id, apr_size_t id_len, ap_ssl_ocsp_copy_resp *cb, void *userdata)
Definition mod_md_ocsp.c:98
int md_ocsp_prime_status(server_rec *s, apr_pool_t *p, const char *id, apr_size_t id_len, const char *pem)
Definition mod_md_ocsp.c:56
apr_status_t md_ocsp_start_watching(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p)
apr_status_t md_make_worker_accessible(const char *fname, apr_pool_t *p)
Definition mod_md_os.c:58
int md_status_handler(request_rec *r)
int md_http_cert_status(request_rec *r)
int md_domains_status_hook(request_rec *r, int flags)
int md_ocsp_status_hook(request_rec *r, int flags)
const char * argv[3]
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
Status Report Extension Module to Apache.
Multi-Processing Modules functions.
char * name
Apache's listeners record.
Definition ap_listen.h:47
ap_listen_rec * next
Definition ap_listen.h:51
apr_sockaddr_t * next
char * fragment
Definition apr_uri.h:103
char * path
Definition apr_uri.h:99
char * query
Definition apr_uri.h:101
Structure to store things which are per connection.
Definition httpd.h:1152
struct apr_bucket_alloc_t * bucket_alloc
Definition httpd.h:1201
const char * protocol
Definition mod_md.c:1033
const char * mdomain
Definition md_status.h:54
apr_array_header_t * mds
const char * hsts_header
struct md_reg_t * reg
const char * ca_eab_kid
struct apr_array_header_t * ca_urls
struct apr_array_header_t * ca_challenges
struct apr_array_header_t * assigned
const char * ca_contact
const char * name
const char * ca_eab_hmac
const server_rec * s
md_mod_conf_t * mc
struct md_pkeys_spec_t * pks
Definition md.h:76
const char * name
Definition md.h:77
md_timeslice_t * renew_window
Definition md.h:82
int transitive
Definition md.h:109
struct apr_array_header_t * domains
Definition md.h:78
const struct md_srv_conf_t * sc
Definition md.h:101
const char * ca_eab_hmac
Definition md.h:94
md_timeslice_t * warn_window
Definition md.h:83
struct apr_array_header_t * acme_tls_1_domains
Definition md.h:98
md_require_t require_https
Definition md.h:107
struct apr_array_header_t * pkey_files
Definition md.h:92
const char * defn_name
Definition md.h:102
unsigned defn_line_number
Definition md.h:103
const char * ca_effective
Definition md.h:87
md_state_t state
Definition md.h:108
int must_staple
Definition md.h:110
const char * ca_proto
Definition md.h:85
struct apr_array_header_t * ca_urls
Definition md.h:86
int watched
Definition md.h:112
struct md_pkeys_spec_t * pks
Definition md.h:81
const char * ca_eab_kid
Definition md.h:93
const char * ca_agreement
Definition md.h:89
struct apr_array_header_t * contacts
Definition md.h:79
int renew_mode
Definition md.h:106
int stapling
Definition md.h:111
struct apr_array_header_t * cert_files
Definition md.h:91
struct apr_array_header_t * ca_challenges
Definition md.h:90
const char * reason
Definition mod_md.c:137
apr_time_t min_interim
Definition mod_md.c:138
A structure that represents the current request.
Definition httpd.h:845
int status
Definition httpd.h:891
char * uri
Definition httpd.h:1016
struct ap_filter_t * output_filters
Definition httpd.h:1070
const char * hostname
Definition httpd.h:883
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
apr_uri_t parsed_uri
Definition httpd.h:1092
conn_rec * connection
Definition httpd.h:849
server_rec * server
Definition httpd.h:851
apr_table_t * headers_out
Definition httpd.h:978
A structure to be used for Per-vhost config.
Definition httpd.h:1301
A structure to store information for each virtual server.
Definition httpd.h:1322
server_rec * next
Definition httpd.h:1326
char * server_hostname
Definition httpd.h:1365
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
char * server_admin
Definition httpd.h:1363
int ap_matches_request_vhost(request_rec *r, const char *host, apr_port_t port)
Definition vhost.c:953
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray