summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2014-03-29 21:56:19 +0100
committerStefan Fritsch <sf@sfritsch.de>2014-03-29 21:56:45 +0100
commit2a463b3cd73c32ee9dcd508248d0194923f435f4 (patch)
tree2ff478255a77a55031056790918b6f983bb7b20a /modules
parent86d5cc79d9d6750da8771fdb0c9ab22c19b8ad45 (diff)
downloadapache2-2a463b3cd73c32ee9dcd508248d0194923f435f4.tar.gz
Imported Upstream version 2.4.9upstream/2.4.9
Diffstat (limited to 'modules')
-rw-r--r--modules/aaa/mod_auth_form.c2
-rw-r--r--modules/aaa/mod_authn_core.c8
-rw-r--r--modules/aaa/mod_authnz_ldap.c103
-rw-r--r--modules/aaa/mod_authz_core.c2
-rw-r--r--modules/aaa/mod_authz_dbd.c36
-rw-r--r--modules/aaa/mod_authz_dbm.c40
-rw-r--r--modules/aaa/mod_authz_groupfile.c36
-rw-r--r--modules/aaa/mod_authz_host.c35
-rw-r--r--modules/aaa/mod_authz_user.c35
-rw-r--r--modules/arch/win32/mod_isapi.c2
-rw-r--r--modules/cache/cache_storage.c2
-rw-r--r--modules/cache/mod_cache.c1
-rw-r--r--modules/cache/mod_cache_disk.c7
-rw-r--r--modules/cache/mod_socache_shmcb.c9
-rw-r--r--modules/cluster/mod_heartmonitor.c2
-rw-r--r--modules/core/mod_macro.c4
-rw-r--r--modules/core/mod_watchdog.c2
-rw-r--r--modules/dav/fs/lock.c1
-rw-r--r--modules/dav/lock/locks.c1
-rw-r--r--modules/dav/main/std_liveprop.c18
-rw-r--r--modules/dav/main/util.c4
-rw-r--r--modules/generators/mod_cgid.c5
-rw-r--r--modules/http/http_filters.c69
-rw-r--r--modules/loggers/mod_log_config.c23
-rw-r--r--modules/lua/NWGNUmakefile9
-rw-r--r--modules/lua/lua_dbd.c27
-rw-r--r--modules/lua/lua_request.c168
-rw-r--r--modules/lua/mod_lua.c29
-rw-r--r--modules/mappers/mod_dir.c41
-rw-r--r--modules/mappers/mod_rewrite.c56
-rw-r--r--modules/mappers/mod_rewrite.h2
-rw-r--r--modules/metadata/mod_expires.c5
-rw-r--r--modules/metadata/mod_remoteip.c22
-rw-r--r--modules/proxy/NWGNUproxy2
-rw-r--r--modules/proxy/balancers/mod_lbmethod_heartbeat.c2
-rw-r--r--modules/proxy/fcgi_protocol.h0
-rw-r--r--modules/proxy/mod_proxy.c127
-rw-r--r--modules/proxy/mod_proxy.h23
-rw-r--r--modules/proxy/mod_proxy_ajp.c9
-rw-r--r--modules/proxy/mod_proxy_balancer.c17
-rw-r--r--modules/proxy/mod_proxy_fcgi.c35
-rw-r--r--modules/proxy/mod_proxy_fcgi.dsp4
-rw-r--r--modules/proxy/mod_proxy_ftp.c3
-rw-r--r--modules/proxy/mod_proxy_http.c30
-rw-r--r--modules/proxy/mod_proxy_wstunnel.c23
-rw-r--r--modules/proxy/proxy_util.c430
-rw-r--r--modules/session/mod_session.c36
-rw-r--r--modules/session/mod_session_crypto.c2
-rw-r--r--modules/slotmem/mod_slotmem_shm.c18
-rw-r--r--modules/ssl/mod_ssl.c8
-rw-r--r--modules/ssl/ssl_engine_config.c161
-rw-r--r--modules/ssl/ssl_engine_init.c773
-rw-r--r--modules/ssl/ssl_engine_kernel.c89
-rw-r--r--modules/ssl/ssl_engine_log.c10
-rw-r--r--modules/ssl/ssl_engine_pphrase.c726
-rw-r--r--modules/ssl/ssl_private.h111
-rw-r--r--modules/ssl/ssl_scache.c12
-rw-r--r--modules/ssl/ssl_util.c130
-rw-r--r--modules/ssl/ssl_util_ocsp.c1
-rw-r--r--modules/ssl/ssl_util_ssl.c68
-rw-r--r--modules/ssl/ssl_util_ssl.h4
-rw-r--r--modules/ssl/ssl_util_stapling.c10
62 files changed, 2104 insertions, 1566 deletions
diff --git a/modules/aaa/mod_auth_form.c b/modules/aaa/mod_auth_form.c
index 7bba517b..474a9de2 100644
--- a/modules/aaa/mod_auth_form.c
+++ b/modules/aaa/mod_auth_form.c
@@ -149,7 +149,7 @@ static const char *add_authn_provider(cmd_parms * cmd, void *config,
authn_provider_list *newp;
newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list));
- newp->provider_name = apr_pstrdup(cmd->pool, arg);
+ newp->provider_name = arg;
/* lookup and cache the actual provider now */
newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP,
diff --git a/modules/aaa/mod_authn_core.c b/modules/aaa/mod_authn_core.c
index 29d1988f..1f1163ec 100644
--- a/modules/aaa/mod_authn_core.c
+++ b/modules/aaa/mod_authn_core.c
@@ -179,6 +179,12 @@ static void *create_authn_alias_svr_config(apr_pool_t *p, server_rec *s)
return (void *) authcfg;
}
+/* Only per-server directive we have is GLOBAL_ONLY */
+static void *merge_authn_alias_svr_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+ return basev;
+}
+
static const authn_provider authn_alias_provider =
{
&authn_alias_check_password,
@@ -373,7 +379,7 @@ AP_DECLARE_MODULE(authn_core) =
create_authn_core_dir_config, /* dir config creater */
merge_authn_core_dir_config, /* dir merger --- default is to override */
create_authn_alias_svr_config, /* server config */
- NULL, /* merge server config */
+ merge_authn_alias_svr_config, /* merge server config */
authn_cmds,
register_hooks /* register hooks */
};
diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c
index d46eeb44..53a60853 100644
--- a/modules/aaa/mod_authnz_ldap.c
+++ b/modules/aaa/mod_authnz_ldap.c
@@ -607,6 +607,10 @@ static authz_status ldapuser_check_authorization(request_rec *r,
util_ldap_connection_t *ldc = NULL;
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char *w;
@@ -680,11 +684,19 @@ static authz_status ldapuser_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02585)
+ "auth_ldap authorize: require user: Can't evaluate expression: %s",
+ err);
+ return AUTHZ_DENIED;
+ }
+
/*
* First do a whole-line compare, in case it's something like
* require user Babs Jensen
*/
- result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require_args);
+ result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, require);
switch(result) {
case LDAP_COMPARE_TRUE: {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01703)
@@ -704,7 +716,7 @@ static authz_status ldapuser_check_authorization(request_rec *r,
/*
* Now break apart the line and compare each word on it
*/
- t = require_args;
+ t = require;
while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
result = util_ldap_cache_compare(r, ldc, sec->url, req->dn, sec->attribute, w);
switch(result) {
@@ -744,6 +756,10 @@ static authz_status ldapgroup_check_authorization(request_rec *r,
util_ldap_connection_t *ldc = NULL;
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char filtbuf[FILTER_LENGTH];
@@ -863,7 +879,15 @@ static authz_status ldapgroup_check_authorization(request_rec *r,
}
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02586)
+ "auth_ldap authorize: require group: Can't evaluate expression: %s",
+ err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01713)
"auth_ldap authorize: require group: testing for group "
@@ -959,6 +983,10 @@ static authz_status ldapdn_check_authorization(request_rec *r,
util_ldap_connection_t *ldc = NULL;
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char filtbuf[FILTER_LENGTH];
@@ -1021,7 +1049,15 @@ static authz_status ldapdn_check_authorization(request_rec *r,
req->user = r->user;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02587)
+ "auth_ldap authorize: require dn: Can't evaluate expression: %s",
+ err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
if (req->dn == NULL || strlen(req->dn) == 0) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01725)
@@ -1068,6 +1104,10 @@ static authz_status ldapattribute_check_authorization(request_rec *r,
util_ldap_connection_t *ldc = NULL;
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char *w, *value;
@@ -1138,7 +1178,16 @@ static authz_status ldapattribute_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02588)
+ "auth_ldap authorize: require ldap-attribute: Can't "
+ "evaluate expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
+
while (t[0]) {
w = ap_getword(r->pool, &t, '=');
value = ap_getword_conf(r->pool, &t);
@@ -1183,6 +1232,11 @@ static authz_status ldapfilter_check_authorization(request_rec *r,
(authn_ldap_config_t *)ap_get_module_config(r->per_dir_config, &authnz_ldap_module);
util_ldap_connection_t *ldc = NULL;
+
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char filtbuf[FILTER_LENGTH];
@@ -1252,7 +1306,15 @@ static authz_status ldapfilter_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02589)
+ "auth_ldap authorize: require ldap-filter: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
if (t[0]) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01743)
@@ -1311,6 +1373,25 @@ static authz_status ldapfilter_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
+static const char *ldap_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
/*
* Use the ldap url parsing routines to break up the ldap url into
@@ -1769,30 +1850,30 @@ static const authn_provider authn_ldap_provider =
static const authz_provider authz_ldapuser_provider =
{
&ldapuser_check_authorization,
- NULL,
+ &ldap_parse_config,
};
static const authz_provider authz_ldapgroup_provider =
{
&ldapgroup_check_authorization,
- NULL,
+ &ldap_parse_config,
};
static const authz_provider authz_ldapdn_provider =
{
&ldapdn_check_authorization,
- NULL,
+ &ldap_parse_config,
};
static const authz_provider authz_ldapattribute_provider =
{
&ldapattribute_check_authorization,
- NULL,
+ &ldap_parse_config,
};
static const authz_provider authz_ldapfilter_provider =
{
&ldapfilter_check_authorization,
- NULL,
+ &ldap_parse_config,
};
static void ImportULDAPOptFn(void)
diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c
index 9b7173c8..c9ed22ff 100644
--- a/modules/aaa/mod_authz_core.c
+++ b/modules/aaa/mod_authz_core.c
@@ -314,7 +314,7 @@ static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig,
provider_name);
}
if (prvdraliasrec->provider->parse_require_line) {
- const char *err = prvdraliasrec->provider->parse_require_line(cmd,
+ err = prvdraliasrec->provider->parse_require_line(cmd,
provider_args, &prvdraliasrec->provider_parsed_args);
if (err)
return apr_psprintf(cmd->pool,
diff --git a/modules/aaa/mod_authz_dbd.c b/modules/aaa/mod_authz_dbd.c
index 2d4925f5..30749914 100644
--- a/modules/aaa/mod_authz_dbd.c
+++ b/modules/aaa/mod_authz_dbd.c
@@ -253,6 +253,11 @@ static authz_status dbdgroup_check_authorization(request_rec *r,
int i, rv;
const char *w;
apr_array_header_t *groups = NULL;
+
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
authz_dbd_cfg *cfg = ap_get_module_config(r->per_dir_config,
&authz_dbd_module);
@@ -269,7 +274,15 @@ static authz_status dbdgroup_check_authorization(request_rec *r,
}
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02590)
+ "authz_dbd authorize: require dbd-group: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
while (t[0]) {
w = ap_getword_white(r->pool, &t);
for (i=0; i < groups->nelts; ++i) {
@@ -310,10 +323,29 @@ static authz_status dbdlogout_check_authorization(request_rec *r,
return (authz_dbd_login(r, cfg, "logout") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED);
}
+static const char *dbd_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
static const authz_provider authz_dbdgroup_provider =
{
&dbdgroup_check_authorization,
- NULL,
+ &dbd_parse_config,
};
static const authz_provider authz_dbdlogin_provider =
diff --git a/modules/aaa/mod_authz_dbm.c b/modules/aaa/mod_authz_dbm.c
index 4f13caea..c329eacd 100644
--- a/modules/aaa/mod_authz_dbm.c
+++ b/modules/aaa/mod_authz_dbm.c
@@ -137,6 +137,11 @@ static authz_status dbmgroup_check_authorization(request_rec *r,
authz_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
&authz_dbm_module);
char *user = r->user;
+
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t;
char *w;
const char *orig_groups = NULL;
@@ -180,7 +185,15 @@ static authz_status dbmgroup_check_authorization(request_rec *r,
orig_groups = groups;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02591)
+ "authz_dbm authorize: require dbm-group: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
while ((w = ap_getword_white(r->pool, &t)) && w[0]) {
groups = orig_groups;
while (groups[0]) {
@@ -210,7 +223,6 @@ static authz_status dbmfilegroup_check_authorization(request_rec *r,
char *user = r->user;
const char *realm = ap_auth_name(r);
const char *filegroup = NULL;
- const char *orig_groups = NULL;
apr_status_t status;
const char *groups;
char *v;
@@ -245,12 +257,9 @@ static authz_status dbmfilegroup_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
- orig_groups = groups;
-
filegroup = authz_owner_get_file_group(r);
if (filegroup) {
- groups = orig_groups;
while (groups[0]) {
v = ap_getword(r->pool, &groups, ',');
if (!strcmp(v, filegroup)) {
@@ -267,10 +276,29 @@ static authz_status dbmfilegroup_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
+static const char *dbm_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
static const authz_provider authz_dbmgroup_provider =
{
&dbmgroup_check_authorization,
- NULL,
+ &dbm_parse_config,
};
static const authz_provider authz_dbmfilegroup_provider =
diff --git a/modules/aaa/mod_authz_groupfile.c b/modules/aaa/mod_authz_groupfile.c
index c7fd13b6..70e68153 100644
--- a/modules/aaa/mod_authz_groupfile.c
+++ b/modules/aaa/mod_authz_groupfile.c
@@ -139,6 +139,11 @@ static authz_status group_check_authorization(request_rec *r,
authz_groupfile_config_rec *conf = ap_get_module_config(r->per_dir_config,
&authz_groupfile_module);
char *user = r->user;
+
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t, *w;
apr_table_t *grpstatus = NULL;
apr_status_t status;
@@ -175,7 +180,15 @@ static authz_status group_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02592)
+ "authz_groupfile authorize: require group: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
if (apr_table_get(grpstatus, w)) {
return AUTHZ_GRANTED;
@@ -257,10 +270,29 @@ static authz_status filegroup_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
+static const char *groupfile_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
static const authz_provider authz_group_provider =
{
&group_check_authorization,
- NULL,
+ &groupfile_parse_config,
};
static const authz_provider authz_filegroup_provider =
diff --git a/modules/aaa/mod_authz_host.c b/modules/aaa/mod_authz_host.c
index f4d5c41c..83fc6e6c 100644
--- a/modules/aaa/mod_authz_host.c
+++ b/modules/aaa/mod_authz_host.c
@@ -179,10 +179,22 @@ static authz_status host_check_authorization(request_rec *r,
"remote host name", require_line, r->uri);
}
else {
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_line;
+ const char *require;
+
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02593)
+ "authz_host authorize: require host: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
/* The 'host' provider will allow the configuration to specify a list of
host names to check rather than a single name. This is different
from the previous host based syntax. */
- t = require_line;
+ t = require;
while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
if (in_domain(w, remotehost)) {
return AUTHZ_GRANTED;
@@ -212,6 +224,25 @@ static authz_status local_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
+static const char *host_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
static const authz_provider authz_ip_provider =
{
&ip_check_authorization,
@@ -221,7 +252,7 @@ static const authz_provider authz_ip_provider =
static const authz_provider authz_host_provider =
{
&host_check_authorization,
- NULL,
+ &host_parse_config,
};
static const authz_provider authz_local_provider =
diff --git a/modules/aaa/mod_authz_user.c b/modules/aaa/mod_authz_user.c
index e4af7946..881f77f1 100644
--- a/modules/aaa/mod_authz_user.c
+++ b/modules/aaa/mod_authz_user.c
@@ -49,13 +49,25 @@ static authz_status user_check_authorization(request_rec *r,
const char *require_args,
const void *parsed_require_args)
{
+ const char *err = NULL;
+ const ap_expr_info_t *expr = parsed_require_args;
+ const char *require;
+
const char *t, *w;
if (!r->user) {
return AUTHZ_DENIED_NO_USER;
}
- t = require_args;
+ require = ap_expr_str_exec(r, expr, &err);
+ if (err) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02594)
+ "authz_user authorize: require user: Can't "
+ "evaluate require expression: %s", err);
+ return AUTHZ_DENIED;
+ }
+
+ t = require;
while ((w = ap_getword_conf(r->pool, &t)) && w[0]) {
if (!strcmp(r->user, w)) {
return AUTHZ_GRANTED;
@@ -81,10 +93,29 @@ static authz_status validuser_check_authorization(request_rec *r,
return AUTHZ_GRANTED;
}
+static const char *user_parse_config(cmd_parms *cmd, const char *require_line,
+ const void **parsed_require_line)
+{
+ const char *expr_err = NULL;
+ ap_expr_info_t *expr;
+
+ expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
+ &expr_err, NULL);
+
+ if (expr_err)
+ return apr_pstrcat(cmd->temp_pool,
+ "Cannot parse expression in require line: ",
+ expr_err, NULL);
+
+ *parsed_require_line = expr;
+
+ return NULL;
+}
+
static const authz_provider authz_user_provider =
{
&user_check_authorization,
- NULL,
+ &user_parse_config,
};
static const authz_provider authz_validuser_provider =
{
diff --git a/modules/arch/win32/mod_isapi.c b/modules/arch/win32/mod_isapi.c
index f6cb99a2..801c7dea 100644
--- a/modules/arch/win32/mod_isapi.c
+++ b/modules/arch/win32/mod_isapi.c
@@ -877,7 +877,7 @@ static int APR_THREAD_FUNC regfnServerSupportFunction(isapi_cid *cid,
/* Set the status to be returned when the HttpExtensionProc()
* is done.
* WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP
- * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK.
+ * and HSE_REQ_SEND_URL as equivalent per the Jan 2000 SDK.
* They most definitely are not, even in their own samples.
*/
apr_table_set (r->headers_out, "Location", buf_data);
diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c
index 782dc712..234eb9bb 100644
--- a/modules/cache/cache_storage.c
+++ b/modules/cache/cache_storage.c
@@ -582,7 +582,7 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p,
&& !strncmp(param + 1, *identifier, len)
&& (*(param + len + 1) == '=')
&& !ap_strchr_c(param + len + 2, '/')) {
- path = apr_pstrndup(p, path, param - path);
+ path = apr_pstrmemdup(p, path, param - path);
continue;
}
/*
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c
index 6e644e67..20360553 100644
--- a/modules/cache/mod_cache.c
+++ b/modules/cache/mod_cache.c
@@ -1130,7 +1130,6 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
"Content-Range")))
|| ((reason = cache_header_cmp(r->pool, left, right,
"Content-Type")))
- || ((reason = cache_header_cmp(r->pool, left, right, "Expires")))
|| ((reason = cache_header_cmp(r->pool, left, right, "ETag")))
|| ((reason = cache_header_cmp(r->pool, left, right,
"Last-Modified")))) {
diff --git a/modules/cache/mod_cache_disk.c b/modules/cache/mod_cache_disk.c
index 2b50aef9..ddf64314 100644
--- a/modules/cache/mod_cache_disk.c
+++ b/modules/cache/mod_cache_disk.c
@@ -381,7 +381,7 @@ static int create_entity(cache_handle_t *h, request_rec *r, const char *key, apr
dobj->name = obj->key;
dobj->prefix = NULL;
/* Save the cache root */
- dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len);
+ dobj->root = apr_pstrmemdup(r->pool, conf->cache_root, conf->cache_root_len);
dobj->root_len = conf->cache_root_len;
apr_pool_create(&pool, r->pool);
@@ -441,7 +441,7 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
dobj->prefix = NULL;
/* Save the cache root */
- dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len);
+ dobj->root = apr_pstrmemdup(r->pool, conf->cache_root, conf->cache_root_len);
dobj->root_len = conf->cache_root_len;
dobj->vary.file = header_file(r->pool, conf, dobj, key);
@@ -529,13 +529,13 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
return DECLINED;
}
- apr_file_close(dobj->hdrs.fd);
/* Is this a cached HEAD request? */
if (dobj->disk_info.header_only && !r->header_only) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(00707)
"HEAD request cached, non-HEAD requested, ignoring: %s",
dobj->hdrs.file);
+ apr_file_close(dobj->hdrs.fd);
return DECLINED;
}
@@ -593,6 +593,7 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key)
"Cached URL info header '%s' didn't match body, ignoring this entry",
dobj->name);
+ apr_file_close(dobj->hdrs.fd);
return DECLINED;
}
diff --git a/modules/cache/mod_socache_shmcb.c b/modules/cache/mod_socache_shmcb.c
index f6bf1dab..a9164311 100644
--- a/modules/cache/mod_socache_shmcb.c
+++ b/modules/cache/mod_socache_shmcb.c
@@ -30,7 +30,14 @@
#include "ap_socache.h"
-#define SHMCB_MAX_SIZE (64 * 1024 * 1024)
+/* XXX Unfortunately, there are still many unsigned ints in use here, so we
+ * XXX cannot allow more than UINT_MAX. Since some of the ints are exposed in
+ * XXX public interfaces, a simple search and replace is not enough.
+ * XXX It should be possible to extend that so that the total cache size can
+ * XXX be APR_SIZE_MAX and only the object size needs to be smaller than
+ * XXX UINT_MAX.
+ */
+#define SHMCB_MAX_SIZE (UINT_MAX<APR_SIZE_MAX ? UINT_MAX : APR_SIZE_MAX)
#define DEFAULT_SHMCB_PREFIX "socache-shmcb-"
diff --git a/modules/cluster/mod_heartmonitor.c b/modules/cluster/mod_heartmonitor.c
index 8e4231dc..b3d666ba 100644
--- a/modules/cluster/mod_heartmonitor.c
+++ b/modules/cluster/mod_heartmonitor.c
@@ -292,7 +292,7 @@ static apr_status_t hm_file_update_stat(hm_ctx_t *ctx, hm_server_t *s, apr_pool_
buf[bsize - 1] = 0;
t = strchr(buf, ' ');
if (t) {
- ip = apr_pstrndup(pool, buf, t - buf);
+ ip = apr_pstrmemdup(pool, buf, t - buf);
} else {
ip = NULL;
}
diff --git a/modules/core/mod_macro.c b/modules/core/mod_macro.c
index ad730054..75180930 100644
--- a/modules/core/mod_macro.c
+++ b/modules/core/mod_macro.c
@@ -15,7 +15,7 @@
*/
/*
- $Id: mod_macro.c 1455215 2013-03-11 16:28:43Z jim $
+ $Id: mod_macro.c 1562134 2014-01-28 18:11:59Z jim $
*/
#include "httpd.h"
@@ -468,7 +468,7 @@ static const char *process_content(apr_pool_t * pool,
int i;
if (result) {
- *result = apr_array_make(pool, 1, sizeof(char *));
+ *result = apr_array_make(pool, contents->nelts, sizeof(char *));
}
/* for each line of the macro body */
diff --git a/modules/core/mod_watchdog.c b/modules/core/mod_watchdog.c
index 7ad13bf8..dfdff2f9 100644
--- a/modules/core/mod_watchdog.c
+++ b/modules/core/mod_watchdog.c
@@ -388,7 +388,7 @@ static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w,
/* */
/* Pre config hook. */
/* Create default watchdogs for parent and child */
-/* Parent watchdog executes inside parent proces so it doesn't need the */
+/* Parent watchdog executes inside parent process so it doesn't need the */
/* singleton mutex */
/* */
/*--------------------------------------------------------------------------*/
diff --git a/modules/dav/fs/lock.c b/modules/dav/fs/lock.c
index a15b4b91..c058e2ed 100644
--- a/modules/dav/fs/lock.c
+++ b/modules/dav/fs/lock.c
@@ -1327,6 +1327,7 @@ static int dav_fs_do_refresh(dav_lock_discovery *dp,
{
dp->f.timeout = new_time;
dirty = 1;
+ break;
}
}
diff --git a/modules/dav/lock/locks.c b/modules/dav/lock/locks.c
index 264a851a..ccf972d3 100644
--- a/modules/dav/lock/locks.c
+++ b/modules/dav/lock/locks.c
@@ -1093,6 +1093,7 @@ static int dav_generic_do_refresh(dav_lock_discovery *dp,
{
dp->f.timeout = new_time;
dirty = 1;
+ break;
}
}
diff --git a/modules/dav/main/std_liveprop.c b/modules/dav/main/std_liveprop.c
index 1f79dc71..e760c655 100644
--- a/modules/dav/main/std_liveprop.c
+++ b/modules/dav/main/std_liveprop.c
@@ -86,18 +86,18 @@ static dav_prop_insert dav_core_insert_prop(const dav_resource *resource,
continue;
if (!res_hooks->get_resource_type(resource, &name, &uri) &&
- name) {
+ name) {
if (!uri || !strcasecmp(uri, "DAV:"))
value = apr_pstrcat(p, value ? value : "",
- "<D:", name, "/>", NULL);
- else
+ "<D:", name, "/>", NULL);
+ else
value = apr_pstrcat(p, value ? value : "",
- "<x:", name,
- " xmlns:x=\"", uri,
- "\"/>", NULL);
+ "<x:", name,
+ " xmlns:x=\"", uri,
+ "\"/>", NULL);
}
- }
+ }
}
switch (resource->type) {
case DAV_RESOURCE_TYPE_VERSION:
@@ -114,8 +114,8 @@ static dav_prop_insert dav_core_insert_prop(const dav_resource *resource,
else {
/* ### should we denote lock-null resources? */
if (value == NULL) {
- value = ""; /* becomes: <D:resourcetype/> */
- }
+ value = ""; /* becomes: <D:resourcetype/> */
+ }
}
break;
case DAV_RESOURCE_TYPE_HISTORY:
diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c
index 1f393401..4e85a04f 100644
--- a/modules/dav/main/util.c
+++ b/modules/dav/main/util.c
@@ -396,8 +396,10 @@ DAV_DECLARE(const char *) dav_xml_get_cdata(const apr_xml_elem *elem, apr_pool_t
if (strip_white) {
/* trim leading whitespace */
- while (apr_isspace(*cdata)) /* assume: return false for '\0' */
+ while (apr_isspace(*cdata)) { /* assume: return false for '\0' */
++cdata;
+ --len;
+ }
/* trim trailing whitespace */
while (len-- > 0 && apr_isspace(cdata[len]))
diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c
index 56d35243..499e37dc 100644
--- a/modules/generators/mod_cgid.c
+++ b/modules/generators/mod_cgid.c
@@ -87,7 +87,6 @@ static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgid_pfn_gtv;
static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgid_pfn_ps;
static apr_pool_t *pcgi = NULL;
-static int total_modules = 0;
static pid_t daemon_pid;
static int daemon_should_exit = 0;
static server_rec *root_server = NULL;
@@ -896,7 +895,6 @@ static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
{
apr_proc_t *procnew = NULL;
const char *userdata_key = "cgid_init";
- module **m;
int ret = OK;
void *data;
@@ -918,9 +916,6 @@ static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) {
char *tmp_sockname;
- total_modules = 0;
- for (m = ap_preloaded_modules; *m != NULL; m++)
- total_modules++;
parent_pid = getpid();
tmp_sockname = ap_runtime_dir_relative(p, sockname);
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index c7274194..2a0a979d 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -87,6 +87,23 @@ static apr_status_t bail_out_on_error(http_ctx_t *ctx,
apr_bucket_brigade *bb = ctx->bb;
apr_brigade_cleanup(bb);
+
+ if (f->r->proxyreq == PROXYREQ_RESPONSE) {
+ switch (http_error) {
+ case HTTP_REQUEST_ENTITY_TOO_LARGE:
+ return APR_ENOSPC;
+
+ case HTTP_REQUEST_TIME_OUT:
+ return APR_INCOMPLETE;
+
+ case HTTP_NOT_IMPLEMENTED:
+ return APR_ENOTIMPL;
+
+ default:
+ return APR_EGENERAL;
+ }
+ }
+
e = ap_bucket_error_create(http_error,
NULL, f->r->pool,
f->c->bucket_alloc);
@@ -259,25 +276,30 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
lenp = apr_table_get(f->r->headers_in, "Content-Length");
if (tenc) {
- if (!strcasecmp(tenc, "chunked")) {
+ if (strcasecmp(tenc, "chunked") == 0 /* fast path */
+ || ap_find_last_token(f->r->pool, tenc, "chunked")) {
ctx->state = BODY_CHUNK;
}
- /* test lenp, because it gives another case we can handle */
- else if (!lenp) {
- /* Something that isn't in HTTP, unless some future
- * edition defines new transfer encodings, is unsupported.
+ else if (f->r->proxyreq == PROXYREQ_RESPONSE) {
+ /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ * Section 3.3.3.3: "If a Transfer-Encoding header field is
+ * present in a response and the chunked transfer coding is not
+ * the final encoding, the message body length is determined by
+ * reading the connection until it is closed by the server."
*/
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(02555)
+ "Unknown Transfer-Encoding: %s;"
+ " using read-until-close", tenc);
+ tenc = NULL;
+ }
+ else {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01585)
"Unknown Transfer-Encoding: %s", tenc);
return bail_out_on_error(ctx, f, HTTP_NOT_IMPLEMENTED);
}
- else {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, f->r, APLOGNO(01586)
- "Unknown Transfer-Encoding: %s; using Content-Length", tenc);
- tenc = NULL;
- }
+ lenp = NULL;
}
- if (lenp && !tenc) {
+ if (lenp) {
char *endstr;
ctx->state = BODY_LENGTH;
@@ -394,11 +416,11 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
if (rv != APR_SUCCESS || ctx->remaining < 0) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01589) "Error reading first chunk %s ",
(ctx->remaining < 0) ? "(overflow)" : "");
- ctx->remaining = 0; /* Reset it in case we have to
- * come back here later */
- if (APR_STATUS_IS_TIMEUP(rv)) {
+ if (APR_STATUS_IS_TIMEUP(rv) || ctx->remaining > 0) {
http_error = HTTP_REQUEST_TIME_OUT;
}
+ ctx->remaining = 0; /* Reset it in case we have to
+ * come back here later */
return bail_out_on_error(ctx, f, http_error);
}
@@ -447,6 +469,9 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
return APR_EAGAIN;
}
/* If we get an error, then leave */
+ if (rv == APR_EOF) {
+ return APR_INCOMPLETE;
+ }
if (rv != APR_SUCCESS) {
return rv;
}
@@ -500,11 +525,11 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
if (rv != APR_SUCCESS || ctx->remaining < 0) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, f->r, APLOGNO(01590) "Error reading chunk %s ",
(ctx->remaining < 0) ? "(overflow)" : "");
- ctx->remaining = 0; /* Reset it in case we have to
- * come back here later */
- if (APR_STATUS_IS_TIMEUP(rv)) {
+ if (APR_STATUS_IS_TIMEUP(rv) || ctx->remaining > 0) {
http_error = HTTP_REQUEST_TIME_OUT;
}
+ ctx->remaining = 0; /* Reset it in case we have to
+ * come back here later */
return bail_out_on_error(ctx, f, http_error);
}
@@ -532,6 +557,10 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
rv = ap_get_brigade(f->next, b, mode, block, readbytes);
+ if (rv == APR_EOF && ctx->state != BODY_NONE &&
+ ctx->remaining > 0) {
+ return APR_INCOMPLETE;
+ }
if (rv != APR_SUCCESS) {
return rv;
}
@@ -547,8 +576,10 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
ctx->remaining -= totalread;
if (ctx->remaining > 0) {
e = APR_BRIGADE_LAST(b);
- if (APR_BUCKET_IS_EOS(e))
- return APR_EOF;
+ if (APR_BUCKET_IS_EOS(e)) {
+ apr_bucket_delete(e);
+ return APR_INCOMPLETE;
+ }
}
}
diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c
index f17e1641..792756db 100644
--- a/modules/loggers/mod_log_config.c
+++ b/modules/loggers/mod_log_config.c
@@ -543,14 +543,24 @@ static const char *log_cookie(request_rec *r, char *a)
while ((cookie = apr_strtok(cookies, ";", &last1))) {
char *name = apr_strtok(cookie, "=", &last2);
- if (name) {
- char *value = name + strlen(name) + 1;
- apr_collapse_spaces(name, name);
+ /* last2 points to the next char following an '=' delim,
+ or the trailing NUL char of the string */
+ char *value = last2;
+ if (name && *name && value && *value) {
+ char *last = value - 2;
+ /* Move past leading WS */
+ name += strspn(name, " \t");
+ while (last >= name && apr_isspace(*last)) {
+ *last = '\0';
+ --last;
+ }
if (!strcasecmp(name, a)) {
- char *last;
- value += strspn(value, " \t"); /* Move past leading WS */
- last = value + strlen(value) - 1;
+ /* last1 points to the next char following the ';' delim,
+ or the trailing NUL char of the string */
+ last = last1 - (*last1 ? 2 : 1);
+ /* Move past leading WS */
+ value += strspn(value, " \t");
while (last >= value && apr_isspace(*last)) {
*last = '\0';
--last;
@@ -559,6 +569,7 @@ static const char *log_cookie(request_rec *r, char *a)
return ap_escape_logitem(r->pool, value);
}
}
+ /* Iterate the remaining tokens using apr_strtok(NULL, ...) */
cookies = NULL;
}
}
diff --git a/modules/lua/NWGNUmakefile b/modules/lua/NWGNUmakefile
index 15e6c91e..fd86b3c9 100644
--- a/modules/lua/NWGNUmakefile
+++ b/modules/lua/NWGNUmakefile
@@ -185,6 +185,7 @@ FILES_nlm_objs = \
$(OBJDIR)/lua_request.o \
$(OBJDIR)/lua_vmprep.o \
$(OBJDIR)/lua_dbd.o \
+ $(OBJDIR)/libprews.o \
$(EOLIST)
#
@@ -229,6 +230,12 @@ FILES_nlm_Ximports = \
@libc.imp \
$(EOLIST)
+# Don't link with Winsock if standard sockets are being used
+ifndef USE_STDSOCKETS
+FILES_nlm_Ximports += @ws2nlm.imp \
+ $(EOLIST)
+endif
+
#
# Any symbols exported to here
#
@@ -265,7 +272,7 @@ install :: nlms FORCE
# Any specialized rules here
#
-vpath %.c $(LUASRC)/src
+vpath %.c $(LUASRC)/src ../arch/netware
#
# Include the 'tail' makefile that has targets that depend on variables defined
diff --git a/modules/lua/lua_dbd.c b/modules/lua/lua_dbd.c
index 501156f8..8b61a60b 100644
--- a/modules/lua/lua_dbd.c
+++ b/modules/lua/lua_dbd.c
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+
#include "mod_lua.h"
#include "lua_dbd.h"
@@ -228,15 +229,19 @@ int lua_db_escape(lua_State *L)
*/
int lua_db_get_row(lua_State *L)
{
- int row_no,x;
- const char *entry;
+ int row_no,x,alpha = 0;
+ const char *entry, *rowname;
apr_dbd_row_t *row = 0;
lua_db_result_set *res = lua_get_result_set(L);
row_no = luaL_optinteger(L, 2, 0);
+ if (lua_isboolean(L, 3)) {
+ alpha = lua_toboolean(L, 3);
+ }
lua_settop(L,0);
/* Fetch all rows at once? */
+
if (row_no == 0) {
row_no = 1;
lua_newtable(L);
@@ -248,7 +253,14 @@ int lua_db_get_row(lua_State *L)
for (x = 0; x < res->cols; x++) {
entry = apr_dbd_get_entry(res->driver, row, x);
if (entry) {
- lua_pushinteger(L, x + 1);
+ if (alpha == 1) {
+ rowname = apr_dbd_get_name(res->driver,
+ res->results, x);
+ lua_pushstring(L, rowname ? rowname : "(oob)");
+ }
+ else {
+ lua_pushinteger(L, x + 1);
+ }
lua_pushstring(L, entry);
lua_rawset(L, -3);
}
@@ -268,7 +280,14 @@ int lua_db_get_row(lua_State *L)
for (x = 0; x < res->cols; x++) {
entry = apr_dbd_get_entry(res->driver, row, x);
if (entry) {
- lua_pushinteger(L, x + 1);
+ if (alpha == 1) {
+ rowname = apr_dbd_get_name(res->driver,
+ res->results, x);
+ lua_pushstring(L, rowname ? rowname : "(oob)");
+ }
+ else {
+ lua_pushinteger(L, x + 1);
+ }
lua_pushstring(L, entry);
lua_rawset(L, -3);
}
diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c
index 8dce13cc..609b0167 100644
--- a/modules/lua/lua_request.c
+++ b/modules/lua/lua_request.c
@@ -28,6 +28,8 @@
#include "apr_thread_mutex.h"
#include "apr_tables.h"
#include "util_cookies.h"
+
+#define APR_WANT_BYTEFUNC
#include "apr_want.h"
extern apr_thread_mutex_t* lua_ivm_mutex;
@@ -169,6 +171,55 @@ static int req_aprtable2luatable_cb(void *l, const char *key,
return 1;
}
+/* helper callback for req_parseargs */
+static int req_aprtable2luatable_cb_len(void *l, const char *key,
+ const char *value, size_t len)
+{
+ int t;
+ lua_State *L = (lua_State *) l; /* [table<s,t>, table<s,s>] */
+ /* rstack_dump(L, RRR, "start of cb"); */
+ /* L is [table<s,t>, table<s,s>] */
+ /* build complex */
+
+ lua_getfield(L, -1, key); /* [VALUE, table<s,t>, table<s,s>] */
+ /* rstack_dump(L, RRR, "after getfield"); */
+ t = lua_type(L, -1);
+ switch (t) {
+ case LUA_TNIL:
+ case LUA_TNONE:{
+ lua_pop(L, 1); /* [table<s,t>, table<s,s>] */
+ lua_newtable(L); /* [array, table<s,t>, table<s,s>] */
+ lua_pushnumber(L, 1); /* [1, array, table<s,t>, table<s,s>] */
+ lua_pushlstring(L, value, len); /* [string, 1, array, table<s,t>, table<s,s>] */
+ lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
+ lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
+ break;
+ }
+ case LUA_TTABLE:{
+ /* [array, table<s,t>, table<s,s>] */
+ int size = lua_objlen(L, -1);
+ lua_pushnumber(L, size + 1); /* [#, array, table<s,t>, table<s,s>] */
+ lua_pushlstring(L, value, len); /* [string, #, array, table<s,t>, table<s,s>] */
+ lua_settable(L, -3); /* [array, table<s,t>, table<s,s>] */
+ lua_setfield(L, -2, key); /* [table<s,t>, table<s,s>] */
+ break;
+ }
+ }
+
+ /* L is [table<s,t>, table<s,s>] */
+ /* build simple */
+ lua_getfield(L, -2, key); /* [VALUE, table<s,s>, table<s,t>] */
+ if (lua_isnoneornil(L, -1)) { /* only set if not already set */
+ lua_pop(L, 1); /* [table<s,s>, table<s,t>]] */
+ lua_pushlstring(L, value, len); /* [string, table<s,s>, table<s,t>] */
+ lua_setfield(L, -3, key); /* [table<s,s>, table<s,t>] */
+ }
+ else {
+ lua_pop(L, 1);
+ }
+ return 1;
+}
+
/*
=======================================================================================================================
@@ -311,7 +362,7 @@ static int req_parsebody(lua_State *L)
"Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
key, filename);
if (strlen(key)) {
- req_aprtable2luatable_cb(L, key, buffer);
+ req_aprtable2luatable_cb_len(L, key, buffer, vlen);
}
}
}
@@ -647,7 +698,14 @@ static const char* lua_ap_allowoverrides(request_rec* r)
{
int opts;
opts = ap_allow_overrides(r);
- return apr_psprintf(r->pool, "%s %s %s %s %s %s", (opts&OR_NONE) ? "None" : "", (opts&OR_LIMIT) ? "Limit" : "", (opts&OR_OPTIONS) ? "Options" : "", (opts&OR_FILEINFO) ? "FileInfo" : "", (opts&OR_AUTHCFG) ? "AuthCfg" : "", (opts&OR_INDEXES) ? "Indexes" : "" );
+ if ( (opts & OR_ALL) == OR_ALL) {
+ return "All";
+ }
+ else if (opts == OR_NONE) {
+ return "None";
+ }
+ return apr_psprintf(r->pool, "%s %s %s %s %s", (opts & OR_LIMIT) ? "Limit" : "", (opts & OR_OPTIONS) ? "Options" : "", (opts & OR_FILEINFO) ? "FileInfo" : "", (opts & OR_AUTHCFG) ? "AuthCfg" : "", (opts & OR_INDEXES) ? "Indexes" : "" );
+
}
static int lua_ap_started(request_rec* r)
@@ -1905,27 +1963,101 @@ static int lua_get_cookie(lua_State *L)
static int lua_set_cookie(lua_State *L)
{
- const char *key, *value, *out, *strexpires;
- int secure, expires;
+ const char *key, *value, *out, *path = "", *domain = "";
+ const char *strexpires = "", *strdomain = "", *strpath = "";
+ int secure = 0, expires = 0, httponly = 0;
char cdate[APR_RFC822_DATE_LEN+1];
apr_status_t rv;
request_rec *r = ap_lua_check_request_rec(L, 1);
- key = luaL_checkstring(L, 2);
- value = luaL_checkstring(L, 3);
- secure = 0;
- if (lua_isboolean(L, 4)) {
- secure = lua_toboolean(L, 4);
+
+ /* New >= 2.4.8 method: */
+ if (lua_istable(L, 2)) {
+
+ /* key */
+ lua_pushstring(L, "key");
+ lua_gettable(L, -2);
+ key = luaL_checkstring(L, -1);
+ lua_pop(L, 1);
+
+ /* value */
+ lua_pushstring(L, "value");
+ lua_gettable(L, -2);
+ value = luaL_checkstring(L, -1);
+ lua_pop(L, 1);
+
+ /* expiry */
+ lua_pushstring(L, "expires");
+ lua_gettable(L, -2);
+ expires = luaL_optint(L, -1, 0);
+ lua_pop(L, 1);
+
+ /* secure */
+ lua_pushstring(L, "secure");
+ lua_gettable(L, -2);
+ if (lua_isboolean(L, -1)) {
+ secure = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+
+ /* httponly */
+ lua_pushstring(L, "httponly");
+ lua_gettable(L, -2);
+ if (lua_isboolean(L, -1)) {
+ httponly = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+
+ /* path */
+ lua_pushstring(L, "path");
+ lua_gettable(L, -2);
+ path = luaL_optstring(L, -1, "/");
+ lua_pop(L, 1);
+
+ /* domain */
+ lua_pushstring(L, "domain");
+ lua_gettable(L, -2);
+ domain = luaL_optstring(L, -1, "");
+ lua_pop(L, 1);
+ }
+ /* Old <= 2.4.7 method: */
+ else {
+ key = luaL_checkstring(L, 2);
+ value = luaL_checkstring(L, 3);
+ secure = 0;
+ if (lua_isboolean(L, 4)) {
+ secure = lua_toboolean(L, 4);
+ }
+ expires = luaL_optinteger(L, 5, 0);
}
- expires = luaL_optinteger(L, 5, 0);
- strexpires = "";
+
+ /* Calculate expiry if set */
if (expires > 0) {
rv = apr_rfc822_date(cdate, apr_time_from_sec(expires));
if (rv == APR_SUCCESS) {
- strexpires = apr_psprintf(r->pool, "Expires=%s", cdate);
+ strexpires = apr_psprintf(r->pool, "Expires=\"%s\";", cdate);
}
}
- out = apr_psprintf(r->pool, "%s=%s; %s %s", key, value, secure ? "Secure;" : "", expires ? strexpires : "");
- apr_table_set(r->headers_out, "Set-Cookie", out);
+
+ /* Create path segment */
+ if (path != NULL && strlen(path) > 0) {
+ strpath = apr_psprintf(r->pool, "Path=\"%s\";", path);
+ }
+
+ /* Create domain segment */
+ if (domain != NULL && strlen(domain) > 0) {
+ /* Domain does NOT like quotes in most browsers, so let's avoid that */
+ strdomain = apr_psprintf(r->pool, "Domain=%s;", domain);
+ }
+
+ /* Create the header */
+ out = apr_psprintf(r->pool, "%s=%s; %s %s %s %s %s", key, value,
+ secure ? "Secure;" : "",
+ expires ? strexpires : "",
+ httponly ? "HttpOnly;" : "",
+ strlen(strdomain) ? strdomain : "",
+ strlen(strpath) ? strpath : "");
+
+ apr_table_add(r->err_headers_out, "Set-Cookie", out);
return 0;
}
@@ -2098,7 +2230,7 @@ static int lua_websocket_read(lua_State *L)
}
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
- "Websocket: Reading %lu (%s) bytes, masking is %s. %s",
+ "Websocket: Reading %" APR_SIZE_T_FMT " (%s) bytes, masking is %s. %s",
plen,
(payload >= 126) ? "extra payload" : "no extra payload",
mask ? "on" : "off",
@@ -2133,14 +2265,14 @@ static int lua_websocket_read(lua_State *L)
}
}
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Websocket: Frame contained %lu bytes, pushed to Lua stack",
+ "Websocket: Frame contained %" APR_OFF_T_FMT " bytes, pushed to Lua stack",
at);
}
else {
rv = lua_websocket_readbytes(r->connection, buffer,
remaining);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Websocket: SSL Frame contained %lu bytes, "\
+ "Websocket: SSL Frame contained %" APR_SIZE_T_FMT " bytes, "\
"pushed to Lua stack",
remaining);
}
@@ -2280,7 +2412,7 @@ static int lua_websocket_ping(lua_State *L)
}
if (plen > 0) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
- "Websocket: Reading %lu bytes of PONG", plen);
+ "Websocket: Reading %" APR_SIZE_T_FMT " bytes of PONG", plen);
return 1;
}
if (mask) {
diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c
index 6e3390fb..8f09cfe1 100644
--- a/modules/lua/mod_lua.c
+++ b/modules/lua/mod_lua.c
@@ -709,6 +709,29 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap
return DECLINED;
}
+static int lua_map_handler_fixups(request_rec *r)
+{
+ /* If there is no handler set yet, this might be a LuaMapHandler request */
+ if (r->handler == NULL) {
+ int n = 0;
+ ap_regmatch_t match[10];
+ const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config,
+ &lua_module);
+ for (n = 0; n < cfg->mapped_handlers->nelts; n++) {
+ ap_lua_mapped_handler_spec *hook_spec =
+ ((ap_lua_mapped_handler_spec **) cfg->mapped_handlers->elts)[n];
+
+ if (hook_spec == NULL) {
+ continue;
+ }
+ if (!ap_regexec(hook_spec->uri_pattern, r->uri, 10, match, 0)) {
+ r->handler = apr_pstrdup(r->pool, "lua-map-handler");
+ return OK;
+ }
+ }
+ }
+ return DECLINED;
+}
static int lua_map_handler(request_rec *r)
{
@@ -954,11 +977,11 @@ static const char *register_named_block_function_hook(const char *name,
if (line[0]) {
const char *word;
word = ap_getword_conf(cmd->temp_pool, &line);
- if (word && *word) {
+ if (*word) {
function = apr_pstrdup(cmd->pool, word);
}
word = ap_getword_conf(cmd->temp_pool, &line);
- if (word && *word) {
+ if (*word) {
if (!strcasecmp("early", word)) {
when = AP_LUA_HOOK_FIRST;
}
@@ -2032,6 +2055,8 @@ static void lua_register_hooks(apr_pool_t *p)
APR_OPTIONAL_HOOK(ap_lua, lua_request, lua_request_hook, NULL, NULL,
APR_HOOK_REALLY_FIRST);
ap_hook_handler(lua_map_handler, NULL, NULL, AP_LUA_HOOK_FIRST);
+ /* Hook this right before FallbackResource kicks in */
+ ap_hook_fixups(lua_map_handler_fixups, NULL, NULL, AP_LUA_HOOK_LAST-2);
#if APR_HAS_THREADS
ap_hook_child_init(ap_lua_init_mutex, NULL, NULL, APR_HOOK_MIDDLE);
#endif
diff --git a/modules/mappers/mod_dir.c b/modules/mappers/mod_dir.c
index 4364ff95..2a359c7f 100644
--- a/modules/mappers/mod_dir.c
+++ b/modules/mappers/mod_dir.c
@@ -29,21 +29,23 @@
#include "http_log.h"
#include "http_main.h"
#include "util_script.h"
+#include "mod_rewrite.h"
module AP_MODULE_DECLARE_DATA dir_module;
typedef enum {
- SLASH_OFF = 0,
- SLASH_ON,
- SLASH_UNSET
-} slash_cfg;
+ MODDIR_OFF = 0,
+ MODDIR_ON,
+ MODDIR_UNSET
+} moddir_cfg;
#define REDIRECT_OFF 0
#define REDIRECT_UNSET 1
typedef struct dir_config_struct {
apr_array_header_t *index_names;
- slash_cfg do_slash;
+ moddir_cfg do_slash;
+ moddir_cfg checkhandler;
int redirect_index;
const char *dflt;
} dir_config_rec;
@@ -66,7 +68,7 @@ static const char *add_index(cmd_parms *cmd, void *dummy, const char *arg)
/* peek to see if "disabled" is first in a series of arguments */
const char *tt = t;
const char *ww = ap_getword_conf(cmd->temp_pool, &tt);
- if (ww == NULL || !ww[0]) {
+ if (ww[0] == '\0') {
/* "disabled" is first, and alone */
apr_array_clear(d->index_names);
break;
@@ -83,7 +85,14 @@ static const char *configure_slash(cmd_parms *cmd, void *d_, int arg)
{
dir_config_rec *d = d_;
- d->do_slash = arg ? SLASH_ON : SLASH_OFF;
+ d->do_slash = arg ? MODDIR_ON : MODDIR_OFF;
+ return NULL;
+}
+static const char *configure_checkhandler(cmd_parms *cmd, void *d_, int arg)
+{
+ dir_config_rec *d = d_;
+
+ d->checkhandler = arg ? MODDIR_ON : MODDIR_OFF;
return NULL;
}
static const char *configure_redirect(cmd_parms *cmd, void *d_, const char *arg1)
@@ -123,6 +132,8 @@ static const command_rec dir_cmds[] =
"a list of file names"),
AP_INIT_FLAG("DirectorySlash", configure_slash, NULL, DIR_CMD_PERMS,
"On or Off"),
+ AP_INIT_FLAG("DirectoryCheckHandler", configure_checkhandler, NULL, DIR_CMD_PERMS,
+ "On or Off"),
AP_INIT_TAKE1("DirectoryIndexRedirect", configure_redirect,
NULL, DIR_CMD_PERMS, "On, Off, or a 3xx status code."),
@@ -134,7 +145,8 @@ static void *create_dir_config(apr_pool_t *p, char *dummy)
dir_config_rec *new = apr_pcalloc(p, sizeof(dir_config_rec));
new->index_names = NULL;
- new->do_slash = SLASH_UNSET;
+ new->do_slash = MODDIR_UNSET;
+ new->checkhandler = MODDIR_UNSET;
new->redirect_index = REDIRECT_UNSET;
return (void *) new;
}
@@ -147,7 +159,9 @@ static void *merge_dir_configs(apr_pool_t *p, void *basev, void *addv)
new->index_names = add->index_names ? add->index_names : base->index_names;
new->do_slash =
- (add->do_slash == SLASH_UNSET) ? base->do_slash : add->do_slash;
+ (add->do_slash == MODDIR_UNSET) ? base->do_slash : add->do_slash;
+ new->checkhandler =
+ (add->checkhandler == MODDIR_UNSET) ? base->checkhandler : add->checkhandler;
new->redirect_index=
(add->redirect_index == REDIRECT_UNSET) ? base->redirect_index : add->redirect_index;
new->dflt = add->dflt ? add->dflt : base->dflt;
@@ -260,6 +274,15 @@ static int fixup_dir(request_rec *r)
return HTTP_MOVED_PERMANENTLY;
}
+ /* we're running between mod_rewrites fixup and its internal redirect handler, step aside */
+ if (!strcmp(r->handler, REWRITE_REDIRECT_HANDLER_NAME)) {
+ return DECLINED;
+ }
+
+ if (d->checkhandler == MODDIR_ON && strcmp(r->handler, DIR_MAGIC_TYPE)) {
+ return DECLINED;
+ }
+
if (d->index_names) {
names_ptr = (char **)d->index_names->elts;
num_names = d->index_names->nelts;
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 0ac4dc9d..7646407b 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -192,6 +192,9 @@ static const char* really_last_key = "rewrite_really_last";
#define OPTION_NOSLASH 1<<3
#define OPTION_ANYURI 1<<4
#define OPTION_MERGEBASE 1<<5
+#define OPTION_INHERIT_DOWN 1<<6
+#define OPTION_INHERIT_DOWN_BEFORE 1<<7
+#define OPTION_IGNORE_INHERIT 1<<8
#ifndef RAND_MAX
#define RAND_MAX 32767
@@ -231,6 +234,9 @@ static const char* really_last_key = "rewrite_really_last";
#define subreq_ok(r) (!r->main || \
(r->main->uri && r->uri && strcmp(r->main->uri, r->uri)))
+#ifndef REWRITE_MAX_ROUNDS
+#define REWRITE_MAX_ROUNDS 32000
+#endif
/*
* +-------------------------------------------------------+
@@ -308,6 +314,7 @@ typedef struct {
data_item *env; /* added environment variables */
data_item *cookie; /* added cookies */
int skip; /* number of next rules to skip */
+ int maxrounds; /* limit on number of loops with N flag */
} rewriterule_entry;
typedef struct {
@@ -2135,7 +2142,10 @@ static char *lookup_variable(char *var, rewrite_ctx *ctx)
break;
case 16:
- if (!strcmp(var, "REQUEST_FILENAME")) {
+ if (*var == 'C' && !strcmp(var, "CONN_REMOTE_ADDR")) {
+ result = r->connection->client_ip;
+ }
+ else if (!strcmp(var, "REQUEST_FILENAME")) {
result = r->filename; /* same as script_filename (15) */
}
break;
@@ -2758,7 +2768,9 @@ static void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv)
a->server = overrides->server;
- if (a->options & OPTION_INHERIT) {
+ if (a->options & OPTION_INHERIT ||
+ (base->options & OPTION_INHERIT_DOWN &&
+ !(a->options & OPTION_IGNORE_INHERIT))) {
/*
* local directives override
* and anything else is inherited
@@ -2770,7 +2782,9 @@ static void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv)
a->rewriterules = apr_array_append(p, overrides->rewriterules,
base->rewriterules);
}
- else if (a->options & OPTION_INHERIT_BEFORE) {
+ else if (a->options & OPTION_INHERIT_BEFORE ||
+ (base->options & OPTION_INHERIT_DOWN_BEFORE &&
+ !(a->options & OPTION_IGNORE_INHERIT))) {
/*
* local directives override
* and anything else is inherited (preserving order)
@@ -2847,13 +2861,17 @@ static void *config_perdir_merge(apr_pool_t *p, void *basev, void *overridesv)
a->directory = overrides->directory;
- if (a->options & OPTION_INHERIT) {
+ if (a->options & OPTION_INHERIT ||
+ (base->options & OPTION_INHERIT_DOWN &&
+ !(a->options & OPTION_IGNORE_INHERIT))) {
a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
base->rewriteconds);
a->rewriterules = apr_array_append(p, overrides->rewriterules,
base->rewriterules);
}
- else if (a->options & OPTION_INHERIT_BEFORE) {
+ else if (a->options & OPTION_INHERIT_BEFORE ||
+ (base->options & OPTION_INHERIT_DOWN_BEFORE &&
+ !(a->options & OPTION_IGNORE_INHERIT))) {
a->rewriteconds = apr_array_append(p, base->rewriteconds,
overrides->rewriteconds);
a->rewriterules = apr_array_append(p, base->rewriterules,
@@ -2905,6 +2923,15 @@ static const char *cmd_rewriteoptions(cmd_parms *cmd,
else if (!strcasecmp(w, "inheritbefore")) {
options |= OPTION_INHERIT_BEFORE;
}
+ else if (!strcasecmp(w, "inheritdown")) {
+ options |= OPTION_INHERIT_DOWN;
+ }
+ else if(!strcasecmp(w, "inheritdownbefore")) {
+ options |= OPTION_INHERIT_DOWN_BEFORE;
+ }
+ else if (!strcasecmp(w, "ignoreinherit")) {
+ options |= OPTION_IGNORE_INHERIT;
+ }
else if (!strcasecmp(w, "allownoslash")) {
options |= OPTION_NOSLASH;
}
@@ -3498,6 +3525,10 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg,
}
else if (!*key || !strcasecmp(key, "ext")) { /* next */
cfg->flags |= RULEFLAG_NEWROUND;
+ if (val && *val) {
+ cfg->maxrounds = atoi(val);
+ }
+
}
else if (((*key == 'S' || *key == 's') && !key[1])
|| !strcasecmp(key, "osubreq")) { /* nosubreq */
@@ -3649,6 +3680,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
newrule->env = NULL;
newrule->cookie = NULL;
newrule->skip = 0;
+ newrule->maxrounds = REWRITE_MAX_ROUNDS;
if (a3 != NULL) {
if ((err = cmd_parseflagfield(cmd->pool, newrule, a3,
cmd_rewriterule_setflag)) != NULL) {
@@ -4192,6 +4224,7 @@ static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
int rc;
int s;
rewrite_ctx *ctx;
+ int round = 1;
ctx = apr_palloc(r->pool, sizeof(*ctx));
ctx->perdir = perdir;
@@ -4280,6 +4313,15 @@ static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
* the rewriting ruleset again.
*/
if (p->flags & RULEFLAG_NEWROUND) {
+ if (++round >= p->maxrounds) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02596)
+ "RewriteRule '%s' and URI '%s' exceeded "
+ "maximum number of rounds (%d) via the [N] flag",
+ p->pattern, r->uri, p->maxrounds);
+
+ r->status = HTTP_INTERNAL_SERVER_ERROR;
+ return ACTION_STATUS;
+ }
goto loop;
}
@@ -5004,7 +5046,7 @@ static int hook_fixup(request_rec *r)
rewritelog((r, 1, dconf->directory, "internal redirect with %s "
"[INTERNAL REDIRECT]", r->filename));
r->filename = apr_pstrcat(r->pool, "redirect:", r->filename, NULL);
- r->handler = "redirect-handler";
+ r->handler = REWRITE_REDIRECT_HANDLER_NAME;
return OK;
}
}
@@ -5050,7 +5092,7 @@ static int hook_mimetype(request_rec *r)
*/
static int handler_redirect(request_rec *r)
{
- if (strcmp(r->handler, "redirect-handler")) {
+ if (strcmp(r->handler, REWRITE_REDIRECT_HANDLER_NAME)) {
return DECLINED;
}
diff --git a/modules/mappers/mod_rewrite.h b/modules/mappers/mod_rewrite.h
index 040baeea..8fa158ec 100644
--- a/modules/mappers/mod_rewrite.h
+++ b/modules/mappers/mod_rewrite.h
@@ -29,6 +29,8 @@
#include "apr_optional.h"
#include "httpd.h"
+#define REWRITE_REDIRECT_HANDLER_NAME "redirect-handler"
+
/* rewrite map function prototype */
typedef char *(rewrite_mapfunc_t)(request_rec *r, char *key);
diff --git a/modules/metadata/mod_expires.c b/modules/metadata/mod_expires.c
index 2ef3d899..049cfc22 100644
--- a/modules/metadata/mod_expires.c
+++ b/modules/metadata/mod_expires.c
@@ -267,10 +267,7 @@ static char *check_code(apr_pool_t *p, const char *code, char **real_code)
/* <type>
*/
word = ap_getword_conf(p, &code);
- if (word[0]) {
- /* do nothing */
- }
- else {
+ if (word[0] == '\0') {
return apr_pstrcat(p, "bad expires code, missing <type>", NULL);
}
diff --git a/modules/metadata/mod_remoteip.c b/modules/metadata/mod_remoteip.c
index b0af3a32..61087590 100644
--- a/modules/metadata/mod_remoteip.c
+++ b/modules/metadata/mod_remoteip.c
@@ -37,11 +37,11 @@ typedef struct {
} remoteip_proxymatch_t;
typedef struct {
- /** The header to retrieve a proxy-via ip list */
+ /** The header to retrieve a proxy-via IP list */
const char *header_name;
/** A header to record the proxied IP's
* (removed as the physical connection and
- * from the proxy-via ip header value list)
+ * from the proxy-via IP header value list)
*/
const char *proxies_header_name;
/** A list of trusted proxies, ideally configured
@@ -53,9 +53,9 @@ typedef struct {
typedef struct {
apr_sockaddr_t *useragent_addr;
char *useragent_ip;
- /** The list of proxy ip's ignored as remote ip's */
+ /** The list of proxy IP's ignored as remote IP's */
const char *proxy_ips;
- /** The remaining list of untrusted proxied remote ip's */
+ /** The remaining list of untrusted proxied remote IP's */
const char *proxied_remote;
} remoteip_req_t;
@@ -198,7 +198,7 @@ static const char *proxylist_read(cmd_parms *cmd, void *cfg,
while (!(ap_cfg_getline(lbuf, MAX_STRING_LEN, cfp))) {
args = lbuf;
while (*(arg = ap_getword_conf(cmd->temp_pool, &args)) != '\0') {
- if (*arg == '#' || *arg == '\0') {
+ if (*arg == '#') {
break;
}
errmsg = proxies_set(cmd, cfg, arg);
@@ -246,14 +246,14 @@ static int remoteip_modify_request(request_rec *r)
while (remote) {
- /* verify c->client_addr is trusted if there is a trusted proxy list
+ /* verify user agent IP against the trusted proxy list
*/
if (config->proxymatch_ip) {
int i;
remoteip_proxymatch_t *match;
match = (remoteip_proxymatch_t *)config->proxymatch_ip->elts;
for (i = 0; i < config->proxymatch_ip->nelts; ++i) {
- if (apr_ipsubnet_test(match[i].ip, c->client_addr)) {
+ if (apr_ipsubnet_test(match[i].ip, temp_sa)) {
internal = match[i].internal;
break;
}
@@ -290,7 +290,7 @@ static int remoteip_modify_request(request_rec *r)
break;
}
- /* We map as IPv4 rather than IPv6 for equivilant host names
+ /* We map as IPv4 rather than IPv6 for equivalent host names
* or IPV4OVERIPV6
*/
rv = apr_sockaddr_info_get(&temp_sa, parse_remote,
@@ -309,7 +309,6 @@ static int remoteip_modify_request(request_rec *r)
remote = parse_remote;
}
break;
-
}
addrbyte = (unsigned char *) &temp_sa->sa.sin.sin_addr;
@@ -353,16 +352,17 @@ static int remoteip_modify_request(request_rec *r)
/* save away our results */
if (!req) {
req = (remoteip_req_t *) apr_palloc(r->pool, sizeof(remoteip_req_t));
+ req->useragent_ip = r->useragent_ip;
}
/* Set useragent_ip string */
if (!internal) {
if (proxy_ips) {
proxy_ips = apr_pstrcat(r->pool, proxy_ips, ", ",
- c->client_ip, NULL);
+ req->useragent_ip, NULL);
}
else {
- proxy_ips = c->client_ip;
+ proxy_ips = req->useragent_ip;
}
}
diff --git a/modules/proxy/NWGNUproxy b/modules/proxy/NWGNUproxy
index 443b4cb2..b66cccfa 100644
--- a/modules/proxy/NWGNUproxy
+++ b/modules/proxy/NWGNUproxy
@@ -302,6 +302,7 @@ $(OBJDIR)/mod_proxy.imp: NWGNUproxy
@echo $(DL) ap_proxy_location_reverse_map,$(DL)>> $@
@echo $(DL) ap_proxy_parse_wstatus,$(DL)>> $@
@echo $(DL) ap_proxy_pass_brigade,$(DL)>> $@
+ @echo $(DL) ap_proxy_port_of_scheme,$(DL)>> $@
@echo $(DL) ap_proxy_post_request,$(DL)>> $@
@echo $(DL) ap_proxy_pre_http_request,$(DL)>> $@
@echo $(DL) ap_proxy_pre_request,$(DL)>> $@
@@ -317,6 +318,7 @@ $(OBJDIR)/mod_proxy.imp: NWGNUproxy
@echo $(DL) ap_proxy_sync_balancer,$(DL)>> $@
@echo $(DL) ap_proxy_trans_match,$(DL)>> $@
@echo $(DL) ap_proxy_valid_balancer_name,$(DL)>> $@
+ @echo $(DL) ap_proxy_worker_name,$(DL)>> $@
@echo $(DL) ap_proxyerror$(DL)>> $@
#
diff --git a/modules/proxy/balancers/mod_lbmethod_heartbeat.c b/modules/proxy/balancers/mod_lbmethod_heartbeat.c
index 77fb994f..e9e10344 100644
--- a/modules/proxy/balancers/mod_lbmethod_heartbeat.c
+++ b/modules/proxy/balancers/mod_lbmethod_heartbeat.c
@@ -162,7 +162,7 @@ static apr_status_t readfile_heartbeats(const char *path, apr_hash_t *servers,
continue;
}
- ip = apr_pstrndup(pool, buf, t - buf);
+ ip = apr_pstrmemdup(pool, buf, t - buf);
t++;
server = apr_hash_get(servers, ip, APR_HASH_KEY_STRING);
diff --git a/modules/proxy/fcgi_protocol.h b/modules/proxy/fcgi_protocol.h
deleted file mode 100644
index e69de29b..00000000
--- a/modules/proxy/fcgi_protocol.h
+++ /dev/null
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 88ddb899..627a0496 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -744,22 +744,52 @@ static int proxy_walk(request_rec *r)
*/
const char *proxyname = r->filename + 6;
int j;
+ apr_pool_t *rxpool = NULL;
for (j = 0; j < num_sec; ++j)
{
+ int nmatch = 0;
+ int i;
+ ap_regmatch_t *pmatch = NULL;
+
entry_config = sec_proxy[j];
entry_proxy = ap_get_module_config(entry_config, &proxy_module);
- /* XXX: What about case insensitive matching ???
- * Compare regex, fnmatch or string as appropriate
- * If the entry doesn't relate, then continue
- */
- if (entry_proxy->r
- ? ap_regexec(entry_proxy->r, proxyname, 0, NULL, 0)
- : (entry_proxy->p_is_fnmatch
- ? apr_fnmatch(entry_proxy->p, proxyname, 0)
- : strncmp(proxyname, entry_proxy->p,
- strlen(entry_proxy->p)))) {
+ if (entry_proxy->r) {
+
+ if (entry_proxy->refs && entry_proxy->refs->nelts) {
+ if (!rxpool) {
+ apr_pool_create(&rxpool, r->pool);
+ }
+ nmatch = entry_proxy->refs->nelts;
+ pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t));
+ }
+
+ if (ap_regexec(entry_proxy->r, proxyname, nmatch, pmatch, 0)) {
+ continue;
+ }
+
+ for (i = 0; i < nmatch; i++) {
+ if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
+ ((const char **)entry_proxy->refs->elts)[i]) {
+ apr_table_setn(r->subprocess_env,
+ ((const char **)entry_proxy->refs->elts)[i],
+ apr_pstrndup(r->pool,
+ proxyname + pmatch[i].rm_so,
+ pmatch[i].rm_eo - pmatch[i].rm_so));
+ }
+ }
+ }
+
+ else if (
+ /* XXX: What about case insensitive matching ???
+ * Compare regex, fnmatch or string as appropriate
+ * If the entry doesn't relate, then continue
+ */
+ entry_proxy->p_is_fnmatch ? apr_fnmatch(entry_proxy->p,
+ proxyname, 0) :
+ strncmp(proxyname, entry_proxy->p,
+ strlen(entry_proxy->p))) {
continue;
}
per_dir_defaults = ap_merge_per_dir_configs(r->pool, per_dir_defaults,
@@ -768,6 +798,10 @@ static int proxy_walk(request_rec *r)
r->per_dir_config = per_dir_defaults;
+ if (rxpool) {
+ apr_pool_destroy(rxpool);
+ }
+
return OK;
}
@@ -1314,6 +1348,7 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
new->p = add->p;
new->p_is_fnmatch = add->p_is_fnmatch;
new->r = add->r;
+ new->refs = add->refs;
/* Put these in the dir config so they work inside <Location> */
new->raliases = apr_array_append(p, base->raliases, add->raliases);
@@ -1335,7 +1370,6 @@ static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
return new;
}
-
static const char *
add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, int regex)
{
@@ -1410,6 +1444,36 @@ static const char *
return add_proxy(cmd, dummy, f1, r1, 1);
}
+static char *de_socketfy(apr_pool_t *p, char *url)
+{
+ char *ptr;
+ /*
+ * We could be passed a URL during the config stage that contains
+ * the UDS path... ignore it
+ */
+ if (!strncasecmp(url, "unix:", 5) &&
+ ((ptr = ap_strchr(url, '|')) != NULL)) {
+ /* move past the 'unix:...|' UDS path info */
+ char *ret, *c;
+
+ ret = ptr + 1;
+ /* special case: "unix:....|scheme:" is OK, expand
+ * to "unix:....|scheme://localhost"
+ * */
+ c = ap_strchr(ret, ':');
+ if (c == NULL) {
+ return NULL;
+ }
+ if (c[1] == '\0') {
+ return apr_pstrcat(p, ret, "//localhost", NULL);
+ }
+ else {
+ return ret;
+ }
+ }
+ return url;
+}
+
static const char *
add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
{
@@ -1501,7 +1565,7 @@ static const char *
}
new->fake = apr_pstrdup(cmd->pool, f);
- new->real = apr_pstrdup(cmd->pool, r);
+ new->real = apr_pstrdup(cmd->pool, de_socketfy(cmd->pool, r));
new->flags = flags;
if (use_regex) {
new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
@@ -1537,7 +1601,7 @@ static const char *
new->balancer = balancer;
}
else {
- proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, r);
+ proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, de_socketfy(cmd->pool, r));
int reuse = 0;
if (!worker) {
const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r, 0);
@@ -1549,14 +1613,14 @@ static const char *
reuse = 1;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01145)
"Sharing worker '%s' instead of creating new worker '%s'",
- worker->s->name, new->real);
+ ap_proxy_worker_name(cmd->pool, worker), new->real);
}
for (i = 0; i < arr->nelts; i++) {
if (reuse) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(01146)
"Ignoring parameter '%s=%s' for worker '%s' because of worker sharing",
- elts[i].key, elts[i].val, worker->s->name);
+ elts[i].key, elts[i].val, ap_proxy_worker_name(cmd->pool, worker));
} else {
const char *err = set_worker_param(cmd->pool, worker, elts[i].key,
elts[i].val);
@@ -1662,6 +1726,7 @@ static const char *
for (i = 0; i < conf->noproxies->nelts; i++) {
if (strcasecmp(arg, list[i].name) == 0) { /* ignore case for host names */
found = 1;
+ break;
}
}
@@ -1695,8 +1760,10 @@ static const char *
/* Don't duplicate entries */
for (i = 0; i < conf->dirconn->nelts; i++) {
- if (strcasecmp(arg, list[i].name) == 0)
+ if (strcasecmp(arg, list[i].name) == 0) {
found = 1;
+ break;
+ }
}
if (!found) {
@@ -2013,7 +2080,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
}
/* Try to find existing worker */
- worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, name);
+ worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, de_socketfy(cmd->temp_pool, name));
if (!worker) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147)
"Defining worker '%s' for balancer '%s'",
@@ -2022,13 +2089,13 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01148)
"Defined worker '%s' for balancer '%s'",
- worker->s->name, balancer->s->name);
+ ap_proxy_worker_name(cmd->pool, worker), balancer->s->name);
PROXY_COPY_CONF_PARAMS(worker, conf);
} else {
reuse = 1;
ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01149)
"Sharing worker '%s' instead of creating new worker '%s'",
- worker->s->name, name);
+ ap_proxy_worker_name(cmd->pool, worker), name);
}
arr = apr_table_elts(params);
@@ -2037,7 +2104,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
if (reuse) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(01150)
"Ignoring parameter '%s=%s' for worker '%s' because of worker sharing",
- elts[i].key, elts[i].val, worker->s->name);
+ elts[i].key, elts[i].val, ap_proxy_worker_name(cmd->pool, worker));
} else {
err = set_worker_param(cmd->pool, worker, elts[i].key,
elts[i].val);
@@ -2099,7 +2166,7 @@ static const char *
}
}
else {
- worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, name);
+ worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, de_socketfy(cmd->temp_pool, name));
if (!worker) {
if (in_proxy_section) {
err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
@@ -2196,17 +2263,6 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
return "Regex could not be compiled";
}
}
- else if (!strcmp(cmd->path, "~")) {
- cmd->path = ap_getword_conf(cmd->pool, &arg);
- if (!cmd->path)
- return "<Proxy ~ > block must specify a path";
- if (strncasecmp(cmd->path, "proxy:", 6))
- cmd->path += 6;
- r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);
- if (!r) {
- return "Regex could not be compiled";
- }
- }
/* initialize our config and fetch it */
conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,
@@ -2220,6 +2276,11 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
conf->p = cmd->path;
conf->p_is_fnmatch = apr_fnmatch_test(conf->p);
+ if (r) {
+ conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
+ ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ }
+
ap_add_per_proxy_conf(cmd->server, new_dir_conf);
if (*arg != '\0') {
@@ -2245,7 +2306,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
}
else {
worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf,
- conf->p);
+ de_socketfy(cmd->temp_pool, (char*)conf->p));
if (!worker) {
err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
sconf, conf->p, 0);
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index aef8b209..eb0106d6 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -219,6 +219,10 @@ typedef struct {
unsigned int error_override_set:1;
unsigned int alias_set:1;
unsigned int add_forwarded_headers:1;
+
+ /** Named back references */
+ apr_array_header_t *refs;
+
} proxy_dir_conf;
/* if we interpolate env vars per-request, we'll need a per-request
@@ -249,6 +253,7 @@ typedef struct {
unsigned int need_flush:1; /* Flag to decide whether we need to flush the
* filter chain or not */
unsigned int inreslist:1; /* connection in apr_reslist? */
+ const char *uds_path; /* Unix domain socket path */
} proxy_conn_rec;
typedef struct {
@@ -341,6 +346,7 @@ typedef struct {
char route[PROXY_WORKER_MAX_ROUTE_SIZE]; /* balancing route */
char redirect[PROXY_WORKER_MAX_ROUTE_SIZE]; /* temporary balancing redirection route */
char flusher[PROXY_WORKER_MAX_SCHEME_SIZE]; /* flush provider used by mod_proxy_fdpass */
+ char uds_path[PROXY_WORKER_MAX_NAME_SIZE]; /* path to worker's unix domain socket if applicable */
int lbset; /* load balancer cluster set */
int retries; /* number of retries on this worker */
int lbstatus; /* Current lbstatus */
@@ -586,6 +592,16 @@ typedef __declspec(dllimport) const char *
/* Connection pool API */
/**
+ * Return the user-land, UDS aware worker name
+ * @param p memory pool used for displaying worker name
+ * @param worker the worker
+ * @return name
+ */
+
+PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
+ proxy_worker *worker);
+
+/**
* Get the worker from proxy configuration
* @param p memory pool used for finding worker
* @param balancer the balancer that the worker belongs to
@@ -983,6 +999,13 @@ APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection,
*/
int ap_proxy_lb_workers(void);
+/**
+ * Return the port number of a known scheme (eg: http -> 80).
+ * @param scheme scheme to test
+ * @return port number or 0 if unknown
+ */
+PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(const char *scheme);
+
extern module PROXY_DECLARE_DATA proxy_module;
#endif /*MOD_PROXY_H*/
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index 3736156a..cf52a7d9 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -32,7 +32,7 @@ static int proxy_ajp_canon(request_rec *r, char *url)
char *host, *path, sport[7];
char *search = NULL;
const char *err;
- apr_port_t port = AJP13_DEF_PORT;
+ apr_port_t port, def_port;
/* ap_port_of_scheme() */
if (strncasecmp(url, "ajp:", 4) == 0) {
@@ -48,6 +48,8 @@ static int proxy_ajp_canon(request_rec *r, char *url)
* do syntactic check.
* We break the URL into host, port, path, search
*/
+ port = def_port = ap_proxy_port_of_scheme("ajp");
+
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00867) "error parsing URL %s: %s",
@@ -71,7 +73,10 @@ static int proxy_ajp_canon(request_rec *r, char *url)
if (path == NULL)
return HTTP_BAD_REQUEST;
- apr_snprintf(sport, sizeof(sport), ":%d", port);
+ if (port != def_port)
+ apr_snprintf(sport, sizeof(sport), ":%d", port);
+ else
+ sport[0] = '\0';
if (ap_strchr_c(host, ':')) {
/* if literal IPv6 address */
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 5fd9e151..c927d3bf 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -118,7 +118,8 @@ static void init_balancer_members(apr_pool_t *p, server_rec *s,
int worker_is_initialized;
proxy_worker *worker = *workers;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01158)
- "Looking at %s -> %s initialized?", balancer->s->name, worker->s->name);
+ "Looking at %s -> %s initialized?", balancer->s->name,
+ ap_proxy_worker_name(p, worker));
worker_is_initialized = PROXY_WORKER_IS_INITIALIZED(worker);
if (!worker_is_initialized) {
ap_proxy_initialize_worker(worker, s, p);
@@ -638,10 +639,11 @@ static int proxy_balancer_post_request(proxy_worker *worker,
int val = ((int *)balancer->errstatuses->elts)[i];
if (r->status == val) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01174)
- "%s: Forcing worker (%s) into error state "
+ "%s: Forcing worker (%s) into error state "
"due to status code %d matching 'failonstatus' "
"balancer parameter",
- balancer->s->name, worker->s->name, val);
+ balancer->s->name, ap_proxy_worker_name(r->pool, worker),
+ val);
worker->s->status |= PROXY_WORKER_IN_ERROR;
worker->s->error_time = apr_time_now();
break;
@@ -654,7 +656,7 @@ static int proxy_balancer_post_request(proxy_worker *worker,
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02460)
"%s: Forcing worker (%s) into error state "
"due to timeout and 'failonstatus' parameter being set",
- balancer->s->name, worker->s->name);
+ balancer->s->name, ap_proxy_worker_name(r->pool, worker));
worker->s->status |= PROXY_WORKER_IN_ERROR;
worker->s->error_time = apr_time_now();
@@ -1282,7 +1284,7 @@ static int balancer_handler(request_rec *r)
worker = *workers;
/* Start proxy_worker */
ap_rputs(" <httpd:worker>\n", r);
- ap_rvputs(r, " <httpd:name>", worker->s->name,
+ ap_rvputs(r, " <httpd:name>", ap_proxy_worker_name(r->pool, worker),
"</httpd:name>\n", NULL);
ap_rvputs(r, " <httpd:scheme>", worker->s->scheme,
"</httpd:scheme>\n", NULL);
@@ -1531,7 +1533,8 @@ static int balancer_handler(request_rec *r)
ap_escape_uri(r->pool, worker->s->name),
"&nonce=", balancer->s->nonce,
"\">", NULL);
- ap_rvputs(r, worker->s->name, "</a></td>", NULL);
+ ap_rvputs(r, (*worker->s->uds_path ? "<i>" : ""), ap_proxy_worker_name(r->pool, worker),
+ (*worker->s->uds_path ? "</i>" : ""), "</a></td>", NULL);
ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route),
NULL);
ap_rvputs(r, "</td><td>",
@@ -1556,7 +1559,7 @@ static int balancer_handler(request_rec *r)
ap_rputs("<hr />\n", r);
if (wsel && bsel) {
ap_rputs("<h3>Edit worker settings for ", r);
- ap_rvputs(r, wsel->s->name, "</h3>\n", NULL);
+ ap_rvputs(r, (*wsel->s->uds_path?"<i>":""), ap_proxy_worker_name(r->pool, wsel), (*wsel->s->uds_path?"</i>":""), "</h3>\n", NULL);
ap_rputs("<form method=\"POST\" enctype=\"application/x-www-form-urlencoded\" action=\"", r);
ap_rvputs(r, ap_escape_uri(r->pool, action), "\">\n", NULL);
ap_rputs("<dl>\n<table><tr><td>Load factor:</td><td><input name='w_lf' id='w_lf' type=text ", r);
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index ee702900..4f407951 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -30,7 +30,7 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
{
char *host, sport[7];
const char *err, *path;
- apr_port_t port = 8000;
+ apr_port_t port, def_port;
if (strncasecmp(url, "fcgi:", 5) == 0) {
url += 5;
@@ -39,9 +39,10 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
return DECLINED;
}
+ port = def_port = ap_proxy_port_of_scheme("fcgi");
+
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"canonicalising URL %s", url);
-
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01059)
@@ -49,7 +50,10 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
return HTTP_BAD_REQUEST;
}
- apr_snprintf(sport, sizeof(sport), ":%d", port);
+ if (port != def_port)
+ apr_snprintf(sport, sizeof(sport), ":%d", port);
+ else
+ sport[0] = '\0';
if (ap_strchr_c(host, ':')) {
/* if literal IPv6 address */
@@ -510,7 +514,7 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
if (version != AP_FCGI_VERSION_1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01068)
- "Got bogus version %d", (int) header.version);
+ "Got bogus version %d", (int)version);
rv = APR_EINVAL;
break;
}
@@ -750,7 +754,7 @@ static int proxy_fcgi_handler(request_rec *r, proxy_worker *worker,
int status;
char server_portstr[32];
conn_rec *origin = NULL;
- proxy_conn_rec *backend = NULL;
+ proxy_conn_rec *backend;
proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
&proxy_module);
@@ -763,10 +767,7 @@ static int proxy_fcgi_handler(request_rec *r, proxy_worker *worker,
"url: %s proxyname: %s proxyport: %d",
url, proxyname, proxyport);
- if (strncasecmp(url, "fcgi:", 5) == 0) {
- url += 5;
- }
- else {
+ if (strncasecmp(url, "fcgi:", 5) != 0) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01077) "declining URL %s", url);
return DECLINED;
}
@@ -774,16 +775,14 @@ static int proxy_fcgi_handler(request_rec *r, proxy_worker *worker,
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01078) "serving URL %s", url);
/* Create space for state information */
- if (! backend) {
- status = ap_proxy_acquire_connection(FCGI_SCHEME, &backend, worker,
- r->server);
- if (status != OK) {
- if (backend) {
- backend->close = 1;
- ap_proxy_release_connection(FCGI_SCHEME, backend, r->server);
- }
- return status;
+ status = ap_proxy_acquire_connection(FCGI_SCHEME, &backend, worker,
+ r->server);
+ if (status != OK) {
+ if (backend) {
+ backend->close = 1;
+ ap_proxy_release_connection(FCGI_SCHEME, backend, r->server);
}
+ return status;
}
backend->is_ssl = 0;
diff --git a/modules/proxy/mod_proxy_fcgi.dsp b/modules/proxy/mod_proxy_fcgi.dsp
index fdb34b3d..ac778edc 100644
--- a/modules/proxy/mod_proxy_fcgi.dsp
+++ b/modules/proxy/mod_proxy_fcgi.dsp
@@ -114,10 +114,6 @@ SOURCE=.\mod_proxy_fcgi.c
SOURCE=.\mod_proxy.h
# End Source File
-# Begin Source File
-
-SOURCE=.\fcgi_protocol.h
-# End Source File
# End Group
# Begin Source File
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
index 680be8b8..cf5d5130 100644
--- a/modules/proxy/mod_proxy_ftp.c
+++ b/modules/proxy/mod_proxy_ftp.c
@@ -975,7 +975,6 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
char *buf, *connectname;
apr_port_t connectport;
- char buffer[MAX_STRING_LEN];
char *ftpmessage = NULL;
char *path, *strp, *type_suffix, *cwd = NULL;
apr_uri_t uri;
@@ -1626,7 +1625,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
"Error reading from remote server");
}
if (rc != 200) {
- return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, buffer);
+ return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage);
}
/* signal that we must use the EPRT/PORT loop */
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 714014de..3aec4cfe 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -54,7 +54,7 @@ static int proxy_http_canon(request_rec *r, char *url)
else {
return DECLINED;
}
- def_port = apr_uri_port_of_scheme(scheme);
+ port = def_port = ap_proxy_port_of_scheme(scheme);
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"HTTP: canonicalising URL %s", url);
@@ -62,7 +62,6 @@ static int proxy_http_canon(request_rec *r, char *url)
/* do syntatic check.
* We break the URL into host, port, path, search
*/
- port = def_port;
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
if (err) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01083)
@@ -319,6 +318,12 @@ static int stream_reqbody_chunked(apr_pool_t *p,
HUGE_STRING_LEN);
if (status != APR_SUCCESS) {
+ conn_rec *c = r->connection;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02608)
+ "read request body failed to %pI (%s)"
+ " from %s (%s)", p_conn->addr,
+ p_conn->hostname ? p_conn->hostname: "",
+ c->client_ip, c->remote_host ? c->remote_host: "");
return HTTP_BAD_REQUEST;
}
}
@@ -464,6 +469,12 @@ static int stream_reqbody_cl(apr_pool_t *p,
HUGE_STRING_LEN);
if (status != APR_SUCCESS) {
+ conn_rec *c = r->connection;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02609)
+ "read request body failed to %pI (%s)"
+ " from %s (%s)", p_conn->addr,
+ p_conn->hostname ? p_conn->hostname: "",
+ c->client_ip, c->remote_host ? c->remote_host: "");
return HTTP_BAD_REQUEST;
}
}
@@ -607,6 +618,12 @@ static int spool_reqbody_cl(apr_pool_t *p,
HUGE_STRING_LEN);
if (status != APR_SUCCESS) {
+ conn_rec *c = r->connection;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02610)
+ "read request body failed to %pI (%s)"
+ " from %s (%s)", p_conn->addr,
+ p_conn->hostname ? p_conn->hostname: "",
+ c->client_ip, c->remote_host ? c->remote_host: "");
return HTTP_BAD_REQUEST;
}
}
@@ -710,7 +727,7 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
force10 = 0;
}
- header_brigade = apr_brigade_create(p, origin->bucket_alloc);
+ header_brigade = apr_brigade_create(p, bucket_alloc);
rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
worker, conf, uri, url, server_portstr,
&old_cl_val, &old_te_val);
@@ -1197,7 +1214,7 @@ apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec
}
/*
- * Limit the number of interim respones we sent back to the client. Otherwise
+ * Limit the number of interim responses we sent back to the client. Otherwise
* we suffer from a memory build up. Besides there is NO sense in sending back
* an unlimited number of interim responses to the client. Thus if we cross
* this limit send back a 502 (Bad Gateway).
@@ -1699,6 +1716,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
continue;
}
else if (rv == APR_EOF) {
+ backend->close = 1;
break;
}
else if (rv != APR_SUCCESS) {
@@ -1813,6 +1831,10 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
}
} while (interim_response && (interim_response < AP_MAX_INTERIM_RESPONSES));
+ /* We have to cleanup bb brigade, because buckets inserted to it could be
+ * created from scpool and this pool can be freed before this brigade. */
+ apr_brigade_cleanup(bb);
+
/* See define of AP_MAX_INTERIM_RESPONSES for why */
if (interim_response >= AP_MAX_INTERIM_RESPONSES) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index 365a2054..d17eaff6 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -249,7 +249,7 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02444) "error apr_poll()");
return HTTP_INTERNAL_SERVER_ERROR;
}
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02445)
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02445)
"woke from poll(), i=%d", pollcnt);
for (pi = 0; pi < pollcnt; pi++) {
@@ -258,7 +258,7 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
if (cur->desc.s == sock) {
pollevent = cur->rtnevents;
if (pollevent & APR_POLLIN) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02446)
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02446)
"sock was readable");
rv = proxy_wstunnel_transfer(r, backconn, c, bb, "sock");
}
@@ -268,16 +268,33 @@ static int ap_proxy_wstunnel_request(apr_pool_t *p, request_rec *r,
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02447)
"err/hup on backconn");
}
+ else {
+ rv = APR_EGENERAL;
+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02605)
+ "unknown event on backconn %d", pollevent);
+ }
if (rv != APR_SUCCESS)
client_error = 1;
}
else if (cur->desc.s == client_socket) {
pollevent = cur->rtnevents;
if (pollevent & APR_POLLIN) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02448)
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02448)
"client was readable");
rv = proxy_wstunnel_transfer(r, c, backconn, bb, "client");
}
+ else if ((pollevent & APR_POLLERR)
+ || (pollevent & APR_POLLHUP)) {
+ rv = APR_EPIPE;
+ c->aborted = 1;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02607)
+ "err/hup on client conn");
+ }
+ else {
+ rv = APR_EGENERAL;
+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO(02606)
+ "unknown event on client conn %d", pollevent);
+ }
}
else {
rv = APR_EBADF;
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index d3dd0686..d05f0cdc 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -21,6 +21,7 @@
#include "apr_version.h"
#include "apr_hash.h"
#include "proxy_util.h"
+#include "ajp.h"
#if APR_HAVE_UNISTD_H
#include <unistd.h> /* for getpid() */
@@ -31,6 +32,13 @@
#define apr_socket_create apr_socket_create_ex
#endif
+#if APR_HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#if (APR_MAJOR_VERSION < 2)
+#include "apr_support.h" /* for apr_wait_for_io_or_timeout() */
+#endif
+
APLOG_USE_MODULE(proxy);
/*
@@ -86,14 +94,20 @@ PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
char *thenil;
apr_size_t thelen;
+ /* special case handling */
+ if (!dlen) {
+ /* XXX: APR_ENOSPACE would be better */
+ return APR_EGENERAL;
+ }
+ if (!src) {
+ *dst = '\0';
+ return APR_SUCCESS;
+ }
thenil = apr_cpystrn(dst, src, dlen);
thelen = thenil - dst;
- /* Assume the typical case is smaller copying into bigger
- so we have a fast return */
- if ((thelen < dlen-1) || ((strlen(src)) == thelen)) {
+ if (src[thelen] == '\0') {
return APR_SUCCESS;
}
- /* XXX: APR_ENOSPACE would be better */
return APR_EGENERAL;
}
@@ -1218,11 +1232,11 @@ PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer,
} else {
action = "re-using";
}
+ balancer->s = shm;
+ balancer->s->index = i;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02337)
"%s shm[%d] (0x%pp) for %s", action, i, (void *)shm,
balancer->s->name);
- balancer->s = shm;
- balancer->s->index = i;
/* the below should always succeed */
lbmethod = ap_lookup_provider(PROXY_LBMETHOD, balancer->s->lbpname, "0");
if (lbmethod) {
@@ -1356,7 +1370,7 @@ static apr_status_t connection_cleanup(void *theconn)
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, conn->pool, APLOGNO(00923)
"Pooled connection 0x%pp for worker %s has been"
" already returned to the connection pool.", conn,
- worker->s->name);
+ ap_proxy_worker_name(conn->pool, worker));
return APR_SUCCESS;
}
@@ -1480,6 +1494,16 @@ static apr_status_t connection_destructor(void *resource, void *params,
* WORKER related...
*/
+PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p,
+ proxy_worker *worker)
+{
+ if (!(*worker->s->uds_path) || !p) {
+ /* just in case */
+ return worker->s->name;
+ }
+ return apr_pstrcat(p, "unix:", worker->s->uds_path, "|", worker->s->name, NULL);
+}
+
PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
proxy_balancer *balancer,
proxy_server_conf *conf,
@@ -1495,6 +1519,10 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
char *url_copy;
int i;
+ if (!url) {
+ return NULL;
+ }
+
c = ap_strchr_c(url, ':');
if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
return NULL;
@@ -1573,20 +1601,47 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
int do_malloc)
{
int rv;
- apr_uri_t uri;
+ apr_uri_t uri, urisock;
proxy_worker_shared *wshared;
- char *ptr;
+ char *ptr, *sockpath = NULL;
+ /*
+ * Look to see if we are using UDS:
+ * require format: unix:/path/foo/bar.sock|http://ignored/path2/
+ * This results in talking http to the socket at /path/foo/bar.sock
+ */
+ ptr = ap_strchr((char *)url, '|');
+ if (ptr) {
+ *ptr = '\0';
+ rv = apr_uri_parse(p, url, &urisock);
+ if (rv == APR_SUCCESS && !strcasecmp(urisock.scheme, "unix")) {
+ sockpath = ap_runtime_dir_relative(p, urisock.path);;
+ url = ptr+1; /* so we get the scheme for the uds */
+ }
+ else {
+ *ptr = '|';
+ }
+ }
rv = apr_uri_parse(p, url, &uri);
if (rv != APR_SUCCESS) {
- return "Unable to parse URL";
+ return apr_pstrcat(p, "Unable to parse URL: ", url, NULL);
}
- if (!uri.hostname || !uri.scheme) {
- return "URL must be absolute!";
+ if (!uri.scheme) {
+ return apr_pstrcat(p, "URL must be absolute!: ", url, NULL);
+ }
+ /* allow for unix:/path|http: */
+ if (!uri.hostname) {
+ if (sockpath) {
+ uri.hostname = "localhost";
+ }
+ else {
+ return apr_pstrcat(p, "URL must be absolute!: ", url, NULL);
+ }
+ }
+ else {
+ ap_str_tolower(uri.hostname);
}
-
- ap_str_tolower(uri.hostname);
ap_str_tolower(uri.scheme);
/*
* Workers can be associated w/ balancers or on their
@@ -1642,6 +1697,15 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p,
wshared->hash.def = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_DEFAULT);
wshared->hash.fnv = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_FNV);
wshared->was_malloced = (do_malloc != 0);
+ if (sockpath) {
+ if (PROXY_STRNCPY(wshared->uds_path, sockpath) != APR_SUCCESS) {
+ return apr_psprintf(p, "worker uds path (%s) too long", sockpath);
+ }
+
+ }
+ else {
+ *wshared->uds_path = '\0';
+ }
(*worker)->hash = wshared->hash;
(*worker)->context = NULL;
@@ -1670,12 +1734,18 @@ PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_wo
} else {
action = "re-using";
}
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02338)
- "%s shm[%d] (0x%pp) for worker: %s", action, i, (void *)shm,
- worker->s->name);
-
worker->s = shm;
worker->s->index = i;
+ {
+ apr_pool_t *pool;
+ apr_pool_create(&pool, ap_server_conf->process->pool);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02338)
+ "%s shm[%d] (0x%pp) for worker: %s", action, i, (void *)shm,
+ ap_proxy_worker_name(pool, worker));
+ if (pool) {
+ apr_pool_destroy(pool);
+ }
+ }
return APR_SUCCESS;
}
@@ -1687,11 +1757,13 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
if (worker->s->status & PROXY_WORKER_INITIALIZED) {
/* The worker is already initialized */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00924)
- "worker %s shared already initialized", worker->s->name);
+ "worker %s shared already initialized",
+ ap_proxy_worker_name(p, worker));
}
else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00925)
- "initializing worker %s shared", worker->s->name);
+ "initializing worker %s shared",
+ ap_proxy_worker_name(p, worker));
/* Set default parameters */
if (!worker->s->retry_set) {
worker->s->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
@@ -1727,11 +1799,13 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
/* What if local is init'ed and shm isn't?? Even possible? */
if (worker->local_status & PROXY_WORKER_INITIALIZED) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00926)
- "worker %s local already initialized", worker->s->name);
+ "worker %s local already initialized",
+ ap_proxy_worker_name(p, worker));
}
else {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00927)
- "initializing worker %s local", worker->s->name);
+ "initializing worker %s local",
+ ap_proxy_worker_name(p, worker));
apr_global_mutex_lock(proxy_mutex);
/* Now init local worker data */
if (worker->tmutex == NULL) {
@@ -2023,6 +2097,29 @@ PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
(*conn)->close = 0;
(*conn)->inreslist = 0;
+ if (*worker->s->uds_path) {
+ if ((*conn)->uds_path == NULL) {
+ /* use (*conn)->pool instead of worker->cp->pool to match lifetime */
+ (*conn)->uds_path = apr_pstrdup((*conn)->pool, worker->s->uds_path);
+ }
+ if ((*conn)->uds_path) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02545)
+ "%s: has determined UDS as %s",
+ proxy_function, (*conn)->uds_path);
+ }
+ else {
+ /* should never happen */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02546)
+ "%s: cannot determine UDS (%s)",
+ proxy_function, worker->s->uds_path);
+
+ }
+ }
+ else {
+ (*conn)->uds_path = NULL;
+ }
+
+
return OK;
}
@@ -2065,7 +2162,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
NULL));
}
if (!uri->port) {
- uri->port = apr_uri_port_of_scheme(uri->scheme);
+ uri->port = ap_proxy_port_of_scheme(uri->scheme);
}
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00944)
@@ -2094,7 +2191,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
* spilling the cached addr from the worker.
*/
if (!conn->hostname || !worker->s->is_address_reusable ||
- worker->s->disablereuse) {
+ worker->s->disablereuse || *worker->s->uds_path) {
if (proxyname) {
conn->hostname = apr_pstrdup(conn->pool, proxyname);
conn->port = proxyport;
@@ -2132,7 +2229,8 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
conn->port = uri->port;
}
socket_cleanup(conn);
- if (!worker->s->is_address_reusable || worker->s->disablereuse) {
+ if (!(*worker->s->uds_path) &&
+ (!worker->s->is_address_reusable || worker->s->disablereuse)) {
/*
* Only do a lookup if we should not reuse the backend address.
* Otherwise we will look it up once for the worker.
@@ -2143,7 +2241,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
conn->pool);
}
}
- if (worker->s->is_address_reusable && !worker->s->disablereuse) {
+ if (!(*worker->s->uds_path) && worker->s->is_address_reusable && !worker->s->disablereuse) {
/*
* Looking up the backend address for the worker only makes sense if
* we can reuse the address.
@@ -2372,6 +2470,52 @@ static apr_status_t send_http_connect(proxy_conn_rec *backend,
}
+#if APR_HAVE_SYS_UN_H
+/* lifted from mod_proxy_fdpass.c; tweaked addrlen in connect() call */
+static apr_status_t socket_connect_un(apr_socket_t *sock,
+ struct sockaddr_un *sa)
+{
+ apr_status_t rv;
+ apr_os_sock_t rawsock;
+ apr_interval_time_t t;
+
+ rv = apr_os_sock_get(&rawsock, sock);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_socket_timeout_get(sock, &t);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ do {
+ const socklen_t addrlen = APR_OFFSETOF(struct sockaddr_un, sun_path)
+ + strlen(sa->sun_path) + 1;
+ rv = connect(rawsock, (struct sockaddr*)sa, addrlen);
+ } while (rv == -1 && errno == EINTR);
+
+ if ((rv == -1) && (errno == EINPROGRESS || errno == EALREADY)
+ && (t > 0)) {
+#if APR_MAJOR_VERSION < 2
+ rv = apr_wait_for_io_or_timeout(NULL, sock, 0);
+#else
+ rv = apr_socket_wait(sock, APR_WAIT_WRITE);
+#endif
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ if (rv == -1 && errno != EISCONN) {
+ return errno;
+ }
+
+ return APR_SUCCESS;
+}
+#endif
+
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
proxy_conn_rec *conn,
proxy_worker *worker,
@@ -2396,93 +2540,131 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
proxy_function);
}
}
- while (backend_addr && !connected) {
- if ((rv = apr_socket_create(&newsock, backend_addr->family,
- SOCK_STREAM, APR_PROTO_TCP,
- conn->scpool)) != APR_SUCCESS) {
- loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
- ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00952)
- "%s: error creating fam %d socket for target %s",
- proxy_function,
- backend_addr->family,
- worker->s->hostname);
- /*
- * this could be an IPv6 address from the DNS but the
- * local machine won't give us an IPv6 socket; hopefully the
- * DNS returned an additional address to try
- */
- backend_addr = backend_addr->next;
- continue;
- }
- conn->connection = NULL;
+ while ((backend_addr || conn->uds_path) && !connected) {
+#if APR_HAVE_SYS_UN_H
+ if (conn->uds_path)
+ {
+ struct sockaddr_un sa;
- if (worker->s->recv_buffer_size > 0 &&
- (rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF,
- worker->s->recv_buffer_size))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00953)
- "apr_socket_opt_set(SO_RCVBUF): Failed to set "
- "ProxyReceiveBufferSize, using default");
- }
+ rv = apr_socket_create(&newsock, AF_UNIX, SOCK_STREAM, 0,
+ conn->scpool);
+ if (rv != APR_SUCCESS) {
+ loglevel = APLOG_ERR;
+ ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(02453)
+ "%s: error creating Unix domain socket for "
+ "target %s",
+ proxy_function,
+ worker->s->hostname);
+ break;
+ }
+ conn->connection = NULL;
- rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1);
- if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00954)
- "apr_socket_opt_set(APR_TCP_NODELAY): "
- "Failed to set");
- }
+ sa.sun_family = AF_UNIX;
+ apr_cpystrn(sa.sun_path, conn->uds_path, sizeof(sa.sun_path));
- /* Set a timeout for connecting to the backend on the socket */
- if (worker->s->conn_timeout_set) {
- apr_socket_timeout_set(newsock, worker->s->conn_timeout);
- }
- else if (worker->s->timeout_set) {
- apr_socket_timeout_set(newsock, worker->s->timeout);
- }
- else if (conf->timeout_set) {
- apr_socket_timeout_set(newsock, conf->timeout);
- }
- else {
- apr_socket_timeout_set(newsock, s->timeout);
- }
- /* Set a keepalive option */
- if (worker->s->keepalive) {
- if ((rv = apr_socket_opt_set(newsock,
- APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00955)
- "apr_socket_opt_set(SO_KEEPALIVE): Failed to set"
- " Keepalive");
+ rv = socket_connect_un(newsock, &sa);
+ if (rv != APR_SUCCESS) {
+ apr_socket_close(newsock);
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(02454)
+ "%s: attempt to connect to Unix domain socket "
+ "%s (%s) failed",
+ proxy_function,
+ conn->uds_path,
+ worker->s->hostname);
+ break;
}
}
- ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s,
- "%s: fam %d socket created to connect to %s",
- proxy_function, backend_addr->family, worker->s->hostname);
+ else
+#endif
+ {
+ if ((rv = apr_socket_create(&newsock, backend_addr->family,
+ SOCK_STREAM, APR_PROTO_TCP,
+ conn->scpool)) != APR_SUCCESS) {
+ loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
+ ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00952)
+ "%s: error creating fam %d socket for "
+ "target %s",
+ proxy_function,
+ backend_addr->family,
+ worker->s->hostname);
+ /*
+ * this could be an IPv6 address from the DNS but the
+ * local machine won't give us an IPv6 socket; hopefully the
+ * DNS returned an additional address to try
+ */
+ backend_addr = backend_addr->next;
+ continue;
+ }
+ conn->connection = NULL;
+
+ if (worker->s->recv_buffer_size > 0 &&
+ (rv = apr_socket_opt_set(newsock, APR_SO_RCVBUF,
+ worker->s->recv_buffer_size))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00953)
+ "apr_socket_opt_set(SO_RCVBUF): Failed to set "
+ "ProxyReceiveBufferSize, using default");
+ }
- if (conf->source_address_set) {
- local_addr = apr_pmemdup(conn->pool, conf->source_address,
- sizeof(apr_sockaddr_t));
- local_addr->pool = conn->pool;
- rv = apr_socket_bind(newsock, local_addr);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00956)
- "%s: failed to bind socket to local address",
- proxy_function);
+ rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1);
+ if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00954)
+ "apr_socket_opt_set(APR_TCP_NODELAY): "
+ "Failed to set");
}
- }
- /* make the connection out of the socket */
- rv = apr_socket_connect(newsock, backend_addr);
+ /* Set a timeout for connecting to the backend on the socket */
+ if (worker->s->conn_timeout_set) {
+ apr_socket_timeout_set(newsock, worker->s->conn_timeout);
+ }
+ else if (worker->s->timeout_set) {
+ apr_socket_timeout_set(newsock, worker->s->timeout);
+ }
+ else if (conf->timeout_set) {
+ apr_socket_timeout_set(newsock, conf->timeout);
+ }
+ else {
+ apr_socket_timeout_set(newsock, s->timeout);
+ }
+ /* Set a keepalive option */
+ if (worker->s->keepalive) {
+ if ((rv = apr_socket_opt_set(newsock,
+ APR_SO_KEEPALIVE, 1)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00955)
+ "apr_socket_opt_set(SO_KEEPALIVE): Failed to set"
+ " Keepalive");
+ }
+ }
+ ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s,
+ "%s: fam %d socket created to connect to %s",
+ proxy_function, backend_addr->family, worker->s->hostname);
+
+ if (conf->source_address_set) {
+ local_addr = apr_pmemdup(conn->pool, conf->source_address,
+ sizeof(apr_sockaddr_t));
+ local_addr->pool = conn->pool;
+ rv = apr_socket_bind(newsock, local_addr);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00956)
+ "%s: failed to bind socket to local address",
+ proxy_function);
+ }
+ }
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- apr_socket_close(newsock);
- loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
- ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00957)
- "%s: attempt to connect to %pI (%s) failed",
- proxy_function,
- backend_addr,
- worker->s->hostname);
- backend_addr = backend_addr->next;
- continue;
+ /* make the connection out of the socket */
+ rv = apr_socket_connect(newsock, backend_addr);
+
+ /* if an error occurred, loop round and try again */
+ if (rv != APR_SUCCESS) {
+ apr_socket_close(newsock);
+ loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
+ ap_log_error(APLOG_MARK, loglevel, rv, s, APLOGNO(00957)
+ "%s: attempt to connect to %pI (%s) failed",
+ proxy_function,
+ backend_addr,
+ worker->s->hostname);
+ backend_addr = backend_addr->next;
+ continue;
+ }
}
/* Set a timeout on the socket */
@@ -2498,7 +2680,7 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
conn->sock = newsock;
- if (conn->forward) {
+ if (!conn->uds_path && conn->forward) {
forward_info *forward = (forward_info *)conn->forward;
/*
* For HTTP CONNECT we need to prepend CONNECT request before
@@ -2779,7 +2961,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_sync_balancer(proxy_balancer *b, server_rec
found = 1;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02402)
"re-grabbing shm[%d] (0x%pp) for worker: %s", i, (void *)shm,
- worker->s->name);
+ ap_proxy_worker_name(conf->pool, worker));
break;
}
}
@@ -3190,6 +3372,9 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc,
if (transferred != -1)
p_conn->worker->s->transferred += transferred;
status = ap_pass_brigade(origin->output_filters, bb);
+ /* Cleanup the brigade now to avoid buckets lifetime
+ * issues in case of error returned below. */
+ apr_brigade_cleanup(bb);
if (status != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01084)
"pass request body failed to %pI (%s)",
@@ -3209,10 +3394,41 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc,
return HTTP_BAD_REQUEST;
}
}
- apr_brigade_cleanup(bb);
return OK;
}
+/* Fill in unknown schemes from apr_uri_port_of_scheme() */
+
+typedef struct proxy_schemes_t {
+ const char *name;
+ apr_port_t default_port;
+} proxy_schemes_t ;
+
+static proxy_schemes_t pschemes[] =
+{
+ {"fcgi", 8000},
+ {"ajp", AJP13_DEF_PORT},
+ { NULL, 0xFFFF } /* unknown port */
+};
+
+PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(const char *scheme)
+{
+ if (scheme) {
+ apr_port_t port;
+ if ((port = apr_uri_port_of_scheme(scheme)) != 0) {
+ return port;
+ } else {
+ proxy_schemes_t *pscheme;
+ for (pscheme = pschemes; pscheme->name != NULL; ++pscheme) {
+ if (strcasecmp(scheme, pscheme->name) == 0) {
+ return pscheme->default_port;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
void proxy_util_register_hooks(apr_pool_t *p)
{
APR_REGISTER_OPTIONAL_FN(ap_proxy_retry_worker);
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
index 89c80747..0b472a24 100644
--- a/modules/session/mod_session.c
+++ b/modules/session/mod_session.c
@@ -62,16 +62,16 @@ static int session_included(request_rec * r, session_dir_conf * conf)
included = 0;
for (i = 0; !included && i < conf->includes->nelts; i++) {
const char *include = includes[i];
- if (strncmp(r->uri, include, strlen(include))) {
+ if (strncmp(r->uri, include, strlen(include)) == 0) {
included = 1;
}
}
}
if (conf->excludes->nelts) {
- for (i = 0; included && i < conf->includes->nelts; i++) {
+ for (i = 0; included && i < conf->excludes->nelts; i++) {
const char *exclude = excludes[i];
- if (strncmp(r->uri, exclude, strlen(exclude))) {
+ if (strncmp(r->uri, exclude, strlen(exclude)) == 0) {
included = 0;
}
}
@@ -126,22 +126,28 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
/* found a session that hasn't expired? */
now = apr_time_now();
- if (!zz || (zz->expiry && zz->expiry < now)) {
+ if (zz) {
+ if (zz->expiry && zz->expiry < now) {
+ zz = NULL;
+ }
+ else {
+ /* having a session we cannot decode is just as good as having
+ none at all */
+ rv = ap_run_session_decode(r, zz);
+ if (OK != rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
+ "error while decoding the session, "
+ "session not loaded: %s", r->uri);
+ zz = NULL;
+ }
+ }
+ }
- /* no luck, create a blank session */
+ /* no luck, create a blank session */
+ if (!zz) {
zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec));
zz->pool = r->pool;
zz->entries = apr_table_make(zz->pool, 10);
-
- }
- else {
- rv = ap_run_session_decode(r, zz);
- if (OK != rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817)
- "error while decoding the session, "
- "session not loaded: %s", r->uri);
- return rv;
- }
}
/* make sure the expiry and maxage are set, if present */
diff --git a/modules/session/mod_session_crypto.c b/modules/session/mod_session_crypto.c
index 984a0487..4d65bb83 100644
--- a/modules/session/mod_session_crypto.c
+++ b/modules/session/mod_session_crypto.c
@@ -593,7 +593,7 @@ static const char *set_crypto_passphrase_file(cmd_parms *cmd, void *config,
while (!(ap_cfg_getline(buffer, sizeof(buffer), file))) {
args = buffer;
while (*(arg = ap_getword_conf(cmd->pool, &args)) != '\0') {
- if (*arg == '#' || *arg == 0) {
+ if (*arg == '#') {
break;
}
set_crypto_passphrase(cmd, config, arg);
diff --git a/modules/slotmem/mod_slotmem_shm.c b/modules/slotmem/mod_slotmem_shm.c
index 1f7e557c..0c4da367 100644
--- a/modules/slotmem/mod_slotmem_shm.c
+++ b/modules/slotmem/mod_slotmem_shm.c
@@ -354,6 +354,8 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
if (strcmp(next->name, fname) == 0) {
/* we already have it */
*new = next;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02603)
+ "create found %s in global list", fname);
return APR_SUCCESS;
}
if (!next->next) {
@@ -362,6 +364,8 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
next = next->next;
}
}
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02602)
+ "create didn't find %s in global list", fname);
}
else {
fbased = 0;
@@ -379,15 +383,24 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
rv = APR_EINVAL;
}
if (rv == APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598)
+ "apr_shm_attach() succeeded");
+
/* check size */
if (apr_shm_size_get(shm) != size) {
apr_shm_detach(shm);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599)
+ "existing shared memory for %s could not be used (failed size check)",
+ fname);
return APR_EINVAL;
}
ptr = (char *)apr_shm_baseaddr_get(shm);
memcpy(&desc, ptr, sizeof(desc));
if (desc.size != item_size || desc.num != item_num) {
apr_shm_detach(shm);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600)
+ "existing shared memory for %s could not be used (failed contents check)",
+ fname);
return APR_EINVAL;
}
ptr += AP_SLOTMEM_OFFSET;
@@ -401,6 +414,11 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
else {
rv = apr_shm_create(&shm, size, NULL, gpool);
}
+ ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
+ rv, ap_server_conf, APLOGNO(02611)
+ "create: apr_shm_create(%s) %s",
+ fname ? fname : "",
+ rv == APR_SUCCESS ? "succeeded" : "failed");
if (rv != APR_SUCCESS) {
return rv;
}
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index f0499405..6e632a38 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -91,9 +91,6 @@ static const command_rec ssl_config_cmds[] = {
SSL_CMD_SRV(CertificateChainFile, TAKE1,
"SSL Server CA Certificate Chain file "
"('/path/to/file' - PEM encoded)")
- SSL_CMD_SRV(PKCS7CertificateFile, TAKE1,
- "PKCS#7 file containing server certificate and chain"
- " certificates ('/path/to/file' - PEM encoded)")
#ifdef HAVE_TLS_SESSION_TICKETS
SSL_CMD_SRV(SessionTicketKeyFile, TAKE1,
"TLS session ticket encryption/decryption key file (RFC 5077) "
@@ -266,6 +263,11 @@ static const command_rec ssl_config_cmds[] = {
"SSL stapling option to Force the OCSP Stapling URL")
#endif
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CMD_SRV(OpenSSLConfCmd, TAKE2,
+ "OpenSSL configuration command")
+#endif
+
/* Deprecated directives. */
AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
"SSLLog directive is no longer supported - use ErrorLog."),
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index f519151e..2dda6a95 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -66,7 +66,6 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
sizeof(ssl_randseed_t));
mc->tVHostKeys = apr_hash_make(pool);
mc->tPrivateKey = apr_hash_make(pool);
- mc->tPublicCert = apr_hash_make(pool);
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
mc->szCryptoDevice = NULL;
#endif
@@ -98,7 +97,7 @@ BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
** _________________________________________________________________
*/
-static void modssl_ctx_init(modssl_ctx_t *mctx)
+static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
{
mctx->sc = NULL; /* set during module init */
@@ -116,7 +115,6 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)
mctx->pphrase_dialog_type = SSL_PPTYPE_UNSET;
mctx->pphrase_dialog_path = NULL;
- mctx->pkcs7 = NULL;
mctx->cert_chain = NULL;
mctx->crl_path = NULL;
@@ -153,6 +151,13 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)
mctx->srp_unknown_user_seed = NULL;
mctx->srp_vbase = NULL;
#endif
+#ifdef HAVE_SSL_CONF_CMD
+ mctx->ssl_ctx_config = SSL_CONF_CTX_new();
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_FILE);
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_SERVER);
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
+ mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
+#endif
}
static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
@@ -162,7 +167,7 @@ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy));
- modssl_ctx_init(mctx);
+ modssl_ctx_init(mctx, p);
mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp));
@@ -180,11 +185,12 @@ static void modssl_ctx_init_server(SSLSrvConfigRec *sc,
mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
- modssl_ctx_init(mctx);
+ modssl_ctx_init(mctx, p);
mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks));
- /* mctx->pks->... certs/keys are set during module init */
+ mctx->pks->cert_files = apr_array_make(p, 3, sizeof(char *));
+ mctx->pks->key_files = apr_array_make(p, 3, sizeof(char *));
#ifdef HAVE_TLS_SESSION_TICKETS
mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key));
@@ -241,7 +247,8 @@ void *ssl_config_server_create(apr_pool_t *p, server_rec *s)
#define cfgMergeBool(el) cfgMerge(el, UNSET)
#define cfgMergeInt(el) cfgMerge(el, UNSET)
-static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
@@ -284,31 +291,33 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
cfgMergeString(srp_vfile);
cfgMergeString(srp_unknown_user_seed);
#endif
+
+#ifdef HAVE_SSL_CONF_CMD
+ cfgMergeArray(ssl_ctx_param);
+#endif
}
-static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
- modssl_ctx_cfg_merge(base, add, mrg);
+ modssl_ctx_cfg_merge(p, base, add, mrg);
cfgMergeString(pkp->cert_file);
cfgMergeString(pkp->cert_path);
cfgMergeString(pkp->ca_cert_file);
}
-static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge_server(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
- int i;
+ modssl_ctx_cfg_merge(p, base, add, mrg);
- modssl_ctx_cfg_merge(base, add, mrg);
-
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- cfgMergeString(pks->cert_files[i]);
- cfgMergeString(pks->key_files[i]);
- }
+ cfgMergeArray(pks->cert_files);
+ cfgMergeArray(pks->key_files);
cfgMergeString(pks->ca_name_path);
cfgMergeString(pks->ca_name_file);
@@ -346,9 +355,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
cfgMergeBool(compression);
#endif
- modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
+ modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy);
- modssl_ctx_cfg_merge_server(base->server, add->server, mrg->server);
+ modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server);
return mrg;
}
@@ -707,7 +716,7 @@ const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag)
sc->cipher_server_pref = flag?TRUE:FALSE;
return NULL;
#else
- return "SSLHonorCiperOrder unsupported; not implemented by the SSL library";
+ return "SSLHonorCipherOrder unsupported; not implemented by the SSL library";
#endif
}
@@ -745,56 +754,20 @@ static const char *ssl_cmd_check_dir(cmd_parms *parms,
}
-#define SSL_AIDX_CERTS 1
-#define SSL_AIDX_KEYS 2
-
-static const char *ssl_cmd_check_aidx_max(cmd_parms *parms,
- const char *arg,
- int idx)
-{
- SSLSrvConfigRec *sc = mySrvConfig(parms->server);
- const char *err, *desc=NULL, **files=NULL;
- int i;
-
- if ((err = ssl_cmd_check_file(parms, &arg))) {
- return err;
- }
-
- switch (idx) {
- case SSL_AIDX_CERTS:
- desc = "certificates";
- files = sc->server->pks->cert_files;
- break;
- case SSL_AIDX_KEYS:
- desc = "private keys";
- files = sc->server->pks->key_files;
- break;
- }
-
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- if (!files[i]) {
- files[i] = arg;
- return NULL;
- }
- }
-
- return apr_psprintf(parms->pool,
- "%s: only up to %d "
- "different %s per virtual host allowed",
- parms->cmd->name, SSL_AIDX_MAX, desc);
-}
-
const char *ssl_cmd_SSLCertificateFile(cmd_parms *cmd,
void *dcfg,
const char *arg)
{
-
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
const char *err;
- if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_CERTS))) {
+ if ((err = ssl_cmd_check_file(cmd, &arg))) {
return err;
}
+ *(const char **)apr_array_push(sc->server->pks->cert_files) =
+ apr_pstrdup(cmd->pool, arg);
+
return NULL;
}
@@ -802,19 +775,6 @@ const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd,
void *dcfg,
const char *arg)
{
- const char *err;
-
- if ((err = ssl_cmd_check_aidx_max(cmd, arg, SSL_AIDX_KEYS))) {
- return err;
- }
-
- return NULL;
-}
-
-const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd,
- void *dcfg,
- const char *arg)
-{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
const char *err;
@@ -822,23 +782,30 @@ const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd,
return err;
}
- sc->server->cert_chain = arg;
+ *(const char **)apr_array_push(sc->server->pks->key_files) =
+ apr_pstrdup(cmd->pool, arg);
return NULL;
}
-const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *cmd,
+const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd,
void *dcfg,
const char *arg)
{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
const char *err;
+ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_STARTUP, 0, cmd->server,
+ APLOGNO(02559)
+ "The SSLCertificateChainFile directive (%s:%d) is deprecated, "
+ "SSLCertificateFile should be used instead",
+ cmd->directive->filename, cmd->directive->line_num);
+
if ((err = ssl_cmd_check_file(cmd, &arg))) {
return err;
}
- sc->server->pkcs7 = arg;
+ sc->server->cert_chain = arg;
return NULL;
}
@@ -1808,6 +1775,38 @@ const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg,
#endif /* HAVE_OCSP_STAPLING */
+#ifdef HAVE_SSL_CONF_CMD
+const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg,
+ const char *arg1, const char *arg2)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
+ int value_type = SSL_CONF_cmd_value_type(cctx, arg1);
+ const char *err;
+ ssl_ctx_param_t *param;
+
+ if (value_type == SSL_CONF_TYPE_UNKNOWN) {
+ return apr_psprintf(cmd->pool,
+ "'%s': invalid OpenSSL configuration command",
+ arg1);
+ }
+
+ if (value_type == SSL_CONF_TYPE_FILE) {
+ if ((err = ssl_cmd_check_file(cmd, &arg2)))
+ return err;
+ }
+ else if (value_type == SSL_CONF_TYPE_DIR) {
+ if ((err = ssl_cmd_check_dir(cmd, &arg2)))
+ return err;
+ }
+
+ param = apr_array_push(sc->server->ssl_ctx_param);
+ param->name = arg1;
+ param->value = arg2;
+ return NULL;
+}
+#endif
+
#ifdef HAVE_SRP
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
@@ -1852,8 +1851,12 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
modssl_pk_server_t *const pks = sc->server->pks;
int i;
- for (i = 0; (i < SSL_AIDX_MAX) && pks->cert_files[i]; i++) {
- apr_file_printf(out, " %s\n", pks->cert_files[i]);
+ for (i = 0; (i < pks->cert_files->nelts) &&
+ APR_ARRAY_IDX(pks->cert_files, i, const char *);
+ i++) {
+ apr_file_printf(out, " %s\n",
+ APR_ARRAY_IDX(pks->cert_files,
+ i, const char *));
}
}
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index f6e010de..21c68a1a 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -59,13 +59,15 @@ static void ssl_add_version_components(apr_pool_t *p,
/*
* Per-module initialization
*/
-int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp,
- server_rec *base_server)
+apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp,
+ server_rec *base_server)
{
SSLModConfigRec *mc = myModConfig(base_server);
SSLSrvConfigRec *sc;
server_rec *s;
+ apr_status_t rv;
+ apr_array_header_t *pphrases;
if (SSLeay() < SSL_LIBRARY_VERSION) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01882)
@@ -152,7 +154,9 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
* SSL external crypto device ("engine") support
*/
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
- ssl_init_Engine(base_server, p);
+ if ((rv = ssl_init_Engine(base_server, p)) != APR_SUCCESS) {
+ return rv;
+ }
#endif
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01883)
@@ -175,7 +179,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
else {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
}
}
@@ -186,14 +190,6 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
#endif
/*
- * read server private keys/public certs into memory.
- * decrypting any encrypted keys via configured SSLPassPhraseDialogs
- * anything that needs to live longer than ptemp needs to also survive
- * restarts, in which case they'll live inside s->process->pool.
- */
- ssl_pphrase_Handle(base_server, ptemp);
-
- /*
* initialize the mutex handling
*/
if (!ssl_mutex_init(base_server, p)) {
@@ -206,7 +202,11 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
/*
* initialize session caching
*/
- ssl_scache_init(base_server, p);
+ if ((rv = ssl_scache_init(base_server, p)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ pphrases = apr_array_make(ptemp, 2, sizeof(char *));
/*
* initialize servers
@@ -225,13 +225,25 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
/*
* Read the server certificate and key
*/
- ssl_init_ConfigureServer(s, p, ptemp, sc);
+ if ((rv = ssl_init_ConfigureServer(s, p, ptemp, sc, pphrases))
+ != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ if (pphrases->nelts > 0) {
+ memset(pphrases->elts, 0, pphrases->elt_size * pphrases->nelts);
+ pphrases->nelts = 0;
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02560)
+ "Init: Wiped out the queried pass phrases from memory");
}
/*
* Configuration consistency checks
*/
- ssl_init_CheckServers(base_server, ptemp);
+ if ((rv = ssl_init_CheckServers(base_server, ptemp)) != APR_SUCCESS) {
+ return rv;
+ }
/*
* Announce mod_ssl and SSL library in HTTP Server field
@@ -249,7 +261,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
* a hardware accellerator card for crypto operations.
*/
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
-void ssl_init_Engine(server_rec *s, apr_pool_t *p)
+apr_status_t ssl_init_Engine(server_rec *s, apr_pool_t *p)
{
SSLModConfigRec *mc = myModConfig(s);
ENGINE *e;
@@ -260,7 +272,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p)
"Init: Failed to load Crypto Device API `%s'",
mc->szCryptoDevice);
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
if (strEQ(mc->szCryptoDevice, "chil")) {
@@ -272,7 +284,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p)
"Init: Failed to enable Crypto Device API `%s'",
mc->szCryptoDevice);
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890)
"Init: loaded Crypto Device API `%s'",
@@ -280,47 +292,19 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p)
ENGINE_free(e);
}
-}
-#endif
-static void ssl_init_server_check(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
-{
- /*
- * check for important parameters and the
- * possibility that the user forgot to set them.
- */
- if (!mctx->pks->cert_files[0] && !mctx->pkcs7) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01891)
- "No SSL Certificate set [hint: SSLCertificateFile]");
- ssl_die(s);
- }
-
- /*
- * Check for problematic re-initializations
- */
- if (mctx->pks->certs[SSL_AIDX_RSA] ||
- mctx->pks->certs[SSL_AIDX_DSA]
-#ifdef HAVE_ECC
- || mctx->pks->certs[SSL_AIDX_ECC]
-#endif
- )
- {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01892)
- "Illegal attempt to re-initialise SSL for server "
- "(SSLEngine On should go in the VirtualHost, not in global scope.)");
- ssl_die(s);
- }
+ return APR_SUCCESS;
}
+#endif
#ifdef HAVE_TLSEXT
-static void ssl_init_ctx_tls_extensions(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_tls_extensions(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
+ apr_status_t rv;
+
/*
* Configure TLS extensions support
*/
@@ -337,7 +321,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
"Unable to initialize TLS servername extension "
"callback (incompatible OpenSSL version?)");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
#ifdef HAVE_OCSP_STAPLING
@@ -345,7 +329,9 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
* OCSP Stapling support, status_request extension
*/
if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) {
- modssl_init_stapling(s, p, ptemp, mctx);
+ if ((rv = modssl_init_stapling(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
+ }
}
#endif
@@ -364,7 +350,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
"[%s seed]",
mctx->srp_unknown_user_seed ? "with" : "without");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
err = SRP_VBASE_init(mctx->srp_vbase, mctx->srp_vfile);
@@ -372,7 +358,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02310)
"Unable to load SRP verifier file [error %d]", err);
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
SSL_CTX_set_srp_username_callback(mctx->ssl_ctx,
@@ -380,13 +366,14 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
SSL_CTX_set_srp_cb_arg(mctx->ssl_ctx, mctx);
}
#endif
+ return APR_SUCCESS;
}
#endif
-static void ssl_init_ctx_protocol(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_protocol(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
SSL_CTX *ctx = NULL;
MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL;
@@ -400,7 +387,7 @@ static void ssl_init_ctx_protocol(server_rec *s,
if (protocol == SSL_PROTOCOL_NONE) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231)
"No SSL protocols available [hint: SSLProtocol]");
- ssl_die(s);
+ return ssl_die(s);
}
cp = apr_pstrcat(p,
@@ -517,6 +504,8 @@ static void ssl_init_ctx_protocol(server_rec *s,
if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED)
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
+
+ return APR_SUCCESS;
}
static void ssl_init_ctx_session_cache(server_rec *s,
@@ -548,10 +537,10 @@ static void ssl_init_ctx_callbacks(server_rec *s,
SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
}
-static void ssl_init_ctx_verify(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_verify(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
SSL_CTX *ctx = mctx->ssl_ctx;
@@ -596,7 +585,7 @@ static void ssl_init_ctx_verify(server_rec *s,
"Unable to configure verify locations "
"for client authentication");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
if (mctx->pks && (mctx->pks->ca_name_file || mctx->pks->ca_name_path)) {
@@ -611,7 +600,7 @@ static void ssl_init_ctx_verify(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01896)
"Unable to determine list of acceptable "
"CA certificates for client authentication");
- ssl_die(s);
+ return ssl_die(s);
}
SSL_CTX_set_client_CA_list(ctx, ca_list);
@@ -631,12 +620,14 @@ static void ssl_init_ctx_verify(server_rec *s,
"verification!? [Hint: SSLCACertificate*]");
}
}
+
+ return APR_SUCCESS;
}
-static void ssl_init_ctx_cipher_suite(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_cipher_suite(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
SSL_CTX *ctx = mctx->ssl_ctx;
const char *suite;
@@ -658,14 +649,16 @@ static void ssl_init_ctx_cipher_suite(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01898)
"Unable to configure permitted SSL ciphers");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
+
+ return APR_SUCCESS;
}
-static void ssl_init_ctx_crl(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_crl(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx);
unsigned long crlflags = 0;
@@ -682,9 +675,9 @@ static void ssl_init_ctx_crl(server_rec *s,
"Host %s: CRL checking has been enabled, but "
"neither %sCARevocationFile nor %sCARevocationPath "
"is configured", mctx->sc->vhost_id, cfgp, cfgp);
- ssl_die(s);
+ return ssl_die(s);
}
- return;
+ return APR_SUCCESS;
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01900)
@@ -696,7 +689,7 @@ static void ssl_init_ctx_crl(server_rec *s,
"Host %s: unable to configure X.509 CRL storage "
"for certificate revocation", mctx->sc->vhost_id);
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
switch (mctx->crl_check_mode) {
@@ -718,39 +711,19 @@ static void ssl_init_ctx_crl(server_rec *s,
"but CRL checking (%sCARevocationCheck) is not "
"enabled", mctx->sc->vhost_id, cfgp);
}
-}
-static void ssl_init_ctx_pkcs7_cert_chain(server_rec *s, modssl_ctx_t *mctx)
-{
- STACK_OF(X509) *certs = ssl_read_pkcs7(s, mctx->pkcs7);
- int n;
- STACK_OF(X509) *extra_certs = NULL;
-
-#ifdef OPENSSL_NO_SSL_INTERN
- SSL_CTX_get_extra_chain_certs(mctx->ssl_ctx, &extra_certs);
-#else
- extra_certs = mctx->ssl_ctx->extra_certs;
-#endif
-
- if (!extra_certs)
- for (n = 1; n < sk_X509_num(certs); ++n)
- SSL_CTX_add_extra_chain_cert(mctx->ssl_ctx, sk_X509_value(certs, n));
+ return APR_SUCCESS;
}
-static void ssl_init_ctx_cert_chain(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ctx_cert_chain(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
BOOL skip_first = FALSE;
int i, n;
const char *chain = mctx->cert_chain;
- if (mctx->pkcs7) {
- ssl_init_ctx_pkcs7_cert_chain(s, mctx);
- return;
- }
-
/*
* Optionally configure extra server certificate chain certificates.
* This is usually done by OpenSSL automatically when one of the
@@ -766,11 +739,12 @@ static void ssl_init_ctx_cert_chain(server_rec *s,
* used only for the server certificate chain.
*/
if (!chain) {
- return;
+ return APR_SUCCESS;
}
- for (i = 0; (i < SSL_AIDX_MAX) && mctx->pks->cert_files[i]; i++) {
- if (strEQ(mctx->pks->cert_files[i], chain)) {
+ for (i = 0; (i < mctx->pks->cert_files->nelts) &&
+ APR_ARRAY_IDX(mctx->pks->cert_files, i, const char *); i++) {
+ if (strEQ(APR_ARRAY_IDX(mctx->pks->cert_files, i, const char *), chain)) {
skip_first = TRUE;
break;
}
@@ -782,155 +756,64 @@ static void ssl_init_ctx_cert_chain(server_rec *s,
if (n < 0) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01903)
"Failed to configure CA certificate chain!");
- ssl_die(s);
+ return ssl_die(s);
}
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01904)
"Configuring server certificate chain "
"(%d CA certificate%s)",
n, n == 1 ? "" : "s");
-}
-
-static void ssl_init_ctx(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
-{
- ssl_init_ctx_protocol(s, p, ptemp, mctx);
-
- ssl_init_ctx_session_cache(s, p, ptemp, mctx);
-
- ssl_init_ctx_callbacks(s, p, ptemp, mctx);
-
- ssl_init_ctx_verify(s, p, ptemp, mctx);
- ssl_init_ctx_cipher_suite(s, p, ptemp, mctx);
-
- ssl_init_ctx_crl(s, p, ptemp, mctx);
-
- if (mctx->pks) {
- /* XXX: proxy support? */
- ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
-#ifdef HAVE_TLSEXT
- ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
-#endif
- }
+ return APR_SUCCESS;
}
-static int ssl_server_import_cert(server_rec *s,
- modssl_ctx_t *mctx,
- const char *id,
- int idx)
+static apr_status_t ssl_init_ctx(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
- SSLModConfigRec *mc = myModConfig(s);
- ssl_asn1_t *asn1;
- const unsigned char *ptr;
- const char *type = ssl_asn1_keystr(idx);
- X509 *cert;
-
- if (!(asn1 = ssl_asn1_table_get(mc->tPublicCert, id))) {
- return FALSE;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02232)
- "Configuring %s server certificate", type);
+ apr_status_t rv;
- ptr = asn1->cpData;
- if (!(cert = d2i_X509(NULL, &ptr, asn1->nData))) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02233)
- "Unable to import %s server certificate", type);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ if ((rv = ssl_init_ctx_protocol(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
}
- if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) <= 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02234)
- "Unable to configure %s server certificate", type);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
- }
-
-#ifdef HAVE_OCSP_STAPLING
- if ((mctx->pkp == FALSE) && (mctx->stapling_enabled == TRUE)) {
- if (!ssl_stapling_init_cert(s, mctx, cert)) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02235)
- "Unable to configure server certificate for stapling");
- }
- }
-#endif
-
- mctx->pks->certs[idx] = cert;
-
- return TRUE;
-}
-
-static int ssl_server_import_key(server_rec *s,
- modssl_ctx_t *mctx,
- const char *id,
- int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
- ssl_asn1_t *asn1;
- const unsigned char *ptr;
- const char *type = ssl_asn1_keystr(idx);
- int pkey_type;
- EVP_PKEY *pkey;
+ ssl_init_ctx_session_cache(s, p, ptemp, mctx);
-#ifdef HAVE_ECC
- if (idx == SSL_AIDX_ECC)
- pkey_type = EVP_PKEY_EC;
- else
-#endif
- pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA;
+ ssl_init_ctx_callbacks(s, p, ptemp, mctx);
- if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) {
- return FALSE;
+ if ((rv = ssl_init_ctx_verify(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
}
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02236)
- "Configuring %s server private key", type);
-
- ptr = asn1->cpData;
- if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData)))
- {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237)
- "Unable to import %s server private key", type);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ if ((rv = ssl_init_ctx_cipher_suite(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
}
- if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02238)
- "Unable to configure %s server private key", type);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ if ((rv = ssl_init_ctx_crl(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
}
- /*
- * XXX: wonder if this is still needed, this is old todo doc.
- * (see http://www.psy.uq.edu.au/~ftp/Crypto/ssleay/TODO.html)
- */
- if ((pkey_type == EVP_PKEY_DSA) && mctx->pks->certs[idx]) {
- EVP_PKEY *pubkey = X509_get_pubkey(mctx->pks->certs[idx]);
-
- if (pubkey && EVP_PKEY_missing_parameters(pubkey)) {
- EVP_PKEY_copy_parameters(pubkey, pkey);
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02239)
- "Copying DSA parameters from private key to certificate");
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- EVP_PKEY_free(pubkey);
+ if (mctx->pks) {
+ /* XXX: proxy support? */
+ if ((rv = ssl_init_ctx_cert_chain(s, p, ptemp, mctx)) != APR_SUCCESS) {
+ return rv;
}
+#ifdef HAVE_TLSEXT
+ if ((rv = ssl_init_ctx_tls_extensions(s, p, ptemp, mctx)) !=
+ APR_SUCCESS) {
+ return rv;
+ }
+#endif
}
- mctx->pks->keys[idx] = pkey;
-
- return TRUE;
+ return APR_SUCCESS;
}
static void ssl_check_public_cert(server_rec *s,
apr_pool_t *ptemp,
X509 *cert,
- int type)
+ const char *key_id)
{
int is_ca, pathlen;
@@ -942,141 +825,228 @@ static void ssl_check_public_cert(server_rec *s,
* Some information about the certificate(s)
*/
- if (SSL_X509_isSGC(cert)) {
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01905)
- "%s server certificate enables "
- "Server Gated Cryptography (SGC)",
- ssl_asn1_keystr(type));
- }
-
if (SSL_X509_getBC(cert, &is_ca, &pathlen)) {
if (is_ca) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01906)
"%s server certificate is a CA certificate "
- "(BasicConstraints: CA == TRUE !?)",
- ssl_asn1_keystr(type));
+ "(BasicConstraints: CA == TRUE !?)", key_id);
}
if (pathlen > 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01907)
"%s server certificate is not a leaf certificate "
"(BasicConstraints: pathlen == %d > 0 !?)",
- ssl_asn1_keystr(type), pathlen);
+ key_id, pathlen);
}
}
if (SSL_X509_match_name(ptemp, cert, (const char *)s->server_hostname,
TRUE, s) == FALSE) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01909)
- "%s certificate configured for %s does NOT include "
- "an ID which matches the server name",
- ssl_asn1_keystr(type), (mySrvConfig(s))->vhost_id);
+ "%s server certificate does NOT include an ID "
+ "which matches the server name", key_id);
}
}
-static void ssl_init_server_certs(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+/* prevent OpenSSL from showing its "Enter PEM pass phrase:" prompt */
+static int ssl_no_passwd_prompt_cb(char *buf, int size, int rwflag,
+ void *userdata) {
+ return 0;
+}
+
+static apr_status_t ssl_init_server_certs(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx,
+ apr_array_header_t *pphrases)
{
- const char *rsa_id, *dsa_id;
+ SSLModConfigRec *mc = myModConfig(s);
+ const char *vhost_id = mctx->sc->vhost_id, *key_id, *certfile, *keyfile;
+ int i;
+ X509 *cert;
+ DH *dhparams;
#ifdef HAVE_ECC
- const char *ecc_id;
EC_GROUP *ecparams;
int nid;
EC_KEY *eckey;
#endif
- const char *vhost_id = mctx->sc->vhost_id;
- int i;
- int have_rsa, have_dsa;
- DH *dhparams;
-#ifdef HAVE_ECC
- int have_ecc;
+#ifndef HAVE_SSL_CONF_CMD
+ SSL *ssl;
#endif
- rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA);
- dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA);
-#ifdef HAVE_ECC
- ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC);
-#endif
+ /* no OpenSSL default prompts for any of the SSL_CTX_use_* calls, please */
+ SSL_CTX_set_default_passwd_cb(mctx->ssl_ctx, ssl_no_passwd_prompt_cb);
+
+ /* Iterate over the SSLCertificateFile array */
+ for (i = 0; (i < mctx->pks->cert_files->nelts) &&
+ (certfile = APR_ARRAY_IDX(mctx->pks->cert_files, i,
+ const char *));
+ i++) {
+ key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
+
+ /* first the certificate (public key) */
+ if (mctx->cert_chain) {
+ if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile,
+ SSL_FILETYPE_PEM) < 1)) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561)
+ "Failed to configure certificate %s, check %s",
+ key_id, certfile);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return APR_EGENERAL;
+ }
+ } else {
+ if ((SSL_CTX_use_certificate_chain_file(mctx->ssl_ctx,
+ certfile) < 1)) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02562)
+ "Failed to configure certificate %s (with chain),"
+ " check %s", key_id, certfile);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return APR_EGENERAL;
+ }
+ }
- have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA);
- have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA);
-#ifdef HAVE_ECC
- have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
-#endif
+ /* and second, the private key */
+ keyfile = APR_ARRAY_IDX(mctx->pks->key_files, i, const char *);
+ if (keyfile == NULL)
+ keyfile = certfile;
- if (!(have_rsa || have_dsa
-#ifdef HAVE_ECC
- || have_ecc
+ ERR_clear_error();
+
+ if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
+ SSL_FILETYPE_PEM) < 1) &&
+ (ERR_GET_FUNC(ERR_peek_last_error())
+ != X509_F_X509_CHECK_PRIVATE_KEY)) {
+ ssl_asn1_t *asn1;
+ EVP_PKEY *pkey;
+ const unsigned char *ptr;
+
+ ERR_clear_error();
+
+ /* perhaps it's an encrypted private key, so try again */
+ ssl_load_encrypted_pkey(s, ptemp, i, keyfile, &pphrases);
+
+ if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id)) ||
+ !(ptr = asn1->cpData) ||
+ !(pkey = d2i_AutoPrivateKey(NULL, &ptr, asn1->nData)) ||
+ (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1)) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02564)
+ "Failed to configure encrypted (?) private key %s,"
+ " check %s", key_id, keyfile);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return APR_EGENERAL;
+ }
+ }
+
+ if (SSL_CTX_check_private_key(mctx->ssl_ctx) < 1) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02565)
+ "Certificate and private key %s from %s and %s "
+ "do not match", key_id, certfile, keyfile);
+ return APR_EGENERAL;
+ }
+
+#ifdef HAVE_SSL_CONF_CMD
+ /*
+ * workaround for those OpenSSL versions where SSL_CTX_get0_certificate
+ * is not yet available: create an SSL struct which we dispose of
+ * as soon as we no longer need access to the cert. (Strictly speaking,
+ * SSL_CTX_get0_certificate does not depend on the SSL_CONF stuff,
+ * but there's no reliable way to check for its existence, so we
+ * assume that if SSL_CONF is available, it's OpenSSL 1.0.2 or later,
+ * and SSL_CTX_get0_certificate is implemented.)
+ */
+ if (!(cert = SSL_CTX_get0_certificate(mctx->ssl_ctx))) {
+#else
+ ssl = SSL_new(mctx->ssl_ctx);
+ if (ssl) {
+ /* Workaround bug in SSL_get_certificate in OpenSSL 0.9.8y */
+ SSL_set_connect_state(ssl);
+ cert = SSL_get_certificate(ssl);
+ }
+ if (!ssl || !cert) {
#endif
-)) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01910)
- "Oops, no " KEYTYPES " server certificate found "
- "for '%s:%d'?!", s->server_hostname, s->port);
- ssl_die(s);
- }
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02566)
+ "Unable to retrieve certificate %s", key_id);
+#ifndef HAVE_SSL_CONF_CMD
+ if (ssl)
+ SSL_free(ssl);
+#endif
+ return APR_EGENERAL;
+ }
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- ssl_check_public_cert(s, ptemp, mctx->pks->certs[i], i);
- }
+ /* warn about potential cert issues */
+ ssl_check_public_cert(s, ptemp, cert, key_id);
- have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA);
- have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA);
-#ifdef HAVE_ECC
- have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC);
+#if defined(HAVE_OCSP_STAPLING) && !defined(SSL_CTRL_SET_CURRENT_CERT)
+ /*
+ * OpenSSL up to 1.0.1: configure stapling as we go. In 1.0.2
+ * and later, there's SSL_CTX_set_current_cert, which allows
+ * iterating over all certs in an SSL_CTX (including those possibly
+ * loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and
+ * later, we defer to the code in ssl_init_server_ctx.
+ */
+ if ((mctx->stapling_enabled == TRUE) &&
+ !ssl_stapling_init_cert(s, mctx, cert)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567)
+ "Unable to configure certificate %s for stapling",
+ key_id);
+ }
#endif
- if (!(have_rsa || have_dsa
-#ifdef HAVE_ECC
- || have_ecc
+#ifndef HAVE_SSL_CONF_CMD
+ SSL_free(ssl);
#endif
- )) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01911)
- "Oops, no " KEYTYPES " server private key found?!");
- ssl_die(s);
+
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02568)
+ "Certificate and private key %s configured from %s and %s",
+ key_id, certfile, keyfile);
}
/*
* Try to read DH parameters from the (first) SSLCertificateFile
*/
- if ((mctx->pks->cert_files[0] != NULL) &&
- (dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) {
+ if ((certfile = APR_ARRAY_IDX(mctx->pks->cert_files, 0, const char *)) &&
+ (dhparams = ssl_dh_GetParamFromFile(certfile))) {
SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
"Custom DH parameters (%d bits) for %s loaded from %s",
- BN_num_bits(dhparams->p), vhost_id,
- mctx->pks->cert_files[0]);
+ BN_num_bits(dhparams->p), vhost_id, certfile);
}
#ifdef HAVE_ECC
/*
* Similarly, try to read the ECDH curve name from SSLCertificateFile...
*/
- if ((mctx->pks->cert_files[0] != NULL) &&
- (ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) &&
+ if ((certfile != NULL) &&
+ (ecparams = ssl_ec_GetParamFromFile(certfile)) &&
(nid = EC_GROUP_get_curve_name(ecparams)) &&
(eckey = EC_KEY_new_by_curve_name(nid))) {
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541)
"ECDH curve %s for %s specified in %s",
- OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]);
+ OBJ_nid2sn(nid), vhost_id, certfile);
}
/*
- * ...otherwise, configure NIST P-256 (required to enable ECDHE)
+ * ...otherwise, enable auto curve selection (OpenSSL 1.0.2 and later)
+ * or configure NIST P-256 (required to enable ECDHE for earlier versions)
*/
else {
+#if defined(SSL_CTX_set_ecdh_auto)
+ SSL_CTX_set_ecdh_auto(mctx->ssl_ctx, 1);
+#else
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+#endif
}
#endif
+
+ return APR_SUCCESS;
}
#ifdef HAVE_TLS_SESSION_TICKETS
-static void ssl_init_ticket_key(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_ticket_key(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
apr_status_t rv;
apr_file_t *fp;
@@ -1086,7 +1056,7 @@ static void ssl_init_ticket_key(server_rec *s,
modssl_ticket_key_t *ticket_key = mctx->ticket_key;
if (!ticket_key->file_path) {
- return;
+ return APR_SUCCESS;
}
path = ap_server_root_relative(p, ticket_key->file_path);
@@ -1098,7 +1068,7 @@ static void ssl_init_ticket_key(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02286)
"Failed to open ticket key file %s: (%d) %pm",
path, rv, &rv);
- ssl_die(s);
+ return ssl_die(s);
}
rv = apr_file_read_full(fp, &buf[0], TLSEXT_TICKET_KEY_LEN, &len);
@@ -1107,7 +1077,7 @@ static void ssl_init_ticket_key(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02287)
"Failed to read %d bytes from %s: (%d) %pm",
TLSEXT_TICKET_KEY_LEN, path, rv, &rv);
- ssl_die(s);
+ return ssl_die(s);
}
memcpy(ticket_key->key_name, buf, 16);
@@ -1120,19 +1090,21 @@ static void ssl_init_ticket_key(server_rec *s,
"Unable to initialize TLS session ticket key callback "
"(incompatible OpenSSL version?)");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02288)
"TLS session ticket key for %s successfully loaded from %s",
(mySrvConfig(s))->vhost_id, path);
+
+ return APR_SUCCESS;
}
#endif
-static void ssl_init_proxy_certs(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+static apr_status_t ssl_init_proxy_certs(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ modssl_ctx_t *mctx)
{
int n, ncerts = 0;
STACK_OF(X509_INFO) *sk;
@@ -1145,7 +1117,7 @@ static void ssl_init_proxy_certs(server_rec *s,
ssl_callback_proxy_cert);
if (!(pkp->cert_file || pkp->cert_path)) {
- return;
+ return APR_SUCCESS;
}
sk = sk_X509_INFO_new_null();
@@ -1162,7 +1134,7 @@ static void ssl_init_proxy_certs(server_rec *s,
sk_X509_INFO_free(sk);
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206)
"no client certs found for SSL proxy");
- return;
+ return APR_SUCCESS;
}
/* Check that all client certs have got certificates and private
@@ -1176,8 +1148,7 @@ static void ssl_init_proxy_certs(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252)
"incomplete client cert configured for SSL proxy "
"(missing or encrypted private key?)");
- ssl_die(s);
- return;
+ return ssl_die(s);
}
if (X509_check_private_key(inf->x509, inf->x_pkey->dec_pkey) != 1) {
@@ -1185,8 +1156,7 @@ static void ssl_init_proxy_certs(server_rec *s,
APLOGNO(02326) "proxy client certificate and "
"private key do not match");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- ssl_die(s);
- return;
+ return ssl_die(s);
}
}
@@ -1197,7 +1167,7 @@ static void ssl_init_proxy_certs(server_rec *s,
if (!pkp->ca_cert_file || !store) {
- return;
+ return APR_SUCCESS;
}
/* If SSLProxyMachineCertificateChainFile is configured, load all
@@ -1212,7 +1182,7 @@ static void ssl_init_proxy_certs(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02208)
"SSL proxy client cert initialization failed");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
+ return ssl_die(s);
}
X509_STORE_load_locations(store, pkp->ca_cert_file, NULL);
@@ -1270,56 +1240,162 @@ static void ssl_init_proxy_certs(server_rec *s,
}
X509_STORE_CTX_free(sctx);
+
+ return APR_SUCCESS;
}
-static void ssl_init_proxy_ctx(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- SSLSrvConfigRec *sc)
+static apr_status_t ssl_init_proxy_ctx(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ SSLSrvConfigRec *sc)
{
- ssl_init_ctx(s, p, ptemp, sc->proxy);
+ apr_status_t rv;
+
+ if ((rv = ssl_init_ctx(s, p, ptemp, sc->proxy)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ if ((rv = ssl_init_proxy_certs(s, p, ptemp, sc->proxy)) != APR_SUCCESS) {
+ return rv;
+ }
- ssl_init_proxy_certs(s, p, ptemp, sc->proxy);
+ return APR_SUCCESS;
}
-static void ssl_init_server_ctx(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- SSLSrvConfigRec *sc)
+static apr_status_t ssl_init_server_ctx(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ SSLSrvConfigRec *sc,
+ apr_array_header_t *pphrases)
{
- ssl_init_server_check(s, p, ptemp, sc->server);
+ apr_status_t rv;
+#ifdef HAVE_SSL_CONF_CMD
+ ssl_ctx_param_t *param = (ssl_ctx_param_t *)sc->server->ssl_ctx_param->elts;
+ SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
+ int i;
+#endif
- ssl_init_ctx(s, p, ptemp, sc->server);
+ /*
+ * Check for problematic re-initializations
+ */
+ if (sc->server->ssl_ctx) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02569)
+ "Illegal attempt to re-initialise SSL for server "
+ "(SSLEngine On should go in the VirtualHost, not in global scope.)");
+ return APR_EGENERAL;
+ }
- ssl_init_server_certs(s, p, ptemp, sc->server);
+ if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ if ((rv = ssl_init_server_certs(s, p, ptemp, sc->server, pphrases))
+ != APR_SUCCESS) {
+ return rv;
+ }
+
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CONF_CTX_set_ssl_ctx(cctx, sc->server->ssl_ctx);
+ for (i = 0; i < sc->server->ssl_ctx_param->nelts; i++, param++) {
+ ERR_clear_error();
+ if (SSL_CONF_cmd(cctx, param->name, param->value) <= 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02407)
+ "\"SSLOpenSSLConfCmd %s %s\" failed for %s",
+ param->name, param->value, sc->vhost_id);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return ssl_die(s);
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02556)
+ "\"SSLOpenSSLConfCmd %s %s\" applied to %s",
+ param->name, param->value, sc->vhost_id);
+ }
+ }
+
+ if (SSL_CONF_CTX_finish(cctx) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02547)
+ "SSL_CONF_CTX_finish() failed");
+ SSL_CONF_CTX_free(cctx);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return ssl_die(s);
+ }
+ SSL_CONF_CTX_free(cctx);
+#endif
+
+ if (SSL_CTX_check_private_key(sc->server->ssl_ctx) != 1) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02572)
+ "Failed to configure at least one certificate and key "
+ "for %s", sc->vhost_id);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return ssl_die(s);
+ }
+
+#if defined(HAVE_OCSP_STAPLING) && defined(SSL_CTRL_SET_CURRENT_CERT)
+ /*
+ * OpenSSL 1.0.2 and later allows iterating over all SSL_CTX certs
+ * by means of SSL_CTX_set_current_cert. Enabling stapling at this
+ * (late) point makes sure that we catch both certificates loaded
+ * via SSLCertificateFile and SSLOpenSSLConfCmd Certificate.
+ */
+ if (sc->server->stapling_enabled == TRUE) {
+ X509 *cert;
+ int i = 0;
+ int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx,
+ SSL_CERT_SET_FIRST);
+ while (ret) {
+ cert = SSL_CTX_get0_certificate(sc->server->ssl_ctx);
+ if (!cert || !ssl_stapling_init_cert(s, sc->server, cert)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02604)
+ "Unable to configure certificate %s:%d "
+ "for stapling", sc->vhost_id, i);
+ }
+ ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx,
+ SSL_CERT_SET_NEXT);
+ i++;
+ }
+ }
+#endif
#ifdef HAVE_TLS_SESSION_TICKETS
- ssl_init_ticket_key(s, p, ptemp, sc->server);
+ if ((rv = ssl_init_ticket_key(s, p, ptemp, sc->server)) != APR_SUCCESS) {
+ return rv;
+ }
#endif
+
+ return APR_SUCCESS;
}
/*
* Configure a particular server
*/
-void ssl_init_ConfigureServer(server_rec *s,
- apr_pool_t *p,
- apr_pool_t *ptemp,
- SSLSrvConfigRec *sc)
+apr_status_t ssl_init_ConfigureServer(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+ SSLSrvConfigRec *sc,
+ apr_array_header_t *pphrases)
{
+ apr_status_t rv;
+
/* Initialize the server if SSL is enabled or optional.
*/
if ((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01914)
"Configuring server %s for SSL protocol", sc->vhost_id);
- ssl_init_server_ctx(s, p, ptemp, sc);
+ if ((rv = ssl_init_server_ctx(s, p, ptemp, sc, pphrases))
+ != APR_SUCCESS) {
+ return rv;
+ }
}
if (sc->proxy_enabled) {
- ssl_init_proxy_ctx(s, p, ptemp, sc);
+ if ((rv = ssl_init_proxy_ctx(s, p, ptemp, sc)) != APR_SUCCESS) {
+ return rv;
+ }
}
+
+ return APR_SUCCESS;
}
-void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
+apr_status_t ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
{
server_rec *s, *ps;
SSLSrvConfigRec *sc;
@@ -1412,6 +1488,8 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
"support (RFC 4366)");
#endif
}
+
+ return APR_SUCCESS;
}
static int ssl_init_FindCAList_X509NameCmp(const X509_NAME * const *a,
@@ -1502,7 +1580,8 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s,
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02211)
"Failed to open Certificate Path `%s'",
ca_path);
- ssl_die(s);
+ sk_X509_NAME_pop_free(ca_list, X509_NAME_free);
+ return NULL;
}
while ((apr_dir_read(&direntry, finfo_flags, dir)) == APR_SUCCESS) {
@@ -1579,21 +1658,6 @@ static void ssl_init_ctx_cleanup_proxy(modssl_ctx_t *mctx)
}
}
-static void ssl_init_ctx_cleanup_server(modssl_ctx_t *mctx)
-{
- int i;
-
- ssl_init_ctx_cleanup(mctx);
-
- for (i=0; i < SSL_AIDX_MAX; i++) {
- MODSSL_CFG_ITEM_FREE(X509_free,
- mctx->pks->certs[i]);
-
- MODSSL_CFG_ITEM_FREE(EVP_PKEY_free,
- mctx->pks->keys[i]);
- }
-}
-
apr_status_t ssl_init_ModuleKill(void *data)
{
SSLSrvConfigRec *sc;
@@ -1614,9 +1678,8 @@ apr_status_t ssl_init_ModuleKill(void *data)
ssl_init_ctx_cleanup_proxy(sc->proxy);
- ssl_init_ctx_cleanup_server(sc->server);
+ ssl_init_ctx_cleanup(sc->server);
}
return APR_SUCCESS;
}
-
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index 6d93ac99..c60f0a6c 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -163,48 +163,59 @@ int ssl_hook_ReadReq(request_rec *r)
return DECLINED;
}
#ifdef HAVE_TLSEXT
- if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
- char *host, *scope_id;
- apr_port_t port;
- apr_status_t rv;
-
- /*
- * The SNI extension supplied a hostname. So don't accept requests
- * with either no hostname or a different hostname.
- */
- if (!r->hostname) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031)
- "Hostname %s provided via SNI, but no hostname"
- " provided in HTTP request", servername);
- return HTTP_BAD_REQUEST;
- }
- rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
- if (rv != APR_SUCCESS || scope_id) {
- return HTTP_BAD_REQUEST;
+ if (r->proxyreq != PROXYREQ_PROXY) {
+ if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+ char *host, *scope_id;
+ apr_port_t port;
+ apr_status_t rv;
+
+ /*
+ * The SNI extension supplied a hostname. So don't accept requests
+ * with either no hostname or a different hostname as this could
+ * cause us to end up in a different virtual host as the one that
+ * was used for the handshake causing different SSL parameters to
+ * be applied as SSLProtocol, SSLCACertificateFile/Path and
+ * SSLCADNRequestFile/Path cannot be renegotioated (SSLCA* due
+ * to current limitiations in Openssl, see
+ * http://mail-archives.apache.org/mod_mbox/httpd-dev/200806.mbox/%3C48592955.2090303@velox.ch%3E
+ * and
+ * http://mail-archives.apache.org/mod_mbox/httpd-dev/201312.mbox/%3CCAKQ1sVNpOrdiBm-UPw1hEdSN7YQXRRjeaT-MCWbW_7mN%3DuFiOw%40mail.gmail.com%3E
+ * )
+ */
+ if (!r->hostname) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031)
+ "Hostname %s provided via SNI, but no hostname"
+ " provided in HTTP request", servername);
+ return HTTP_BAD_REQUEST;
+ }
+ rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
+ if (rv != APR_SUCCESS || scope_id) {
+ return HTTP_BAD_REQUEST;
+ }
+ if (strcasecmp(host, servername)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
+ "Hostname %s provided via SNI and hostname %s provided"
+ " via HTTP are different", servername, host);
+ return HTTP_BAD_REQUEST;
+ }
}
- if (strcasecmp(host, servername)) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
- "Hostname %s provided via SNI and hostname %s provided"
- " via HTTP are different", servername, host);
- return HTTP_BAD_REQUEST;
+ else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)
+ || (mySrvConfig(sslconn->server))->strict_sni_vhost_check
+ == SSL_ENABLED_TRUE)
+ && r->connection->vhost_lookup_data) {
+ /*
+ * We are using a name based configuration here, but no hostname was
+ * provided via SNI. Don't allow that if are requested to do strict
+ * checking. Check wether this strict checking was setup either in the
+ * server config we used for handshaking or in our current server.
+ * This should avoid insecure configuration by accident.
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033)
+ "No hostname was provided via SNI for a name based"
+ " virtual host");
+ return HTTP_FORBIDDEN;
}
}
- else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)
- || (mySrvConfig(sslconn->server))->strict_sni_vhost_check
- == SSL_ENABLED_TRUE)
- && r->connection->vhost_lookup_data) {
- /*
- * We are using a name based configuration here, but no hostname was
- * provided via SNI. Don't allow that if are requested to do strict
- * checking. Check wether this strict checking was setup either in the
- * server config we used for handshaking or in our current server.
- * This should avoid insecure configuration by accident.
- */
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02033)
- "No hostname was provided via SNI for a name based"
- " virtual host");
- return HTTP_FORBIDDEN;
- }
#endif
SSL_set_app_data2(ssl, r);
diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c
index 3f6d6edc..2c87638f 100644
--- a/modules/ssl/ssl_engine_log.c
+++ b/modules/ssl/ssl_engine_log.c
@@ -63,7 +63,7 @@ static const char *ssl_log_annotation(const char *error)
return ssl_log_annotate[i].cpAnnotation;
}
-void ssl_die(server_rec *s)
+apr_status_t ssl_die(server_rec *s)
{
if (s != NULL && s->is_virtual && s->error_fname != NULL)
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02311)
@@ -75,13 +75,7 @@ void ssl_die(server_rec *s)
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02312)
"Fatal error initialising mod_ssl, exiting.");
- /*
- * This is used for fatal errors and here
- * it is common module practice to really
- * exit from the complete program.
- * XXX: The config hooks should return errors instead of calling exit().
- */
- exit(1);
+ return APR_EGENERAL;
}
/*
diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c
index ca8e130f..df81d121 100644
--- a/modules/ssl/ssl_engine_pphrase.c
+++ b/modules/ssl/ssl_engine_pphrase.c
@@ -30,11 +30,25 @@
-- Clifford Stoll */
#include "ssl_private.h"
+typedef struct {
+ server_rec *s;
+ apr_pool_t *p;
+ apr_array_header_t *aPassPhrase;
+ int nPassPhraseCur;
+ char *cpPassPhraseCur;
+ int nPassPhraseDialog;
+ int nPassPhraseDialogCur;
+ BOOL bPassPhraseDialogOnce;
+ const char *key_id;
+ const char *pkey_file;
+} pphrase_cb_arg_t;
+
/*
* Return true if the named file exists and is readable
*/
-static apr_status_t exists_and_readable(char *fname, apr_pool_t *pool, apr_time_t *mtime)
+static apr_status_t exists_and_readable(const char *fname, apr_pool_t *pool,
+ apr_time_t *mtime)
{
apr_status_t stat;
apr_finfo_t sbuf;
@@ -73,11 +87,11 @@ static apr_status_t exists_and_readable(char *fname, apr_pool_t *pool, apr_time_
* since apr_array_push() will apr_alloc arr->nalloc * 2 elts,
* leaving the original arr->elts to waste.
*/
-static char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p,
- char *id, char *an)
+static const char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p,
+ const char *id, int i)
{
/* 'p' pool used here is cleared on restarts (or sooner) */
- char *key = apr_psprintf(p, "%s:%s", id, an);
+ char *key = apr_psprintf(p, "%s:%d", id, i);
void *keyptr = apr_hash_get(mc->tVHostKeys, key,
APR_HASH_KEY_STRING);
@@ -103,12 +117,6 @@ static char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p,
static apr_file_t *writetty = NULL;
static apr_file_t *readtty = NULL;
-/*
- * sslc has a nasty flaw where its
- * PEM_read_bio_PrivateKey does not take a callback arg.
- */
-static server_rec *ssl_pphrase_server_rec = NULL;
-
int ssl_pphrase_Handle_CB(char *, int, int, void *);
static char *pphrase_array_get(apr_array_header_t *arr, int idx)
@@ -120,458 +128,260 @@ static char *pphrase_array_get(apr_array_header_t *arr, int idx)
return ((char **)arr->elts)[idx];
}
-static void pphrase_array_clear(apr_array_header_t *arr)
-{
- if (arr->nelts > 0) {
- memset(arr->elts, 0, arr->elt_size * arr->nelts);
- }
- arr->nelts = 0;
-}
-
-/* Abandon all hope, ye who read this code. Don't believe the name:
- * "passphrase handling" is really a peripheral (if complex) concern;
- * the core purpose of this function to load into memory all
- * configured certs and key from files. The private key handling in
- * here should be split out into a separate function for improved
- * readability. The myCtxVarGet abomination can be thrown away with
- * SSLC support, vastly simplifying the code. */
-void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p)
+apr_status_t ssl_load_encrypted_pkey(server_rec *s, apr_pool_t *p, int idx,
+ const char *pkey_file,
+ apr_array_header_t **pphrases)
{
SSLModConfigRec *mc = myModConfig(s);
- SSLSrvConfigRec *sc;
- server_rec *pServ;
- char *cpVHostID;
- char szPath[MAX_STRING_LEN];
- EVP_PKEY *pPrivateKey;
+ SSLSrvConfigRec *sc = mySrvConfig(s);
+ const char *key_id = asn1_table_vhost_key(mc, p, sc->vhost_id, idx);
+ EVP_PKEY *pPrivateKey = NULL;
ssl_asn1_t *asn1;
unsigned char *ucp;
long int length;
- X509 *pX509Cert;
BOOL bReadable;
- apr_array_header_t *aPassPhrase;
- int nPassPhrase;
- int nPassPhraseCur;
- char *cpPassPhraseCur;
- int nPassPhraseRetry;
- int nPassPhraseDialog;
- int nPassPhraseDialogCur;
- BOOL bPassPhraseDialogOnce;
- char **cpp;
- int i, j;
- ssl_algo_t algoCert, algoKey, at;
- char *an;
+ int nPassPhrase = (*pphrases)->nelts;
+ int nPassPhraseRetry = 0;
apr_time_t pkey_mtime = 0;
apr_status_t rv;
- /*
- * Start with a fresh pass phrase array
- */
- aPassPhrase = apr_array_make(p, 2, sizeof(char *));
- nPassPhrase = 0;
- nPassPhraseDialog = 0;
+ pphrase_cb_arg_t ppcb_arg;
+
+ if (!pkey_file) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02573)
+ "Init: No private key specified for %s", key_id);
+ return ssl_die(s);
+ }
+ else if ((rv = exists_and_readable(pkey_file, p, &pkey_mtime))
+ != APR_SUCCESS ) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02574)
+ "Init: Can't open server private key file %s", pkey_file);
+ return ssl_die(s);
+ }
+
+ ppcb_arg.s = s;
+ ppcb_arg.p = p;
+ ppcb_arg.aPassPhrase = *pphrases;
+ ppcb_arg.nPassPhraseCur = 0;
+ ppcb_arg.cpPassPhraseCur = NULL;
+ ppcb_arg.nPassPhraseDialog = 0;
+ ppcb_arg.nPassPhraseDialogCur = 0;
+ ppcb_arg.bPassPhraseDialogOnce = TRUE;
+ ppcb_arg.key_id = key_id;
+ ppcb_arg.pkey_file = pkey_file;
/*
- * Walk through all configured servers
+ * if the private key is encrypted and SSLPassPhraseDialog
+ * is configured to "builtin" it isn't possible to prompt for
+ * a password after httpd has detached from the tty.
+ * in this case if we already have a private key and the
+ * file name/mtime hasn't changed, then reuse the existing key.
+ * we also reuse existing private keys that were encrypted for
+ * exec: and pipe: dialogs to minimize chances to snoop the
+ * password. that and pipe: dialogs might prompt the user
+ * for password, which on win32 for example could happen 4
+ * times at startup. twice for each child and twice within
+ * each since apache "restarts itself" on startup.
+ * of course this will not work for the builtin dialog if
+ * the server was started without LoadModule ssl_module
+ * configured, then restarted with it configured.
+ * but we fall through with a chance of success if the key
+ * is not encrypted or can be handled via exec or pipe dialog.
+ * and in the case of fallthrough, pkey_mtime and isatty()
+ * are used to give a better idea as to what failed.
*/
- for (pServ = s; pServ != NULL; pServ = pServ->next) {
- sc = mySrvConfig(pServ);
- cpVHostID = ssl_util_vhostid(p, pServ);
- if (!sc->enabled) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02199)
- "SSL not enabled on vhost %s, skipping SSL setup",
- cpVHostID);
- continue;
+ if (pkey_mtime) {
+ ssl_asn1_t *asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
+ if (asn1 && (asn1->source_mtime == pkey_mtime)) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02575)
+ "Reusing existing private key from %s on restart",
+ ppcb_arg.pkey_file);
+ return APR_SUCCESS;
}
+ }
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, pServ, APLOGNO(02200)
- "Loading certificate & private key of SSL-aware server '%s'",
- cpVHostID);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02576)
+ "Attempting to load encrypted (?) private key %s", key_id);
+ for (;;) {
/*
- * Read in server certificate(s): This is the easy part
- * because this file isn't encrypted in any way.
+ * Try to read the private key file with the help of
+ * the callback function which serves the pass
+ * phrases to OpenSSL
*/
- if (sc->server->pks->cert_files[0] == NULL
- && sc->server->pkcs7 == NULL) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02240)
- "Server should be SSL-aware but has no certificate "
- "configured [Hint: SSLCertificateFile] (%s:%d)",
- pServ->defn_name, pServ->defn_line_number);
- ssl_die(pServ);
- }
-
- /* Bitmasks for all key algorithms configured for this server;
- * initialize to zero. */
- algoCert = SSL_ALGO_UNKNOWN;
- algoKey = SSL_ALGO_UNKNOWN;
-
- /* Iterate through configured certificate files for this
- * server. */
- for (i = 0, j = 0; i < SSL_AIDX_MAX
- && (sc->server->pks->cert_files[i] != NULL
- || sc->server->pkcs7); i++) {
- const char *key_id;
- int using_cache = 0;
-
- if (sc->server->pkcs7) {
- STACK_OF(X509) *certs = ssl_read_pkcs7(pServ,
- sc->server->pkcs7);
- pX509Cert = sk_X509_value(certs, 0);
- i = SSL_AIDX_MAX;
- } else {
- apr_cpystrn(szPath, sc->server->pks->cert_files[i],
- sizeof(szPath));
- if ((rv = exists_and_readable(szPath, p, NULL))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201)
- "Init: Can't open server certificate file %s",
- szPath);
- ssl_die(s);
- }
- if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241)
- "Init: Unable to read server certificate from"
- " file %s", szPath);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202)
- "Init: Read server certificate from '%s'",
- szPath);
- }
- /*
- * check algorithm type of certificate and make
- * sure only one certificate per type is used.
- */
- at = ssl_util_algotypeof(pX509Cert, NULL);
- an = ssl_util_algotypestr(at);
- if (algoCert & at) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02242)
- "Init: Multiple %s server certificates not "
- "allowed", an);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
- }
- algoCert |= at;
-
- /* Determine the hash key used for this (vhost, algo-type)
- * pair used to index both the mc->tPrivateKey and
- * mc->tPublicCert tables: */
- key_id = asn1_table_vhost_key(mc, p, cpVHostID, an);
- /*
- * Insert the certificate into global module configuration to let it
- * survive the processing between the 1st Apache API init round (where
- * we operate here) and the 2nd Apache init round (where the
- * certificate is actually used to configure mod_ssl's per-server
- * configuration structures).
- */
- length = i2d_X509(pX509Cert, NULL);
- ucp = ssl_asn1_table_set(mc->tPublicCert, key_id, length);
- (void)i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */
+ ppcb_arg.cpPassPhraseCur = NULL;
- /*
- * Free the X509 structure
- */
- X509_free(pX509Cert);
-
- /*
- * Read in the private key: This is the non-trivial part, because the
- * key is typically encrypted, so a pass phrase dialog has to be used
- * to request it from the user (or it has to be alternatively gathered
- * from a dialog program). The important point here is that ISPs
- * usually have hundrets of virtual servers configured and a lot of
- * them use SSL, so really we have to minimize the pass phrase
- * dialogs.
- *
- * The idea is this: When N virtual hosts are configured and all of
- * them use encrypted private keys with different pass phrases, we
- * have no chance and have to pop up N pass phrase dialogs. But
- * usually the admin is clever enough and uses the same pass phrase
- * for more private key files (typically he even uses one single pass
- * phrase for all). When this is the case we can minimize the dialogs
- * by trying to re-use already known/entered pass phrases.
- */
- if (sc->server->pks->key_files[j] != NULL)
- apr_cpystrn(szPath, sc->server->pks->key_files[j++], sizeof(szPath));
+ /* Ensure that the error stack is empty; some SSL
+ * functions will fail spuriously if the error stack
+ * is not empty. */
+ ERR_clear_error();
- /*
- * Try to read the private key file with the help of
- * the callback function which serves the pass
- * phrases to OpenSSL
- */
- myCtxVarSet(mc, 1, pServ);
- myCtxVarSet(mc, 2, p);
- myCtxVarSet(mc, 3, aPassPhrase);
- myCtxVarSet(mc, 4, &nPassPhraseCur);
- myCtxVarSet(mc, 5, &cpPassPhraseCur);
- myCtxVarSet(mc, 6, cpVHostID);
- myCtxVarSet(mc, 7, an);
- myCtxVarSet(mc, 8, &nPassPhraseDialog);
- myCtxVarSet(mc, 9, &nPassPhraseDialogCur);
- myCtxVarSet(mc, 10, &bPassPhraseDialogOnce);
-
- nPassPhraseCur = 0;
- nPassPhraseRetry = 0;
- nPassPhraseDialogCur = 0;
- bPassPhraseDialogOnce = TRUE;
-
- pPrivateKey = NULL;
-
- for (;;) {
- /*
- * Try to read the private key file with the help of
- * the callback function which serves the pass
- * phrases to OpenSSL
- */
- if ((rv = exists_and_readable(szPath, p,
- &pkey_mtime)) != APR_SUCCESS ) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243)
- "Init: Can't open server private key file "
- "%s",szPath);
- ssl_die(s);
- }
+ bReadable = ((pPrivateKey = SSL_read_PrivateKey(ppcb_arg.pkey_file,
+ NULL, ssl_pphrase_Handle_CB, &ppcb_arg)) != NULL ?
+ TRUE : FALSE);
- /*
- * if the private key is encrypted and SSLPassPhraseDialog
- * is configured to "builtin" it isn't possible to prompt for
- * a password after httpd has detached from the tty.
- * in this case if we already have a private key and the
- * file name/mtime hasn't changed, then reuse the existing key.
- * we also reuse existing private keys that were encrypted for
- * exec: and pipe: dialogs to minimize chances to snoop the
- * password. that and pipe: dialogs might prompt the user
- * for password, which on win32 for example could happen 4
- * times at startup. twice for each child and twice within
- * each since apache "restarts itself" on startup.
- * of course this will not work for the builtin dialog if
- * the server was started without LoadModule ssl_module
- * configured, then restarted with it configured.
- * but we fall through with a chance of success if the key
- * is not encrypted or can be handled via exec or pipe dialog.
- * and in the case of fallthrough, pkey_mtime and isatty()
- * are used to give a better idea as to what failed.
- */
- if (pkey_mtime) {
- ssl_asn1_t *asn1 =
- ssl_asn1_table_get(mc->tPrivateKey, key_id);
-
- if (asn1 && (asn1->source_mtime == pkey_mtime)) {
- ap_log_error(APLOG_MARK, APLOG_INFO,
- 0, pServ, APLOGNO(02244)
- "%s reusing existing "
- "%s private key on restart",
- cpVHostID, ssl_asn1_keystr(i));
- using_cache = 1;
- break;
- }
- }
+ /*
+ * when the private key file now was readable,
+ * it's fine and we go out of the loop
+ */
+ if (bReadable)
+ break;
- cpPassPhraseCur = NULL;
- ssl_pphrase_server_rec = s; /* to make up for sslc flaw */
-
- /* Ensure that the error stack is empty; some SSL
- * functions will fail spuriously if the error stack
- * is not empty. */
- ERR_clear_error();
-
- bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, NULL,
- ssl_pphrase_Handle_CB, s)) != NULL ? TRUE : FALSE);
-
- /*
- * when the private key file now was readable,
- * it's fine and we go out of the loop
- */
- if (bReadable)
- break;
-
- /*
- * when we have more remembered pass phrases
- * try to reuse these first.
- */
- if (nPassPhraseCur < nPassPhrase) {
- nPassPhraseCur++;
- continue;
- }
+ /*
+ * when we have more remembered pass phrases
+ * try to reuse these first.
+ */
+ if (ppcb_arg.nPassPhraseCur < nPassPhrase) {
+ ppcb_arg.nPassPhraseCur++;
+ continue;
+ }
- /*
- * else it's not readable and we have no more
- * remembered pass phrases. Then this has to mean
- * that the callback function popped up the dialog
- * but a wrong pass phrase was entered. We give the
- * user (but not the dialog program) a few more
- * chances...
- */
+ /*
+ * else it's not readable and we have no more
+ * remembered pass phrases. Then this has to mean
+ * that the callback function popped up the dialog
+ * but a wrong pass phrase was entered. We give the
+ * user (but not the dialog program) a few more
+ * chances...
+ */
#ifndef WIN32
- if ((sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
- || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE)
+ if ((sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN
+ || sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE)
#else
- if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE
#endif
- && cpPassPhraseCur != NULL
- && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) {
- apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect "
- "(%d more retr%s permitted).\n",
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry),
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies");
- nPassPhraseRetry++;
- if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF)
- apr_sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF)
- * 5 * APR_USEC_PER_SEC);
- continue;
- }
+ && ppcb_arg.cpPassPhraseCur != NULL
+ && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) {
+ apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect "
+ "(%d more retr%s permitted).\n",
+ (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry),
+ (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies");
+ nPassPhraseRetry++;
+ if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF)
+ apr_sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF)
+ * 5 * APR_USEC_PER_SEC);
+ continue;
+ }
#ifdef WIN32
- if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02245)
- "Init: SSLPassPhraseDialog builtin is not "
- "supported on Win32 (key file "
- "%s)", szPath);
- ssl_die(s);
- }
+ if (sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02577)
+ "Init: SSLPassPhraseDialog builtin is not "
+ "supported on Win32 (key file "
+ "%s)", ppcb_arg.pkey_file);
+ return ssl_die(s);
+ }
#endif /* WIN32 */
- /*
- * Ok, anything else now means a fatal error.
- */
- if (cpPassPhraseCur == NULL) {
- if (nPassPhraseDialogCur && pkey_mtime &&
- !isatty(fileno(stdout))) /* XXX: apr_isatty() */
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0,
- pServ, APLOGNO(02246)
- "Init: Unable to read pass phrase "
- "[Hint: key introduced or changed "
- "before restart?]");
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ);
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0,
- pServ, APLOGNO(02203) "Init: Private key not found");
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, pServ);
- }
- if (writetty) {
- apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n");
- apr_file_printf(writetty, "**Stopped\n");
- }
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, pServ, APLOGNO(02204)
- "Init: Pass phrase incorrect for key of %s",
- cpVHostID);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, pServ);
-
- if (writetty) {
- apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n");
- apr_file_printf(writetty, "**Stopped\n");
- }
- }
- ssl_die(pServ);
- }
-
- /* If a cached private key was found, nothing more to do
- * here; loop through to the next configured cert for this
- * vhost. */
- if (using_cache)
- continue;
-
- if (pPrivateKey == NULL) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247)
- "Init: Unable to read server private key from "
- "file %s [Hint: Perhaps it is in a separate file? "
- " See SSLCertificateKeyFile]", szPath);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
- }
-
- /*
- * check algorithm type of private key and make
- * sure only one private key per type is used.
- */
- at = ssl_util_algotypeof(NULL, pPrivateKey);
- an = ssl_util_algotypestr(at);
- if (algoKey & at) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02248)
- "Init: Multiple %s server private keys not "
- "allowed", an);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
- ssl_die(s);
- }
- algoKey |= at;
-
- /*
- * Log the type of reading
- */
- if (nPassPhraseDialogCur == 0) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, pServ, APLOGNO(02249)
- "unencrypted %s private key - pass phrase not "
- "required", an);
+ /*
+ * Ok, anything else now means a fatal error.
+ */
+ if (ppcb_arg.cpPassPhraseCur == NULL) {
+ if (ppcb_arg.nPassPhraseDialogCur && pkey_mtime &&
+ !isatty(fileno(stdout))) /* XXX: apr_isatty() */
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0,
+ s, APLOGNO(02578)
+ "Init: Unable to read pass phrase "
+ "[Hint: key introduced or changed "
+ "before restart?]");
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
}
else {
- if (cpPassPhraseCur != NULL) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- pServ, APLOGNO(02250)
- "encrypted %s private key - pass phrase "
- "requested", an);
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- pServ, APLOGNO(02251)
- "encrypted %s private key - pass phrase"
- " reused", an);
- }
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0,
+ s, APLOGNO(02579) "Init: Private key not found");
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
}
-
- /*
- * Ok, when we have one more pass phrase store it
- */
- if (cpPassPhraseCur != NULL) {
- cpp = (char **)apr_array_push(aPassPhrase);
- *cpp = cpPassPhraseCur;
- nPassPhrase++;
+ if (writetty) {
+ apr_file_printf(writetty, "Apache:mod_ssl:Error: Private key not found.\n");
+ apr_file_printf(writetty, "**Stopped\n");
}
-
- /*
- * Insert private key into the global module configuration
- * (we convert it to a stand-alone DER byte sequence
- * because the SSL library uses static variables inside a
- * RSA structure which do not survive DSO reloads!)
- */
- length = i2d_PrivateKey(pPrivateKey, NULL);
- ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
- (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
-
- if (nPassPhraseDialogCur != 0) {
- /* remember mtime of encrypted keys */
- asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
- asn1->source_mtime = pkey_mtime;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02580)
+ "Init: Pass phrase incorrect for key %s",
+ key_id);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+
+ if (writetty) {
+ apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase incorrect.\n");
+ apr_file_printf(writetty, "**Stopped\n");
}
+ }
+ return ssl_die(s);
+ }
- /*
- * Free the private key structure
- */
- EVP_PKEY_free(pPrivateKey);
+ if (pPrivateKey == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02581)
+ "Init: Unable to read server private key from file %s",
+ ppcb_arg.pkey_file);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ return ssl_die(s);
+ }
+
+ /*
+ * Log the type of reading
+ */
+ if (ppcb_arg.nPassPhraseDialogCur == 0) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02582)
+ "unencrypted %s private key - pass phrase not "
+ "required", key_id);
+ }
+ else {
+ if (ppcb_arg.cpPassPhraseCur != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
+ s, APLOGNO(02583)
+ "encrypted %s private key - pass phrase "
+ "requested", key_id);
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
+ s, APLOGNO(02584)
+ "encrypted %s private key - pass phrase"
+ " reused", key_id);
}
}
/*
+ * Ok, when we have one more pass phrase store it
+ */
+ if (ppcb_arg.cpPassPhraseCur != NULL) {
+ *(const char **)apr_array_push(ppcb_arg.aPassPhrase) =
+ ppcb_arg.cpPassPhraseCur;
+ nPassPhrase++;
+ }
+
+ /*
+ * Insert private key into the global module configuration
+ * (we convert it to a stand-alone DER byte sequence
+ * because the SSL library uses static variables inside a
+ * RSA structure which do not survive DSO reloads!)
+ */
+ length = i2d_PrivateKey(pPrivateKey, NULL);
+ ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length);
+ (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
+
+ if (ppcb_arg.nPassPhraseDialogCur != 0) {
+ /* remember mtime of encrypted keys */
+ asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id);
+ asn1->source_mtime = pkey_mtime;
+ }
+
+ /*
+ * Free the private key structure
+ */
+ EVP_PKEY_free(pPrivateKey);
+
+ /*
* Let the user know when we're successful.
*/
- if (nPassPhraseDialog > 0) {
+ if ((ppcb_arg.nPassPhraseDialog > 0) &&
+ (ppcb_arg.cpPassPhraseCur != NULL)) {
if (writetty) {
apr_file_printf(writetty, "\n"
"OK: Pass Phrase Dialog successful.\n");
}
}
- /*
- * Wipe out the used memory from the
- * pass phrase array and then deallocate it
- */
- if (aPassPhrase->nelts) {
- pphrase_array_clear(aPassPhrase);
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02205)
- "Init: Wiped out the queried pass phrases from memory");
- }
-
/* Close the pipes if they were opened
*/
if (readtty) {
@@ -579,7 +389,8 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p)
apr_file_close(writetty);
readtty = writetty = NULL;
}
- return;
+
+ return APR_SUCCESS;
}
static apr_status_t ssl_pipe_child_create(apr_pool_t *p, const char *progname)
@@ -646,45 +457,19 @@ static int pipe_get_passwd_cb(char *buf, int length, char *prompt, int verify)
int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
{
- SSLModConfigRec *mc;
- server_rec *s;
- apr_pool_t *p;
- apr_array_header_t *aPassPhrase;
- SSLSrvConfigRec *sc;
- int *pnPassPhraseCur;
- char **cppPassPhraseCur;
- char *cpVHostID;
- char *cpAlgoType;
- int *pnPassPhraseDialog;
- int *pnPassPhraseDialogCur;
- BOOL *pbPassPhraseDialogOnce;
+ pphrase_cb_arg_t *ppcb_arg = (pphrase_cb_arg_t *)srv;
+ SSLSrvConfigRec *sc = mySrvConfig(ppcb_arg->s);
char *cpp;
int len = -1;
- mc = myModConfig((server_rec *)srv);
-
- /*
- * Reconnect to the context of ssl_phrase_Handle()
- */
- s = myCtxVarGet(mc, 1, server_rec *);
- p = myCtxVarGet(mc, 2, apr_pool_t *);
- aPassPhrase = myCtxVarGet(mc, 3, apr_array_header_t *);
- pnPassPhraseCur = myCtxVarGet(mc, 4, int *);
- cppPassPhraseCur = myCtxVarGet(mc, 5, char **);
- cpVHostID = myCtxVarGet(mc, 6, char *);
- cpAlgoType = myCtxVarGet(mc, 7, char *);
- pnPassPhraseDialog = myCtxVarGet(mc, 8, int *);
- pnPassPhraseDialogCur = myCtxVarGet(mc, 9, int *);
- pbPassPhraseDialogOnce = myCtxVarGet(mc, 10, BOOL *);
- sc = mySrvConfig(s);
-
- (*pnPassPhraseDialog)++;
- (*pnPassPhraseDialogCur)++;
+ ppcb_arg->nPassPhraseDialog++;
+ ppcb_arg->nPassPhraseDialogCur++;
/*
* When remembered pass phrases are available use them...
*/
- if ((cpp = pphrase_array_get(aPassPhrase, *pnPassPhraseCur)) != NULL) {
+ if ((cpp = pphrase_array_get(ppcb_arg->aPassPhrase,
+ ppcb_arg->nPassPhraseCur)) != NULL) {
apr_cpystrn(buf, cpp, bufsize);
len = strlen(buf);
return len;
@@ -700,25 +485,29 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
if (sc->server->pphrase_dialog_type == SSL_PPTYPE_PIPE) {
if (!readtty) {
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01965)
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s,
+ APLOGNO(01965)
"Init: Creating pass phrase dialog pipe child "
"'%s'", sc->server->pphrase_dialog_path);
- if (ssl_pipe_child_create(p, sc->server->pphrase_dialog_path)
+ if (ssl_pipe_child_create(ppcb_arg->p,
+ sc->server->pphrase_dialog_path)
!= APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01966)
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ppcb_arg->s,
+ APLOGNO(01966)
"Init: Failed to create pass phrase pipe '%s'",
sc->server->pphrase_dialog_path);
- PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
+ PEMerr(PEM_F_PEM_DEF_CALLBACK,
+ PEM_R_PROBLEMS_GETTING_PASSWORD);
memset(buf, 0, (unsigned int)bufsize);
return (-1);
}
}
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01967)
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01967)
"Init: Requesting pass phrase via piped dialog");
}
else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
#ifdef WIN32
- PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
+ PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD);
memset(buf, 0, (unsigned int)bufsize);
return (-1);
#else
@@ -728,9 +517,9 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
* we print the prompt to stdout before EVP_read_pw_string turns
* off tty echo
*/
- apr_file_open_stdout(&writetty, p);
+ apr_file_open_stdout(&writetty, ppcb_arg->p);
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01968)
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01968)
"Init: Requesting pass phrase via builtin terminal "
"dialog");
#endif
@@ -742,16 +531,17 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
* this terminal dialog and why to the hell he has to enter
* something...
*/
- if (*pnPassPhraseDialog == 1) {
+ if (ppcb_arg->nPassPhraseDialog == 1) {
apr_file_printf(writetty, "%s mod_ssl (Pass Phrase Dialog)\n",
AP_SERVER_BASEVERSION);
apr_file_printf(writetty, "Some of your private key files are encrypted for security reasons.\n");
apr_file_printf(writetty, "In order to read them you have to provide the pass phrases.\n");
}
- if (*pbPassPhraseDialogOnce) {
- *pbPassPhraseDialogOnce = FALSE;
+ if (ppcb_arg->bPassPhraseDialogOnce) {
+ ppcb_arg->bPassPhraseDialogOnce = FALSE;
apr_file_printf(writetty, "\n");
- apr_file_printf(writetty, "Server %s (%s)\n", cpVHostID, cpAlgoType);
+ apr_file_printf(writetty, "Private key %s (%s)\n",
+ ppcb_arg->key_id, ppcb_arg->pkey_file);
}
/*
@@ -786,19 +576,18 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
*/
else if (sc->server->pphrase_dialog_type == SSL_PPTYPE_FILTER) {
const char *cmd = sc->server->pphrase_dialog_path;
- const char **argv = apr_palloc(p, sizeof(char *) * 4);
+ const char **argv = apr_palloc(ppcb_arg->p, sizeof(char *) * 3);
char *result;
- ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01969)
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ppcb_arg->s, APLOGNO(01969)
"Init: Requesting pass phrase from dialog filter "
"program (%s)", cmd);
argv[0] = cmd;
- argv[1] = cpVHostID;
- argv[2] = cpAlgoType;
- argv[3] = NULL;
+ argv[1] = ppcb_arg->key_id;
+ argv[2] = NULL;
- result = ssl_util_readfilter(s, p, cmd, argv);
+ result = ssl_util_readfilter(ppcb_arg->s, ppcb_arg->p, cmd, argv);
apr_cpystrn(buf, result, bufsize);
len = strlen(buf);
}
@@ -806,11 +595,10 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
/*
* Ok, we now have the pass phrase, so give it back
*/
- *cppPassPhraseCur = apr_pstrdup(p, buf);
+ ppcb_arg->cpPassPhraseCur = apr_pstrdup(ppcb_arg->p, buf);
/*
* And return its length to OpenSSL...
*/
return (len);
}
-
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 4ea924f3..516d7e65 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -131,6 +131,10 @@
#define HAVE_TLSV1_X
#endif
+#if defined(SSL_CONF_FLAG_FILE)
+#define HAVE_SSL_CONF_CMD
+#endif
+
/**
* The following features all depend on TLS extension support.
* Within this block, check again for features (not version numbers).
@@ -232,9 +236,6 @@ ap_set_module_config(c->conn_config, &ssl_module, val)
#define mySrvConfigFromConn(c) mySrvConfig(mySrvFromConn(c))
#define myModConfigFromConn(c) myModConfig(mySrvFromConn(c))
-#define myCtxVarSet(mc,num,val) mc->rCtx.pV##num = val
-#define myCtxVarGet(mc,num,type) (type)(mc->rCtx.pV##num)
-
/**
* Defaults for the configuration
*/
@@ -258,31 +259,6 @@ ap_set_module_config(c->conn_config, &ssl_module, val)
#endif
/**
- * Define the certificate algorithm types
- */
-
-typedef int ssl_algo_t;
-
-#define SSL_ALGO_UNKNOWN (0)
-#define SSL_ALGO_RSA (1<<0)
-#define SSL_ALGO_DSA (1<<1)
-#ifdef HAVE_ECC
-#define SSL_ALGO_ECC (1<<2)
-#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC)
-#else
-#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA)
-#endif
-
-#define SSL_AIDX_RSA (0)
-#define SSL_AIDX_DSA (1)
-#ifdef HAVE_ECC
-#define SSL_AIDX_ECC (2)
-#define SSL_AIDX_MAX (3)
-#else
-#define SSL_AIDX_MAX (2)
-#endif
-
-/**
* Define the SSL options
*/
#define SSL_OPT_NONE (0)
@@ -498,13 +474,10 @@ typedef struct {
apr_array_header_t *aRandSeed;
apr_hash_t *tVHostKeys;
- /* Two hash tables of pointers to ssl_asn1_t structures. The
- * structures are used to store certificates and private keys
- * respectively, in raw DER format (serialized OpenSSL X509 and
- * PrivateKey structures). The tables are indexed by (vhost-id,
- * algorithm type) using the function ssl_asn1_table_keyfmt(); for
- * example the string "vhost.example.com:443:RSA". */
- apr_hash_t *tPublicCert;
+ /* A hash table of pointers to ssl_asn1_t structures. The structures
+ * are used to store private keys in raw DER format (serialized OpenSSL
+ * PrivateKey structures). The table is indexed by (vhost-id,
+ * index), for example the string "vhost.example.com:443:0". */
apr_hash_t *tPrivateKey;
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
@@ -516,27 +489,14 @@ typedef struct {
ap_socache_instance_t *stapling_cache_context;
apr_global_mutex_t *stapling_mutex;
#endif
-
- struct {
- void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
- } rCtx;
} SSLModConfigRec;
/** Structure representing configured filenames for certs and keys for
- * a given vhost, and the corresponding in-memory structures once the
- * files are parsed. */
+ * a given vhost */
typedef struct {
- /* Lists of configured certs and keys for this server; from index
- * 0 up to SSL_AIDX_MAX-1 or the first NULL pointer. Note that
- * these arrays are NOT indexed by algorithm type, they are simply
- * unordered lists. */
- const char *cert_files[SSL_AIDX_MAX];
- const char *key_files[SSL_AIDX_MAX];
- /* Loaded certs and keys; these arrays ARE indexed by the
- * algorithm type, i.e. keys[SSL_AIDX_RSA] maps to the RSA
- * private key. */
- X509 *certs[SSL_AIDX_MAX];
- EVP_PKEY *keys[SSL_AIDX_MAX];
+ /* Lists of configured certs and keys for this server */
+ apr_array_header_t *cert_files;
+ apr_array_header_t *key_files;
/** Certificates which specify the set of CA names which should be
* sent in the CertificateRequest message: */
@@ -577,6 +537,13 @@ typedef struct {
} modssl_ticket_key_t;
#endif
+#ifdef HAVE_SSL_CONF_CMD
+typedef struct {
+ const char *name;
+ const char *value;
+} ssl_ctx_param_t;
+#endif
+
typedef struct SSLSrvConfigRec SSLSrvConfigRec;
typedef struct {
@@ -598,7 +565,6 @@ typedef struct {
const char *pphrase_dialog_path;
const char *cert_chain;
- const char *pkcs7;
/** certificate revocation list */
const char *crl_path;
@@ -633,7 +599,10 @@ typedef struct {
long ocsp_resptime_skew;
long ocsp_resp_maxage;
apr_interval_time_t ocsp_responder_timeout;
-
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
+ apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
+#endif
} modssl_ctx_t;
struct SSLSrvConfigRec {
@@ -704,7 +673,6 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *);
-const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *, void *, const char *);
@@ -754,6 +722,10 @@ const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char
const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg);
const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag);
+#ifdef HAVE_SSL_CONF_CMD
+const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
+#endif
+
#ifdef HAVE_SRP
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
@@ -762,10 +734,11 @@ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char
const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag);
/** module initialization */
-int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
-void ssl_init_Engine(server_rec *, apr_pool_t *);
-void ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *);
-void ssl_init_CheckServers(server_rec *, apr_pool_t *);
+apr_status_t ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
+apr_status_t ssl_init_Engine(server_rec *, apr_pool_t *);
+apr_status_t ssl_init_ConfigureServer(server_rec *, apr_pool_t *, apr_pool_t *, SSLSrvConfigRec *,
+ apr_array_header_t *);
+apr_status_t ssl_init_CheckServers(server_rec *, apr_pool_t *);
STACK_OF(X509_NAME)
*ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *);
void ssl_init_Child(apr_pool_t *, server_rec *);
@@ -802,7 +775,7 @@ int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *,
#endif
/** Session Cache Support */
-void ssl_scache_init(server_rec *, apr_pool_t *);
+apr_status_t ssl_scache_init(server_rec *, apr_pool_t *);
void ssl_scache_status_register(apr_pool_t *p);
void ssl_scache_kill(server_rec *);
BOOL ssl_scache_store(server_rec *, UCHAR *, int,
@@ -827,7 +800,7 @@ const char *ssl_cmd_SSLStaplingReturnResponderErrors(cmd_parms *, void *, int);
const char *ssl_cmd_SSLStaplingFakeTryLater(cmd_parms *, void *, int);
const char *ssl_cmd_SSLStaplingResponderTimeout(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *, void *, const char *);
-void modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *);
+apr_status_t modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, modssl_ctx_t *);
void ssl_stapling_ex_init(void);
int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x);
#endif
@@ -855,13 +828,12 @@ void ssl_util_ppclose(server_rec *, apr_pool_t *, apr_file_t *);
char *ssl_util_readfilter(server_rec *, apr_pool_t *, const char *,
const char * const *);
BOOL ssl_util_path_check(ssl_pathcheck_t, const char *, apr_pool_t *);
-ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *);
-char *ssl_util_algotypestr(ssl_algo_t);
void ssl_util_thread_setup(apr_pool_t *);
int ssl_init_ssl_connection(conn_rec *c, request_rec *r);
/** Pass Phrase Support */
-void ssl_pphrase_Handle(server_rec *, apr_pool_t *);
+apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
+ const char *, apr_array_header_t **);
/** Diffie-Hellman Parameter Support */
DH *ssl_dh_GetParamFromFile(const char *);
@@ -879,14 +851,6 @@ ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
void ssl_asn1_table_unset(apr_hash_t *table,
const char *key);
-const char *ssl_asn1_keystr(int keytype);
-
-const char *ssl_asn1_table_keyfmt(apr_pool_t *p,
- const char *id,
- int keytype);
-
-STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7);
-
/** Mutex Support */
int ssl_mutex_init(server_rec *, apr_pool_t *);
int ssl_mutex_reinit(server_rec *, apr_pool_t *);
@@ -899,8 +863,9 @@ int ssl_stapling_mutex_reinit(server_rec *, apr_pool_t *);
#define SSL_CACHE_MUTEX_TYPE "ssl-cache"
#define SSL_STAPLING_MUTEX_TYPE "ssl-stapling"
+apr_status_t ssl_die(server_rec *);
+
/** Logfile Support */
-void ssl_die(server_rec *);
void ssl_log_ssl_error(const char *, int, int, server_rec *);
/* ssl_log_xerror, ssl_log_cxerror and ssl_log_rxerror are wrappers for the
diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c
index bfed6e7c..01f72546 100644
--- a/modules/ssl/ssl_scache.c
+++ b/modules/ssl/ssl_scache.c
@@ -37,7 +37,7 @@
** _________________________________________________________________
*/
-void ssl_scache_init(server_rec *s, apr_pool_t *p)
+apr_status_t ssl_scache_init(server_rec *s, apr_pool_t *p)
{
SSLModConfigRec *mc = myModConfig(s);
apr_status_t rv;
@@ -49,7 +49,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p)
* will be immediately cleared anyway. For every subsequent
* invocation, initialize the configured cache. */
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
- return;
+ return APR_SUCCESS;
#ifdef HAVE_OCSP_STAPLING
if (mc->stapling_cache) {
@@ -63,7 +63,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p)
if (rv) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01872)
"Could not initialize stapling cache. Exiting.");
- ssl_die(s);
+ return ssl_die(s);
}
}
#endif
@@ -76,7 +76,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p)
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(01873)
"Init: Session Cache is not configured "
"[hint: SSLSessionCache]");
- return;
+ return APR_SUCCESS;
}
memset(&hints, 0, sizeof hints);
@@ -88,8 +88,10 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p)
if (rv) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01874)
"Could not initialize session cache. Exiting.");
- ssl_die(s);
+ return ssl_die(s);
}
+
+ return APR_SUCCESS;
}
void ssl_scache_kill(server_rec *s)
diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
index d2122784..476aa0b6 100644
--- a/modules/ssl/ssl_util.c
+++ b/modules/ssl/ssl_util.c
@@ -135,61 +135,8 @@ BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
return TRUE;
}
-ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
-{
- ssl_algo_t t;
- EVP_PKEY *pFreeKey = NULL;
-
- t = SSL_ALGO_UNKNOWN;
- if (pCert != NULL)
- pFreeKey = pKey = X509_get_pubkey(pCert);
- if (pKey != NULL) {
- switch (EVP_PKEY_type(pKey->type)) {
- case EVP_PKEY_RSA:
- t = SSL_ALGO_RSA;
- break;
- case EVP_PKEY_DSA:
- t = SSL_ALGO_DSA;
- break;
-#ifdef HAVE_ECC
- case EVP_PKEY_EC:
- t = SSL_ALGO_ECC;
- break;
-#endif
- default:
- break;
- }
- }
- if (pFreeKey != NULL)
- EVP_PKEY_free(pFreeKey);
- return t;
-}
-
-char *ssl_util_algotypestr(ssl_algo_t t)
-{
- char *cp;
-
- cp = "UNKNOWN";
- switch (t) {
- case SSL_ALGO_RSA:
- cp = "RSA";
- break;
- case SSL_ALGO_DSA:
- cp = "DSA";
- break;
-#ifdef HAVE_ECC
- case SSL_ALGO_ECC:
- cp = "ECC";
- break;
-#endif
- default:
- break;
- }
- return cp;
-}
-
/*
- * certain key and cert data needs to survive restarts,
+ * certain key data needs to survive restarts,
* which are stored in the user data table of s->process->pool.
* to prevent "leaking" of this data, we use malloc/free
* rather than apr_palloc and these wrappers to help make sure
@@ -253,81 +200,6 @@ void ssl_asn1_table_unset(apr_hash_t *table,
apr_hash_set(table, key, klen, NULL);
}
-#ifdef HAVE_ECC
-static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"};
-#else
-static const char *ssl_asn1_key_types[] = {"RSA", "DSA"};
-#endif
-
-const char *ssl_asn1_keystr(int keytype)
-{
- if (keytype >= SSL_AIDX_MAX) {
- return NULL;
- }
-
- return ssl_asn1_key_types[keytype];
-}
-
-const char *ssl_asn1_table_keyfmt(apr_pool_t *p,
- const char *id,
- int keytype)
-{
- const char *keystr = ssl_asn1_keystr(keytype);
-
- return apr_pstrcat(p, id, ":", keystr, NULL);
-}
-
-STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7)
-{
- PKCS7 *p7;
- STACK_OF(X509) *certs = NULL;
- FILE *f;
-
- f = fopen(pkcs7, "r");
- if (!f) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02212) "Can't open %s", pkcs7);
- ssl_die(s);
- }
-
- p7 = PEM_read_PKCS7(f, NULL, NULL, NULL);
- if (!p7) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02274)
- "Can't read PKCS7 object %s", pkcs7);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_CRIT, s);
- exit(1);
- }
-
- switch (OBJ_obj2nid(p7->type)) {
- case NID_pkcs7_signed:
- certs = p7->d.sign->cert;
- p7->d.sign->cert = NULL;
- PKCS7_free(p7);
- break;
-
- case NID_pkcs7_signedAndEnveloped:
- certs = p7->d.signed_and_enveloped->cert;
- p7->d.signed_and_enveloped->cert = NULL;
- PKCS7_free(p7);
- break;
-
- default:
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02213)
- "Don't understand PKCS7 file %s", pkcs7);
- ssl_die(s);
- }
-
- if (!certs) {
- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02214)
- "No certificates in %s", pkcs7);
- ssl_die(s);
- }
-
- fclose(f);
-
- return certs;
-}
-
-
#if APR_HAS_THREADS
/*
* To ensure thread-safetyness in OpenSSL - work in progress
diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c
index 757df05f..90160405 100644
--- a/modules/ssl/ssl_util_ocsp.c
+++ b/modules/ssl/ssl_util_ocsp.c
@@ -96,7 +96,6 @@ static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri,
ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974)
"could not connect to OCSP responder '%s'",
uri->hostinfo);
- apr_socket_close(sd);
return NULL;
}
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
index 9f4cfa2c..0bf37768 100644
--- a/modules/ssl/ssl_util_ssl.c
+++ b/modules/ssl/ssl_util_ssl.c
@@ -70,52 +70,11 @@ void SSL_set_app_data2(SSL *ssl, void *arg)
/* _________________________________________________________________
**
-** High-Level Certificate / Private Key Loading
+** High-Level Private Key Loading
** _________________________________________________________________
*/
-X509 *SSL_read_X509(char* filename, X509 **x509, pem_password_cb *cb)
-{
- X509 *rc;
- BIO *bioS;
- BIO *bioF;
-
- /* 1. try PEM (= DER+Base64+headers) */
- if ((bioS=BIO_new_file(filename, "r")) == NULL)
- return NULL;
- rc = PEM_read_bio_X509 (bioS, x509, cb, NULL);
- BIO_free(bioS);
-
- if (rc == NULL) {
- /* 2. try DER+Base64 */
- if ((bioS=BIO_new_file(filename, "r")) == NULL)
- return NULL;
-
- if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
- BIO_free(bioS);
- return NULL;
- }
- bioS = BIO_push(bioF, bioS);
- rc = d2i_X509_bio(bioS, NULL);
- BIO_free_all(bioS);
-
- if (rc == NULL) {
- /* 3. try plain DER */
- if ((bioS=BIO_new_file(filename, "r")) == NULL)
- return NULL;
- rc = d2i_X509_bio(bioS, NULL);
- BIO_free(bioS);
- }
- }
- if (rc != NULL && x509 != NULL) {
- if (*x509 != NULL)
- X509_free(*x509);
- *x509 = rc;
- }
- return rc;
-}
-
-EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s)
+EVP_PKEY *SSL_read_PrivateKey(const char* filename, EVP_PKEY **key, pem_password_cb *cb, void *s)
{
EVP_PKEY *rc;
BIO *bioS;
@@ -188,29 +147,6 @@ int SSL_smart_shutdown(SSL *ssl)
** _________________________________________________________________
*/
-/* check whether cert contains extended key usage with a SGC tag */
-BOOL SSL_X509_isSGC(X509 *cert)
-{
- int ext_nid;
- EXTENDED_KEY_USAGE *sk;
- BOOL is_sgc;
- int i;
-
- is_sgc = FALSE;
- sk = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL);
- if (sk) {
- for (i = 0; i < sk_ASN1_OBJECT_num(sk); i++) {
- ext_nid = OBJ_obj2nid(sk_ASN1_OBJECT_value(sk, i));
- if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {
- is_sgc = TRUE;
- break;
- }
- }
- EXTENDED_KEY_USAGE_free(sk);
- }
- return is_sgc;
-}
-
/* retrieve basic constraints ingredients */
BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
{
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
index 4b882db2..6f6873b4 100644
--- a/modules/ssl/ssl_util_ssl.h
+++ b/modules/ssl/ssl_util_ssl.h
@@ -60,10 +60,8 @@
void SSL_init_app_data2_idx(void);
void *SSL_get_app_data2(SSL *);
void SSL_set_app_data2(SSL *, void *);
-X509 *SSL_read_X509(char *, X509 **, pem_password_cb *);
-EVP_PKEY *SSL_read_PrivateKey(char *, EVP_PKEY **, pem_password_cb *, void *);
+EVP_PKEY *SSL_read_PrivateKey(const char *, EVP_PKEY **, pem_password_cb *, void *);
int SSL_smart_shutdown(SSL *ssl);
-BOOL SSL_X509_isSGC(X509 *);
BOOL SSL_X509_getBC(X509 *, int *, int *);
char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne);
char *SSL_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int);
diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c
index 0387cf92..7633648c 100644
--- a/modules/ssl/ssl_util_stapling.c
+++ b/modules/ssl/ssl_util_stapling.c
@@ -653,8 +653,8 @@ static int stapling_cb(SSL *ssl, void *arg)
}
-void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
- modssl_ctx_t *mctx)
+apr_status_t modssl_init_stapling(server_rec *s, apr_pool_t *p,
+ apr_pool_t *ptemp, modssl_ctx_t *mctx)
{
SSL_CTX *ctx = mctx->ssl_ctx;
SSLModConfigRec *mc = myModConfig(s);
@@ -662,12 +662,12 @@ void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
if (mc->stapling_cache == NULL) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01958)
"SSLStapling: no stapling cache available");
- ssl_die(s);
+ return ssl_die(s);
}
if (ssl_stapling_mutex_init(s, ptemp) == FALSE) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01959)
"SSLStapling: cannot initialise stapling mutex");
- ssl_die(s);
+ return ssl_die(s);
}
/* Set some default values for parameters if they are not set */
if (mctx->stapling_resptime_skew == UNSET) {
@@ -690,6 +690,8 @@ void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
}
SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized");
+
+ return APR_SUCCESS;
}
#endif