Apache HTTPD
md_util.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_strings.h>
22#include <apr_portable.h>
23#include <apr_file_info.h>
24#include <apr_fnmatch.h>
25#include <apr_tables.h>
26#include <apr_uri.h>
27
28#if APR_HAVE_STDLIB_H
29#include <stdlib.h>
30#endif
31
32#include "md.h"
33#include "md_log.h"
34#include "md_util.h"
35
36/**************************************************************************************************/
37/* pool utils */
38
40{
41 apr_pool_t *ptemp;
42 apr_status_t rv = apr_pool_create(&ptemp, p);
43 if (APR_SUCCESS == rv) {
44 apr_pool_tag(ptemp, "md_pool_do");
45 rv = cb(baton, p, ptemp);
46 apr_pool_destroy(ptemp);
47 }
48 return rv;
49}
50
52{
53 apr_pool_t *ptemp;
54 apr_status_t rv;
55
56 rv = apr_pool_create(&ptemp, p);
57 if (APR_SUCCESS == rv) {
58 apr_pool_tag(ptemp, "md_pool_vado");
59 rv = cb(baton, p, ptemp, ap);
60 apr_pool_destroy(ptemp);
61 }
62 return rv;
63}
64
66{
67 va_list ap;
68 apr_status_t rv;
69
70 va_start(ap, p);
71 rv = pool_vado(cb, baton, p, ap);
72 va_end(ap);
73 return rv;
74}
75
76/**************************************************************************************************/
77/* data chunks */
78
80{
82 d->data = apr_pcalloc(p, len);
83 d->len = len;
84}
85
87{
88 md_data_t *d;
89
90 d = apr_palloc(p, sizeof(*d));
92 return d;
93}
94
96{
98 d->len = len;
99 d->data = data;
100}
101
102void md_data_init_str(md_data_t *d, const char *str)
103{
104 md_data_init(d, str, strlen(str));
105}
106
108{
109 memset(d, 0, sizeof(*d));
110}
111
113{
114 if (d) {
115 if (d->data && d->free_data) d->free_data((void*)d->data);
116 memset(d, 0, sizeof(*d));
117 }
118}
119
121{
122 md_data_t *d;
123
124 d = apr_palloc(p, sizeof(*d));
125 d->len = len;
126 d->data = len? apr_pmemdup(p, data, len) : NULL;
127 return d;
128}
129
131{
133 if (src && src_len) {
134 dest->data = malloc(src_len);
135 if (!dest->data) return APR_ENOMEM;
136 memcpy((void*)dest->data, src, src_len);
137 dest->len = src_len;
138 dest->free_data = free;
139 }
140 return APR_SUCCESS;
141}
142
144{
146 dest->data = (src && src_len)? apr_pmemdup(p, src, src_len) : NULL;
147 dest->len = dest->data? src_len : 0;
148}
149
150static const char * const hex_const[] = {
151 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
152 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
153 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
154 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
155 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
156 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
157 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
158 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
159 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
160 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
161 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
162 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
163 "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
164 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
165 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
166 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
167};
168
169apr_status_t md_data_to_hex(const char **phex, char separator,
170 apr_pool_t *p, const md_data_t *data)
171{
172 char *hex, *cp;
173 const char * x;
174 unsigned int i;
175
176 cp = hex = apr_pcalloc(p, ((separator? 3 : 2) * data->len) + 1);
177 if (!hex) {
178 *phex = NULL;
179 return APR_ENOMEM;
180 }
181 for (i = 0; i < data->len; ++i) {
182 x = hex_const[(unsigned char)data->data[i]];
183 if (i && separator) *cp++ = separator;
184 *cp++ = x[0];
185 *cp++ = x[1];
186 }
187 *phex = hex;
188 return APR_SUCCESS;
189}
190
191/**************************************************************************************************/
192/* generic arrays */
193
195{
196 char *ps, *pe;
197
198 if (idx < 0 || idx >= a->nelts) return 0;
199 if (idx+1 == a->nelts) {
200 --a->nelts;
201 }
202 else {
203 ps = (a->elts + (idx * a->elt_size));
204 pe = ps + a->elt_size;
205 memmove(ps, pe, (size_t)((a->nelts - (idx+1)) * a->elt_size));
206 --a->nelts;
207 }
208 return 1;
209}
210
212{
213 int i, n, m;
214 void **pe;
215
216 assert(sizeof(void*) == a->elt_size);
217 n = i = 0;
218 while (i < a->nelts) {
219 pe = &APR_ARRAY_IDX(a, i, void*);
220 if (*pe == elem) {
221 m = a->nelts - (i+1);
222 if (m > 0) memmove(pe, pe+1, (unsigned)m*sizeof(void*));
223 a->nelts--;
224 n++;
225 continue;
226 }
227 ++i;
228 }
229 return n;
230}
231
232/**************************************************************************************************/
233/* string related */
234
235int md_array_is_empty(const struct apr_array_header_t *array)
236{
237 return (array == NULL) || (array->nelts == 0);
238}
239
241{
242 char *orig = s;
243 while (*s) {
244 *s = (char)apr_tolower(*s);
245 ++s;
246 }
247 return orig;
248}
249
250int md_array_str_index(const apr_array_header_t *array, const char *s,
251 int start, int case_sensitive)
252{
253 if (start >= 0) {
254 int i;
255
256 for (i = start; i < array->nelts; i++) {
257 const char *p = APR_ARRAY_IDX(array, i, const char *);
258 if ((case_sensitive && !strcmp(p, s))
259 || (!case_sensitive && !apr_strnatcasecmp(p, s))) {
260 return i;
261 }
262 }
263 }
264
265 return -1;
266}
267
269 const struct apr_array_header_t *a2, int case_sensitive)
270{
271 int i;
272 const char *s1, *s2;
273
274 if (a1 == a2) return 1;
275 if (!a1 || !a2) return 0;
276 if (a1->nelts != a2->nelts) return 0;
277 for (i = 0; i < a1->nelts; ++i) {
278 s1 = APR_ARRAY_IDX(a1, i, const char *);
279 s2 = APR_ARRAY_IDX(a2, i, const char *);
280 if ((case_sensitive && strcmp(s1, s2))
282 return 0;
283 }
284 }
285 return 1;
286}
287
289{
290 apr_array_header_t *dest = apr_array_make(p, src->nelts, sizeof(const char*));
291 if (dest) {
292 int i;
293 for (i = 0; i < src->nelts; i++) {
294 const char *s = APR_ARRAY_IDX(src, i, const char *);
295 APR_ARRAY_PUSH(dest, const char *) = apr_pstrdup(p, s);
296 }
297 }
298 return dest;
299}
300
302 int case_sensitive)
303{
304 apr_array_header_t *dest = apr_array_make(p, src->nelts, sizeof(const char*));
305 if (dest) {
306 const char *s;
307 int i;
308 for (i = 0; i < src->nelts; ++i) {
309 s = APR_ARRAY_IDX(src, i, const char *);
310 if (md_array_str_index(dest, s, 0, case_sensitive) < 0) {
312 }
313 }
314 }
315 return dest;
316}
317
319 const char *exclude, int case_sensitive)
320{
321 apr_array_header_t *dest = apr_array_make(p, src->nelts, sizeof(const char*));
322 if (dest) {
323 int i;
324 for (i = 0; i < src->nelts; i++) {
325 const char *s = APR_ARRAY_IDX(src, i, const char *);
326 if (!exclude
329 APR_ARRAY_PUSH(dest, const char *) = apr_pstrdup(p, s);
330 }
331 }
332 }
333 return dest;
334}
335
337{
338 int i, added = 0;
339 for (i = 0; i < src->nelts; i++) {
340 const char *s = APR_ARRAY_IDX(src, i, const char *);
341 if (md_array_str_index(dest, s, 0, case_sensitive) < 0) {
342 APR_ARRAY_PUSH(dest, const char *) = s;
343 ++added;
344 }
345 }
346 return added;
347}
348
349/**************************************************************************************************/
350/* file system related */
351
352apr_status_t md_util_fopen(FILE **pf, const char *fn, const char *mode)
353{
354 *pf = fopen(fn, mode);
355 if (*pf == NULL) {
356 return errno;
357 }
358
359 return APR_SUCCESS;
360}
361
364{
365 apr_status_t rv;
367 perms, p);
368 if (APR_SUCCESS == rv) {
369 /* See <https://github.com/icing/mod_md/issues/117>
370 * Some people set umask 007 to deny all world read/writability to files
371 * created by apache. While this is a noble effort, we need the store files
372 * to have the permissions as specified. */
373 rv = apr_file_perms_set(fn, perms);
374 if (APR_STATUS_IS_ENOTIMPL(rv)) {
375 rv = APR_SUCCESS;
376 }
377 }
378 return rv;
379}
380
382{
385 if (rv == APR_SUCCESS) {
386 rv = (info.filetype == APR_DIR)? APR_SUCCESS : APR_EINVAL;
387 }
388 return rv;
389}
390
392{
395 if (rv == APR_SUCCESS) {
396 rv = (info.filetype == APR_REG)? APR_SUCCESS : APR_EINVAL;
397 }
398 return rv;
399}
400
402{
405 if (rv == APR_SUCCESS) {
406 rv = (info.filetype == APR_SOCK)? APR_SUCCESS : APR_EINVAL;
407 }
408 return rv;
409}
410
412{
413 return (fname && *fname && APR_SUCCESS == md_util_is_file(fname, p));
414}
415
417{
418 const char *segment, *path;
419 va_list ap;
421
422 va_start(ap, p);
423 path = va_arg(ap, char *);
424 while (path && APR_SUCCESS == rv && (segment = va_arg(ap, char *))) {
426 }
427 va_end(ap);
428
429 *ppath = (APR_SUCCESS == rv)? (path? path : "") : NULL;
430 return rv;
431}
432
435{
437 apr_file_t *f;
438 const char *tmp;
439 int i, max;
440
441 tmp = apr_psprintf(p, "%s.tmp", fpath);
442 i = 0; max = 20;
443creat:
444 while (i < max && APR_EEXIST == (rv = md_util_fcreatex(&f, tmp, perms, p))) {
445 ++i;
447 }
448 if (APR_EEXIST == rv
449 && APR_SUCCESS == (rv = apr_file_remove(tmp, p))
450 && max <= 20) {
451 max *= 2;
452 goto creat;
453 }
454
455 if (APR_SUCCESS == rv) {
456 rv = write_cb(baton, f, p);
458
459 if (APR_SUCCESS == rv) {
460 rv = apr_file_rename(tmp, fpath, p);
461 if (APR_SUCCESS != rv) {
462 apr_file_remove(tmp, p);
463 }
464 }
465 }
466 return rv;
467}
468
469/**************************************************************************************************/
470/* text files */
471
473{
474 apr_status_t rv;
475 apr_file_t *f;
476 char buffer[8 * 1024];
477
478 *ptext = NULL;
479 if (APR_SUCCESS == (rv = apr_file_open(&f, fpath, APR_FOPEN_READ, 0, p))) {
480 apr_size_t blen = sizeof(buffer)/sizeof(buffer[0]) - 1;
481 rv = apr_file_read_full(f, buffer, blen, &blen);
482 if (APR_SUCCESS == rv || APR_STATUS_IS_EOF(rv)) {
483 *ptext = apr_pstrndup(p, buffer, blen);
484 rv = APR_SUCCESS;
485 }
487 }
488 return rv;
489}
490
492{
493 const char *text = baton;
494 apr_size_t len = strlen(text);
495
496 (void)p;
497 return apr_file_write_full(f, text, len, &len);
498}
499
501 apr_pool_t *p, const char *text)
502{
503 apr_status_t rv;
504 apr_file_t *f;
505
506 rv = md_util_fcreatex(&f, fpath, perms, p);
507 if (APR_SUCCESS == rv) {
508 rv = write_text((void*)text, f, p);
510 /* See <https://github.com/icing/mod_md/issues/117>: when a umask
511 * is set, files need to be assigned permissions explicitly.
512 * Otherwise, as in the issues reported, it will break our access model. */
514 if (APR_STATUS_IS_ENOTIMPL(rv)) {
515 rv = APR_SUCCESS;
516 }
517 }
518 return rv;
519}
520
522 apr_pool_t *p, const char *text)
523{
524 return md_util_freplace(fpath, perms, p, write_text, (void*)text);
525}
526
534
536{
538 apr_status_t rv;
539 const char *npath;
540
542 return rv;
543 }
544
545 if (info.filetype == APR_DIR) {
546 if (max_level > 0) {
547 apr_dir_t *d;
548
549 if (APR_SUCCESS == (rv = apr_dir_open(&d, fpath, p))) {
550
551 while (APR_SUCCESS == rv &&
553 if (!strcmp(".", info.name) || !strcmp("..", info.name)) {
554 continue;
555 }
556
557 rv = md_util_path_merge(&npath, p, fpath, info.name, NULL);
558 if (APR_SUCCESS == rv) {
559 rv = rm_recursive(npath, p, max_level - 1);
560 }
561 }
563 if (APR_STATUS_IS_ENOENT(rv)) {
564 rv = APR_SUCCESS;
565 }
566 }
567 }
568 if (APR_SUCCESS == rv) {
569 rv = apr_dir_remove(fpath, p);
570 }
571 }
572 else {
573 rv = apr_file_remove(fpath, p);
574 }
575 return rv;
576}
577
579{
580 int max_level = va_arg(ap, int);
581
582 (void)p;
583 return rm_recursive(baton, ptemp, max_level);
584}
585
590
591static apr_status_t match_and_do(md_util_fwalk_t *ctx, const char *path, int depth,
592 apr_pool_t *p, apr_pool_t *ptemp)
593{
595 const char *pattern, *npath;
596 apr_dir_t *d;
597 apr_finfo_t finfo;
598 int ndepth = depth + 1;
600
601 if (depth >= ctx->patterns->nelts) {
602 return APR_SUCCESS;
603 }
604 pattern = APR_ARRAY_IDX(ctx->patterns, depth, const char *);
605
606 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
607 "path=%s depth=%d pattern=%s", path, depth, pattern);
608 rv = apr_dir_open(&d, path, ptemp);
609 if (APR_SUCCESS != rv) {
610 return rv;
611 }
612
613 while (APR_SUCCESS == (rv = apr_dir_read(&finfo, wanted, d))) {
614 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
615 "candidate=%s", finfo.name);
616 if (!strcmp(".", finfo.name) || !strcmp("..", finfo.name)) {
617 continue;
618 }
619 if (APR_SUCCESS == apr_fnmatch(pattern, finfo.name, 0)) {
620 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
621 "candidate=%s matches pattern", finfo.name);
622 if (ndepth < ctx->patterns->nelts) {
623 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
624 "need to go deeper");
625 if (APR_DIR == finfo.filetype) {
626 /* deeper and deeper, irgendwo in der tiefe leuchtet ein licht */
627 rv = md_util_path_merge(&npath, ptemp, path, finfo.name, NULL);
628 if (APR_SUCCESS == rv) {
629 rv = match_and_do(ctx, npath, ndepth, p, ptemp);
630 }
631 }
632 }
633 else {
634 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
635 "invoking inspector on name=%s", finfo.name);
636 rv = ctx->cb(ctx->baton, p, ptemp, path, finfo.name, finfo.filetype);
637 }
638 }
639 if (APR_SUCCESS != rv) {
640 break;
641 }
642 }
643
644 if (APR_STATUS_IS_ENOENT(rv)) {
645 rv = APR_SUCCESS;
646 }
647
649 return rv;
650}
651
653{
655 const char *segment;
656
657 ctx->patterns = apr_array_make(ptemp, 5, sizeof(const char*));
658
659 segment = va_arg(ap, char *);
660 while (segment) {
661 APR_ARRAY_PUSH(ctx->patterns, const char *) = segment;
662 segment = va_arg(ap, char *);
663 }
664
665 return match_and_do(ctx, ctx->path, 0, p, ptemp);
666}
667
669 const char *path, ...)
670{
671 apr_status_t rv;
672 va_list ap;
674
675 memset(&ctx, 0, sizeof(ctx));
676 ctx.path = path;
677 ctx.follow_links = 1;
678 ctx.cb = cb;
679 ctx.baton = baton;
680
681 va_start(ap, path);
682 rv = pool_vado(files_do_start, &ctx, p, ap);
683 va_end(ap);
684
685 return rv;
686}
687
688static apr_status_t tree_do(void *baton, apr_pool_t *p, apr_pool_t *ptemp, const char *path)
689{
691
693 const char *name, *fpath;
694 apr_filetype_e ftype;
695 apr_dir_t *d;
697 apr_finfo_t finfo;
698
699 if (APR_SUCCESS == (rv = apr_dir_open(&d, path, ptemp))) {
700 while (APR_SUCCESS == (rv = apr_dir_read(&finfo, wanted, d))) {
701 name = finfo.name;
702 if (!strcmp(".", name) || !strcmp("..", name)) {
703 continue;
704 }
705
706 fpath = NULL;
707 ftype = finfo.filetype;
708
709 if (APR_LNK == ftype && ctx->follow_links) {
710 rv = md_util_path_merge(&fpath, ptemp, path, name, NULL);
711 if (APR_SUCCESS == rv) {
712 rv = apr_stat(&finfo, ctx->path, wanted, ptemp);
713 }
714 }
715
716 if (APR_DIR == finfo.filetype) {
717 if (!fpath) {
718 rv = md_util_path_merge(&fpath, ptemp, path, name, NULL);
719 }
720 if (APR_SUCCESS == rv) {
721 rv = tree_do(ctx, p, ptemp, fpath);
722 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, ptemp, "dir cb(%s/%s)",
723 path, name);
724 rv = ctx->cb(ctx->baton, p, ptemp, path, name, ftype);
725 }
726 }
727 else {
728 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, ptemp, "file cb(%s/%s)",
729 path, name);
730 rv = ctx->cb(ctx->baton, p, ptemp, path, name, finfo.filetype);
731 }
732 }
733
735
736 if (APR_STATUS_IS_ENOENT(rv)) {
737 rv = APR_SUCCESS;
738 }
739 }
740 return rv;
741}
742
744{
747 apr_status_t rv;
749
750 rv = apr_stat(&info, ctx->path, wanted, ptemp);
751 if (rv == APR_SUCCESS) {
752 switch (info.filetype) {
753 case APR_DIR:
754 rv = tree_do(ctx, p, ptemp, ctx->path);
755 break;
756 default:
757 rv = APR_EINVAL;
758 }
759 }
760 return rv;
761}
762
764 const char *path, int follow_links)
765{
766 apr_status_t rv;
768
769 memset(&ctx, 0, sizeof(ctx));
770 ctx.path = path;
771 ctx.follow_links = follow_links;
772 ctx.cb = cb;
773 ctx.baton = baton;
774
776
777 return rv;
778}
779
781 const char *path, const char *name, apr_filetype_e ftype)
782{
783 apr_status_t rv;
784 const char *fpath;
785
786 (void)baton;
787 (void)p;
788 rv = md_util_path_merge(&fpath, ptemp, path, name, NULL);
789 if (APR_SUCCESS == rv) {
790 if (APR_DIR == ftype) {
791 rv = apr_dir_remove(fpath, ptemp);
792 }
793 else {
794 rv = apr_file_remove(fpath, ptemp);
795 }
796 }
797 return rv;
798}
799
801{
803 if (APR_SUCCESS == rv) {
804 rv = apr_dir_remove(path, p);
805 }
806 return rv;
807}
808
809/* DNS name checks ********************************************************************************/
810
812{
813 char c, last = 0;
814 const char *cp = hostname;
815 int dots = 0;
816
817 /* Since we use the names in certificates, we need pure ASCII domain names
818 * and IDN need to be converted to unicode. */
819 while ((c = *cp++)) {
820 switch (c) {
821 case '.':
822 if (last == '.') {
823 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "dns name with ..: %s",
824 hostname);
825 return 0;
826 }
827 ++dots;
828 break;
829 case '-':
830 break;
831 default:
832 if (!apr_isalnum(c)) {
833 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "dns invalid char %c: %s",
834 c, hostname);
835 return 0;
836 }
837 break;
838 }
839 last = c;
840 }
841
842 if (last == '.') { /* DNS names may end with '.' */
843 --dots;
844 }
845 if (need_fqdn && dots <= 0) { /* do not accept just top level domains */
846 md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p, "not a FQDN: %s", hostname);
847 return 0;
848 }
849 return 1; /* empty string not allowed */
850}
851
852int md_dns_is_wildcard(apr_pool_t *p, const char *domain)
853{
854 if (domain[0] != '*' || domain[1] != '.') return 0;
855 return md_dns_is_name(p, domain+2, 1);
856}
857
858int md_dns_matches(const char *pattern, const char *domain)
859{
860 const char *s;
861
862 if (!apr_strnatcasecmp(pattern, domain)) return 1;
863 if (pattern[0] == '*' && pattern[1] == '.') {
864 s = strchr(domain, '.');
865 if (s && !apr_strnatcasecmp(pattern+1, s)) return 1;
866 }
867 return 0;
868}
869
871{
873 const char *domain, *pattern;
874 int i, j, duplicate;
875
876 minimal = apr_array_make(p, domains->nelts, sizeof(const char *));
877 for (i = 0; i < domains->nelts; ++i) {
878 domain = APR_ARRAY_IDX(domains, i, const char*);
879 duplicate = 0;
880 /* is it matched in minimal already? */
881 for (j = 0; j < minimal->nelts; ++j) {
882 pattern = APR_ARRAY_IDX(minimal, j, const char*);
883 if (md_dns_matches(pattern, domain)) {
884 duplicate = 1;
885 break;
886 }
887 }
888 if (!duplicate) {
889 if (!md_dns_is_wildcard(p, domain)) {
890 /* plain name, will we see a wildcard that replaces it? */
891 for (j = i+1; j < domains->nelts; ++j) {
892 pattern = APR_ARRAY_IDX(domains, j, const char*);
894 duplicate = 1;
895 break;
896 }
897 }
898 }
899 if (!duplicate) {
900 APR_ARRAY_PUSH(minimal, const char *) = domain;
901 }
902 }
903 }
904 return minimal;
905}
906
907int md_dns_domains_match(const apr_array_header_t *domains, const char *name)
908{
909 const char *domain;
910 int i;
911
912 for (i = 0; i < domains->nelts; ++i) {
913 domain = APR_ARRAY_IDX(domains, i, const char*);
914 if (md_dns_matches(domain, name)) return 1;
915 }
916 return 0;
917}
918
919int md_is_wild_match(const apr_array_header_t *domains, const char *name)
920{
921 const char *domain;
922 int i;
923
924 for (i = 0; i < domains->nelts; ++i) {
925 domain = APR_ARRAY_IDX(domains, i, const char*);
926 if (md_dns_matches(domain, name))
927 return (domain[0] == '*' && domain[1] == '.');
928 }
929 return 0;
930}
931
932const char *md_util_schemify(apr_pool_t *p, const char *s, const char *def_scheme)
933{
934 const char *cp = s;
935 while (*cp) {
936 if (*cp == ':') {
937 /* could be an url scheme, leave unchanged */
938 return s;
939 }
940 else if (!apr_isalnum(*cp)) {
941 break;
942 }
943 ++cp;
944 }
945 return apr_psprintf(p, "%s:%s", def_scheme, s);
946}
947
949 const char *uri, const char **perr)
950{
951 const char *s, *err = NULL;
952 apr_status_t rv;
953
954 if (APR_SUCCESS != (rv = apr_uri_parse(p, uri, uri_parsed))) {
955 err = "not an uri";
956 }
957 else if (uri_parsed->scheme) {
958 if (strlen(uri_parsed->scheme) + 1 >= strlen(uri)) {
959 err = "missing uri identifier";
960 }
961 else if (!strncmp("http", uri_parsed->scheme, 4)) {
962 if (!uri_parsed->hostname) {
963 err = "missing hostname";
964 }
965 else if (!md_dns_is_name(p, uri_parsed->hostname, 0)) {
966 err = "invalid hostname";
967 }
968 if (uri_parsed->port_str
969 && (!apr_isdigit(uri_parsed->port_str[0])
970 || uri_parsed->port == 0
971 || uri_parsed->port > 65353)) {
972 err = "invalid port";
973 }
974 }
975 else if (!strcmp("mailto", uri_parsed->scheme)) {
976 s = strchr(uri, '@');
977 if (!s) {
978 err = "missing @";
979 }
980 else if (strchr(s+1, '@')) {
981 err = "duplicate @";
982 }
983 else if (s == uri + strlen(uri_parsed->scheme) + 1) {
984 err = "missing local part";
985 }
986 else if (s == (uri + strlen(uri)-1)) {
987 err = "missing hostname";
988 }
989 else if (strstr(uri, "..")) {
990 err = "double period";
991 }
992 }
993 }
994 if (strchr(uri, ' ') || strchr(uri, '\t') ) {
995 err = "whitespace in uri";
996 }
997
998 if (err) {
999 rv = APR_EINVAL;
1000 }
1001 *perr = err;
1002 return rv;
1003}
1004
1006{
1008 apr_status_t rv;
1009
1010 if (APR_SUCCESS == (rv = uri_check(&uri_parsed, p, uri, perr))) {
1011 if (!uri_parsed.scheme) {
1012 *perr = "missing uri scheme";
1013 return APR_EINVAL;
1014 }
1015 }
1016 return rv;
1017}
1018
1020{
1022 apr_status_t rv;
1023
1024 if (APR_SUCCESS == (rv = uri_check(&uri_parsed, p, uri, perr))) {
1025 if (!uri_parsed.scheme) {
1026 *perr = "missing uri scheme";
1027 return APR_EINVAL;
1028 }
1029 if (apr_strnatcasecmp("http", uri_parsed.scheme)
1030 && apr_strnatcasecmp("https", uri_parsed.scheme)) {
1031 *perr = "uri scheme must be http or https";
1032 return APR_EINVAL;
1033 }
1034 }
1035 return rv;
1036}
1037
1038/* try and retry for a while **********************************************************************/
1039
1043{
1044 apr_status_t rv;
1050 int i = 0;
1051
1052 while (1) {
1053 if (APR_SUCCESS == (rv = fn(baton, i++))) {
1054 break;
1055 }
1056 else if (!APR_STATUS_IS_EAGAIN(rv) && !ignore_errs) {
1057 break;
1058 }
1059
1060 now = apr_time_now();
1061 if (now > giveup) {
1062 rv = APR_TIMEUP;
1063 break;
1064 }
1065
1066 left = giveup - now;
1067 if (nap_duration > left) {
1068 nap_duration = left;
1069 }
1070 if (nap_duration > nap_max) {
1072 }
1073
1075 if (backoff) {
1076 nap_duration *= 2;
1077 }
1078 }
1079 return rv;
1080}
1081
1082/* execute process ********************************************************************************/
1083
1085 const char * const *argv, int *exit_code)
1086{
1087 apr_status_t rv;
1088 apr_procattr_t *procattr;
1091 char buffer[1024];
1092
1093 *exit_code = 0;
1094 if (!(proc = apr_pcalloc(p, sizeof(*proc)))) {
1095 return APR_ENOMEM;
1096 }
1097 if ( APR_SUCCESS == (rv = apr_procattr_create(&procattr, p))
1098 && APR_SUCCESS == (rv = apr_procattr_io_set(procattr, APR_NO_FILE,
1101 && APR_SUCCESS == (rv = apr_proc_create(proc, cmd, argv, NULL, procattr, p))) {
1102
1103 /* read stderr and log on INFO for possible fault analysis. */
1104 while(APR_SUCCESS == (rv = apr_file_gets(buffer, sizeof(buffer)-1, proc->err))) {
1105 md_log_perror(MD_LOG_MARK, MD_LOG_INFO, 0, p, "cmd(%s) stderr: %s", cmd, buffer);
1106 }
1107 if (!APR_STATUS_IS_EOF(rv)) goto out;
1109
1111 /* let's not dwell on exit stati, but core should signal something's bad */
1112 if (*exit_code > 127 || APR_PROC_SIGNAL_CORE == ewhy) {
1113 return APR_EINCOMPLETE;
1114 }
1115 return APR_SUCCESS;
1116 }
1117 }
1118out:
1119 return rv;
1120}
1121
1122/* base64 url encoding ****************************************************************************/
1123
1124#define N6 (unsigned int)-1
1125
1126static const unsigned int BASE64URL_UINT6[] = {
1127/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1128 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 0 */
1129 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 1 */
1130 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, 62, N6, N6, /* 2 */
1131 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, N6, N6, N6, N6, N6, N6, /* 3 */
1132 N6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 4 */
1133 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, N6, N6, N6, N6, 63, /* 5 */
1134 N6, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 6 */
1135 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, N6, N6, N6, N6, N6, /* 7 */
1136 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 8 */
1137 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* 9 */
1138 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* a */
1139 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* b */
1140 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* c */
1141 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* d */
1142 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, /* e */
1143 N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6, N6 /* f */
1144};
1145static const unsigned char BASE64URL_CHARS[] = {
1146 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0 - 9 */
1147 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10 - 19 */
1148 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20 - 29 */
1149 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30 - 39 */
1150 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40 - 49 */
1151 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50 - 59 */
1152 '8', '9', '-', '_', ' ', ' ', ' ', ' ', ' ', ' ', /* 60 - 69 */
1153};
1154
1155#define BASE64URL_CHAR(x) BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ]
1156
1159{
1160 const unsigned char *e = (const unsigned char *)encoded;
1161 const unsigned char *p = e;
1162 unsigned char *d;
1163 unsigned int n;
1164 long len, mlen, remain, i;
1165
1166 while (*p && BASE64URL_UINT6[ *p ] != N6) {
1167 ++p;
1168 }
1169 len = (int)(p - e);
1170 mlen = (len/4)*4;
1171 decoded->data = apr_pcalloc(pool, (apr_size_t)len + 1);
1172
1173 i = 0;
1174 d = (unsigned char*)decoded->data;
1175 for (; i < mlen; i += 4) {
1176 n = ((BASE64URL_UINT6[ e[i+0] ] << 18) +
1177 (BASE64URL_UINT6[ e[i+1] ] << 12) +
1178 (BASE64URL_UINT6[ e[i+2] ] << 6) +
1179 (BASE64URL_UINT6[ e[i+3] ]));
1180 *d++ = (unsigned char)(n >> 16);
1181 *d++ = (unsigned char)(n >> 8 & 0xffu);
1182 *d++ = (unsigned char)(n & 0xffu);
1183 }
1184 remain = len - mlen;
1185 switch (remain) {
1186 case 2:
1187 n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
1188 (BASE64URL_UINT6[ e[mlen+1] ] << 12));
1189 *d++ = (unsigned char)(n >> 16);
1190 remain = 1;
1191 break;
1192 case 3:
1193 n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
1194 (BASE64URL_UINT6[ e[mlen+1] ] << 12) +
1195 (BASE64URL_UINT6[ e[mlen+2] ] << 6));
1196 *d++ = (unsigned char)(n >> 16);
1197 *d++ = (unsigned char)(n >> 8 & 0xffu);
1198 remain = 2;
1199 break;
1200 default: /* do nothing */
1201 break;
1202 }
1203 decoded->len = (apr_size_t)(mlen/4*3 + remain);
1204 return decoded->len;
1205}
1206
1208{
1209 int i, len = (int)data->len;
1210 apr_size_t slen = ((data->len+2)/3)*4 + 1; /* 0 terminated */
1211 const unsigned char *udata = (const unsigned char*)data->data;
1212 unsigned char *enc, *p = apr_pcalloc(pool, slen);
1213
1214 enc = p;
1215 for (i = 0; i < len-2; i+= 3) {
1216 *p++ = BASE64URL_CHAR( (udata[i] >> 2) );
1217 *p++ = BASE64URL_CHAR( (udata[i] << 4) + (udata[i+1] >> 4) );
1218 *p++ = BASE64URL_CHAR( (udata[i+1] << 2) + (udata[i+2] >> 6) );
1219 *p++ = BASE64URL_CHAR( (udata[i+2]) );
1220 }
1221
1222 if (i < len) {
1223 *p++ = BASE64URL_CHAR( (udata[i] >> 2) );
1224 if (i == (len - 1)) {
1225 *p++ = BASE64URL_CHARS[ ((unsigned int)udata[i] << 4) & 0x3fu ];
1226 }
1227 else {
1228 *p++ = BASE64URL_CHAR( (udata[i] << 4) + (udata[i+1] >> 4) );
1229 *p++ = BASE64URL_CHAR( (udata[i+1] << 2) );
1230 }
1231 }
1232 *p++ = '\0';
1233 return (char *)enc;
1234}
1235
1236/*******************************************************************************
1237 * link header handling
1238 ******************************************************************************/
1239
1240typedef struct {
1241 const char *s;
1250} link_ctx;
1251
1252static int attr_char(char c)
1253{
1254 switch (c) {
1255 case '!':
1256 case '#':
1257 case '$':
1258 case '&':
1259 case '+':
1260 case '-':
1261 case '.':
1262 case '^':
1263 case '_':
1264 case '`':
1265 case '|':
1266 case '~':
1267 return 1;
1268 default:
1269 return apr_isalnum(c);
1270 }
1271}
1272
1273static int ptoken_char(char c)
1274{
1275 switch (c) {
1276 case '!':
1277 case '#':
1278 case '$':
1279 case '&':
1280 case '\'':
1281 case '(':
1282 case ')':
1283 case '*':
1284 case '+':
1285 case '-':
1286 case '.':
1287 case '/':
1288 case ':':
1289 case '<':
1290 case '=':
1291 case '>':
1292 case '?':
1293 case '@':
1294 case '[':
1295 case ']':
1296 case '^':
1297 case '_':
1298 case '`':
1299 case '{':
1300 case '|':
1301 case '}':
1302 case '~':
1303 return 1;
1304 default:
1305 return apr_isalnum(c);
1306 }
1307}
1308
1310{
1311 char c;
1312 while (ctx->i < ctx->slen
1313 && (((c = ctx->s[ctx->i]) == ' ') || (c == '\t'))) {
1314 ++ctx->i;
1315 }
1316 return (ctx->i < ctx->slen);
1317}
1318
1320{
1321 char c;
1322 while (ctx->i < ctx->slen
1323 && (((c = ctx->s[ctx->i]) != ' ') && (c != '\t'))) {
1324 ++ctx->i;
1325 }
1326 return (ctx->i < ctx->slen);
1327}
1328
1329static unsigned int find_chr(link_ctx *ctx, char c, apr_size_t *pidx)
1330{
1331 apr_size_t j;
1332 for (j = ctx->i; j < ctx->slen; ++j) {
1333 if (ctx->s[j] == c) {
1334 *pidx = j;
1335 return 1;
1336 }
1337 }
1338 return 0;
1339}
1340
1341static int read_chr(link_ctx *ctx, char c)
1342{
1343 if (ctx->i < ctx->slen && ctx->s[ctx->i] == c) {
1344 ++ctx->i;
1345 return 1;
1346 }
1347 return 0;
1348}
1349
1351{
1352 if (skip_ws(ctx) && read_chr(ctx, '\"')) {
1354 if (find_chr(ctx, '\"', &end)) {
1355 ctx->i = end + 1;
1356 return 1;
1357 }
1358 }
1359 return 0;
1360}
1361
1363{
1364 if (skip_ws(ctx)) {
1365 apr_size_t i;
1366 for (i = ctx->i; i < ctx->slen && ptoken_char(ctx->s[i]); ++i) {
1367 /* nop */
1368 }
1369 if (i > ctx->i) {
1370 ctx->i = i;
1371 return 1;
1372 }
1373 }
1374 return 0;
1375}
1376
1377
1379{
1380 ctx->link_start = ctx->link_len = 0;
1381 if (skip_ws(ctx) && read_chr(ctx, '<')) {
1383 if (find_chr(ctx, '>', &end)) {
1384 ctx->link_start = ctx->i;
1385 ctx->link_len = end - ctx->link_start;
1386 ctx->i = end + 1;
1387 return 1;
1388 }
1389 }
1390 return 0;
1391}
1392
1394{
1395 if (skip_ws(ctx)) {
1396 apr_size_t i;
1397 for (i = ctx->i; i < ctx->slen && attr_char(ctx->s[i]); ++i) {
1398 /* nop */
1399 }
1400 if (i > ctx->i) {
1401 ctx->i = i;
1402 return 1;
1403 }
1404 }
1405 return 0;
1406}
1407
1409{
1410 if (skip_ws(ctx) && read_chr(ctx, '=')) {
1411 ctx->pv_start = ctx->i;
1412 if (skip_qstring(ctx) || skip_ptoken(ctx)) {
1413 ctx->pv_len = ctx->i - ctx->pv_start;
1414 return 1;
1415 }
1416 }
1417 return 0;
1418}
1419
1421{
1422 if (skip_ws(ctx) && read_chr(ctx, ';')) {
1423 ctx->pn_start = ctx->i;
1424 ctx->pn_len = 0;
1425 if (skip_pname(ctx)) {
1426 ctx->pn_len = ctx->i - ctx->pn_start;
1427 ctx->pv_len = 0;
1428 skip_pvalue(ctx); /* value is optional */
1429 return 1;
1430 }
1431 }
1432 return 0;
1433}
1434
1435static int pv_contains(link_ctx *ctx, const char *s)
1436{
1437 apr_size_t pvstart = ctx->pv_start;
1438 apr_size_t pvlen = ctx->pv_len;
1439
1440 if (ctx->s[pvstart] == '\"' && pvlen > 1) {
1441 ++pvstart;
1442 pvlen -= 2;
1443 }
1444 if (pvlen > 0) {
1445 apr_size_t slen = strlen(s);
1447 apr_size_t i;
1448
1449 memset(&pvctx, 0, sizeof(pvctx));
1450 pvctx.s = ctx->s + pvstart;
1451 pvctx.slen = pvlen;
1452
1453 for (i = 0; i < pvctx.slen; i = pvctx.i) {
1454 skip_nonws(&pvctx);
1455 if ((pvctx.i - i) == slen && !strncmp(s, pvctx.s + i, slen)) {
1456 return 1;
1457 }
1458 skip_ws(&pvctx);
1459 }
1460 }
1461 return 0;
1462}
1463
1464/* RFC 5988 <https://tools.ietf.org/html/rfc5988#section-6.2.1>
1465 Link = "Link" ":" #link-value
1466 link-value = "<" URI-Reference ">" *( ";" link-param )
1467 link-param = ( ( "rel" "=" relation-types )
1468 | ( "anchor" "=" <"> URI-Reference <"> )
1469 | ( "rev" "=" relation-types )
1470 | ( "hreflang" "=" Language-Tag )
1471 | ( "media" "=" ( MediaDesc | ( <"> MediaDesc <"> ) ) )
1472 | ( "title" "=" quoted-string )
1473 | ( "title*" "=" ext-value )
1474 | ( "type" "=" ( media-type | quoted-mt ) )
1475 | ( link-extension ) )
1476 link-extension = ( parmname [ "=" ( ptoken | quoted-string ) ] )
1477 | ( ext-name-star "=" ext-value )
1478 ext-name-star = parmname "*" ; reserved for RFC2231-profiled
1479 ; extensions. Whitespace NOT
1480 ; allowed in between.
1481 ptoken = 1*ptokenchar
1482 ptokenchar = "!" | "#" | "$" | "%" | "&" | "'" | "("
1483 | ")" | "*" | "+" | "-" | "." | "/" | DIGIT
1484 | ":" | "<" | "=" | ">" | "?" | "@" | ALPHA
1485 | "[" | "]" | "^" | "_" | "`" | "{" | "|"
1486 | "}" | "~"
1487 media-type = type-name "/" subtype-name
1488 quoted-mt = <"> media-type <">
1489 relation-types = relation-type
1490 | <"> relation-type *( 1*SP relation-type ) <">
1491 relation-type = reg-rel-type | ext-rel-type
1492 reg-rel-type = LOALPHA *( LOALPHA | DIGIT | "." | "-" )
1493 ext-rel-type = URI
1494
1495 and from <https://tools.ietf.org/html/rfc5987>
1496 parmname = 1*attr-char
1497 attr-char = ALPHA / DIGIT
1498 / "!" / "#" / "$" / "&" / "+" / "-" / "."
1499 / "^" / "_" / "`" / "|" / "~"
1500 */
1501
1502typedef struct {
1504 const char *relation;
1505 const char *url;
1506} find_ctx;
1507
1508static int find_url(void *baton, const char *key, const char *value)
1509{
1510 find_ctx *outer = baton;
1511
1512 if (!apr_strnatcasecmp("link", key)) {
1513 link_ctx ctx;
1514
1515 memset(&ctx, 0, sizeof(ctx));
1516 ctx.s = value;
1517 ctx.slen = strlen(value);
1518
1519 while (read_link(&ctx)) {
1520 while (skip_param(&ctx)) {
1521 if (ctx.pn_len == 3 && !strncmp("rel", ctx.s + ctx.pn_start, 3)
1522 && pv_contains(&ctx, outer->relation)) {
1523 /* this is the link relation we are looking for */
1524 outer->url = apr_pstrndup(outer->pool, ctx.s + ctx.link_start, ctx.link_len);
1525 return 0;
1526 }
1527 }
1528 }
1529 }
1530 return 1;
1531}
1532
1533const char *md_link_find_relation(const apr_table_t *headers,
1534 apr_pool_t *pool, const char *relation)
1535{
1536 find_ctx ctx;
1537
1538 memset(&ctx, 0, sizeof(ctx));
1539 ctx.pool = pool;
1540 ctx.relation = relation;
1541
1542 apr_table_do(find_url, &ctx, headers, NULL);
1543
1544 return ctx.url;
1545}
1546
1547const char *md_util_parse_ct(apr_pool_t *pool, const char *cth)
1548{
1549 char *type;
1550 const char *p;
1552
1553 if (!cth) return NULL;
1554
1555 for( p = cth; *p && *p != ' ' && *p != ';'; ++p)
1556 ;
1557 hlen = (apr_size_t)(p - cth);
1558 type = apr_pcalloc( pool, hlen + 1 );
1559 assert(type);
1560 memcpy(type, cth, hlen);
1561 type[hlen] = '\0';
1562
1563 return type;
1564 /* Could parse and return parameters here, but we don't need any at present.
1565 */
1566}
int n
Definition ap_regex.h:278
const char * pattern
Definition ap_regex.h:243
const char apr_size_t len
Definition ap_regex.h:187
static int exclude
Definition abts.c:25
char * strstr(char *s1, char *s2)
APR File Information.
APR FNMatch Functions.
APR general purpose library routines.
APR Portability Routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR Table library.
APR-UTIL URI Routines.
const char * hostname
request_rec int int apr_table_t const char * path
const char server_rec server_rec ** ps
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
#define APR_CHILD_DONE
Definition apr_errno.h:446
#define APR_ENOMEM
Definition apr_errno.h:683
#define APR_TIMEUP
Definition apr_errno.h:450
#define APR_EINCOMPLETE
Definition apr_errno.h:328
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_EEXIST
Definition apr_errno.h:648
#define APR_STATUS_IS_EAGAIN(s)
Definition apr_errno.h:1272
#define APR_STATUS_IS_ENOTIMPL(s)
Definition apr_errno.h:615
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
#define APR_STATUS_IS_EOF(s)
Definition apr_errno.h:567
apr_file_t * f
apr_file_t apr_off_t start
apr_bucket * e
apr_brigade_flush void * ctx
apr_bucket apr_bucket_brigade * a
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const char * src
Definition apr_encode.h:167
const char apr_ssize_t slen
Definition apr_encode.h:168
const char int case_sensitive
const char * uri
Definition apr_uri.h:159
apr_text_header const char * text
Definition apr_xml.h:78
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isalnum(c)
Definition apr_lib.h:203
#define apr_isdigit(c)
Definition apr_lib.h:209
#define apr_tolower(c)
Definition apr_lib.h:231
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_int32_t apr_fileperms_t
apr_filetype_e
@ APR_LNK
@ APR_REG
@ APR_SOCK
@ APR_DIR
const char * key
const char apr_fileperms_t perms
void * data
int type
char * buffer
#define APR_FOPEN_EXCL
Definition apr_file_io.h:63
#define APR_FOPEN_WRITE
Definition apr_file_io.h:55
#define APR_FOPEN_READ
Definition apr_file_io.h:54
#define APR_FOPEN_CREATE
Definition apr_file_io.h:56
const char apr_int32_t wanted
const char * fname
#define APR_FINFO_LINK
#define APR_FINFO_TYPE
#define APR_FILEPATH_SECUREROOT
#define memmove(a, b, c)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** end
const char char ** last
const char * s
Definition apr_strings.h:95
const void * m
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
int nelts
Definition apr_tables.h:122
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_proc_t * proc
apr_int32_t apr_int32_t apr_int32_t err
#define APR_NO_FILE
#define APR_FULL_BLOCK
apr_cmdtype_e cmd
#define APR_NO_PIPE
apr_exit_why_e
@ APR_WAIT
@ APR_PROC_SIGNAL_CORE
@ APR_PROGRAM_ENV
#define apr_time_from_msec(msec)
Definition apr_time.h:75
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_size_t apr_size_t max
Definition apr_time.h:220
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_pool_t * p
Definition md_event.c:32
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_TRACE4
Definition md_log.h:32
@ MD_LOG_TRACE3
Definition md_log.h:31
@ MD_LOG_INFO
Definition md_log.h:27
const char * md_link_find_relation(const apr_table_t *headers, apr_pool_t *pool, const char *relation)
Definition md_util.c:1533
apr_status_t md_util_rm_recursive(const char *fpath, apr_pool_t *p, int max_level)
Definition md_util.c:586
apr_size_t md_util_base64url_decode(md_data_t *decoded, const char *encoded, apr_pool_t *pool)
Definition md_util.c:1157
static apr_status_t prm_recursive(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
Definition md_util.c:578
apr_status_t md_util_pool_do(md_util_action *cb, void *baton, apr_pool_t *p)
Definition md_util.c:39
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_array_header_t * md_array_str_clone(apr_pool_t *p, apr_array_header_t *src)
Definition md_util.c:288
apr_status_t md_util_pool_vdo(md_util_vaction *cb, void *baton, apr_pool_t *p,...)
Definition md_util.c:65
void md_data_init_str(md_data_t *d, const char *str)
Definition md_util.c:102
static apr_status_t uri_check(apr_uri_t *uri_parsed, apr_pool_t *p, const char *uri, const char **perr)
Definition md_util.c:948
apr_status_t md_util_is_dir(const char *path, apr_pool_t *pool)
Definition md_util.c:381
int md_array_remove(struct apr_array_header_t *a, void *elem)
Definition md_util.c:211
int md_dns_domains_match(const apr_array_header_t *domains, const char *name)
Definition md_util.c:907
apr_status_t md_util_files_do(md_util_fdo_cb *cb, void *baton, apr_pool_t *p, const char *path,...)
Definition md_util.c:668
static apr_status_t match_and_do(md_util_fwalk_t *ctx, const char *path, int depth, apr_pool_t *p, apr_pool_t *ptemp)
Definition md_util.c:591
static apr_status_t tree_do(void *baton, apr_pool_t *p, apr_pool_t *ptemp, const char *path)
Definition md_util.c:688
#define N6
Definition md_util.c:1124
void md_data_pinit(md_data_t *d, apr_size_t len, apr_pool_t *p)
Definition md_util.c:79
static int skip_ws(link_ctx *ctx)
Definition md_util.c:1309
static int read_link(link_ctx *ctx)
Definition md_util.c:1378
static const unsigned int BASE64URL_UINT6[]
Definition md_util.c:1126
int md_dns_is_wildcard(apr_pool_t *p, const char *domain)
Definition md_util.c:852
apr_status_t md_text_freplace(const char *fpath, apr_fileperms_t perms, apr_pool_t *p, const char *text)
Definition md_util.c:521
static int read_chr(link_ctx *ctx, char c)
Definition md_util.c:1341
#define BASE64URL_CHAR(x)
Definition md_util.c:1155
static const char *const hex_const[]
Definition md_util.c:150
apr_status_t md_util_abs_uri_check(apr_pool_t *p, const char *uri, const char **perr)
Definition md_util.c:1005
apr_status_t md_util_path_merge(const char **ppath, apr_pool_t *p,...)
Definition md_util.c:416
static int find_url(void *baton, const char *key, const char *value)
Definition md_util.c:1508
apr_status_t md_util_fopen(FILE **pf, const char *fn, const char *mode)
Definition md_util.c:352
apr_status_t md_text_fread8k(const char **ptext, apr_pool_t *p, const char *fpath)
Definition md_util.c:472
int md_array_is_empty(const struct apr_array_header_t *array)
Definition md_util.c:235
static int skip_nonws(link_ctx *ctx)
Definition md_util.c:1319
int md_array_str_eq(const struct apr_array_header_t *a1, const struct apr_array_header_t *a2, int case_sensitive)
Definition md_util.c:268
char * md_util_str_tolower(char *s)
Definition md_util.c:240
apr_status_t md_util_is_unix_socket(const char *path, apr_pool_t *pool)
Definition md_util.c:401
void md_data_clear(md_data_t *d)
Definition md_util.c:112
static int attr_char(char c)
Definition md_util.c:1252
apr_status_t md_util_is_file(const char *path, apr_pool_t *pool)
Definition md_util.c:391
int md_is_wild_match(const apr_array_header_t *domains, const char *name)
Definition md_util.c:919
void md_data_init(md_data_t *d, const char *data, apr_size_t len)
Definition md_util.c:95
const char * md_util_schemify(apr_pool_t *p, const char *s, const char *def_scheme)
Definition md_util.c:932
void md_data_assign_pcopy(md_data_t *dest, const char *src, apr_size_t src_len, apr_pool_t *p)
Definition md_util.c:143
const char * md_util_base64url_encode(const md_data_t *data, apr_pool_t *pool)
Definition md_util.c:1207
struct apr_array_header_t * md_array_str_compact(apr_pool_t *p, struct apr_array_header_t *src, int case_sensitive)
Definition md_util.c:301
int md_array_str_index(const apr_array_header_t *array, const char *s, int start, int case_sensitive)
Definition md_util.c:250
md_data_t * md_data_make_pcopy(apr_pool_t *p, const char *data, apr_size_t len)
Definition md_util.c:120
const char * md_util_parse_ct(apr_pool_t *pool, const char *cth)
Definition md_util.c:1547
static int skip_pvalue(link_ctx *ctx)
Definition md_util.c:1408
apr_status_t md_data_assign_copy(md_data_t *dest, const char *src, apr_size_t src_len)
Definition md_util.c:130
static apr_status_t rm_cb(void *baton, apr_pool_t *p, apr_pool_t *ptemp, const char *path, const char *name, apr_filetype_e ftype)
Definition md_util.c:780
static apr_status_t pool_vado(md_util_vaction *cb, void *baton, apr_pool_t *p, va_list ap)
Definition md_util.c:51
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 unsigned int find_chr(link_ctx *ctx, char c, apr_size_t *pidx)
Definition md_util.c:1329
int md_array_remove_at(struct apr_array_header_t *a, int idx)
Definition md_util.c:194
static int pv_contains(link_ctx *ctx, const char *s)
Definition md_util.c:1435
apr_status_t md_util_ftree_remove(const char *path, apr_pool_t *p)
Definition md_util.c:800
apr_status_t md_data_to_hex(const char **phex, char separator, apr_pool_t *p, const md_data_t *data)
Definition md_util.c:169
int md_dns_is_name(apr_pool_t *p, const char *hostname, int need_fqdn)
Definition md_util.c:811
void md_data_null(md_data_t *d)
Definition md_util.c:107
static apr_status_t rm_recursive(const char *fpath, apr_pool_t *p, int max_level)
Definition md_util.c:535
apr_status_t md_util_freplace(const char *fpath, apr_fileperms_t perms, apr_pool_t *p, md_util_file_cb *write_cb, void *baton)
Definition md_util.c:433
int md_file_exists(const char *fname, apr_pool_t *p)
Definition md_util.c:411
static const unsigned char BASE64URL_CHARS[]
Definition md_util.c:1145
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 int skip_param(link_ctx *ctx)
Definition md_util.c:1420
apr_status_t md_text_fcreatex(const char *fpath, apr_fileperms_t perms, apr_pool_t *p, const char *text)
Definition md_util.c:500
static int skip_ptoken(link_ctx *ctx)
Definition md_util.c:1362
int md_array_str_add_missing(apr_array_header_t *dest, apr_array_header_t *src, int case_sensitive)
Definition md_util.c:336
apr_array_header_t * md_dns_make_minimal(apr_pool_t *p, apr_array_header_t *domains)
Definition md_util.c:870
int md_dns_matches(const char *pattern, const char *domain)
Definition md_util.c:858
static int skip_pname(link_ctx *ctx)
Definition md_util.c:1393
static int ptoken_char(char c)
Definition md_util.c:1273
static apr_status_t write_text(void *baton, struct apr_file_t *f, apr_pool_t *p)
Definition md_util.c:491
apr_status_t md_util_abs_http_uri_check(apr_pool_t *p, const char *uri, const char **perr)
Definition md_util.c:1019
apr_status_t md_util_fcreatex(apr_file_t **pf, const char *fn, apr_fileperms_t perms, apr_pool_t *p)
Definition md_util.c:362
static int skip_qstring(link_ctx *ctx)
Definition md_util.c:1350
static apr_status_t tree_start_do(void *baton, apr_pool_t *p, apr_pool_t *ptemp)
Definition md_util.c:743
md_data_t * md_data_pmake(apr_size_t len, apr_pool_t *p)
Definition md_util.c:86
static apr_status_t files_do_start(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
Definition md_util.c:652
apr_status_t md_util_tree_do(md_util_fdo_cb *cb, void *baton, apr_pool_t *p, const char *path, int follow_links)
Definition md_util.c:763
apr_status_t md_util_action(void *baton, apr_pool_t *p, apr_pool_t *ptemp)
Definition md_util.h:29
apr_status_t md_util_file_cb(void *baton, struct apr_file_t *f, apr_pool_t *p)
Definition md_util.h:200
apr_status_t md_util_vaction(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
Definition md_util.h:30
apr_status_t md_util_fdo_cb(void *baton, apr_pool_t *p, apr_pool_t *ptemp, const char *dir, const char *name, apr_filetype_e ftype)
Definition md_util.h:211
apr_status_t md_util_try_fn(void *baton, int i)
Definition md_util.h:252
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_filetype_e filetype
const char * name
apr_file_t * err
const char * relation
Definition md_util.c:1504
apr_pool_t * pool
Definition md_util.c:1503
const char * url
Definition md_util.c:1505
apr_array_header_t * patterns
Definition md_util.c:529
const char * path
Definition md_util.c:528
md_util_fdo_cb * cb
Definition md_util.c:532
static struct pattern_s patterns[]
static apr_array_header_t * a1
Definition testtable.c:33
static apr_time_t now
Definition testtime.c:33
apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, apr_dir_t *thedir)
Definition dir.c:142
apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool)
Definition dir.c:343
apr_status_t apr_dir_close(apr_dir_t *thedir)
Definition dir.c:109
apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
Definition dir.c:75
#define str
IN ULONG IN INT timeout
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray
INT info