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 2017/09/01 12:11:39 UTC
svn commit: r1806939 [2/2] - in /httpd/httpd/trunk: ./ docs/manual/mod/
modules/md/ modules/ssl/
Modified: httpd/httpd/trunk/modules/md/mod_md.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md.c Fri Sep 1 12:11:38 2017
@@ -78,6 +78,9 @@ static void md_merge_srv(md_t *md, md_sr
if (md->drive_mode == MD_DRIVE_DEFAULT) {
md->drive_mode = md_config_geti(md->sc, MD_CONFIG_DRIVE_MODE);
}
+ if (md->renew_norm <= 0) {
+ md->renew_norm = md_config_get_interval(md->sc, MD_CONFIG_RENEW_NORM);
+ }
if (md->renew_window <= 0) {
md->renew_window = md_config_get_interval(md->sc, MD_CONFIG_RENEW_WINDOW);
}
@@ -87,6 +90,10 @@ static void md_merge_srv(md_t *md, md_sr
if (!md->ca_challenges && md->sc->ca_challenges) {
md->ca_challenges = apr_array_copy(p, md->sc->ca_challenges);
}
+ if (!md->pkey_spec) {
+ md->pkey_spec = md->sc->pkey_spec;
+
+ }
}
static apr_status_t check_coverage(md_t *md, const char *domain, server_rec *s, apr_pool_t *p)
@@ -460,6 +467,9 @@ static apr_status_t drive_md(md_watchdog
int errored, renew;
char ts[APR_RFC822_DATE_LEN];
+ if (md->state == MD_S_MISSING) {
+ rv = APR_INCOMPLETE;
+ }
if (md->state == MD_S_COMPLETE && !md->expires) {
/* This is our indicator that we did already renewed this managed domain
* successfully and only wait on the next restart for it to activate */
@@ -508,7 +518,7 @@ static apr_status_t run_watchdog(int sta
md_watchdog *wd = baton;
apr_status_t rv = APR_SUCCESS;
md_t *md;
- apr_interval_time_t interval, now;
+ apr_time_t next_run, now;
int i;
switch (state) {
@@ -519,9 +529,6 @@ static apr_status_t run_watchdog(int sta
case AP_WATCHDOG_STATE_RUNNING:
assert(wd->reg);
- /* normally, we'd like to run at least twice a day */
- interval = apr_time_from_sec(MD_SECS_PER_DAY / 2);
-
wd->all_valid = 1;
wd->valid_not_before = 0;
wd->processed_count = 0;
@@ -536,7 +543,13 @@ static apr_status_t run_watchdog(int sta
for (i = 0; i < wd->mds->nelts; ++i) {
md = APR_ARRAY_IDX(wd->mds, i, md_t *);
- if (APR_SUCCESS != (rv = drive_md(wd, md, ptemp))) {
+ rv = drive_md(wd, md, ptemp);
+
+ if (APR_STATUS_IS_INCOMPLETE(rv)) {
+ /* configuration not complete, this MD cannot be driven further */
+ wd->all_valid = 0;
+ }
+ else if (APR_SUCCESS != rv) {
wd->all_valid = 0;
++wd->error_count;
ap_log_error( APLOG_MARK, APLOG_ERR, rv, wd->s, APLOGNO(10056)
@@ -546,50 +559,57 @@ static apr_status_t run_watchdog(int sta
/* Determine when we want to run next */
wd->error_runs = wd->error_count? (wd->error_runs + 1) : 0;
+
if (wd->all_valid) {
- now = apr_time_now();
- if (wd->next_valid > now && (wd->next_valid - now < interval)) {
- interval = wd->next_valid - now;
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, wd->s,
- "Delaying activation of %d Managed Domain%s by %s",
- wd->processed_count, (wd->processed_count > 1)? "s have" : " has",
- md_print_duration(ptemp, interval));
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, wd->s,
- "all managed domains are valid");
- }
+ ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, wd->s, "all managed domains are valid");
}
- else {
- /* back off duration, depending on the errors we encounter in a row */
- interval = apr_time_from_sec(5 << (wd->error_runs - 1));
- if (interval > apr_time_from_sec(60*60)) {
- interval = apr_time_from_sec(60*60);
- }
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, wd->s, APLOGNO(10057)
- "encountered errors for the %d. time, next run in %d seconds",
- wd->error_runs, (int)apr_time_sec(interval));
+ else if (wd->error_count == 0) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, wd->s, APLOGNO()
+ "all managed domains driven as far as possible");
+ }
+
+ now = apr_time_now();
+ /* normally, we'd like to run at least twice a day */
+ next_run = now + apr_time_from_sec(MD_SECS_PER_DAY / 2);
+
+ /* Unless we know of an MD change before that */
+ if (wd->next_change > 0 && wd->next_change < next_run) {
+ next_run = wd->next_change;
}
- /* We follow the chosen min_interval for re-evaluation, unless we
- * know of a change (renewal) that happens before that. */
- if (wd->next_change) {
- apr_interval_time_t until_next = wd->next_change - apr_time_now();
- if (until_next < interval) {
- interval = until_next;
+ /* Or have to activate a new cert even before that */
+ if (wd->next_valid > now && wd->next_valid < next_run) {
+ next_run = wd->next_valid;
+ ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, wd->s,
+ "Delaying activation of %d Managed Domain%s by %s",
+ wd->processed_count, (wd->processed_count > 1)? "s have" : " has",
+ md_print_duration(ptemp, next_run - now));
+ }
+
+ /* Or encountered errors and like to retry even before that */
+ if (wd->error_count > 0) {
+ apr_interval_time_t delay;
+
+ /* back off duration, depending on the errors we encounter in a row */
+ delay = apr_time_from_sec(5 << (wd->error_runs - 1));
+ if (delay > apr_time_from_sec(60*60)) {
+ delay = apr_time_from_sec(60*60);
+ }
+ if (now + delay < next_run) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, wd->s, APLOGNO(10057)
+ "encountered errors for the %d. time, next try by %s",
+ wd->error_runs, md_print_duration(ptemp, delay));
+ next_run = now + delay;
}
}
- /* Set when we'd like to be run next time.
- * TODO: it seems that this is really only ticking down when the server
- * runs. When you wake up a hibernated machine, the watchdog will not run right away
- */
if (APLOGdebug(wd->s)) {
- ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, wd->s, "next run in %s",
- md_print_duration(ptemp, interval));
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd->s, APLOGNO()
+ "next run in %s", md_print_duration(ptemp, next_run - now));
}
- wd_set_interval(wd->watchdog, interval, wd, run_watchdog);
+ wd_set_interval(wd->watchdog, next_run - now, wd, run_watchdog);
break;
+
case AP_WATCHDOG_STATE_STOPPING:
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wd->s, APLOGNO(10058)
"md watchdog stopping");
@@ -684,7 +704,7 @@ static apr_status_t start_watchdog(apr_a
if (!wd->mds->nelts) {
ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(10065)
"no managed domain in state to drive, no watchdog needed, "
- "will check again on next server restart");
+ "will check again on next server (graceful) restart");
apr_pool_destroy(wd->p);
return APR_SUCCESS;
}
Modified: httpd/httpd/trunk/modules/md/mod_md_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_config.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md_config.c Fri Sep 1 12:11:38 2017
@@ -25,6 +25,7 @@
#include <http_vhost.h>
#include "md.h"
+#include "md_crypt.h"
#include "md_util.h"
#include "mod_md_private.h"
#include "mod_md_config.h"
@@ -39,6 +40,7 @@
#define MD_CMD_MEMBER "MDMember"
#define MD_CMD_MEMBERS "MDMembers"
#define MD_CMD_PORTMAP "MDPortMap"
+#define MD_CMD_PKEYS "MDPrivateKeys"
#define MD_CMD_RENEWWINDOW "MDRenewWindow"
#define MD_CMD_STOREDIR "MDStoreDir"
@@ -65,8 +67,9 @@ static md_srv_conf_t defconf = {
1,
MD_DRIVE_AUTO,
0,
- apr_time_from_sec(14 * MD_SECS_PER_DAY),
-
+ NULL,
+ apr_time_from_sec(90 * MD_SECS_PER_DAY), /* If the cert lifetime were 90 days, renew */
+ apr_time_from_sec(30 * MD_SECS_PER_DAY), /* 30 days before. Adjust to actual lifetime */
MD_ACME_DEF_URL,
"ACME",
NULL,
@@ -109,6 +112,8 @@ static void srv_conf_props_clear(md_srv_
sc->transitive = DEF_VAL;
sc->drive_mode = DEF_VAL;
sc->must_staple = DEF_VAL;
+ sc->pkey_spec = NULL;
+ sc->renew_norm = DEF_VAL;
sc->renew_window = DEF_VAL;
sc->ca_url = NULL;
sc->ca_proto = NULL;
@@ -121,6 +126,8 @@ static void srv_conf_props_copy(md_srv_c
to->transitive = from->transitive;
to->drive_mode = from->drive_mode;
to->must_staple = from->must_staple;
+ to->pkey_spec = from->pkey_spec;
+ to->renew_norm = from->renew_norm;
to->renew_window = from->renew_window;
to->ca_url = from->ca_url;
to->ca_proto = from->ca_proto;
@@ -133,6 +140,8 @@ static void srv_conf_props_apply(md_t *m
if (from->transitive != DEF_VAL) md->transitive = from->transitive;
if (from->drive_mode != DEF_VAL) md->drive_mode = from->drive_mode;
if (from->must_staple != DEF_VAL) md->must_staple = from->must_staple;
+ if (from->pkey_spec) md->pkey_spec = from->pkey_spec;
+ if (from->renew_norm != DEF_VAL) md->renew_norm = from->renew_norm;
if (from->renew_window != DEF_VAL) md->renew_window = from->renew_window;
if (from->ca_url) md->ca_url = from->ca_url;
@@ -166,6 +175,9 @@ static void *md_config_merge(apr_pool_t
nsc->transitive = (add->transitive != DEF_VAL)? add->transitive : base->transitive;
nsc->drive_mode = (add->drive_mode != DEF_VAL)? add->drive_mode : base->drive_mode;
+ nsc->must_staple = (add->must_staple != DEF_VAL)? add->must_staple : base->must_staple;
+ nsc->pkey_spec = add->pkey_spec? add->pkey_spec : base->pkey_spec;
+ nsc->renew_window = (add->renew_norm != DEF_VAL)? add->renew_norm : base->renew_norm;
nsc->renew_window = (add->renew_window != DEF_VAL)? add->renew_window : base->renew_window;
nsc->ca_url = add->ca_url? add->ca_url : base->ca_url;
@@ -242,7 +254,7 @@ static const char *md_config_sec_start(c
return MD_CMD_MD_SECTION "> directive missing closing '>'";
}
- arg = apr_pstrndup(cmd->pool, arg, endp-arg);
+ arg = apr_pstrndup(cmd->pool, arg, (apr_size_t)(endp-arg));
if (!arg || !*arg) {
return MD_CMD_MD_SECTION " > section must specify a unique domain name";
}
@@ -444,23 +456,54 @@ static apr_status_t duration_parse(const
return rv;
}
+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 || n >= 100) {
+ return APR_BADARG;
+ }
+ *ppercent = (int)n;
+ return APR_SUCCESS;
+ }
+ return APR_EINVAL;
+}
+
static const char *md_config_set_renew_window(cmd_parms *cmd, void *dc, const char *value)
{
md_srv_conf_t *config = md_config_get(cmd->server);
const char *err;
apr_interval_time_t timeout;
-
- /* Inspired by http_core.c */
- if (duration_parse(value, &timeout, "d") != APR_SUCCESS) {
- return "MDRenewWindow has wrong format";
- }
-
+ int percent;
+
if (!inside_section(cmd, MD_CMD_MD_SECTION)
&& (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
return err;
}
- config->renew_window = timeout;
- return NULL;
+
+ /* Inspired by http_core.c */
+ if (duration_parse(value, &timeout, "d") == APR_SUCCESS) {
+ config->renew_norm = 0;
+ config->renew_window = timeout;
+ return NULL;
+ }
+ else {
+ switch (percentage_parse(value, &percent)) {
+ case APR_SUCCESS:
+ config->renew_norm = 100;
+ config->renew_window = percent;
+ return NULL;
+ case APR_BADARG:
+ return "MDRenewWindow as percent must be less than 100";
+ }
+ }
+ return "MDRenewWindow has unrecognized format";
}
static const char *md_config_set_store_dir(cmd_parms *cmd, void *arg, const char *value)
@@ -555,6 +598,57 @@ static const char *md_config_set_cha_tye
return NULL;
}
+static const char *md_config_set_pkeys(cmd_parms *cmd, void *arg,
+ int argc, char *const argv[])
+{
+ md_srv_conf_t *config = md_config_get(cmd->server);
+ const char *err, *ptype;
+ apr_int64_t bits;
+
+ if (!inside_section(cmd, MD_CMD_MD_SECTION)
+ && (err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+ return err;
+ }
+ if (argc <= 0) {
+ return "needs to specify the private key type";
+ }
+
+ ptype = argv[0];
+ if (!apr_strnatcasecmp("Default", ptype)) {
+ if (argc > 1) {
+ return "type 'Default' takes no parameter";
+ }
+ if (!config->pkey_spec) {
+ config->pkey_spec = apr_pcalloc(cmd->pool, sizeof(*config->pkey_spec));
+ }
+ config->pkey_spec->type = MD_PKEY_TYPE_DEFAULT;
+ return NULL;
+ }
+ else if (!apr_strnatcasecmp("RSA", ptype)) {
+ if (argc == 1) {
+ bits = MD_PKEY_RSA_BITS_DEF;
+ }
+ else if (argc == 2) {
+ bits = (int)apr_atoi64(argv[1]);
+ if (bits < 2048 || bits >= INT_MAX) {
+ return "must be a 2048 or higher in order to be considered safe. "
+ "Too large a value will slow down everything. Larger then 4096 probably does "
+ "not make sense unless quantum cryptography really changes spin.";
+ }
+ }
+ else {
+ return "key type 'RSA' has only one optinal parameter, the number of bits";
+ }
+
+ if (!config->pkey_spec) {
+ config->pkey_spec = apr_pcalloc(cmd->pool, sizeof(*config->pkey_spec));
+ }
+ config->pkey_spec->type = MD_PKEY_TYPE_RSA;
+ config->pkey_spec->params.rsa.bits = (unsigned int)bits;
+ return NULL;
+ }
+ return apr_pstrcat(cmd->pool, "unsupported private key type \"", ptype, "\"", NULL);
+}
const command_rec md_cmds[] = {
AP_INIT_TAKE1( MD_CMD_CA, md_config_set_ca, NULL, RSRC_CONF,
@@ -582,6 +676,8 @@ const command_rec md_cmds[] = {
"to indicate that the server port 8000 is reachable as port 80 from the "
"internet. Use 80:- to indicate that port 80 is not reachable from "
"the outside."),
+ AP_INIT_TAKE_ARGV( MD_CMD_PKEYS, md_config_set_pkeys, NULL, RSRC_CONF,
+ "set the type and parameters for private key generation"),
AP_INIT_TAKE1( MD_CMD_STOREDIR, md_config_set_store_dir, NULL, RSRC_CONF,
"the directory for file system storage of managed domain data."),
AP_INIT_TAKE1( MD_CMD_RENEWWINDOW, md_config_set_renew_window, NULL, RSRC_CONF,
@@ -654,6 +750,8 @@ int md_config_geti(const md_srv_conf_t *
apr_interval_time_t md_config_get_interval(const md_srv_conf_t *sc, md_config_var_t var)
{
switch (var) {
+ case MD_CONFIG_RENEW_NORM:
+ return (sc->renew_norm != DEF_VAL)? sc->renew_norm : defconf.renew_norm;
case MD_CONFIG_RENEW_WINDOW:
return (sc->renew_window != DEF_VAL)? sc->renew_window : defconf.renew_window;
default:
Modified: httpd/httpd/trunk/modules/md/mod_md_config.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_config.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.h (original)
+++ httpd/httpd/trunk/modules/md/mod_md_config.h Fri Sep 1 12:11:38 2017
@@ -17,6 +17,7 @@
#define mod_md_md_config_h
struct md_store_t;
+struct md_pkey_spec_t;
typedef enum {
MD_CONFIG_CA_URL,
@@ -26,6 +27,7 @@ typedef enum {
MD_CONFIG_DRIVE_MODE,
MD_CONFIG_LOCAL_80,
MD_CONFIG_LOCAL_443,
+ MD_CONFIG_RENEW_NORM,
MD_CONFIG_RENEW_WINDOW,
MD_CONFIG_TRANSITIVE,
} md_config_var_t;
@@ -51,6 +53,10 @@ typedef struct md_srv_conf_t {
int transitive; /* != 0 iff VirtualHost names/aliases are auto-added */
int drive_mode; /* mode of obtaining credentials */
int must_staple; /* certificates should set the OCSP Must Staple extension */
+ struct md_pkey_spec_t *pkey_spec; /* specification for generating private keys */
+ apr_interval_time_t renew_norm; /* If > 0, use as normalizing value for cert lifetime
+ * Example: renew_norm=90d renew_win=30d, cert lives
+ * for 12 days => renewal 4 days before */
apr_interval_time_t renew_window; /* time before expiration that starts renewal */
const char *ca_url; /* url of CA certificate service */
Modified: httpd/httpd/trunk/modules/md/mod_md_os.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_os.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_os.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md_os.c Fri Sep 1 12:11:38 2017
@@ -34,7 +34,7 @@
#include "md_util.h"
#include "mod_md_os.h"
-apr_status_t md_try_chown(const char *fname, int uid, int gid, apr_pool_t *p)
+apr_status_t md_try_chown(const char *fname, unsigned int uid, int gid, apr_pool_t *p)
{
#if AP_NEED_SET_MUTEX_PERMS
if (-1 == chown(fname, (uid_t)uid, (gid_t)gid)) {
Modified: httpd/httpd/trunk/modules/md/mod_md_os.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_os.h?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_os.h (original)
+++ httpd/httpd/trunk/modules/md/mod_md_os.h Fri Sep 1 12:11:38 2017
@@ -20,7 +20,7 @@
* Try chown'ing the file/directory. Give id -1 to not change uid/gid.
* Will return APR_ENOTIMPL on platforms not supporting this operation.
*/
-apr_status_t md_try_chown(const char *fname, int uid, int gid, apr_pool_t *p);
+apr_status_t md_try_chown(const char *fname, unsigned int uid, int gid, apr_pool_t *p);
/**
* Make a file or directory read/write(/searchable) by httpd workers.
Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_init.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_init.c?rev=1806939&r1=1806938&r2=1806939&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_engine_init.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_engine_init.c Fri Sep 1 12:11:38 2017
@@ -1723,8 +1723,9 @@ static apr_status_t ssl_init_server_ctx(
else if (APR_STATUS_IS_EAGAIN(rv)) {
/* Managed Domain not ready yet. This is not a reason to fail the config */
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085)
- "Init: (%s) disabling this host for now as certificate/key data "
- "for the Managed Domain is incomplete.", ssl_util_vhostid(p, s));
+ "Init: %s will respond with '503 Service Unavailable' for now. This "
+ "host is part of a Managed Domain, but no SSL certificate is "
+ "available (yet).", ssl_util_vhostid(p, s));
pks->service_unavailable = 1;
return APR_SUCCESS;
}