You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2019/06/24 16:04:33 UTC

svn commit: r1862013 [6/8] - in /httpd/httpd/trunk: ./ modules/md/

Modified: httpd/httpd/trunk/modules/md/md_store_fs.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store_fs.c?rev=1862013&r1=1862012&r2=1862013&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store_fs.c (original)
+++ httpd/httpd/trunk/modules/md/md_store_fs.c Mon Jun 24 16:04:32 2019
@@ -84,6 +84,8 @@ static apr_status_t fs_move(md_store_t *
 static apr_status_t fs_iterate(md_store_inspect *inspect, void *baton, md_store_t *store, 
                                apr_pool_t *p, md_store_group_t group,  const char *pattern,
                                const char *aspect, md_store_vtype_t vtype);
+static apr_status_t fs_iterate_names(md_store_inspect *inspect, void *baton, md_store_t *store, 
+                                     apr_pool_t *p, md_store_group_t group, const char *pattern);
 
 static apr_status_t fs_get_fname(const char **pfname, 
                                  md_store_t *store, md_store_group_t group, 
@@ -122,13 +124,12 @@ static apr_status_t rename_pkey(void *ba
 {
     const char *from, *to;
     apr_status_t rv = APR_SUCCESS;
-    MD_CHK_VARS;
     
     (void)baton;
     (void)ftype;
     if (   MD_OK(md_util_path_merge(&from, ptemp, dir, name, NULL))
         && MD_OK(md_util_path_merge(&to, ptemp, dir, MD_FN_PRIVKEY, NULL))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, "renaming %s/%s to %s", 
+        md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, p, "renaming %s/%s to %s", 
                       dir, name, MD_FN_PRIVKEY);
         return apr_file_rename(from, to, ptemp);
     }
@@ -143,16 +144,15 @@ static apr_status_t mk_pubcert(void *bat
     apr_array_header_t *chain, *pubcert;
     const char *fname, *fpubcert;
     apr_status_t rv = APR_SUCCESS;
-    MD_CHK_VARS;
     
     (void)baton;
     (void)ftype;
     (void)p;
     if (   MD_OK(md_util_path_merge(&fpubcert, ptemp, dir, MD_FN_PUBCERT, NULL))
-        && MD_IS_ERR(md_chain_fload(&pubcert, ptemp, fpubcert), ENOENT)
+        && APR_STATUS_IS_ENOENT(rv = md_chain_fload(&pubcert, ptemp, fpubcert))
         && MD_OK(md_util_path_merge(&fname, ptemp, dir, name, NULL))
         && MD_OK(md_cert_fload(&cert, ptemp, fname))
-        && MD_OK(md_util_path_merge(&fname, ptemp, dir, MD_FN_CHAIN, NULL))) {
+        && MD_OK(md_util_path_merge(&fname, ptemp, dir, "chain.pem", NULL))) {
         
         rv = md_chain_fload(&chain, ptemp, fname);
         if (APR_STATUS_IS_ENOENT(rv)) {
@@ -196,7 +196,6 @@ static apr_status_t read_store_file(md_s
     const char *key64, *key;
     apr_status_t rv;
     double store_version;
-    MD_CHK_VARS;
     
     if (MD_OK(md_json_readf(&json, p, fname))) {
         store_version = md_json_getn(json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
@@ -249,7 +248,6 @@ static apr_status_t setup_store_file(voi
     md_store_fs_t *s_fs = baton;
     const char *fname;
     apr_status_t rv;
-    MD_CHK_VARS;
 
     (void)ap;
     s_fs->plain_pkey[MD_SG_DOMAINS] = 1;
@@ -264,7 +262,7 @@ read:
         rv = read_store_file(s_fs, fname, p, ptemp);
     }
     else if (APR_STATUS_IS_ENOENT(rv)
-        && MD_IS_ERR(init_store_file(s_fs, fname, p, ptemp), EEXIST)) {
+        && APR_STATUS_IS_EEXIST(rv = init_store_file(s_fs, fname, p, ptemp))) {
         goto read;
     }
     return rv;
@@ -274,7 +272,6 @@ apr_status_t md_store_fs_init(md_store_t
 {
     md_store_fs_t *s_fs;
     apr_status_t rv = APR_SUCCESS;
-    MD_CHK_VARS;
     
     s_fs = apr_pcalloc(p, sizeof(*s_fs));
 
@@ -284,6 +281,7 @@ apr_status_t md_store_fs_init(md_store_t
     s_fs->s.move = fs_move;
     s_fs->s.purge = fs_purge;
     s_fs->s.iterate = fs_iterate;
+    s_fs->s.iterate_names = fs_iterate_names;
     s_fs->s.get_fname = fs_get_fname;
     s_fs->s.is_newer = fs_is_newer;
     
@@ -303,7 +301,7 @@ apr_status_t md_store_fs_init(md_store_t
 
     s_fs->base = apr_pstrdup(p, path);
     
-    if (MD_IS_ERR(md_util_is_dir(s_fs->base, p), ENOENT)
+    if (APR_STATUS_IS_ENOENT(rv = md_util_is_dir(s_fs->base, p))
         && MD_OK(apr_dir_make_recursive(s_fs->base, s_fs->def_perms.dir, p))) {
         rv = apr_file_perms_set(s_fs->base, MD_FPROT_D_UALL_WREAD);
         if (APR_STATUS_IS_ENOTIMPL(rv)) {
@@ -446,7 +444,6 @@ static apr_status_t pfs_load(void *baton
     md_store_group_t group;
     void **pvalue;
     apr_status_t rv;
-    MD_CHK_VARS;
     
     group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char *);
@@ -477,7 +474,6 @@ static apr_status_t mk_group_dir(const c
 {
     const perms_t *perms;
     apr_status_t rv;
-    MD_CHK_VARS;
     
     perms = gperms(s_fs, group);
 
@@ -507,7 +503,6 @@ static apr_status_t pfs_is_newer(void *b
     apr_finfo_t inf1, inf2;
     int *pnewer;
     apr_status_t rv;
-    MD_CHK_VARS;
     
     (void)p;
     group1 = (md_store_group_t)va_arg(ap, int);
@@ -554,7 +549,6 @@ static apr_status_t pfs_save(void *baton
     const perms_t *perms;
     const char *pass;
     apr_size_t pass_len;
-    MD_CHK_VARS;
     
     group = (md_store_group_t)va_arg(ap, int);
     name = va_arg(ap, const char*);
@@ -612,7 +606,6 @@ static apr_status_t pfs_remove(void *bat
     int force;
     apr_finfo_t info;
     md_store_group_t group;
-    MD_CHK_VARS;
     
     (void)p;
     group = (md_store_group_t)va_arg(ap, int);
@@ -624,7 +617,7 @@ static apr_status_t pfs_remove(void *bat
     
     if (   MD_OK(md_util_path_merge(&dir, ptemp, s_fs->base, groupname, name, NULL))
         && MD_OK(md_util_path_merge(&fpath, ptemp, dir, aspect, NULL))) {
-        md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, ptemp, "start remove of md %s/%s/%s", 
+        md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "start remove of md %s/%s/%s", 
                       groupname, name, aspect);
 
         if (!MD_OK(apr_stat(&info, dir, APR_FINFO_TYPE, ptemp))) {
@@ -673,7 +666,6 @@ static apr_status_t pfs_purge(void *bato
     const char *dir, *name, *groupname;
     md_store_group_t group;
     apr_status_t rv;
-    MD_CHK_VARS;
     
     (void)p;
     group = (md_store_group_t)va_arg(ap, int);
@@ -685,7 +677,7 @@ static apr_status_t pfs_purge(void *bato
         /* Remove all files in dir, there should be no sub-dirs */
         rv = md_util_rm_recursive(dir, ptemp, 1);
     }
-    md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "purge %s/%s (%s)", groupname, name, dir);
+    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, ptemp, "purge %s/%s (%s)", groupname, name, dir);
     return APR_SUCCESS;
 }
 
@@ -706,6 +698,7 @@ typedef struct {
     const char *aspect;
     md_store_vtype_t vtype;
     md_store_inspect *inspect;
+    const char *dirname;
     void *baton;
 } inspect_ctx;
 
@@ -716,15 +709,38 @@ static apr_status_t insp(void *baton, ap
     apr_status_t rv;
     void *value;
     const char *fpath;
-    MD_CHK_VARS;
  
     (void)ftype;   
     md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting value at: %s/%s", dir, name);
-    if (   MD_OK(md_util_path_merge(&fpath, ptemp, dir, name, NULL)) 
-        && MD_OK(fs_fload(&value, ctx->s_fs, fpath, ctx->group, ctx->vtype, p, ptemp))
-        && !ctx->inspect(ctx->baton, name, ctx->aspect, ctx->vtype, value, ptemp)) {
-        return APR_EOF;
-    }
+    if (APR_SUCCESS == (rv = md_util_path_merge(&fpath, ptemp, dir, name, NULL))) {
+        rv = fs_fload(&value, ctx->s_fs, fpath, ctx->group, ctx->vtype, p, ptemp);
+        if (APR_SUCCESS == rv 
+            && !ctx->inspect(ctx->baton, ctx->dirname, name, ctx->vtype, value, p)) {
+            return APR_EOF;
+        }
+        else if (APR_STATUS_IS_ENOENT(rv)) {
+            rv = APR_SUCCESS;
+        }
+    } 
+    return rv;
+}
+
+static apr_status_t insp_dir(void *baton, apr_pool_t *p, apr_pool_t *ptemp, 
+                             const char *dir, const char *name, apr_filetype_e ftype)
+{
+    inspect_ctx *ctx = baton;
+    apr_status_t rv;
+    const char *fpath;
+ 
+    (void)ftype;
+    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting dir at: %s/%s", dir, name);
+    if (MD_OK(md_util_path_merge(&fpath, p, dir, name, NULL))) {
+        ctx->dirname = name;
+        rv = md_util_files_do(insp, ctx, p, fpath, ctx->aspect, NULL);
+        if (APR_STATUS_IS_ENOENT(rv)) {
+            rv = APR_SUCCESS;
+        }
+    } 
     return rv;
 }
 
@@ -745,7 +761,37 @@ static apr_status_t fs_iterate(md_store_
     ctx.baton = baton;
     groupname = md_store_group_name(group);
 
-    rv = md_util_files_do(insp, &ctx, p, ctx.s_fs->base, groupname, ctx.pattern, aspect, NULL);
+    rv = md_util_files_do(insp_dir, &ctx, p, ctx.s_fs->base, groupname, pattern, NULL);
+    
+    return rv;
+}
+
+static apr_status_t insp_name(void *baton, apr_pool_t *p, apr_pool_t *ptemp, 
+                              const char *dir, const char *name, apr_filetype_e ftype)
+{
+    inspect_ctx *ctx = baton;
+    
+    (void)ftype;
+    (void)p;
+    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, ptemp, "inspecting name at: %s/%s", dir, name);
+    return ctx->inspect(ctx->baton, dir, name, 0, NULL, ptemp);
+}
+
+static apr_status_t fs_iterate_names(md_store_inspect *inspect, void *baton, md_store_t *store, 
+                                     apr_pool_t *p, md_store_group_t group, const char *pattern)
+{
+    const char *groupname;
+    apr_status_t rv;
+    inspect_ctx ctx;
+    
+    ctx.s_fs = FS_STORE(store);
+    ctx.group = group;
+    ctx.pattern = pattern;
+    ctx.inspect = inspect;
+    ctx.baton = baton;
+    groupname = md_store_group_name(group);
+
+    rv = md_util_files_do(insp_name, &ctx, p, ctx.s_fs->base, groupname, pattern, NULL);
     
     return rv;
 }
@@ -760,7 +806,6 @@ static apr_status_t pfs_move(void *baton
     md_store_group_t from, to;
     int archive;
     apr_status_t rv;
-    MD_CHK_VARS;
     
     (void)p;
     from = (md_store_group_t)va_arg(ap, int);
@@ -802,7 +847,7 @@ static apr_status_t pfs_move(void *baton
             narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
             rv = md_util_is_dir(narch_dir, ptemp);
             if (APR_STATUS_IS_ENOENT(rv)) {
-                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "using archive dir: %s", 
+                md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, ptemp, "using archive dir: %s", 
                               narch_dir);
                 break;
             }
@@ -817,7 +862,7 @@ static apr_status_t pfs_move(void *baton
         while (n < 1000) {
             narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
             if (MD_OK(apr_dir_make(narch_dir, MD_FPROT_D_UONLY, ptemp))) {
-                md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "using archive dir: %s", 
+                md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, ptemp, "using archive dir: %s", 
                               narch_dir);
                 break;
             }

Added: httpd/httpd/trunk/modules/md/md_time.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_time.c?rev=1862013&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/md/md_time.c (added)
+++ httpd/httpd/trunk/modules/md/md_time.c Mon Jun 24 16:04:32 2019
@@ -0,0 +1,284 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include <stdio.h>
+
+#include <apr_lib.h>
+#include <apr_strings.h>
+#include <apr_time.h>
+
+#include "md.h"
+#include "md_time.h"
+
+apr_time_t md_timeperiod_length(const md_timeperiod_t *period)
+{
+    return (period->start < period->end)? (period->end - period->start) : 0;
+}
+
+int md_timeperiod_contains(const md_timeperiod_t *period, apr_time_t time)
+{
+    return md_timeperiod_has_started(period, time) 
+        && !md_timeperiod_has_ended(period, time);
+}
+
+int md_timeperiod_has_started(const md_timeperiod_t *period, apr_time_t time)
+{
+    return (time >= period->start);
+}
+
+int md_timeperiod_has_ended(const md_timeperiod_t *period, apr_time_t time)
+{
+    return (time >= period->start) && (time <= period->end);
+}
+
+char *md_timeperiod_print(apr_pool_t *p, const md_timeperiod_t *period)
+{
+    char tstart[APR_RFC822_DATE_LEN];
+    char tend[APR_RFC822_DATE_LEN];
+
+    apr_rfc822_date(tstart, period->start);
+    apr_rfc822_date(tend, period->end);
+    return apr_pstrcat(p, tstart, " - ", tend, NULL);
+}
+
+const char *md_duration_print(apr_pool_t *p, apr_interval_time_t duration)
+{
+    const char *s = "", *sep = "";
+    long days = (long)(apr_time_sec(duration) / MD_SECS_PER_DAY);
+    int rem = (int)(apr_time_sec(duration) % MD_SECS_PER_DAY);
+    
+    if (days > 0) {
+        s = apr_psprintf(p, "%ld days", days);
+        sep = " "; 
+    }
+    if (rem > 0) {
+        int hours = (rem / MD_SECS_PER_HOUR);
+        rem = (rem % MD_SECS_PER_HOUR);
+        if (hours > 0) {
+            s = apr_psprintf(p, "%s%s%02d hours", s, sep, hours); 
+            sep = " "; 
+        }
+        if (rem > 0) {
+            int minutes = (rem / 60);
+            rem = (rem % 60);
+            if (minutes > 0) {
+                s = apr_psprintf(p, "%s%s%02d minutes", s, sep, minutes); 
+            }
+            if (rem > 0) {
+                s = apr_psprintf(p, "%s%s%02d seconds", s, sep, rem); 
+            }
+        }
+    }
+    else if (days == 0) {
+        s = "0 seconds";
+        if (duration != 0) {
+            s = apr_psprintf(p, "%d ms", (int)apr_time_msec(duration));
+        }
+    }
+    return s;
+}
+
+static const char *duration_format(apr_pool_t *p, apr_interval_time_t duration)
+{
+    const char *s = "0";
+    int units = (int)(apr_time_sec(duration) / MD_SECS_PER_DAY);
+    int rem = (int)(apr_time_sec(duration) % MD_SECS_PER_DAY);
+    
+    if (rem == 0) {
+        s = apr_psprintf(p, "%dd", units); 
+    }
+    else {
+        units = (int)(apr_time_sec(duration) / MD_SECS_PER_HOUR);
+        rem = (int)(apr_time_sec(duration) % MD_SECS_PER_HOUR);
+        if (rem == 0) {
+            s = apr_psprintf(p, "%dh", units); 
+        }
+        else {
+            units = (int)(apr_time_sec(duration) / 60);
+            rem = (int)(apr_time_sec(duration) % 60);
+            if (rem == 0) {
+                s = apr_psprintf(p, "%dmi", units); 
+            }
+            else {
+                units = (int)(apr_time_sec(duration));
+                rem = (int)(apr_time_msec(duration) % 1000);
+                if (rem == 0) {
+                    s = apr_psprintf(p, "%ds", units); 
+                }
+                else {
+                    s = apr_psprintf(p, "%dms", (int)(apr_time_msec(duration))); 
+                }
+            }
+        }
+    }
+    return s;
+}
+
+apr_status_t md_duration_parse(apr_interval_time_t *ptimeout, const char *value, 
+                               const char *def_unit)
+{
+    char *endp;
+    apr_int64_t n;
+    
+    n = apr_strtoi64(value, &endp, 10);
+    if (errno) {
+        return errno;
+    }
+    if (!endp || !*endp) {
+        if (!def_unit) def_unit = "s";
+    }
+    else if (endp == value) {
+        return APR_EINVAL;
+    }
+    else {
+        def_unit = endp;
+    }
+    
+    switch (*def_unit) {
+    case 'D':
+    case 'd':
+        *ptimeout = apr_time_from_sec(n * MD_SECS_PER_DAY);
+        break;
+    case 's':
+    case 'S':
+        *ptimeout = (apr_interval_time_t) apr_time_from_sec(n);
+        break;
+    case 'h':
+    case 'H':
+        /* Time is in hours */
+        *ptimeout = (apr_interval_time_t) apr_time_from_sec(n * MD_SECS_PER_HOUR);
+        break;
+    case 'm':
+    case 'M':
+        switch (*(++def_unit)) {
+        /* Time is in milliseconds */
+        case 's':
+        case 'S':
+            *ptimeout = (apr_interval_time_t) n * 1000;
+            break;
+        /* Time is in minutes */
+        case 'i':
+        case 'I':
+            *ptimeout = (apr_interval_time_t) apr_time_from_sec(n * 60);
+            break;
+        default:
+            return APR_EGENERAL;
+        }
+        break;
+    default:
+        return APR_EGENERAL;
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t percentage_parse(const char *value, int *ppercent)
+{
+    char *endp;
+    apr_int64_t n;
+    
+    n = apr_strtoi64(value, &endp, 10);
+    if (errno) {
+        return errno;
+    }
+    if (*endp == '%') {
+        if (n < 0) {
+            return APR_BADARG;
+        }
+        *ppercent = (int)n;
+        return APR_SUCCESS;
+    }
+    return APR_EINVAL;
+}
+
+apr_status_t md_timeslice_create(const md_timeslice_t **pts, apr_pool_t *p,
+                                 apr_interval_time_t norm, apr_interval_time_t len)
+{
+    md_timeslice_t *ts;
+
+    ts = apr_pcalloc(p, sizeof(*ts));
+    ts->norm = norm;
+    ts->len = len;
+    *pts = ts;
+    return APR_SUCCESS;
+}
+
+const char *md_timeslice_parse(const md_timeslice_t **pts, apr_pool_t *p, 
+                               const char *val, apr_interval_time_t norm)
+{
+    md_timeslice_t *ts;
+    int percent;
+
+    *pts = NULL;
+    if (!val) {
+        return "cannot parse NULL value";
+    }
+
+    ts = apr_pcalloc(p, sizeof(*ts));
+    if (md_duration_parse(&ts->len, val, "d") == APR_SUCCESS) {
+        *pts = ts;
+        return NULL;
+    }
+    else {
+        switch (percentage_parse(val, &percent)) {
+            case APR_SUCCESS:
+                ts->norm = norm;
+                ts->len = apr_time_from_sec((apr_time_sec(norm) * percent / 100L));
+                *pts = ts;
+                return NULL;
+            case APR_BADARG:
+                return "percent must be less than 100";
+        }
+    }
+    return "has unrecognized format";
+}
+
+const char *md_timeslice_format(const md_timeslice_t *ts, apr_pool_t *p) {
+    if (ts->norm > 0) {
+        int percent = (int)(((long)apr_time_sec(ts->len)) * 100L 
+                            / ((long)apr_time_sec(ts->norm))); 
+        return apr_psprintf(p, "%d%%", percent);
+    }
+    return duration_format(p, ts->len);
+}
+
+md_timeperiod_t md_timeperiod_slice_before_end(const md_timeperiod_t *period, 
+                                               const md_timeslice_t *ts)
+{
+    md_timeperiod_t r;
+    apr_time_t duration = ts->len;
+    
+    if (ts->norm > 0) {
+        int percent = (int)(((long)apr_time_sec(ts->len)) * 100L 
+                            / ((long)apr_time_sec(ts->norm))); 
+        apr_time_t plen = md_timeperiod_length(period);
+        if (apr_time_sec(plen) > 100) {
+            duration = apr_time_from_sec(apr_time_sec(plen) * percent / 100);
+        }
+        else {
+            duration = plen * percent / 100;
+        }
+    }
+    r.start = period->end - duration;
+    r.end = period->end;
+    return r;
+}
+
+int md_timeslice_eq(const md_timeslice_t *ts1, const md_timeslice_t *ts2)
+{
+    if (ts1 == ts2) return 1;
+    if (!ts1 || !ts2) return 0;
+    return (ts1->norm == ts2->norm) && (ts1->len == ts2->len);
+}

Added: httpd/httpd/trunk/modules/md/md_time.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_time.h?rev=1862013&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/md/md_time.h (added)
+++ httpd/httpd/trunk/modules/md/md_time.h Mon Jun 24 16:04:32 2019
@@ -0,0 +1,67 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef mod_md_md_time_h
+#define mod_md_md_time_h
+
+#include <stdio.h>
+
+#define MD_SECS_PER_HOUR      (60*60)
+#define MD_SECS_PER_DAY       (24*MD_SECS_PER_HOUR)
+
+typedef struct {
+    apr_time_t start;
+    apr_time_t end;
+} md_timeperiod_t;
+
+apr_time_t md_timeperiod_length(const md_timeperiod_t *period);
+
+int md_timeperiod_contains(const md_timeperiod_t *period, apr_time_t time);
+int md_timeperiod_has_started(const md_timeperiod_t *period, apr_time_t time);
+int md_timeperiod_has_ended(const md_timeperiod_t *period, apr_time_t time);
+
+char *md_timeperiod_print(apr_pool_t *p, const md_timeperiod_t *period);
+
+/**
+ * Print a human readable form of the give duration in days/hours/min/sec 
+ */
+const char *md_duration_print(apr_pool_t *p, apr_interval_time_t duration);
+
+/**
+ * Parse a machine readable string duration in the form of NN[unit], where
+ * unit is d/h/mi/s/ms with the default given should the unit not be specified.
+ */
+apr_status_t md_duration_parse(apr_interval_time_t *ptimeout, const char *value, 
+                               const char *def_unit);
+
+typedef struct {
+    apr_interval_time_t norm; /* if > 0, normalized base length */
+    apr_interval_time_t len;  /* length of the timespan */
+} md_timeslice_t;
+
+apr_status_t md_timeslice_create(const md_timeslice_t **pts, apr_pool_t *p,
+                                 apr_interval_time_t norm, apr_interval_time_t len); 
+
+int md_timeslice_eq(const md_timeslice_t *ts1, const md_timeslice_t *ts2);
+
+const char *md_timeslice_parse(const md_timeslice_t **pts, apr_pool_t *p, 
+                              const char *val, apr_interval_time_t defnorm);
+const char *md_timeslice_format(const md_timeslice_t *ts, apr_pool_t *p);
+
+md_timeperiod_t md_timeperiod_slice_before_end(const md_timeperiod_t *period, 
+                                               const md_timeslice_t *ts);
+
+#endif /* md_util_h */

Modified: httpd/httpd/trunk/modules/md/md_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_util.c?rev=1862013&r1=1862012&r2=1862013&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_util.c (original)
+++ httpd/httpd/trunk/modules/md/md_util.c Mon Jun 24 16:04:32 2019
@@ -24,6 +24,7 @@
 #include <apr_tables.h>
 #include <apr_uri.h>
 
+#include "md.h"
 #include "md_log.h"
 #include "md_util.h"
 
@@ -67,8 +68,67 @@ apr_status_t md_util_pool_vdo(md_util_va
 }
  
 /**************************************************************************************************/
+/* data chunks */
+
+md_data *md_data_create(apr_pool_t *p, const char *data, apr_size_t len)
+{
+    md_data *d;
+    
+    d = apr_palloc(p, sizeof(*d));
+    d->len = len;
+    d->data = len? apr_pstrndup(p, data, len) : NULL;
+    return d;
+}
+
+static const char * const hex_const[] = {
+    "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 
+    "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 
+    "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 
+    "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 
+    "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 
+    "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 
+    "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 
+    "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 
+    "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 
+    "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 
+    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 
+    "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 
+    "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 
+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 
+    "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 
+    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", 
+};
+
+apr_status_t md_data_to_hex(const char **phex, char separator,
+                            apr_pool_t *p, const md_data *data)
+{
+    char *hex, *cp;
+    const char * x;
+    unsigned int i;
+    
+    cp = hex = apr_pcalloc(p, ((separator? 3 : 2) * data->len) + 1);
+    if (!hex) {
+        *phex = NULL;
+        return APR_ENOMEM;
+    }
+    for (i = 0; i < data->len; ++i) {
+        x = hex_const[(unsigned char)data->data[i]];
+        if (i && separator) *cp++ = separator;
+        *cp++ = x[0];
+        *cp++ = x[1];
+    }
+    *phex = hex;
+    return APR_SUCCESS;
+}
+
+/**************************************************************************************************/
 /* string related */
 
+int md_array_is_empty(const struct apr_array_header_t *array)
+{
+    return (array == NULL) || (array->nelts == 0);
+}
+
 char *md_util_str_tolower(char *s)
 {
     char *orig = s;
@@ -230,6 +290,11 @@ apr_status_t md_util_is_file(const char
     return rv;
 }
 
+int md_file_exists(const char *fname, apr_pool_t *p)
+{
+    return (fname && *fname && APR_SUCCESS == md_util_is_file(fname, p));
+}
+
 apr_status_t md_util_path_merge(const char **ppath, apr_pool_t *p, ...)
 {
     const char *segment, *path;
@@ -324,6 +389,13 @@ apr_status_t md_text_fcreatex(const char
     if (APR_SUCCESS == rv) {
         rv = write_text((void*)text, f, p);
         apr_file_close(f);
+        /* See <https://github.com/icing/mod_md/issues/117>: when a umask
+         * is set, files need to be assigned permissions explicitly.
+         * Otherwise, as in the issues reported, it will break our access model. */
+        rv = apr_file_perms_set(fpath, perms);
+        if (APR_STATUS_IS_ENOTIMPL(rv)) {
+            rv = APR_SUCCESS;
+        }
     }
     return rv;
 }
@@ -413,17 +485,25 @@ static apr_status_t match_and_do(md_util
     }
     pattern = APR_ARRAY_IDX(ctx->patterns, depth, const char *);
     
+    md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
+                  "path=%s depth=%d pattern=%s", path, depth, pattern);
     rv = apr_dir_open(&d, path, ptemp);
     if (APR_SUCCESS != rv) {
         return rv;
     }
     
     while (APR_SUCCESS == (rv = apr_dir_read(&finfo, wanted, d))) {
+        md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
+                      "candidate=%s", finfo.name);
         if (!strcmp(".", finfo.name) || !strcmp("..", finfo.name)) {
             continue;
         } 
         if (APR_SUCCESS == apr_fnmatch(pattern, finfo.name, 0)) {
+            md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
+                          "candidate=%s matches pattern", finfo.name);
             if (ndepth < ctx->patterns->nelts) {
+                md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
+                              "need to go deepter");
                 if (APR_DIR == finfo.filetype) { 
                     /* deeper and deeper, irgendwo in der tiefe leuchtet ein licht */
                     rv = md_util_path_merge(&npath, ptemp, path, finfo.name, NULL);
@@ -433,6 +513,8 @@ static apr_status_t match_and_do(md_util
                 }
             }
             else {
+                md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, ptemp, "match_and_do "
+                              "invoking inspector on name=%s", finfo.name);
                 rv = ctx->cb(ctx->baton, p, ptemp, path, finfo.name, finfo.filetype);
             }
         }
@@ -608,7 +690,7 @@ apr_status_t md_util_ftree_remove(const
 
 /* DNS name checks ********************************************************************************/
 
-int md_util_is_dns_name(apr_pool_t *p, const char *hostname, int need_fqdn)
+int md_dns_is_name(apr_pool_t *p, const char *hostname, int need_fqdn)
 {
     char c, last = 0;
     const char *cp = hostname;
@@ -649,6 +731,73 @@ int md_util_is_dns_name(apr_pool_t *p, c
     return 1; /* empty string not allowed */
 }
 
+int md_dns_is_wildcard(apr_pool_t *p, const char *domain)
+{
+    if (domain[0] != '*' || domain[1] != '.') return 0;
+    return md_dns_is_name(p, domain+2, 1);
+}
+
+int md_dns_matches(const char *pattern, const char *domain)
+{
+    const char *s;
+    
+    if (!apr_strnatcasecmp(pattern, domain)) return 1;
+    if (pattern[0] == '*' && pattern[1] == '.') {
+        s = strchr(domain, '.');
+        if (s && !apr_strnatcasecmp(pattern+1, s)) return 1;
+    }
+    return 0;
+}
+
+apr_array_header_t *md_dns_make_minimal(apr_pool_t *p, apr_array_header_t *domains)
+{
+    apr_array_header_t *minimal;
+    const char *domain, *pattern;
+    int i, j, duplicate;
+    
+    minimal = apr_array_make(p, domains->nelts, sizeof(const char *));
+    for (i = 0; i < domains->nelts; ++i) {
+        domain = APR_ARRAY_IDX(domains, i, const char*);
+        duplicate = 0;
+        /* is it matched in minimal already? */
+        for (j = 0; j < minimal->nelts; ++j) {
+            pattern = APR_ARRAY_IDX(minimal, j, const char*);
+            if (md_dns_matches(pattern, domain)) {
+                duplicate = 1;
+                break;
+            }
+        }
+        if (!duplicate) {
+            if (!md_dns_is_wildcard(p, domain)) {
+                /* plain name, will we see a wildcard that replaces it? */
+                for (j = i+1; j < domains->nelts; ++j) {
+                    pattern = APR_ARRAY_IDX(domains, j, const char*);
+                    if (md_dns_is_wildcard(p, pattern) && md_dns_matches(pattern, domain)) {
+                        duplicate = 1;
+                        break;
+                    }
+                }
+            }
+            if (!duplicate) {
+                APR_ARRAY_PUSH(minimal, const char *) = domain; 
+            }
+        }
+    }
+    return minimal;
+}
+
+int md_dns_domains_match(const apr_array_header_t *domains, const char *name)
+{
+    const char *domain;
+    int i;
+    
+    for (i = 0; i < domains->nelts; ++i) {
+        domain = APR_ARRAY_IDX(domains, i, const char*);
+        if (md_dns_matches(domain, name)) return 1;
+    }
+    return 0;
+}
+
 const char *md_util_schemify(apr_pool_t *p, const char *s, const char *def_scheme)
 {
     const char *cp = s;
@@ -682,7 +831,7 @@ static apr_status_t uri_check(apr_uri_t
             if (!uri_parsed->hostname) {
                 err = "missing hostname";
             }
-            else if (!md_util_is_dns_name(p, uri_parsed->hostname, 0)) {
+            else if (!md_dns_is_name(p, uri_parsed->hostname, 0)) {
                 err = "invalid hostname";
             }
             if (uri_parsed->port_str 
@@ -808,38 +957,37 @@ apr_status_t md_util_exec(apr_pool_t *p,
     apr_procattr_t *procattr;
     apr_proc_t *proc;
     apr_exit_why_e ewhy;
-
+    char buffer[1024];
+    
     *exit_code = 0;
     if (!(proc = apr_pcalloc(p, sizeof(*proc)))) {
         return APR_ENOMEM;
     }
     if (   APR_SUCCESS == (rv = apr_procattr_create(&procattr, p))
         && APR_SUCCESS == (rv = apr_procattr_io_set(procattr, APR_NO_FILE, 
-                                                    APR_NO_PIPE, APR_NO_PIPE))
+                                                    APR_NO_PIPE, APR_FULL_BLOCK))
         && APR_SUCCESS == (rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM))
-        && APR_SUCCESS == (rv = apr_proc_create(proc, cmd, argv, NULL, procattr, p))
-        && APR_CHILD_DONE == (rv = apr_proc_wait(proc, exit_code, &ewhy, APR_WAIT))) {
-        /* let's not dwell on exit stati, but core should signal something's bad */
-        if (*exit_code > 127 || APR_PROC_SIGNAL_CORE == ewhy) {
-            return APR_EINCOMPLETE;
+        && APR_SUCCESS == (rv = apr_proc_create(proc, cmd, argv, NULL, procattr, p))) {
+        
+        /* read stderr and log on INFO for possible fault analysis. */
+        while(APR_SUCCESS == (rv = apr_file_gets(buffer, sizeof(buffer)-1, proc->err))) {
+            md_log_perror(MD_LOG_MARK, MD_LOG_INFO, 0, p, "cmd(%s) stderr: %s", cmd, buffer);
+        }
+        if (!APR_STATUS_IS_EOF(rv)) goto out;
+        apr_file_close(proc->err);
+        
+        if (APR_CHILD_DONE == (rv = apr_proc_wait(proc, exit_code, &ewhy, APR_WAIT))) {
+            /* let's not dwell on exit stati, but core should signal something's bad */
+            if (*exit_code > 127 || APR_PROC_SIGNAL_CORE == ewhy) {
+                return APR_EINCOMPLETE;
+            }
+            return APR_SUCCESS;
         }
-        return APR_SUCCESS;
     }
+out:
     return rv;
 }
 
-
-/* date/time encoding *****************************************************************************/
-
-const char *md_print_duration(apr_pool_t *p, apr_interval_time_t duration)
-{
-    int secs = (int)(apr_time_sec(duration) % MD_SECS_PER_DAY);
-    return apr_psprintf(p, "%2d:%02d:%02d hours", 
-                        (int)secs/MD_SECS_PER_HOUR, (int)(secs%(MD_SECS_PER_HOUR))/60,
-                        (int)(secs%60));
-}
-
-
 /* base64 url encoding ****************************************************************************/
 
 #define N6 (unsigned int)-1

Modified: httpd/httpd/trunk/modules/md/md_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_util.h?rev=1862013&r1=1862012&r2=1862013&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_util.h (original)
+++ httpd/httpd/trunk/modules/md/md_util.h Mon Jun 24 16:04:32 2019
@@ -33,9 +33,28 @@ apr_status_t md_util_pool_do(md_util_act
 apr_status_t md_util_pool_vdo(md_util_vaction *cb, void *baton, apr_pool_t *p, ...); 
 
 /**************************************************************************************************/
+/* data chunks */
+
+typedef struct md_data md_data;
+struct md_data {
+    const char *data;
+    apr_size_t len;
+};
+
+md_data *md_data_create(apr_pool_t *p, const char *data, apr_size_t len);
+
+apr_status_t md_data_to_hex(const char **phex, char separator,
+                            apr_pool_t *p, const md_data *data);
+
+/**************************************************************************************************/
 /* string related */
 char *md_util_str_tolower(char *s);
 
+/**
+ * Return != 0 iff array is either NULL or empty 
+ */ 
+int md_array_is_empty(const struct apr_array_header_t *array);
+
 int md_array_str_index(const struct apr_array_header_t *array, const char *s, 
                        int start, int case_sensitive);
 
@@ -44,9 +63,15 @@ int md_array_str_eq(const struct apr_arr
 
 struct apr_array_header_t *md_array_str_clone(apr_pool_t *p, struct apr_array_header_t *array);
 
+/**
+ * Create a new array with duplicates removed.
+ */
 struct apr_array_header_t *md_array_str_compact(apr_pool_t *p, struct apr_array_header_t *src,
                                                 int case_sensitive);
 
+/**
+ * Create a new array with all occurances of <exclude> removed.
+ */
 struct apr_array_header_t *md_array_str_remove(apr_pool_t *p, struct apr_array_header_t *src, 
                                                const char *exclude, int case_sensitive);
 
@@ -61,7 +86,41 @@ apr_status_t md_util_exec(apr_pool_t *p,
 /**************************************************************************************************/
 /* dns name check */
 
-int md_util_is_dns_name(apr_pool_t *p, const char *hostname, int need_fqdn);
+/**
+ * Is a host/domain name using allowed characters. Not a wildcard.
+ * @param domain     name to check
+ * @param need_fqdn  iff != 0, check that domain contains '.'
+ * @return != 0 iff domain looks like  a non-wildcard, legal DNS domain name.
+ */
+int md_dns_is_name(apr_pool_t *p, const char *domain, int need_fqdn);
+
+/**
+ * Check if the given domain is a valid wildcard DNS name, e.g. *.example.org
+ * @param domain    name to check
+ * @return != 0 iff domain is a DNS wildcard.
+ */
+int md_dns_is_wildcard(apr_pool_t *p, const char *domain);
+
+/**
+ * Determine iff pattern matches domain, including case-ignore and wildcard domains.
+ * It is assumed that both names follow dns syntax.
+ * @return != 0 iff pattern matches domain
+ */ 
+int md_dns_matches(const char *pattern, const char *domain);
+
+/**
+ * Create a new array with the minimal set out of the given domain names that match all
+ * of them. If none of the domains is a wildcard, only duplicates are removed.
+ * If domains contain a wildcard, any name matching the wildcard will be removed.
+ */
+struct apr_array_header_t *md_dns_make_minimal(apr_pool_t *p, 
+                                               struct apr_array_header_t *domains);
+
+/**
+ * Determine if the given domains cover the name, including wildcard matching.
+ * @return != 0 iff name is matched by list of domains
+ */
+int md_dns_domains_match(const apr_array_header_t *domains, const char *name);
 
 /**************************************************************************************************/
 /* file system related */
@@ -78,6 +137,7 @@ apr_status_t md_util_path_merge(const ch
 
 apr_status_t md_util_is_dir(const char *path, apr_pool_t *pool);
 apr_status_t md_util_is_file(const char *path, apr_pool_t *pool);
+int md_file_exists(const char *fname, apr_pool_t *p);
 
 typedef apr_status_t md_util_file_cb(void *baton, struct apr_file_t *f, apr_pool_t *p);
 
@@ -137,12 +197,4 @@ apr_status_t md_util_try(md_util_try_fn
                          apr_interval_time_t timeout, apr_interval_time_t start_delay, 
                          apr_interval_time_t max_delay, int backoff);
 
-/**************************************************************************************************/
-/* date/time related */
-
-#define MD_SECS_PER_HOUR      (60*60)
-#define MD_SECS_PER_DAY       (24*MD_SECS_PER_HOUR)
-
-const char *md_print_duration(apr_pool_t *p, apr_interval_time_t duration);
-
 #endif /* md_util_h */

Modified: httpd/httpd/trunk/modules/md/md_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_version.h?rev=1862013&r1=1862012&r2=1862013&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_version.h (original)
+++ httpd/httpd/trunk/modules/md/md_version.h Mon Jun 24 16:04:32 2019
@@ -27,7 +27,7 @@
  * @macro
  * Version number of the md module as c string
  */
-#define MOD_MD_VERSION "1.1.19-DEV"
+#define MOD_MD_VERSION "2.0.6"
 
 /**
  * @macro
@@ -35,8 +35,8 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define MOD_MD_VERSION_NUM 0x010113
+#define MOD_MD_VERSION_NUM 0x020006
 
-#define MD_ACME_DEF_URL    "https://acme-v01.api.letsencrypt.org/directory"
+#define MD_ACME_DEF_URL    "https://acme-v02.api.letsencrypt.org/directory"
 
 #endif /* mod_md_md_version_h */