summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/aaa/mod_auth_basic.c62
-rw-r--r--modules/aaa/mod_auth_digest.c10
-rw-r--r--modules/aaa/mod_authn_socache.c32
-rw-r--r--modules/aaa/mod_authnz_ldap.c2
-rw-r--r--modules/aaa/mod_authz_groupfile.c2
-rw-r--r--modules/aaa/mod_authz_user.c2
-rw-r--r--modules/cache/cache_storage.c9
-rw-r--r--modules/cache/mod_cache.c8
-rw-r--r--modules/cache/mod_cache_socache.c4
-rw-r--r--modules/cache/mod_socache_memcache.c2
-rw-r--r--modules/cache/mod_socache_shmcb.c8
-rw-r--r--modules/dav/fs/repos.c29
-rw-r--r--modules/dav/main/mod_dav.c23
-rw-r--r--modules/dav/main/mod_dav.h5
-rw-r--r--modules/dav/main/util.c7
-rw-r--r--modules/filters/mod_charset_lite.c2
-rw-r--r--modules/filters/mod_data.c3
-rw-r--r--modules/filters/mod_deflate.c20
-rw-r--r--modules/filters/mod_filter.c3
-rw-r--r--modules/filters/mod_proxy_html.dsp2
-rw-r--r--modules/filters/mod_xml2enc.dsp2
-rw-r--r--modules/generators/mod_info.c2
-rw-r--r--modules/http/http_filters.c20
-rw-r--r--modules/ldap/util_ldap.c47
-rw-r--r--modules/ldap/util_ldap_cache.c2
-rw-r--r--modules/loggers/mod_log_config.c14
-rw-r--r--modules/loggers/mod_logio.c19
-rw-r--r--modules/lua/lua_passwd.h1
-rw-r--r--modules/lua/lua_request.c434
-rw-r--r--modules/lua/mod_lua.c89
-rw-r--r--modules/lua/mod_lua.dsp8
-rw-r--r--modules/mappers/mod_rewrite.c12
-rw-r--r--modules/metadata/mod_headers.c52
-rw-r--r--modules/metadata/mod_mime_magic.c2
-rw-r--r--modules/proxy/ajp.h2
-rw-r--r--modules/proxy/fcgi_protocol.h108
-rw-r--r--modules/proxy/mod_proxy.c42
-rw-r--r--modules/proxy/mod_proxy.h12
-rw-r--r--modules/proxy/mod_proxy_balancer.c9
-rw-r--r--modules/proxy/mod_proxy_connect.c2
-rw-r--r--modules/proxy/mod_proxy_fcgi.c446
-rw-r--r--modules/proxy/mod_proxy_http.c2
-rw-r--r--modules/proxy/proxy_util.c66
-rw-r--r--modules/session/mod_session.c15
-rw-r--r--modules/session/mod_session_crypto.c32
-rw-r--r--modules/slotmem/mod_slotmem_shm.c73
-rw-r--r--modules/ssl/config.m41
-rw-r--r--modules/ssl/mod_ssl.c13
-rw-r--r--modules/ssl/mod_ssl.dsp4
-rw-r--r--modules/ssl/ssl_engine_config.c24
-rw-r--r--modules/ssl/ssl_engine_dh.c244
-rw-r--r--modules/ssl/ssl_engine_init.c280
-rw-r--r--modules/ssl/ssl_engine_io.c22
-rw-r--r--modules/ssl/ssl_engine_kernel.c173
-rw-r--r--modules/ssl/ssl_engine_pphrase.c6
-rw-r--r--modules/ssl/ssl_engine_vars.c8
-rw-r--r--modules/ssl/ssl_private.h138
-rw-r--r--modules/ssl/ssl_scache.c2
-rw-r--r--modules/ssl/ssl_util.c6
-rw-r--r--modules/ssl/ssl_util_ssl.c32
-rw-r--r--modules/test/mod_optional_hook_export.h2
61 files changed, 1386 insertions, 1317 deletions
diff --git a/modules/aaa/mod_auth_basic.c b/modules/aaa/mod_auth_basic.c
index 8c1367b3..75044d48 100644
--- a/modules/aaa/mod_auth_basic.c
+++ b/modules/aaa/mod_auth_basic.c
@@ -27,6 +27,7 @@
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
+#include "util_md5.h"
#include "ap_provider.h"
#include "ap_expr.h"
@@ -38,7 +39,9 @@ typedef struct {
int authoritative;
ap_expr_info_t *fakeuser;
ap_expr_info_t *fakepass;
+ const char *use_digest_algorithm;
int fake_set:1;
+ int use_digest_algorithm_set:1;
int authoritative_set:1;
} auth_basic_config_rec;
@@ -70,6 +73,12 @@ static void *merge_auth_basic_dir_config(apr_pool_t *p, void *basev, void *overr
overrides->fake_set ? overrides->fakepass : base->fakepass;
newconf->fake_set = overrides->fake_set || base->fake_set;
+ newconf->use_digest_algorithm =
+ overrides->use_digest_algorithm_set ? overrides->use_digest_algorithm
+ : base->use_digest_algorithm;
+ newconf->use_digest_algorithm_set =
+ overrides->use_digest_algorithm_set || base->use_digest_algorithm_set;
+
newconf->providers = overrides->providers ? overrides->providers : base->providers;
return newconf;
@@ -175,6 +184,23 @@ static const char *add_basic_fake(cmd_parms * cmd, void *config,
return NULL;
}
+static const char *set_use_digest_algorithm(cmd_parms *cmd, void *config,
+ const char *alg)
+{
+ auth_basic_config_rec *conf = (auth_basic_config_rec *)config;
+
+ if (strcasecmp(alg, "Off") && strcasecmp(alg, "MD5")) {
+ return apr_pstrcat(cmd->pool,
+ "Invalid algorithm in "
+ "AuthBasicUseDigestAlgorithm: ", alg, NULL);
+ }
+
+ conf->use_digest_algorithm = apr_pstrdup(cmd->pool, alg);
+ conf->use_digest_algorithm_set = 1;
+
+ return NULL;
+}
+
static const command_rec auth_basic_cmds[] =
{
AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG,
@@ -186,6 +212,10 @@ static const command_rec auth_basic_cmds[] =
"Fake basic authentication using the given expressions for "
"username and password, 'off' to disable. Password defaults "
"to 'password' if missing."),
+ AP_INIT_TAKE1("AuthBasicUseDigestAlgorithm", set_use_digest_algorithm,
+ NULL, OR_AUTHCFG,
+ "Set to 'MD5' to use the auth provider's authentication "
+ "check for digest auth, using a hash of 'user:realm:pass'"),
{NULL}
};
@@ -271,6 +301,8 @@ static int authenticate_basic_user(request_rec *r)
auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config,
&auth_basic_module);
const char *sent_user, *sent_pw, *current_auth;
+ const char *realm = NULL;
+ const char *digest = NULL;
int res;
authn_status auth_result;
authn_provider_list *current_provider;
@@ -295,6 +327,15 @@ static int authenticate_basic_user(request_rec *r)
return res;
}
+ if (conf->use_digest_algorithm
+ && !strcasecmp(conf->use_digest_algorithm, "MD5")) {
+ realm = ap_auth_name(r);
+ digest = ap_md5(r->pool,
+ (unsigned char *)apr_pstrcat(r->pool, sent_user, ":",
+ realm, ":",
+ sent_pw, NULL));
+ }
+
current_provider = conf->providers;
do {
const authn_provider *provider;
@@ -320,8 +361,27 @@ static int authenticate_basic_user(request_rec *r)
apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name);
}
+ if (digest) {
+ char *password;
- auth_result = provider->check_password(r, sent_user, sent_pw);
+ if (!provider->get_realm_hash) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02493)
+ "Authn provider does not support "
+ "AuthBasicUseDigestAlgorithm");
+ auth_result = AUTH_GENERAL_ERROR;
+ break;
+ }
+ /* We expect the password to be hash of user:realm:password */
+ auth_result = provider->get_realm_hash(r, sent_user, realm,
+ &password);
+ if (auth_result == AUTH_USER_FOUND) {
+ auth_result = strcmp(digest, password) ? AUTH_DENIED
+ : AUTH_GRANTED;
+ }
+ }
+ else {
+ auth_result = provider->check_password(r, sent_user, sent_pw);
+ }
apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
index 987e5b5b..dcf1e15b 100644
--- a/modules/aaa/mod_auth_digest.c
+++ b/modules/aaa/mod_auth_digest.c
@@ -1811,7 +1811,15 @@ static int authenticate_digest_user(request_rec *r)
return HTTP_UNAUTHORIZED;
}
- if (strcmp(resp->realm, conf->realm)) {
+ if (!conf->realm) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02533)
+ "realm mismatch - got `%s' but no realm specified",
+ resp->realm);
+ note_digest_auth_failure(r, conf, resp, 0);
+ return HTTP_UNAUTHORIZED;
+ }
+
+ if (!resp->realm || strcmp(resp->realm, conf->realm)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01788)
"realm mismatch - got `%s' but expected `%s'",
resp->realm, conf->realm);
diff --git a/modules/aaa/mod_authn_socache.c b/modules/aaa/mod_authn_socache.c
index cccd076b..f36d49c8 100644
--- a/modules/aaa/mod_authn_socache.c
+++ b/modules/aaa/mod_authn_socache.c
@@ -40,7 +40,7 @@ typedef struct authn_cache_dircfg {
const char *context;
} authn_cache_dircfg;
-/* FIXME: figure out usage of socache create vs init
+/* FIXME:
* I think the cache and mutex should be global
*/
static apr_global_mutex_t *authn_cache_mutex = NULL;
@@ -86,7 +86,6 @@ static int authn_cache_post_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptmp, server_rec *s)
{
apr_status_t rv;
- const char *errmsg;
static struct ap_socache_hints authn_cache_hints = {64, 32, 60000000};
if (!configured) {
@@ -109,12 +108,6 @@ static int authn_cache_post_config(apr_pool_t *pconf, apr_pool_t *plog,
}
apr_pool_cleanup_register(pconf, NULL, remove_lock, apr_pool_cleanup_null);
- errmsg = socache_provider->create(&socache_instance, NULL, ptmp, pconf);
- if (errmsg) {
- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, plog, APLOGNO(01676) "%s", errmsg);
- return 500; /* An HTTP status would be a misnomer! */
- }
-
rv = socache_provider->init(socache_instance, authn_cache_id,
&authn_cache_hints, s, pconf);
if (rv != APR_SUCCESS) {
@@ -144,9 +137,22 @@ static const char *authn_cache_socache(cmd_parms *cmd, void *CFG,
const char *arg)
{
const char *errmsg = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+ const char *sep, *name;
+
if (errmsg)
return errmsg;
- socache_provider = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, arg,
+
+ /* Argument is of form 'name:args' or just 'name'. */
+ sep = ap_strchr_c(arg, ':');
+ if (sep) {
+ name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
+ sep++;
+ }
+ else {
+ name = arg;
+ }
+
+ socache_provider = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, name,
AP_SOCACHE_PROVIDER_VERSION);
if (socache_provider == NULL) {
errmsg = apr_psprintf(cmd->pool,
@@ -154,6 +160,14 @@ static const char *authn_cache_socache(cmd_parms *cmd, void *CFG,
"to load the appropriate socache module "
"(mod_socache_%s?)", arg, arg);
}
+ else {
+ errmsg = socache_provider->create(&socache_instance, sep,
+ cmd->temp_pool, cmd->pool);
+ }
+
+ if (errmsg) {
+ errmsg = apr_psprintf(cmd->pool, "AuthnCacheSOCache: %s", errmsg);
+ }
return errmsg;
}
diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c
index 2c25dbc7..d46eeb44 100644
--- a/modules/aaa/mod_authnz_ldap.c
+++ b/modules/aaa/mod_authnz_ldap.c
@@ -894,7 +894,7 @@ static authz_status ldapgroup_check_authorization(request_rec *r,
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01719)
"auth_ldap authorize: require group \"%s\": "
"didn't match with attr %s [%s][%d - %s]",
- t, ldc->reason, ent[i].name, result,
+ t, ent[i].name, ldc->reason, result,
ldap_err2string(result));
}
}
diff --git a/modules/aaa/mod_authz_groupfile.c b/modules/aaa/mod_authz_groupfile.c
index 934a7d2f..c7fd13b6 100644
--- a/modules/aaa/mod_authz_groupfile.c
+++ b/modules/aaa/mod_authz_groupfile.c
@@ -249,7 +249,7 @@ static authz_status filegroup_check_authorization(request_rec *r,
return AUTHZ_DENIED;
}
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01671)
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01671)
"Authorization of user %s to access %s failed, reason: "
"user is not part of the 'require'ed file group.",
r->user, r->uri);
diff --git a/modules/aaa/mod_authz_user.c b/modules/aaa/mod_authz_user.c
index 7c9462c8..e4af7946 100644
--- a/modules/aaa/mod_authz_user.c
+++ b/modules/aaa/mod_authz_user.c
@@ -62,7 +62,7 @@ static authz_status user_check_authorization(request_rec *r,
}
}
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01663)
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01663)
"access to %s failed, reason: user '%s' does not meet "
"'require'ments for user to be allowed access",
r->uri, r->user);
diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c
index af60a39b..782dc712 100644
--- a/modules/cache/cache_storage.c
+++ b/modules/cache/cache_storage.c
@@ -713,7 +713,9 @@ int cache_invalidate(cache_request_rec *cache, request_rec *r)
|| APR_SUCCESS
!= cache_canonicalise_key(r, r->pool, location,
&location_uri, &location_key)
- || strcmp(r->parsed_uri.hostname, location_uri.hostname)) {
+ || !(r->parsed_uri.hostname && location_uri.hostname
+ && !strcmp(r->parsed_uri.hostname,
+ location_uri.hostname))) {
location_key = NULL;
}
}
@@ -726,8 +728,9 @@ int cache_invalidate(cache_request_rec *cache, request_rec *r)
|| APR_SUCCESS
!= cache_canonicalise_key(r, r->pool, content_location,
&content_location_uri, &content_location_key)
- || strcmp(r->parsed_uri.hostname,
- content_location_uri.hostname)) {
+ || !(r->parsed_uri.hostname && content_location_uri.hostname
+ && !strcmp(r->parsed_uri.hostname,
+ content_location_uri.hostname))) {
content_location_key = NULL;
}
}
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c
index 06bdf460..6e644e67 100644
--- a/modules/cache/mod_cache.c
+++ b/modules/cache/mod_cache.c
@@ -1104,7 +1104,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
reason = "updated entity is older than cached entity";
/* while this response is not cacheable, the previous response still is */
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00770)
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02474)
"cache: Removing CACHE_REMOVE_URL filter.");
ap_remove_output_filter(cache->remove_url_filter);
}
@@ -1171,8 +1171,10 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
*/
if (reason && r->status == HTTP_NOT_MODIFIED && cache->stale_handle) {
- ap_log_rerror(
- APLOG_MARK, APLOG_INFO, 0, r, APLOGNO() "cache: %s responded with an uncacheable 304, retrying the request. Reason: %s", r->unparsed_uri, reason);
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02473)
+ "cache: %s responded with an uncacheable 304, "
+ "retrying the request. Reason: %s",
+ r->unparsed_uri, reason);
/* we've got a cache conditional miss! tell anyone who cares */
cache_run_cache_status(cache->handle, r, r->headers_out, AP_CACHE_MISS,
diff --git a/modules/cache/mod_cache_socache.c b/modules/cache/mod_cache_socache.c
index 913de2ee..220f9c8b 100644
--- a/modules/cache/mod_cache_socache.c
+++ b/modules/cache/mod_cache_socache.c
@@ -168,8 +168,8 @@ static apr_status_t store_array(apr_array_header_t *arr, unsigned char *buffer,
elts = (const char **) arr->elts;
for (i = 0; i < arr->nelts; i++) {
- len = strlen(elts[i]);
- if (len + 3 >= buffer_len - *slider) {
+ apr_size_t e_len = strlen(elts[i]);
+ if (e_len + 3 >= buffer_len - *slider) {
return APR_EOF;
}
len = apr_snprintf(buffer ? (char *) buffer + *slider : NULL,
diff --git a/modules/cache/mod_socache_memcache.c b/modules/cache/mod_socache_memcache.c
index beeeec2c..8cabd8a5 100644
--- a/modules/cache/mod_socache_memcache.c
+++ b/modules/cache/mod_socache_memcache.c
@@ -85,7 +85,7 @@ static apr_status_t socache_mc_init(ap_socache_instance_t *ctx,
{
apr_status_t rv;
int thread_limit = 0;
- int nservers = 0;
+ apr_uint16_t nservers = 0;
char *cache_config;
char *split;
char *tok;
diff --git a/modules/cache/mod_socache_shmcb.c b/modules/cache/mod_socache_shmcb.c
index 4d4246b3..f6bf1dab 100644
--- a/modules/cache/mod_socache_shmcb.c
+++ b/modules/cache/mod_socache_shmcb.c
@@ -316,11 +316,9 @@ static const char *socache_shmcb_create(ap_socache_instance_t **context,
}
if (ctx->shm_size >= SHMCB_MAX_SIZE) {
- return apr_psprintf(tmp,
- "Invalid argument: size has "
- "to be < %d bytes on this platform",
- SHMCB_MAX_SIZE);
-
+ return apr_psprintf(tmp, "Invalid argument: size has "
+ "to be < %" APR_SIZE_T_FMT " bytes on this platform",
+ SHMCB_MAX_SIZE);
}
}
else if (cp2 >= path && *cp2 == ')') {
diff --git a/modules/dav/fs/repos.c b/modules/dav/fs/repos.c
index 6c4c44b1..ae6f5c0e 100644
--- a/modules/dav/fs/repos.c
+++ b/modules/dav/fs/repos.c
@@ -717,13 +717,13 @@ static dav_error * dav_fs_get_resource(
resource->pool = r->pool;
/* make sure the URI does not have a trailing "/" */
- len = strlen(r->uri);
- if (len > 1 && r->uri[len - 1] == '/') {
- s = apr_pstrmemdup(r->pool, r->uri, len-1);
+ len = strlen(r->unparsed_uri);
+ if (len > 1 && r->unparsed_uri[len - 1] == '/') {
+ s = apr_pstrmemdup(r->pool, r->unparsed_uri, len-1);
resource->uri = s;
}
else {
- resource->uri = r->uri;
+ resource->uri = r->unparsed_uri;
}
if (r->finfo.filetype != APR_NOFILE) {
@@ -1482,6 +1482,18 @@ static dav_error * dav_fs_remove_resource(dav_resource *resource,
return dav_fs_deleteset(info->pool, resource);
}
+/* Take an unescaped path component and escape it and append it onto a
+ * dav_buffer for a URI */
+static apr_size_t dav_fs_append_uri(apr_pool_t *p, dav_buffer *pbuf,
+ const char *path, apr_size_t pad)
+{
+ const char *epath = ap_escape_uri(p, path);
+ apr_size_t epath_len = strlen(epath);
+
+ dav_buffer_place_mem(p, pbuf, epath, epath_len + 1, pad);
+ return epath_len;
+}
+
/* ### move this to dav_util? */
/* Walk recursively down through directories, *
* including lock-null resources as we go. */
@@ -1537,6 +1549,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
}
while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
apr_size_t len;
+ apr_size_t escaped_len;
len = strlen(dirent.name);
@@ -1579,7 +1592,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
/* copy the file to the URI, too. NOTE: we will pad an extra byte
for the trailing slash later. */
- dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
+ escaped_len = dav_fs_append_uri(pool, &fsctx->uri_buf, dirent.name, 1);
/* if there is a secondary path, then do that, too */
if (fsctx->path2.buf != NULL) {
@@ -1612,7 +1625,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
fsctx->path2.cur_len += len;
/* adjust URI length to incorporate subdir and a slash */
- fsctx->uri_buf.cur_len += len + 1;
+ fsctx->uri_buf.cur_len += escaped_len + 1;
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
@@ -1678,8 +1691,8 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
*/
dav_buffer_place_mem(pool, &fsctx->path1,
fsctx->locknull_buf.buf + offset, len + 1, 0);
- dav_buffer_place_mem(pool, &fsctx->uri_buf,
- fsctx->locknull_buf.buf + offset, len + 1, 0);
+ dav_fs_append_uri(pool, &fsctx->uri_buf,
+ fsctx->locknull_buf.buf + offset, 0);
if (fsctx->path2.buf != NULL) {
dav_buffer_place_mem(pool, &fsctx->path2,
fsctx->locknull_buf.buf + offset,
diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c
index 9135cd96..f3c2958b 100644
--- a/modules/dav/main/mod_dav.c
+++ b/modules/dav/main/mod_dav.c
@@ -396,11 +396,9 @@ static int dav_error_response_tag(request_rec *r,
*/
static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
{
- const char *e_uri = ap_escape_uri(p, uri);
-
/* check the easy case... */
- if (ap_strchr_c(e_uri, '&') == NULL)
- return e_uri;
+ if (ap_strchr_c(uri, '&') == NULL)
+ return uri;
/* there was a '&', so more work is needed... sigh. */
@@ -408,7 +406,7 @@ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
* Note: this is a teeny bit of overkill since we know there are no
* '<' or '>' characters, but who cares.
*/
- return apr_xml_quote_string(p, e_uri, 0);
+ return apr_xml_quote_string(p, uri, 0);
}
@@ -604,7 +602,8 @@ static int dav_handle_err(request_rec *r, dav_error *err,
return DONE;
}
-/* handy function for return values of methods that (may) create things */
+/* handy function for return values of methods that (may) create things.
+ * locn if provided is assumed to be escaped. */
static int dav_created(request_rec *r, const char *locn, const char *what,
int replaced)
{
@@ -612,8 +611,6 @@ static int dav_created(request_rec *r, const char *locn, const char *what,
if (locn == NULL) {
locn = r->unparsed_uri;
- } else {
- locn = ap_escape_uri(r->pool, locn);
}
/* did the target resource already exist? */
@@ -2756,7 +2753,7 @@ static int dav_method_copymove(request_rec *r, int is_move)
* The multistatus responses will contain the information about any
* resource that fails the validation.
*
- * We check the parent resource, too, since this is a MOVE. Moving the
+ * We check the parent resource, too, if this is a MOVE. Moving the
* resource effectively removes it from the parent collection, so we
* must ensure that we have met the appropriate conditions.
*
@@ -2765,7 +2762,9 @@ static int dav_method_copymove(request_rec *r, int is_move)
*/
if ((err = dav_validate_request(r, resource, depth, NULL,
&multi_response,
- DAV_VALIDATE_PARENT
+ (is_move ? DAV_VALIDATE_PARENT
+ : DAV_VALIDATE_RESOURCE
+ | DAV_VALIDATE_NO_MODIFY)
| DAV_VALIDATE_USE_424,
NULL)) != NULL) {
err = dav_push_error(r->pool, err->status, 0,
@@ -3002,7 +3001,7 @@ static int dav_method_copymove(request_rec *r, int is_move)
}
/* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
- return dav_created(r, lookup.rnew->uri, "Destination",
+ return dav_created(r, lookup.rnew->unparsed_uri, "Destination",
resnew_state == DAV_RESOURCE_EXISTS);
}
@@ -4608,7 +4607,7 @@ static int dav_method_bind(request_rec *r)
/* return an appropriate response (HTTP_CREATED) */
/* ### spec doesn't say what happens when destination was replaced */
- return dav_created(r, lookup.rnew->uri, "Binding", 0);
+ return dav_created(r, lookup.rnew->unparsed_uri, "Binding", 0);
}
diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h
index 7b91b63c..62c21f05 100644
--- a/modules/dav/main/mod_dav.h
+++ b/modules/dav/main/mod_dav.h
@@ -386,7 +386,7 @@ typedef struct dav_resource {
* REGULAR and WORKSPACE resources,
* and is always 1 for WORKING */
- const char *uri; /* the URI for this resource */
+ const char *uri; /* the escaped URI for this resource */
dav_resource_private *info; /* the provider's private info */
@@ -1297,6 +1297,9 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,
the 424 DAV:response */
#define DAV_VALIDATE_USE_424 0x0080 /* return 424 status, not 207 */
#define DAV_VALIDATE_IS_PARENT 0x0100 /* for internal use */
+#define DAV_VALIDATE_NO_MODIFY 0x0200 /* resource is not being modified
+ so allow even if lock token
+ is not provided */
/* Lock-null related public lock functions */
DAV_DECLARE(int) dav_get_resource_state(request_rec *r,
diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c
index ab42af02..1f393401 100644
--- a/modules/dav/main/util.c
+++ b/modules/dav/main/util.c
@@ -954,13 +954,16 @@ static dav_error * dav_validate_resource_state(apr_pool_t *p,
/*
** For methods other than LOCK:
**
- ** If we have no locks, then <seen_locktoken> can be set to true --
+ ** If we have no locks or if the resource is not being modified
+ ** (per RFC 4918 the lock token is not required on resources
+ ** we are not changing), then <seen_locktoken> can be set to true --
** pretending that we've already met the requirement of seeing one
** of the resource's locks in the If: header.
**
** Otherwise, it must be cleared and we'll look for one.
*/
- seen_locktoken = (lock_list == NULL);
+ seen_locktoken = (lock_list == NULL
+ || flags & DAV_VALIDATE_NO_MODIFY);
}
/*
diff --git a/modules/filters/mod_charset_lite.c b/modules/filters/mod_charset_lite.c
index 2d3d1439..934f0477 100644
--- a/modules/filters/mod_charset_lite.c
+++ b/modules/filters/mod_charset_lite.c
@@ -474,7 +474,7 @@ static void log_xlate_error(ap_filter_t *f, apr_status_t rv)
charset_filter_ctx_t *ctx = f->ctx;
const char *msg;
char msgbuf[100];
- int len;
+ apr_size_t len;
switch(ctx->ees) {
case EES_LIMIT:
diff --git a/modules/filters/mod_data.c b/modules/filters/mod_data.c
index 83284dd2..d083d322 100644
--- a/modules/filters/mod_data.c
+++ b/modules/filters/mod_data.c
@@ -109,7 +109,8 @@ static apr_status_t data_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
apr_brigade_length(ctx->bb, 1, &len);
clen = apr_atoi64(content_length);
if (clen >= 0 && clen < APR_INT32_MAX) {
- ap_set_content_length(r, len + apr_base64_encode_len(clen) - 1);
+ ap_set_content_length(r, len +
+ apr_base64_encode_len((int)clen) - 1);
}
else {
apr_table_unset(r->headers_out, "Content-Length");
diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
index 79f6f8d1..5ae06085 100644
--- a/modules/filters/mod_deflate.c
+++ b/modules/filters/mod_deflate.c
@@ -1013,8 +1013,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
if (APR_BUCKET_IS_EOS(bkt)) {
if (!ctx->done) {
inflateEnd(&ctx->stream);
- ap_log_rerror(
- APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02481) "Encountered premature end-of-stream while inflating");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02481)
+ "Encountered premature end-of-stream while inflating");
return APR_EGENERAL;
}
@@ -1053,8 +1053,8 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
/* sanity check - data after completed compressed body and before eos? */
if (ctx->done) {
- ap_log_rerror(
- APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02482) "Encountered extra data after compressed data");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02482)
+ "Encountered extra data after compressed data");
return APR_EGENERAL;
}
@@ -1096,6 +1096,7 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
}
if (zRC == Z_STREAM_END) {
apr_bucket *tmp_heap;
+ apr_size_t avail;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01393)
"Zlib: Inflated %ld to %ld : URL %s",
@@ -1110,8 +1111,10 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
APR_BRIGADE_INSERT_TAIL(ctx->proc_bb, tmp_heap);
ctx->stream.avail_out = c->bufferSize;
+ avail = ctx->stream.avail_in;
+
/* Is the remaining 8 bytes already in the avail stream? */
- if (ctx->stream.avail_in >= 8) {
+ if (avail >= 8) {
unsigned long compCRC, compLen;
compCRC = getLong(ctx->stream.next_in);
if (ctx->crc != compCRC) {
@@ -1143,6 +1146,13 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
inflateEnd(&ctx->stream);
ctx->done = 1;
+
+ /* Did we have trailing data behind the closing 8 bytes? */
+ if (avail > 8) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02485)
+ "Encountered extra data after compressed data");
+ return APR_EGENERAL;
+ }
}
}
diff --git a/modules/filters/mod_filter.c b/modules/filters/mod_filter.c
index 2d8e8b65..8fb872cd 100644
--- a/modules/filters/mod_filter.c
+++ b/modules/filters/mod_filter.c
@@ -368,6 +368,9 @@ static const char *filter_protocol(cmd_parms *cmd, void *CFG, const char *fname,
if (!strcasecmp(arg, "change=yes")) {
flags |= AP_FILTER_PROTO_CHANGE | AP_FILTER_PROTO_CHANGE_LENGTH;
}
+ if (!strcasecmp(arg, "change=no")) {
+ flags &= ~(AP_FILTER_PROTO_CHANGE | AP_FILTER_PROTO_CHANGE_LENGTH);
+ }
else if (!strcasecmp(arg, "change=1:1")) {
flags |= AP_FILTER_PROTO_CHANGE;
}
diff --git a/modules/filters/mod_proxy_html.dsp b/modules/filters/mod_proxy_html.dsp
index be883edd..1d5d54e7 100644
--- a/modules/filters/mod_proxy_html.dsp
+++ b/modules/filters/mod_proxy_html.dsp
@@ -79,7 +79,7 @@ PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).ma
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /i /d "_DEBUG" "../../include" /i "../../srclib/apr/include" /I "../../srclib/apr-util/include" /i "../../srclib/libxml2/include" /d BIN_NAME="mod_proxy_html.so" /d LONG_NAME="proxy_html_module for Apache"
+# ADD RSC /l 0x409 /d "_DEBUG" /i "../../include" /i "../../srclib/apr/include" /I "../../srclib/apr-util/include" /i "../../srclib/libxml2/include" /d BIN_NAME="mod_proxy_html.so" /d LONG_NAME="proxy_html_module for Apache"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
diff --git a/modules/filters/mod_xml2enc.dsp b/modules/filters/mod_xml2enc.dsp
index d5e357a4..69e2904a 100644
--- a/modules/filters/mod_xml2enc.dsp
+++ b/modules/filters/mod_xml2enc.dsp
@@ -79,7 +79,7 @@ PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).ma
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /i /d "_DEBUG" "../../include" /i "../../srclib/apr/include" /i "../../srclib/apr-util/include" /i "../../srclib/libxml2/include" /d BIN_NAME="mod_xml2enc.so" /d LONG_NAME="xml2enc_module for Apache"
+# ADD RSC /l 0x409 /d "_DEBUG" /i "../../include" /i "../../srclib/apr/include" /i "../../srclib/apr-util/include" /i "../../srclib/libxml2/include" /d BIN_NAME="mod_xml2enc.so" /d LONG_NAME="xml2enc_module for Apache"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
diff --git a/modules/generators/mod_info.c b/modules/generators/mod_info.c
index 2f2db9fa..e5e63de1 100644
--- a/modules/generators/mod_info.c
+++ b/modules/generators/mod_info.c
@@ -113,7 +113,7 @@ static void put_int_flush_right(request_rec * r, int i, int field)
if (r)
ap_rputc('0' + i % 10, r);
else
- apr_file_putc('0' + i % 10, out);
+ apr_file_putc((char)('0' + i % 10), out);
}
else {
if (r)
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 24a939a4..c7274194 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -825,7 +825,7 @@ static apr_status_t send_all_header_fields(header_struct *h,
* handler.
* Zap r->status_line if bad.
*/
-static void validate_status_line(request_rec *r)
+static apr_status_t validate_status_line(request_rec *r)
{
char *end;
@@ -836,15 +836,19 @@ static void validate_status_line(request_rec *r)
|| (end - 3) != r->status_line
|| (len >= 4 && ! apr_isspace(r->status_line[3]))) {
r->status_line = NULL;
+ return APR_EGENERAL;
}
/* Since we passed the above check, we know that length three
* is equivalent to only a 3 digit numeric http status.
* RFC2616 mandates a trailing space, let's add it.
*/
- else if (len == 3) {
+ if (len == 3) {
r->status_line = apr_pstrcat(r->pool, r->status_line, " ", NULL);
+ return APR_EGENERAL;
}
+ return APR_SUCCESS;
}
+ return APR_EGENERAL;
}
/*
@@ -856,15 +860,25 @@ static void validate_status_line(request_rec *r)
static void basic_http_header_check(request_rec *r,
const char **protocol)
{
+ apr_status_t rv;
+
if (r->assbackwards) {
/* no such thing as a response protocol */
return;
}
- validate_status_line(r);
+ rv = validate_status_line(r);
if (!r->status_line) {
r->status_line = ap_get_status_line(r->status);
+ } else if (rv != APR_SUCCESS) {
+ /* Status line is OK but our own reason phrase
+ * would be preferred if defined
+ */
+ const char *tmp = ap_get_status_line(r->status);
+ if (!strncmp(tmp, r->status_line, 3)) {
+ r->status_line = tmp;
+ }
}
/* Note that we must downgrade before checking for force responses. */
diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c
index 7c6a5e30..bf37567a 100644
--- a/modules/ldap/util_ldap.c
+++ b/modules/ldap/util_ldap.c
@@ -60,6 +60,7 @@
#endif
#define AP_LDAP_HOPLIMIT_UNSET -1
+#define AP_LDAP_CHASEREFERRALS_SDKDEFAULT -1
#define AP_LDAP_CHASEREFERRALS_OFF 0
#define AP_LDAP_CHASEREFERRALS_ON 1
@@ -364,7 +365,7 @@ static int uldap_connection_init(request_rec *r,
ldap_option = ldc->deref;
ldap_set_option(ldc->ldap, LDAP_OPT_DEREF, &ldap_option);
- if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
+ if (ldc->ChaseReferrals != AP_LDAP_CHASEREFERRALS_SDKDEFAULT) {
/* Set options for rebind and referrals. */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01278)
"LDAP: Setting referrals to %s.",
@@ -384,7 +385,9 @@ static int uldap_connection_init(request_rec *r,
uldap_connection_unbind(ldc);
return(result->rc);
}
+ }
+ if (ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
if ((ldc->ReferralHopLimit != AP_LDAP_HOPLIMIT_UNSET) && ldc->ChaseReferrals == AP_LDAP_CHASEREFERRALS_ON) {
/* Referral hop limit - only if referrals are enabled and a hop limit is explicitly requested */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01280)
@@ -941,6 +944,7 @@ start_over:
"failed with server down";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
if (result == LDAP_TIMEOUT && failures == 0) {
@@ -952,6 +956,7 @@ start_over:
"failed with timeout";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
if (result != LDAP_SUCCESS) {
@@ -1096,6 +1101,7 @@ start_over:
ldc->reason = "ldap_compare_s() failed with server down";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
if (result == LDAP_TIMEOUT && failures == 0) {
@@ -1106,6 +1112,7 @@ start_over:
ldc->reason = "ldap_compare_s() failed with timeout";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
@@ -1206,13 +1213,14 @@ start_over:
/* try to do the search */
result = ldap_search_ext_s(ldc->ldap, (char *)dn, LDAP_SCOPE_BASE,
- (char *)"cn=*", subgroupAttrs, 0,
+ NULL, subgroupAttrs, 0,
NULL, NULL, NULL, APR_LDAP_SIZELIMIT, &sga_res);
if (AP_LDAP_IS_SERVER_DOWN(result)) {
ldc->reason = "ldap_search_ext_s() for subgroups failed with server"
" down";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
if (result == LDAP_TIMEOUT && failures == 0) {
@@ -1223,6 +1231,7 @@ start_over:
ldc->reason = "ldap_search_ext_s() for subgroups failed with timeout";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
@@ -1691,9 +1700,19 @@ start_over:
ldc->reason = "ldap_search_ext_s() for user failed with server down";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
+ goto start_over;
+ }
+
+ if (result == LDAP_TIMEOUT) {
+ ldc->reason = "ldap_search_ext_s() for user failed with timeout";
+ uldap_connection_unbind(ldc);
+ failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
+
/* if there is an error (including LDAP_NO_SUCH_OBJECT) return now */
if (result != LDAP_SUCCESS) {
ldc->reason = "ldap_search_ext_s() for user failed";
@@ -1754,6 +1773,7 @@ start_over:
ldap_msgfree(res);
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
@@ -1949,6 +1969,7 @@ start_over:
ldc->reason = "ldap_search_ext_s() for user failed with server down";
uldap_connection_unbind(ldc);
failures++;
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "%s (attempt %d)", ldc->reason, failures);
goto start_over;
}
@@ -2536,15 +2557,25 @@ static const char *util_ldap_set_connection_timeout(cmd_parms *cmd,
static const char *util_ldap_set_chase_referrals(cmd_parms *cmd,
void *config,
- int mode)
+ const char *arg)
{
util_ldap_config_t *dc = config;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01311)
- "LDAP: Setting referral chasing %s",
- (mode == AP_LDAP_CHASEREFERRALS_ON) ? "ON" : "OFF");
+ "LDAP: Setting referral chasing %s", arg);
- dc->ChaseReferrals = mode;
+ if (0 == strcasecmp(arg, "on")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_ON;
+ }
+ else if (0 == strcasecmp(arg, "off")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_OFF;
+ }
+ else if (0 == strcasecmp(arg, "default")) {
+ dc->ChaseReferrals = AP_LDAP_CHASEREFERRALS_SDKDEFAULT;
+ }
+ else {
+ return "LDAPReferrals must be 'on', 'off', or 'default'";
+ }
return(NULL);
}
@@ -3076,9 +3107,9 @@ static const command_rec util_ldap_cmds[] = {
"Specify the LDAP socket connection timeout in seconds "
"(default: 10)"),
- AP_INIT_FLAG("LDAPReferrals", util_ldap_set_chase_referrals,
+ AP_INIT_TAKE1("LDAPReferrals", util_ldap_set_chase_referrals,
NULL, OR_AUTHCFG,
- "Choose whether referrals are chased ['ON'|'OFF']. Default 'ON'"),
+ "Choose whether referrals are chased ['ON'|'OFF'|'DEFAULT']. Default 'ON'"),
AP_INIT_TAKE1("LDAPReferralHopLimit", util_ldap_set_referral_hop_limit,
NULL, OR_AUTHCFG,
diff --git a/modules/ldap/util_ldap_cache.c b/modules/ldap/util_ldap_cache.c
index 87642e11..b1346f05 100644
--- a/modules/ldap/util_ldap_cache.c
+++ b/modules/ldap/util_ldap_cache.c
@@ -52,7 +52,7 @@ void *util_ldap_url_node_copy(util_ald_cache_t *cache, void *c)
if (node) {
if (!(node->url = util_ald_strdup(cache, n->url))) {
- util_ald_free(cache, node->url);
+ util_ald_free(cache, node);
return NULL;
}
node->search_cache = n->search_cache;
diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c
index e1a82041..f17e1641 100644
--- a/modules/loggers/mod_log_config.c
+++ b/modules/loggers/mod_log_config.c
@@ -194,8 +194,8 @@ static void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,
const char* name);
-static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle);
-static ap_log_writer* ap_log_set_writer(ap_log_writer *handle);
+static ap_log_writer_init *ap_log_set_writer_init(ap_log_writer_init *handle);
+static ap_log_writer *ap_log_set_writer(ap_log_writer *handle);
static ap_log_writer *log_writer = ap_default_log_writer;
static ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
static int buffered_logs = 0; /* default unbuffered */
@@ -1507,7 +1507,7 @@ static void ap_register_log_handler(apr_pool_t *p, char *tag,
apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
}
-static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle)
+static ap_log_writer_init *ap_log_set_writer_init(ap_log_writer_init *handle)
{
ap_log_writer_init *old = log_writer_init;
log_writer_init = handle;
@@ -1536,6 +1536,10 @@ static apr_status_t ap_default_log_writer( request_rec *r,
int i;
apr_status_t rv;
+ /*
+ * We do this memcpy dance because write() is atomic for len < PIPE_BUF,
+ * while writev() need not be.
+ */
str = apr_palloc(r->pool, len + 1);
for (i = 0, s = str; i < nelts; ++i) {
@@ -1616,6 +1620,10 @@ static apr_status_t ap_buffered_log_writer(request_rec *r,
if (len >= LOG_BUFSIZE) {
apr_size_t w;
+ /*
+ * We do this memcpy dance because write() is atomic for
+ * len < PIPE_BUF, while writev() need not be.
+ */
str = apr_palloc(r->pool, len + 1);
for (i = 0, s = str; i < nelts; ++i) {
memcpy(s, strs[i], strl[i]);
diff --git a/modules/loggers/mod_logio.c b/modules/loggers/mod_logio.c
index f58c2922..ad387a9b 100644
--- a/modules/loggers/mod_logio.c
+++ b/modules/loggers/mod_logio.c
@@ -15,15 +15,7 @@
*/
/*
- * Written by Bojan Smojver <bojan rexursive.com>:
- *
- * The argument to LogFormat and CustomLog is a string, which can include
- * literal characters copied into the log files, and '%' directives as
- * follows:
- *
- * %...I: bytes received, including request and headers, cannot be zero
- * %...O: bytes sent, including headers, cannot be zero
- *
+ * Written by Bojan Smojver <bojan rexursive.com>.
*/
#include "apr_strings.h"
@@ -108,6 +100,14 @@ static const char *log_bytes_out(request_rec *r, char *a)
return apr_off_t_toa(r->pool, cf->bytes_out);
}
+static const char *log_bytes_combined(request_rec *r, char *a)
+{
+ logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
+ &logio_module);
+
+ return apr_off_t_toa(r->pool, cf->bytes_out + cf->bytes_in);
+}
+
/*
* Reset counters after logging...
*/
@@ -170,6 +170,7 @@ static int logio_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
if (log_pfn_register) {
log_pfn_register(p, "I", log_bytes_in, 0);
log_pfn_register(p, "O", log_bytes_out, 0);
+ log_pfn_register(p, "S", log_bytes_combined, 0);
}
return OK;
diff --git a/modules/lua/lua_passwd.h b/modules/lua/lua_passwd.h
index 797556bf..8606cc1d 100644
--- a/modules/lua/lua_passwd.h
+++ b/modules/lua/lua_passwd.h
@@ -70,7 +70,6 @@ struct passwd_ctx {
const char *errstr;
char *out;
apr_size_t out_len;
-// const char *passwd;
char *passwd;
int alg;
int cost;
diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c
index c2cfb535..8dce13cc 100644
--- a/modules/lua/lua_request.c
+++ b/modules/lua/lua_request.c
@@ -26,8 +26,9 @@
#include "apr_date.h"
#include "apr_pools.h"
#include "apr_thread_mutex.h"
-
-#include <lua.h>
+#include "apr_tables.h"
+#include "util_cookies.h"
+#include "apr_want.h"
extern apr_thread_mutex_t* lua_ivm_mutex;
@@ -839,6 +840,7 @@ static int lua_apr_sha1(lua_State *L)
apr_sha1_init(&sha1);
apr_sha1_update(&sha1, buffer, len);
apr_sha1_final(digest, &sha1);
+
ap_bin2hex(digest, sizeof(digest), result);
lua_pushstring(L, result);
return 1;
@@ -884,7 +886,7 @@ static int lua_apr_touch(lua_State *L)
r = ap_lua_check_request_rec(L, 1);
luaL_checktype(L, 2, LUA_TSTRING);
path = lua_tostring(L, 2);
- mtime = luaL_optnumber(L, 3, apr_time_now());
+ mtime = (apr_time_t)luaL_optnumber(L, 3, (lua_Number)apr_time_now());
status = apr_file_mtime_set(path, mtime, r->pool);
lua_pushboolean(L, (status == 0));
return 1;
@@ -1887,6 +1889,414 @@ static int lua_ivm_set(lua_State *L)
return 0;
}
+static int lua_get_cookie(lua_State *L)
+{
+ const char *key, *cookie;
+ request_rec *r = ap_lua_check_request_rec(L, 1);
+ key = luaL_checkstring(L, 2);
+ cookie = NULL;
+ ap_cookie_read(r, key, &cookie, 0);
+ if (cookie != NULL) {
+ lua_pushstring(L, cookie);
+ return 1;
+ }
+ return 0;
+}
+
+static int lua_set_cookie(lua_State *L)
+{
+ const char *key, *value, *out, *strexpires;
+ int secure, expires;
+ 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);
+ }
+ expires = luaL_optinteger(L, 5, 0);
+ strexpires = "";
+ 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);
+ }
+ }
+ out = apr_psprintf(r->pool, "%s=%s; %s %s", key, value, secure ? "Secure;" : "", expires ? strexpires : "");
+ apr_table_set(r->headers_out, "Set-Cookie", out);
+ return 0;
+}
+
+static apr_uint64_t ap_ntoh64(const apr_uint64_t *input)
+{
+ apr_uint64_t rval;
+ unsigned char *data = (unsigned char *)&rval;
+ if (APR_IS_BIGENDIAN) {
+ return *input;
+ }
+
+ data[0] = *input >> 56;
+ data[1] = *input >> 48;
+ data[2] = *input >> 40;
+ data[3] = *input >> 32;
+ data[4] = *input >> 24;
+ data[5] = *input >> 16;
+ data[6] = *input >> 8;
+ data[7] = *input >> 0;
+
+ return rval;
+}
+
+static int lua_websocket_greet(lua_State *L)
+{
+ const char *key = NULL;
+ unsigned char digest[APR_SHA1_DIGESTSIZE];
+ apr_sha1_ctx_t sha1;
+ char *encoded;
+ int encoded_len;
+ request_rec *r = ap_lua_check_request_rec(L, 1);
+ key = apr_table_get(r->headers_in, "Sec-WebSocket-Key");
+ if (key != NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Got websocket key: %s", key);
+ key = apr_pstrcat(r->pool, key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
+ NULL);
+ apr_sha1_init(&sha1);
+ apr_sha1_update(&sha1, key, strlen(key));
+ apr_sha1_final(digest, &sha1);
+ encoded_len = apr_base64_encode_len(APR_SHA1_DIGESTSIZE);
+ if (encoded_len) {
+ encoded = apr_palloc(r->pool, encoded_len);
+ encoded_len = apr_base64_encode(encoded, (char*) digest, APR_SHA1_DIGESTSIZE);
+ r->status = 101;
+ apr_table_set(r->headers_out, "Upgrade", "websocket");
+ apr_table_set(r->headers_out, "Connection", "Upgrade");
+ apr_table_set(r->headers_out, "Sec-WebSocket-Accept", encoded);
+
+ /* Trick httpd into NOT using the chunked filter, IMPORTANT!!!111*/
+ apr_table_set(r->headers_out, "Transfer-Encoding", "chunked");
+
+ r->clength = 0;
+ r->bytes_sent = 0;
+ r->read_chunked = 0;
+ ap_rflush(r);
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Upgraded from HTTP to Websocket");
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
+ "Websocket: Upgrade from HTTP to Websocket failed");
+ return 0;
+}
+
+static apr_status_t lua_websocket_readbytes(conn_rec* c, char* buffer,
+ apr_off_t len)
+{
+ apr_bucket_brigade *brigade = apr_brigade_create(c->pool, c->bucket_alloc);
+ apr_status_t rv;
+ rv = ap_get_brigade(c->input_filters, brigade, AP_MODE_READBYTES,
+ APR_BLOCK_READ, len);
+ if (rv == APR_SUCCESS) {
+ if (!APR_BRIGADE_EMPTY(brigade)) {
+ apr_bucket* bucket = APR_BRIGADE_FIRST(brigade);
+ const char* data = NULL;
+ apr_size_t data_length = 0;
+ rv = apr_bucket_read(bucket, &data, &data_length, APR_BLOCK_READ);
+ if (rv == APR_SUCCESS) {
+ memcpy(buffer, data, len);
+ }
+ apr_bucket_delete(bucket);
+ }
+ }
+ apr_brigade_cleanup(brigade);
+ return rv;
+}
+
+static int lua_websocket_read(lua_State *L)
+{
+ apr_socket_t *sock;
+ apr_status_t rv;
+ int n = 0;
+ apr_size_t len = 1;
+ apr_size_t plen = 0;
+ unsigned short payload_short = 0;
+ apr_uint64_t payload_long = 0;
+ unsigned char *mask_bytes;
+ char byte;
+ int plaintext;
+
+
+ request_rec *r = (request_rec *) lua_unboxpointer(L, 1);
+ plaintext = ap_lua_ssl_is_https(r->connection) ? 0 : 1;
+
+
+ mask_bytes = apr_pcalloc(r->pool, 4);
+ sock = ap_get_conn_socket(r->connection);
+
+ /* Get opcode and FIN bit */
+ if (plaintext) {
+ rv = apr_socket_recv(sock, &byte, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection, &byte, 1);
+ }
+ if (rv == APR_SUCCESS) {
+ unsigned char fin, opcode, mask, payload;
+ fin = byte >> 7;
+ opcode = (byte << 4) >> 4;
+
+ /* Get the payload length and mask bit */
+ if (plaintext) {
+ rv = apr_socket_recv(sock, &byte, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection, &byte, 1);
+ }
+ if (rv == APR_SUCCESS) {
+ mask = byte >> 7;
+ payload = byte - 128;
+ plen = payload;
+
+ /* Extended payload? */
+ if (payload == 126) {
+ len = 2;
+ if (plaintext) {
+ rv = apr_socket_recv(sock, (char*) &payload_short, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) &payload_short, 2);
+ }
+ payload_short = ntohs(payload_short);
+
+ if (rv == APR_SUCCESS) {
+ plen = payload_short;
+ }
+ else {
+ return 0;
+ }
+ }
+ /* Super duper extended payload? */
+ if (payload == 127) {
+ len = 8;
+ if (plaintext) {
+ rv = apr_socket_recv(sock, (char*) &payload_long, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) &payload_long, 8);
+ }
+ if (rv == APR_SUCCESS) {
+ plen = ap_ntoh64(&payload_long);
+ }
+ else {
+ return 0;
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Reading %lu (%s) bytes, masking is %s. %s",
+ plen,
+ (payload >= 126) ? "extra payload" : "no extra payload",
+ mask ? "on" : "off",
+ fin ? "This is a final frame" : "more to follow");
+ if (mask) {
+ len = 4;
+ if (plaintext) {
+ rv = apr_socket_recv(sock, (char*) mask_bytes, &len);
+ }
+ else {
+ rv = lua_websocket_readbytes(r->connection,
+ (char*) mask_bytes, 4);
+ }
+ if (rv != APR_SUCCESS) {
+ return 0;
+ }
+ }
+ if (plen < (HUGE_STRING_LEN*1024) && plen > 0) {
+ apr_size_t remaining = plen;
+ apr_size_t received;
+ apr_off_t at = 0;
+ char *buffer = apr_palloc(r->pool, plen+1);
+ buffer[plen] = 0;
+
+ if (plaintext) {
+ while (remaining > 0) {
+ received = remaining;
+ rv = apr_socket_recv(sock, buffer+at, &received);
+ if (received > 0 ) {
+ remaining -= received;
+ at += received;
+ }
+ }
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "Websocket: Frame contained %lu 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, "\
+ "pushed to Lua stack",
+ remaining);
+ }
+ if (mask) {
+ for (n = 0; n < plen; n++) {
+ buffer[n] ^= mask_bytes[n%4];
+ }
+ }
+
+ lua_pushlstring(L, buffer, (size_t) plen); /* push to stack */
+ lua_pushboolean(L, fin); /* push FIN bit to stack as boolean */
+ return 2;
+ }
+
+
+ /* Decide if we need to react to the opcode or not */
+ if (opcode == 0x09) { /* ping */
+ char frame[2];
+ plen = 2;
+ frame[0] = 0x8A;
+ frame[1] = 0;
+ apr_socket_send(sock, frame, &plen); /* Pong! */
+ lua_websocket_read(L); /* read the next frame instead */
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int lua_websocket_write(lua_State *L)
+{
+ const char *string;
+ apr_status_t rv;
+ size_t len;
+ int raw = 0;
+ char prelude;
+ request_rec *r = (request_rec *) lua_unboxpointer(L, 1);
+
+ if (lua_isboolean(L, 3)) {
+ raw = lua_toboolean(L, 3);
+ }
+ string = lua_tolstring(L, 2, &len);
+
+ if (raw != 1) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Writing framed message to client");
+
+ prelude = 0x81; /* text frame, FIN */
+ ap_rputc(prelude, r);
+ if (len < 126) {
+ ap_rputc(len, r);
+ }
+ else if (len < 65535) {
+ apr_uint16_t slen = len;
+ ap_rputc(126, r);
+ slen = htons(slen);
+ ap_rwrite((char*) &slen, 2, r);
+ }
+ else {
+ apr_uint64_t llen = len;
+ ap_rputc(127, r);
+ llen = ap_ntoh64(&llen); /* ntoh doubles as hton */
+ ap_rwrite((char*) &llen, 8, r);
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Writing raw message to client");
+ }
+ ap_rwrite(string, len, r);
+ rv = ap_rflush(r);
+ if (rv == APR_SUCCESS) {
+ lua_pushboolean(L, 1);
+ }
+ else {
+ lua_pushboolean(L, 0);
+ }
+ return 1;
+}
+
+
+static int lua_websocket_close(lua_State *L)
+{
+ apr_socket_t *sock;
+ char prelude[2];
+ request_rec *r = (request_rec *) lua_unboxpointer(L, 1);
+
+ sock = ap_get_conn_socket(r->connection);
+
+ /* Send a header that says: socket is closing. */
+ prelude[0] = 0x88; /* closing socket opcode */
+ prelude[1] = 0; /* zero length frame */
+ ap_rwrite(prelude, 2, r);
+
+ /* Close up tell the MPM and filters to back off */
+ apr_socket_close(sock);
+ r->output_filters = NULL;
+ r->connection->keepalive = AP_CONN_CLOSE;
+ ap_destroy_sub_req(r);
+ return DONE;
+}
+
+
+static int lua_websocket_ping(lua_State *L)
+{
+ apr_socket_t *sock;
+ apr_size_t plen;
+ char prelude[2];
+ apr_status_t rv;
+ request_rec *r = ap_lua_check_request_rec(L, 1);
+ sock = ap_get_conn_socket(r->connection);
+
+ /* Send a header that says: PING. */
+ prelude[0] = 0x89; /* ping opcode */
+ prelude[1] = 0;
+ plen = 2;
+ apr_socket_send(sock, prelude, &plen);
+
+
+ /* Get opcode and FIN bit from pong */
+ plen = 2;
+ rv = apr_socket_recv(sock, prelude, &plen);
+ if (rv == APR_SUCCESS) {
+ unsigned char opcode = prelude[0];
+ unsigned char len = prelude[1];
+ unsigned char mask = len >> 7;
+ if (mask) len -= 128;
+ plen = len;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "Websocket: Got PONG opcode: %x", opcode);
+ if (opcode == 0x8A) {
+ lua_pushboolean(L, 1);
+ }
+ else {
+ lua_pushboolean(L, 0);
+ }
+ if (plen > 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
+ "Websocket: Reading %lu bytes of PONG", plen);
+ return 1;
+ }
+ if (mask) {
+ plen = 2;
+ apr_socket_recv(sock, prelude, &plen);
+ plen = 2;
+ apr_socket_recv(sock, prelude, &plen);
+ }
+ }
+ else {
+ lua_pushboolean(L, 0);
+ }
+ return 1;
+}
+
+
#define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \
{ \
return req_log_at(L, APLOG_TRACE##lev); \
@@ -1994,6 +2404,7 @@ static const char* lua_ap_get_server_name(request_rec* r)
+
static const struct luaL_Reg server_methods[] = {
{NULL, NULL}
};
@@ -2236,7 +2647,22 @@ void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p)
makefun(&lua_ivm_get, APL_REQ_FUNTYPE_LUACFUN, p));
apr_hash_set(dispatch, "ivm_set", APR_HASH_KEY_STRING,
makefun(&lua_ivm_set, APL_REQ_FUNTYPE_LUACFUN, p));
-
+ apr_hash_set(dispatch, "getcookie", APR_HASH_KEY_STRING,
+ makefun(&lua_get_cookie, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "setcookie", APR_HASH_KEY_STRING,
+ makefun(&lua_set_cookie, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "wsupgrade", APR_HASH_KEY_STRING,
+ makefun(&lua_websocket_greet, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "wsread", APR_HASH_KEY_STRING,
+ makefun(&lua_websocket_read, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "wswrite", APR_HASH_KEY_STRING,
+ makefun(&lua_websocket_write, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "wsclose", APR_HASH_KEY_STRING,
+ makefun(&lua_websocket_close, APL_REQ_FUNTYPE_LUACFUN, p));
+ apr_hash_set(dispatch, "wsping", APR_HASH_KEY_STRING,
+ makefun(&lua_websocket_ping, APL_REQ_FUNTYPE_LUACFUN, p));
+
+
lua_pushlightuserdata(L, dispatch);
lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c
index 7c35011e..6e3390fb 100644
--- a/modules/lua/mod_lua.c
+++ b/modules/lua/mod_lua.c
@@ -318,7 +318,10 @@ static apr_status_t lua_setup_filter_ctx(ap_filter_t* f, request_rec* r, lua_fil
ctx = apr_pcalloc(r->pool, sizeof(lua_filter_ctx));
ctx->broken = 0;
*c = ctx;
- /* Find the filter that was called */
+ /* Find the filter that was called.
+ * XXX: If we were wired with mod_filter, the filter (mod_filters name)
+ * and the provider (our underlying filters name) need to have matched.
+ */
for (n = 0; n < cfg->mapped_filters->nelts; n++) {
ap_lua_filter_handler_spec *hook_spec =
((ap_lua_filter_handler_spec **) cfg->mapped_filters->elts)[n];
@@ -374,6 +377,12 @@ static apr_status_t lua_setup_filter_ctx(ap_filter_t* f, request_rec* r, lua_fil
*/
rc = lua_resume(L, 1);
if (rc == LUA_YIELD) {
+ if (f->frec->providers == NULL) {
+ /* Not wired by mod_filter */
+ apr_table_unset(r->headers_out, "Content-Length");
+ apr_table_unset(r->headers_out, "Content-MD5");
+ apr_table_unset(r->headers_out, "ETAG");
+ }
return OK;
}
else {
@@ -407,8 +416,25 @@ static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade
ap_remove_output_filter(f);
return ap_pass_brigade(f->next,pbbIn);
}
- f->ctx = ctx;
- ctx->tmpBucket = apr_brigade_create(r->pool, c->bucket_alloc);
+ else {
+ /* We've got a willing lua filter, setup and check for a prefix */
+ size_t olen;
+ apr_bucket *pbktOut;
+ const char* output = lua_tolstring(ctx->L, 1, &olen);
+
+ f->ctx = ctx;
+ ctx->tmpBucket = apr_brigade_create(r->pool, c->bucket_alloc);
+
+ if (olen > 0) {
+ pbktOut = apr_bucket_heap_create(output, olen, NULL, c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktOut);
+ rv = ap_pass_brigade(f->next, ctx->tmpBucket);
+ apr_brigade_cleanup(ctx->tmpBucket);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+ }
}
ctx = (lua_filter_ctx*) f->ctx;
L = ctx->L;
@@ -433,13 +459,15 @@ static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade
if (lua_resume(L, 0) == LUA_YIELD) {
size_t olen;
const char* output = lua_tolstring(L, 1, &olen);
- pbktOut = apr_bucket_heap_create(output, olen, NULL,
- c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktOut);
- rv = ap_pass_brigade(f->next, ctx->tmpBucket);
- apr_brigade_cleanup(ctx->tmpBucket);
- if (rv != APR_SUCCESS) {
- return rv;
+ if (olen > 0) {
+ pbktOut = apr_bucket_heap_create(output, olen, NULL,
+ c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktOut);
+ rv = ap_pass_brigade(f->next, ctx->tmpBucket);
+ apr_brigade_cleanup(ctx->tmpBucket);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
}
}
else {
@@ -461,9 +489,11 @@ static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade
apr_bucket *pbktOut;
size_t olen;
const char* output = lua_tolstring(L, 1, &olen);
- pbktOut = apr_bucket_heap_create(output, olen, NULL,
- c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktOut);
+ if (olen > 0) {
+ pbktOut = apr_bucket_heap_create(output, olen, NULL,
+ c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktOut);
+ }
}
pbktEOS = apr_bucket_eos_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->tmpBucket, pbktEOS);
@@ -661,6 +691,13 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap
rc = DECLINED;
if (lua_isnumber(L, -1)) {
rc = lua_tointeger(L, -1);
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "Lua hook %s:%s for phase %s returned %d",
+ hook_spec->file_name, hook_spec->function_name, name, rc);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, "Lua hook %s:%s for phase %s did not return a numeric value",
+ hook_spec->file_name, hook_spec->function_name, name);
+ return HTTP_INTERNAL_SERVER_ERROR;
}
if (rc != DECLINED) {
ap_lua_release_state(L, spec, r);
@@ -1076,7 +1113,8 @@ static const char *register_filter_function_hook(const char *filter,
/* TODO: Make it work on other types than just AP_FTYPE_RESOURCE? */
if (direction == AP_LUA_FILTER_OUTPUT) {
spec->direction = AP_LUA_FILTER_OUTPUT;
- ap_register_output_filter(filter, lua_output_filter_handle, NULL, AP_FTYPE_RESOURCE);
+ ap_register_output_filter_protocol(filter, lua_output_filter_handle, NULL, AP_FTYPE_RESOURCE,
+ AP_FILTER_PROTO_CHANGE|AP_FILTER_PROTO_CHANGE_LENGTH);
}
else {
spec->direction = AP_LUA_FILTER_INPUT;
@@ -1155,6 +1193,11 @@ static void lua_insert_filter_harness(request_rec *r)
/* ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "LuaHookInsertFilter not yet implemented"); */
}
+static int lua_log_transaction_harness(request_rec *r)
+{
+ return lua_request_rec_hook_harness(r, "log_transaction", APR_HOOK_FIRST);
+}
+
static int lua_quick_harness(request_rec *r, int lookup)
{
if (lookup) {
@@ -1219,6 +1262,15 @@ static const char *register_map_to_storage_hook(cmd_parms *cmd, void *_cfg,
return register_named_file_function_hook("map_to_storage", cmd, _cfg,
file, function, APR_HOOK_MIDDLE);
}
+
+static const char *register_log_transaction_hook(cmd_parms *cmd, void *_cfg,
+ const char *file,
+ const char *function)
+{
+ return register_named_file_function_hook("log_transaction", cmd, _cfg,
+ file, function, APR_HOOK_FIRST);
+}
+
static const char *register_map_to_storage_block(cmd_parms *cmd, void *_cfg,
const char *line)
{
@@ -1226,6 +1278,7 @@ static const char *register_map_to_storage_block(cmd_parms *cmd, void *_cfg,
line);
}
+
static const char *register_check_user_id_hook(cmd_parms *cmd, void *_cfg,
const char *file,
const char *function,
@@ -1783,6 +1836,10 @@ command_rec lua_commands[] = {
AP_INIT_TAKE2("LuaHookInsertFilter", register_insert_filter_hook, NULL,
OR_ALL,
"Provide a hook for the insert_filter phase of request processing"),
+
+ AP_INIT_TAKE2("LuaHookLog", register_log_transaction_hook, NULL,
+ OR_ALL,
+ "Provide a hook for the logging phase of request processing"),
AP_INIT_TAKE123("LuaScope", register_lua_scope, NULL, OR_ALL,
"One of once, request, conn, server -- default is once"),
@@ -1983,6 +2040,10 @@ static void lua_register_hooks(apr_pool_t *p)
/* ivm mutex */
apr_thread_mutex_create(&lua_ivm_mutex, APR_THREAD_MUTEX_DEFAULT, p);
+
+ /* Logging catcher */
+ ap_hook_log_transaction(lua_log_transaction_harness,NULL,NULL,
+ APR_HOOK_FIRST);
}
AP_DECLARE_MODULE(lua) = {
diff --git a/modules/lua/mod_lua.dsp b/modules/lua/mod_lua.dsp
index 770c13a1..ef3294ed 100644
--- a/modules/lua/mod_lua.dsp
+++ b/modules/lua/mod_lua.dsp
@@ -52,8 +52,8 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so
-# ADD LINK32 kernel32.lib lua51.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so /opt:ref /libpath:"../../srclib/lua/src"
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so
+# ADD LINK32 kernel32.lib ws2_32.lib lua51.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so /opt:ref /libpath:"../../srclib/lua/src"
# Begin Special Build Tool
TargetPath=.\Release\mod_lua.so
SOURCE="$(InputPath)"
@@ -84,8 +84,8 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so
-# ADD LINK32 kernel32.lib lua51.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so /libpath:"../../srclib/lua/src"
+# ADD BASE LINK32 kernel32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so
+# ADD LINK32 kernel32.lib ws2_32.lib lua51.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_lua.so" /base:@..\..\os\win32\BaseAddr.ref,mod_lua.so /libpath:"../../srclib/lua/src"
# Begin Special Build Tool
TargetPath=.\Debug\mod_lua.so
SOURCE="$(InputPath)"
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index a7ac2134..0ac4dc9d 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -585,6 +585,18 @@ static unsigned is_absolute_uri(char *uri, int *supportsqs)
return 7;
}
break;
+
+ case 'w':
+ case 'W':
+ if (!strncasecmp(uri, "s://", 4)) { /* ws:// */
+ *sqs = 1;
+ return 5;
+ }
+ else if (!strncasecmp(uri, "ss://", 5)) { /* wss:// */
+ *sqs = 1;
+ return 6;
+ }
+ break;
}
return 0;
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
index 9ce2fdec..d4e694bf 100644
--- a/modules/metadata/mod_headers.c
+++ b/modules/metadata/mod_headers.c
@@ -96,7 +96,9 @@ typedef enum {
hdr_unset = 'u', /* unset header */
hdr_echo = 'e', /* echo headers from request to response */
hdr_edit = 'r', /* change value by regexp, match once */
- hdr_edit_r = 'R' /* change value by regexp, everymatch */
+ hdr_edit_r = 'R', /* change value by regexp, everymatch */
+ hdr_setifempty = 'i', /* set value if header not already present*/
+ hdr_note = 'n' /* set value of header in a note */
} hdr_actions;
/*
@@ -141,7 +143,7 @@ typedef struct {
/* edit_do is used for Header edit to iterate through the request headers */
typedef struct {
- apr_pool_t *p;
+ request_rec *r;
header_entry *hdr;
apr_table_t *t;
} edit_do;
@@ -390,12 +392,13 @@ static char *parse_format_string(apr_pool_t *p, header_entry *hdr, const char *s
char *res;
/* No string to parse with unset and echo commands */
- if (hdr->action == hdr_unset ||
- hdr->action == hdr_edit ||
- hdr->action == hdr_edit_r ||
- hdr->action == hdr_echo) {
+ if (hdr->action == hdr_unset || hdr->action == hdr_echo) {
return NULL;
}
+ /* Tags are in the replacement value for edit */
+ else if (hdr->action == hdr_edit || hdr->action == hdr_edit_r ) {
+ s = hdr->subs;
+ }
hdr->ta = apr_array_make(p, 10, sizeof(format_tag));
@@ -431,6 +434,8 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd,
if (!strcasecmp(action, "set"))
new->action = hdr_set;
+ else if (!strcasecmp(action, "setifempty"))
+ new->action = hdr_setifempty;
else if (!strcasecmp(action, "add"))
new->action = hdr_add;
else if (!strcasecmp(action, "append"))
@@ -445,9 +450,11 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd,
new->action = hdr_edit;
else if (!strcasecmp(action, "edit*"))
new->action = hdr_edit_r;
+ else if (!strcasecmp(action, "note"))
+ new->action = hdr_note;
else
- return "first argument must be 'add', 'set', 'append', 'merge', "
- "'unset', 'echo', 'edit', or 'edit*'.";
+ return "first argument must be 'add', 'set', 'setifempty', 'append', 'merge', "
+ "'unset', 'echo', 'note', 'edit', or 'edit*'.";
if (new->action == hdr_edit || new->action == hdr_edit_r) {
if (subs == NULL) {
@@ -596,7 +603,7 @@ static char* process_tags(header_entry *hdr, request_rec *r)
return str ? str : "";
}
static const char *process_regexp(header_entry *hdr, const char *value,
- apr_pool_t *pool)
+ request_rec *r)
{
ap_regmatch_t pmatch[AP_MAX_REG_MATCH];
const char *subs;
@@ -607,7 +614,10 @@ static const char *process_regexp(header_entry *hdr, const char *value,
/* no match, nothing to do */
return value;
}
- subs = ap_pregsub(pool, hdr->subs, value, AP_MAX_REG_MATCH, pmatch);
+ /* Process tags in the input string rather than the resulting
+ * substitution to avoid surprises
+ */
+ subs = ap_pregsub(r->pool, process_tags(hdr, r), value, AP_MAX_REG_MATCH, pmatch);
if (subs == NULL)
return NULL;
diffsz = strlen(subs) - (pmatch[0].rm_eo - pmatch[0].rm_so);
@@ -615,12 +625,12 @@ static const char *process_regexp(header_entry *hdr, const char *value,
remainder = value + pmatch[0].rm_eo;
}
else { /* recurse to edit multiple matches if applicable */
- remainder = process_regexp(hdr, value + pmatch[0].rm_eo, pool);
+ remainder = process_regexp(hdr, value + pmatch[0].rm_eo, r);
if (remainder == NULL)
return NULL;
diffsz += strlen(remainder) - strlen(value + pmatch[0].rm_eo);
}
- ret = apr_palloc(pool, strlen(value) + 1 + diffsz);
+ ret = apr_palloc(r->pool, strlen(value) + 1 + diffsz);
memcpy(ret, value, pmatch[0].rm_so);
strcpy(ret + pmatch[0].rm_so, subs);
strcat(ret, remainder);
@@ -642,7 +652,7 @@ static int echo_header(echo_do *v, const char *key, const char *val)
static int edit_header(void *v, const char *key, const char *val)
{
edit_do *ed = (edit_do *)v;
- const char *repl = process_regexp(ed->hdr, val, ed->p);
+ const char *repl = process_regexp(ed->hdr, val, ed->r);
if (repl == NULL)
return 0;
@@ -755,6 +765,14 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
}
apr_table_setn(headers, hdr->header, process_tags(hdr, r));
break;
+ case hdr_setifempty:
+ if (NULL == apr_table_get(headers, hdr->header)) {
+ if (!strcasecmp(hdr->header, "Content-Type")) {
+ ap_set_content_type(r, process_tags(hdr, r));
+ }
+ apr_table_setn(headers, hdr->header, process_tags(hdr, r));
+ }
+ break;
case hdr_unset:
apr_table_unset(headers, hdr->header);
break;
@@ -767,7 +785,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
case hdr_edit:
case hdr_edit_r:
if (!strcasecmp(hdr->header, "Content-Type") && r->content_type) {
- const char *repl = process_regexp(hdr, r->content_type, r->pool);
+ const char *repl = process_regexp(hdr, r->content_type, r);
if (repl == NULL)
return 0;
ap_set_content_type(r, repl);
@@ -775,7 +793,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
if (apr_table_get(headers, hdr->header)) {
edit_do ed;
- ed.p = r->pool;
+ ed.r = r;
ed.hdr = hdr;
ed.t = apr_table_make(r->pool, 5);
if (!apr_table_do(edit_header, (void *) &ed, headers,
@@ -785,6 +803,10 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers,
apr_table_do(add_them_all, (void *) headers, ed.t, NULL);
}
break;
+ case hdr_note:
+ apr_table_setn(r->notes, process_tags(hdr, r), apr_table_get(headers, hdr->header));
+ break;
+
}
}
return 1;
diff --git a/modules/metadata/mod_mime_magic.c b/modules/metadata/mod_mime_magic.c
index 03226aca..693ceca8 100644
--- a/modules/metadata/mod_mime_magic.c
+++ b/modules/metadata/mod_mime_magic.c
@@ -1973,7 +1973,7 @@ static int ascmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes)
{
int has_escapes = 0;
unsigned char *s;
- char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */
+ char nbuf[SMALL_HOWMANY + 1]; /* one extra for terminating '\0' */
char *token;
const struct names *p;
int small_nbytes;
diff --git a/modules/proxy/ajp.h b/modules/proxy/ajp.h
index c65ebe53..814ab0a2 100644
--- a/modules/proxy/ajp.h
+++ b/modules/proxy/ajp.h
@@ -382,7 +382,7 @@ apr_status_t ajp_msg_dump(apr_pool_t *pool, ajp_msg_t *msg, char *err,
/**
* Log an AJP message
*
- * @param request The current request
+ * @param r The current request
* @param msg AJP Message to dump
* @param err error string to display
* @return APR_SUCCESS or error
diff --git a/modules/proxy/fcgi_protocol.h b/modules/proxy/fcgi_protocol.h
index a3cbcfca..e69de29b 100644
--- a/modules/proxy/fcgi_protocol.h
+++ b/modules/proxy/fcgi_protocol.h
@@ -1,108 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file fcgi_protocol.h
- * @brief FastCGI protocol defines
- *
- * @defgroup FCGI_defines FastCGI protocol definition
- * @ingroup APACHE_INTERNAL
- * @{
- */
-
-#ifndef FCGI_PROTOCOL_H
-#define FCGI_PROTOCOL_H
-
-
-#define FCGI_VERSION 1
-
-#define FCGI_BEGIN_REQUEST 1
-#define FCGI_ABORT_REQUEST 2
-#define FCGI_END_REQUEST 3
-#define FCGI_PARAMS 4
-#define FCGI_STDIN 5
-#define FCGI_STDOUT 6
-#define FCGI_STDERR 7
-#define FCGI_DATA 8
-#define FCGI_GET_VALUES 9
-#define FCGI_GET_VALUES_RESULT 10
-#define FCGI_UNKNOWN_TYPE 11
-#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
-
-typedef struct {
- unsigned char version;
- unsigned char type;
- unsigned char requestIdB1;
- unsigned char requestIdB0;
- unsigned char contentLengthB1;
- unsigned char contentLengthB0;
- unsigned char paddingLength;
- unsigned char reserved;
-} fcgi_header;
-
-#define FCGI_HDR_VERSION_OFFSET 0
-#define FCGI_HDR_TYPE_OFFSET 1
-#define FCGI_HDR_REQUEST_ID_B1_OFFSET 2
-#define FCGI_HDR_REQUEST_ID_B0_OFFSET 3
-#define FCGI_HDR_CONTENT_LEN_B1_OFFSET 4
-#define FCGI_HDR_CONTENT_LEN_B0_OFFSET 5
-#define FCGI_HDR_PADDING_LEN_OFFSET 6
-#define FCGI_HDR_RESERVED_OFFSET 7
-
-#define FCGI_BRB_ROLEB1_OFFSET 0
-#define FCGI_BRB_ROLEB0_OFFSET 1
-#define FCGI_BRB_FLAGS_OFFSET 2
-#define FCGI_BRB_RESERVED0_OFFSET 3
-#define FCGI_BRB_RESERVED1_OFFSET 4
-#define FCGI_BRB_RESERVED2_OFFSET 5
-#define FCGI_BRB_RESERVED3_OFFSET 6
-#define FCGI_BRB_RESERVED4_OFFSET 7
-
-/*
- * Number of bytes in a fcgi_header. Future versions of the protocol
- * will not reduce this number.
- */
-#define FCGI_HEADER_LEN 8
-
-/*
- * Mask for flags component of FCGI_BeginRequestBody
- */
-#define FCGI_KEEP_CONN 1
-
-/*
- * Values for role component of FCGI_BeginRequestBody
- */
-#define FCGI_RESPONDER 1
-#define FCGI_AUTHORIZER 2
-#define FCGI_FILTER 3
-
-typedef struct {
- unsigned char roleB1;
- unsigned char roleB0;
- unsigned char flags;
- unsigned char reserved[5];
-} fcgi_begin_request_body;
-
-/*
- * Maximum size of the allowed environment.
- */
-#define FCGI_MAX_ENV_SIZE 65535
-
-/* #define FCGI_DUMP_ENV_VARS */
-
-
-#endif /* FCGI_PROTOCOL_H */
-/** @} */
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 0ee2ff35..88ddb899 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -177,15 +177,17 @@ static const char *set_worker_param(apr_pool_t *p,
else if (!strcasecmp(key, "route")) {
/* Worker route.
*/
- if (strlen(val) >= PROXY_WORKER_MAX_ROUTE_SIZE)
- return "Route length must be < 64 characters";
+ if (strlen(val) >= sizeof(worker->s->route))
+ return apr_psprintf(p, "Route length must be < %d characters",
+ (int)sizeof(worker->s->route));
PROXY_STRNCPY(worker->s->route, val);
}
else if (!strcasecmp(key, "redirect")) {
/* Worker redirection route.
*/
- if (strlen(val) >= PROXY_WORKER_MAX_ROUTE_SIZE)
- return "Redirect length must be < 64 characters";
+ if (strlen(val) >= sizeof(worker->s->redirect))
+ return apr_psprintf(p, "Redirect length must be < %d characters",
+ (int)sizeof(worker->s->redirect));
PROXY_STRNCPY(worker->s->redirect, val);
}
else if (!strcasecmp(key, "status")) {
@@ -256,8 +258,9 @@ static const char *set_worker_param(apr_pool_t *p,
worker->s->conn_timeout_set = 1;
}
else if (!strcasecmp(key, "flusher")) {
- if (strlen(val) >= PROXY_WORKER_MAX_SCHEME_SIZE)
- return "flusher name length must be < 16 characters";
+ if (strlen(val) >= sizeof(worker->s->flusher))
+ apr_psprintf(p, "flusher name length must be < %d characters",
+ (int)sizeof(worker->s->flusher));
PROXY_STRNCPY(worker->s->flusher, val);
}
else {
@@ -280,8 +283,9 @@ static const char *set_balancer_param(proxy_server_conf *conf,
* Set to something like JSESSIONID or
* PHPSESSIONID, etc..,
*/
- if (strlen(val) > (PROXY_BALANCER_MAX_STICKY_SIZE-1))
- return "stickysession length must be < 64 characters";
+ if (strlen(val) >= sizeof(balancer->s->sticky_path))
+ apr_psprintf(p, "stickysession length must be < %d characters",
+ (int)sizeof(balancer->s->sticky_path));
PROXY_STRNCPY(balancer->s->sticky_path, val);
PROXY_STRNCPY(balancer->s->sticky, val);
@@ -1700,19 +1704,19 @@ static const char *
New->name = apr_pstrdup(parms->pool, arg);
New->hostaddr = NULL;
- if (ap_proxy_is_ipaddr(New, parms->pool)) {
+ if (ap_proxy_is_ipaddr(New, parms->pool)) {
#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
- "Parsed addr %s", inet_ntoa(New->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
- "Parsed mask %s", inet_ntoa(New->mask));
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "Parsed addr %s", inet_ntoa(New->addr));
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "Parsed mask %s", inet_ntoa(New->mask));
#endif
- }
- else if (ap_proxy_is_domainname(New, parms->pool)) {
- ap_str_tolower(New->name);
+ }
+ else if (ap_proxy_is_domainname(New, parms->pool)) {
+ ap_str_tolower(New->name);
#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
- "Parsed domain %s", New->name);
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "Parsed domain %s", New->name);
#endif
}
else if (ap_proxy_is_hostname(New, parms->pool)) {
@@ -2435,7 +2439,7 @@ static int proxy_status_hook(request_rec *r, int flags)
proxy_balancer *balancer = NULL;
proxy_worker **worker = NULL;
- if (flags & AP_STATUS_SHORT || conf->balancers->nelts == 0 ||
+ if ((flags & AP_STATUS_SHORT) || conf->balancers->nelts == 0 ||
conf->proxy_status == status_off)
return OK;
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 81fd14c1..aef8b209 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -723,11 +723,11 @@ PROXY_DECLARE(proxy_worker_shared *) ap_proxy_find_workershm(ap_slotmem_provider
/**
* Find the shm of the balancer as needed
- * @param storage slotmem provider
- * @param slot slotmem instance
- * @param worker worker to find
- * @param index pointer to index within slotmem of balancer
- * @return pointer to shm of balancer, or NULL
+ * @param storage slotmem provider
+ * @param slot slotmem instance
+ * @param balancer balancer of shm to find
+ * @param index pointer to index within slotmem of balancer
+ * @return pointer to shm of balancer, or NULL
*/
PROXY_DECLARE(proxy_balancer_shared *) ap_proxy_find_balancershm(ap_slotmem_provider_t *storage,
ap_slotmem_instance_t *slot,
@@ -922,7 +922,7 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r,
/**
* Create a HTTP request header brigade, old_cl_val and old_te_val as required.
- * @parama p pool
+ * @param p pool
* @param header_brigade header brigade to use/fill
* @param r request
* @param p_conn proxy connection rec
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 0f45be7a..5fd9e151 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -1463,7 +1463,14 @@ static int balancer_handler(request_rec *r)
ap_rvputs(r, "<dl><dt>Server Version: ",
ap_get_server_description(), "</dt>\n", NULL);
ap_rvputs(r, "<dt>Server Built: ",
- ap_get_server_built(), "\n</dt></dl>\n", NULL);
+ ap_get_server_built(), "</dt>\n", NULL);
+ ap_rvputs(r, "<dt>Balancer changes will ", conf->bal_persist ? "" : "NOT ",
+ "be persisted on restart.</dt>", NULL);
+ ap_rvputs(r, "<dt>Balancers are ", conf->inherit ? "" : "NOT ",
+ "inherited from main server.</dt>", NULL);
+ ap_rvputs(r, "<dt>ProxyPass settings are ", conf->ppinherit ? "" : "NOT ",
+ "inherited from main server.</dt>", NULL);
+ ap_rputs("</dl>\n", r);
balancer = (proxy_balancer *)conf->balancers->elts;
for (i = 0; i < conf->balancers->nelts; i++) {
diff --git a/modules/proxy/mod_proxy_connect.c b/modules/proxy/mod_proxy_connect.c
index b38edc91..9a1bfefb 100644
--- a/modules/proxy/mod_proxy_connect.c
+++ b/modules/proxy/mod_proxy_connect.c
@@ -220,7 +220,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker,
apr_uri_t uri;
const char *connectname;
- int connectport = 0;
+ apr_port_t connectport = 0;
/* is this for us? */
if (r->method_number != M_CONNECT) {
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 0f844163..ee702900 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -15,59 +15,12 @@
*/
#include "mod_proxy.h"
-#include "fcgi_protocol.h"
+#include "util_fcgi.h"
#include "util_script.h"
module AP_MODULE_DECLARE_DATA proxy_fcgi_module;
/*
- * The below 3 functions serve to map the FCGI structs
- * back and forth between an 8 byte array. We do this to avoid
- * any potential padding issues when we send or read these
- * structures.
- *
- * NOTE: These have specific internal knowledge of the
- * layout of the fcgi_header and fcgi_begin_request_body
- * structs!
- */
-static void fcgi_header_to_array(fcgi_header *h, unsigned char a[])
-{
- a[FCGI_HDR_VERSION_OFFSET] = h->version;
- a[FCGI_HDR_TYPE_OFFSET] = h->type;
- a[FCGI_HDR_REQUEST_ID_B1_OFFSET] = h->requestIdB1;
- a[FCGI_HDR_REQUEST_ID_B0_OFFSET] = h->requestIdB0;
- a[FCGI_HDR_CONTENT_LEN_B1_OFFSET] = h->contentLengthB1;
- a[FCGI_HDR_CONTENT_LEN_B0_OFFSET] = h->contentLengthB0;
- a[FCGI_HDR_PADDING_LEN_OFFSET] = h->paddingLength;
- a[FCGI_HDR_RESERVED_OFFSET] = h->reserved;
-}
-
-static void fcgi_header_from_array(fcgi_header *h, unsigned char a[])
-{
- h->version = a[FCGI_HDR_VERSION_OFFSET];
- h->type = a[FCGI_HDR_TYPE_OFFSET];
- h->requestIdB1 = a[FCGI_HDR_REQUEST_ID_B1_OFFSET];
- h->requestIdB0 = a[FCGI_HDR_REQUEST_ID_B0_OFFSET];
- h->contentLengthB1 = a[FCGI_HDR_CONTENT_LEN_B1_OFFSET];
- h->contentLengthB0 = a[FCGI_HDR_CONTENT_LEN_B0_OFFSET];
- h->paddingLength = a[FCGI_HDR_PADDING_LEN_OFFSET];
- h->reserved = a[FCGI_HDR_RESERVED_OFFSET];
-}
-
-static void fcgi_begin_request_body_to_array(fcgi_begin_request_body *h,
- unsigned char a[])
-{
- a[FCGI_BRB_ROLEB1_OFFSET] = h->roleB1;
- a[FCGI_BRB_ROLEB0_OFFSET] = h->roleB0;
- a[FCGI_BRB_FLAGS_OFFSET] = h->flags;
- a[FCGI_BRB_RESERVED0_OFFSET] = h->reserved[0];
- a[FCGI_BRB_RESERVED1_OFFSET] = h->reserved[1];
- a[FCGI_BRB_RESERVED2_OFFSET] = h->reserved[2];
- a[FCGI_BRB_RESERVED3_OFFSET] = h->reserved[3];
- a[FCGI_BRB_RESERVED4_OFFSET] = h->reserved[4];
-}
-
-/*
* Canonicalise http-like URLs.
* scheme is the scheme for the URL
* url is the URL starting with the first '/'
@@ -129,33 +82,6 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
return OK;
}
-/*
- * Fill in a fastcgi request header with the following type, request id,
- * content length, and padding length.
- *
- * The header array must be at least FCGI_HEADER_LEN bytes long.
- */
-static void fill_in_header(fcgi_header *header,
- unsigned char type,
- apr_uint16_t request_id,
- apr_uint16_t content_len,
- unsigned char padding_len)
-{
- header->version = FCGI_VERSION;
-
- header->type = type;
-
- header->requestIdB1 = ((request_id >> 8) & 0xff);
- header->requestIdB0 = ((request_id) & 0xff);
-
- header->contentLengthB1 = ((content_len >> 8) & 0xff);
- header->contentLengthB0 = ((content_len) & 0xff);
-
- header->paddingLength = padding_len;
-
- header->reserved = 0;
-}
-
/* Wrapper for apr_socket_sendv that handles updating the worker stats. */
static apr_status_t send_data(proxy_conn_rec *conn,
struct iovec *vec,
@@ -234,28 +160,43 @@ static apr_status_t get_data(proxy_conn_rec *conn,
return rv;
}
-static apr_status_t send_begin_request(proxy_conn_rec *conn, int request_id)
+static apr_status_t get_data_full(proxy_conn_rec *conn,
+ char *buffer,
+ apr_size_t buflen)
+{
+ apr_size_t readlen;
+ apr_size_t cumulative_len = 0;
+ apr_status_t rv;
+
+ do {
+ readlen = buflen - cumulative_len;
+ rv = get_data(conn, buffer + cumulative_len, &readlen);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ cumulative_len += readlen;
+ } while (cumulative_len < buflen);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t send_begin_request(proxy_conn_rec *conn,
+ apr_uint16_t request_id)
{
struct iovec vec[2];
- fcgi_header header;
- unsigned char farray[FCGI_HEADER_LEN];
- fcgi_begin_request_body brb;
- unsigned char abrb[FCGI_HEADER_LEN];
+ ap_fcgi_header header;
+ unsigned char farray[AP_FCGI_HEADER_LEN];
+ ap_fcgi_begin_request_body brb;
+ unsigned char abrb[AP_FCGI_HEADER_LEN];
apr_size_t len;
- fill_in_header(&header, FCGI_BEGIN_REQUEST, request_id, sizeof(abrb), 0);
+ ap_fcgi_fill_in_header(&header, AP_FCGI_BEGIN_REQUEST, request_id,
+ sizeof(abrb), 0);
- brb.roleB1 = ((FCGI_RESPONDER >> 8) & 0xff);
- brb.roleB0 = ((FCGI_RESPONDER) & 0xff);
- brb.flags = FCGI_KEEP_CONN;
- brb.reserved[0] = 0;
- brb.reserved[1] = 0;
- brb.reserved[2] = 0;
- brb.reserved[3] = 0;
- brb.reserved[4] = 0;
+ ap_fcgi_fill_in_request_body(&brb, AP_FCGI_RESPONDER, AP_FCGI_KEEP_CONN);
- fcgi_header_to_array(&header, farray);
- fcgi_begin_request_body_to_array(&brb, abrb);
+ ap_fcgi_header_to_array(&header, farray);
+ ap_fcgi_begin_request_body_to_array(&brb, abrb);
vec[0].iov_base = (void *)farray;
vec[0].iov_len = sizeof(farray);
@@ -266,26 +207,24 @@ static apr_status_t send_begin_request(proxy_conn_rec *conn, int request_id)
}
static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
- int request_id)
+ apr_pool_t *temp_pool,
+ apr_uint16_t request_id)
{
const apr_array_header_t *envarr;
const apr_table_entry_t *elts;
struct iovec vec[2];
- fcgi_header header;
- unsigned char farray[FCGI_HEADER_LEN];
- apr_size_t bodylen, envlen;
- char *body, *itr;
+ ap_fcgi_header header;
+ unsigned char farray[AP_FCGI_HEADER_LEN];
+ char *body;
apr_status_t rv;
- apr_size_t len;
- int i, numenv;
+ apr_size_t avail_len, len, required_len;
+ int next_elem, starting_elem;
ap_add_common_vars(r);
ap_add_cgi_vars(r);
/* XXX are there any FastCGI specific env vars we need to send? */
- bodylen = envlen = 0;
-
/* XXX mod_cgi/mod_cgid use ap_create_environment here, which fills in
* the TZ value specially. We could use that, but it would mean
* parsing the key/value pairs back OUT of the allocated env array,
@@ -293,118 +232,75 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
* place, which would suck. */
envarr = apr_table_elts(r->subprocess_env);
-
elts = (const apr_table_entry_t *) envarr->elts;
- for (i = 0; i < envarr->nelts; ++i) {
- apr_size_t keylen, vallen;
-
- if (! elts[i].key) {
- continue;
- }
-
- keylen = strlen(elts[i].key);
-
- if (keylen >> 7 == 0) {
- envlen += 1;
- }
- else {
- envlen += 4;
- }
-
- envlen += keylen;
-
- vallen = strlen(elts[i].val);
-
#ifdef FCGI_DUMP_ENV_VARS
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01062)
- "sending env var '%s' value '%s'",
- elts[i].key, elts[i].val);
-#endif
-
- if (vallen >> 7 == 0) {
- envlen += 1;
+ {
+ int i;
+
+ for (i = 0; i < envarr->nelts; ++i) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01062)
+ "sending env var '%s' value '%s'",
+ elts[i].key, elts[i].val);
}
- else {
- envlen += 4;
- }
-
- envlen += vallen;
+ }
+#endif
- /* The cast of bodylen is safe since FCGI_MAX_ENV_SIZE is for sure an int */
- if (envlen > FCGI_MAX_ENV_SIZE) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01063)
- "truncating environment to %d bytes and %d elements",
- (int)bodylen, i);
+ /* Send envvars over in as many FastCGI records as it takes, */
+ next_elem = 0; /* starting with the first one */
+
+ avail_len = 16 * 1024; /* our limit per record, which could have been up
+ * to AP_FCGI_MAX_CONTENT_LEN
+ */
+
+ while (next_elem < envarr->nelts) {
+ starting_elem = next_elem;
+ required_len = ap_fcgi_encoded_env_len(r->subprocess_env,
+ avail_len,
+ &next_elem);
+
+ if (!required_len) {
+ if (next_elem < envarr->nelts) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+ APLOGNO(02536) "couldn't encode envvar '%s' in %"
+ APR_SIZE_T_FMT " bytes",
+ elts[next_elem].key, avail_len);
+ /* skip this envvar and continue */
+ ++next_elem;
+ continue;
+ }
+ /* only an unused element at the end of the array */
break;
}
- bodylen = envlen;
- }
+ body = apr_palloc(temp_pool, required_len);
+ rv = ap_fcgi_encode_env(r, r->subprocess_env, body, required_len,
+ &starting_elem);
+ /* we pre-compute, so we can't run out of space */
+ ap_assert(rv == APR_SUCCESS);
+ /* compute and encode must be in sync */
+ ap_assert(starting_elem == next_elem);
- numenv = i;
+ ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id,
+ (apr_uint16_t)required_len, 0);
+ ap_fcgi_header_to_array(&header, farray);
- body = apr_pcalloc(r->pool, bodylen);
+ vec[0].iov_base = (void *)farray;
+ vec[0].iov_len = sizeof(farray);
+ vec[1].iov_base = body;
+ vec[1].iov_len = required_len;
- itr = body;
+ rv = send_data(conn, vec, 2, &len, 1);
+ apr_pool_clear(temp_pool);
- for (i = 0; i < numenv; ++i) {
- apr_size_t keylen, vallen;
-
- if (! elts[i].key) {
- continue;
- }
-
- keylen = strlen(elts[i].key);
-
- if (keylen >> 7 == 0) {
- itr[0] = keylen & 0xff;
- itr += 1;
+ if (rv) {
+ return rv;
}
- else {
- itr[0] = ((keylen >> 24) & 0xff) | 0x80;
- itr[1] = ((keylen >> 16) & 0xff);
- itr[2] = ((keylen >> 8) & 0xff);
- itr[3] = ((keylen) & 0xff);
- itr += 4;
- }
-
- vallen = strlen(elts[i].val);
-
- if (vallen >> 7 == 0) {
- itr[0] = vallen & 0xff;
- itr += 1;
- }
- else {
- itr[0] = ((vallen >> 24) & 0xff) | 0x80;
- itr[1] = ((vallen >> 16) & 0xff);
- itr[2] = ((vallen >> 8) & 0xff);
- itr[3] = ((vallen) & 0xff);
- itr += 4;
- }
-
- memcpy(itr, elts[i].key, keylen);
- itr += keylen;
-
- memcpy(itr, elts[i].val, vallen);
- itr += vallen;
}
- fill_in_header(&header, FCGI_PARAMS, request_id, bodylen, 0);
- fcgi_header_to_array(&header, farray);
-
- vec[0].iov_base = (void *)farray;
- vec[0].iov_len = sizeof(farray);
- vec[1].iov_base = body;
- vec[1].iov_len = bodylen;
-
- rv = send_data(conn, vec, 2, &len, 1);
- if (rv) {
- return rv;
- }
-
- fill_in_header(&header, FCGI_PARAMS, request_id, 0, 0);
- fcgi_header_to_array(&header, farray);
+ /* Envvars sent, so say we're done */
+ ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, 0, 0);
+ ap_fcgi_header_to_array(&header, farray);
vec[0].iov_base = (void *)farray;
vec[0].iov_len = sizeof(farray);
@@ -481,69 +377,9 @@ static int handle_headers(request_rec *r,
return 0;
}
-static void dump_header_to_log(request_rec *r, unsigned char fheader[],
- apr_size_t length)
-{
-#ifdef FCGI_DUMP_HEADERS
- apr_size_t posn = 0;
- char asc_line[20];
- char hex_line[60];
- int i = 0;
-
- memset(asc_line, 0, sizeof(asc_line));
- memset(hex_line, 0, sizeof(hex_line));
-
- while (posn < length) {
- unsigned char c = fheader[posn];
-
- if (i >= 20) {
- i = 0;
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01064)
- "HEADER: %s %s", asc_line, hex_line);
-
- memset(asc_line, 0, sizeof(asc_line));
- memset(hex_line, 0, sizeof(hex_line));
- }
-
- if (isprint(c)) {
- asc_line[i] = c;
- }
- else {
- asc_line[i] = '.';
- }
-
- if ((c >> 4) >= 10) {
- hex_line[i * 3] = 'a' + ((c >> 4) - 10);
- }
- else {
- hex_line[i * 3] = '0' + (c >> 4);
- }
-
- if ((c & 0x0F) >= 10) {
- hex_line[i * 3 + 1] = 'a' + ((c & 0x0F) - 10);
- }
- else {
- hex_line[i * 3 + 1] = '0' + (c & 0xF);
- }
-
- hex_line[i * 3 + 2] = ' ';
-
- i++;
- posn++;
- }
-
- if (i != 1) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01065) "HEADER: %s %s",
- asc_line, hex_line);
- }
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01066) "HEADER: -EOH-");
-#endif
-}
-
static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
- request_rec *r, int request_id)
+ request_rec *r, apr_pool_t *setaside_pool,
+ apr_uint16_t request_id)
{
apr_bucket_brigade *ib, *ob;
int seen_end_of_headers = 0, done = 0;
@@ -551,14 +387,11 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
int script_error_status = HTTP_OK;
conn_rec *c = r->connection;
struct iovec vec[2];
- fcgi_header header;
- unsigned char farray[FCGI_HEADER_LEN];
+ ap_fcgi_header header;
+ unsigned char farray[AP_FCGI_HEADER_LEN];
apr_pollfd_t pfd;
int header_state = HDR_STATE_READING_HEADERS;
- apr_pool_t *setaside_pool;
-
- apr_pool_create(&setaside_pool, r->pool);
-
+
pfd.desc_type = APR_POLL_SOCKET;
pfd.desc.s = conn->sock;
pfd.p = r->pool;
@@ -568,15 +401,13 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
ob = apr_brigade_create(r->pool, c->bucket_alloc);
while (! done) {
- apr_interval_time_t timeout = conn->worker->s->timeout;
+ apr_interval_time_t timeout;
apr_size_t len;
int n;
/* We need SOME kind of timeout here, or virtually anything will
* cause timeout errors. */
- if (! conn->worker->s->timeout_set) {
- timeout = apr_time_from_sec(30);
- }
+ apr_socket_timeout_get(conn->sock, &timeout);
rv = apr_poll(&pfd, 1, &n, timeout);
if (rv != APR_SUCCESS) {
@@ -613,9 +444,9 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
break;
}
- fill_in_header(&header, FCGI_STDIN, request_id,
- (apr_uint16_t) writebuflen, 0);
- fcgi_header_to_array(&header, farray);
+ ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id,
+ (apr_uint16_t) writebuflen, 0);
+ ap_fcgi_header_to_array(&header, farray);
vec[nvec].iov_base = (void *)farray;
vec[nvec].iov_len = sizeof(farray);
@@ -634,9 +465,10 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
if (last_stdin) {
pfd.reqevents = APR_POLLIN; /* Done with input data */
- if (writebuflen) { /* empty FCGI_STDIN not already sent? */
- fill_in_header(&header, FCGI_STDIN, request_id, 0, 0);
- fcgi_header_to_array(&header, farray);
+ if (writebuflen) { /* empty AP_FCGI_STDIN not already sent? */
+ ap_fcgi_fill_in_header(&header, AP_FCGI_STDIN, request_id,
+ 0, 0);
+ ap_fcgi_header_to_array(&header, farray);
vec[0].iov_base = (void *)farray;
vec[0].iov_len = sizeof(farray);
@@ -652,47 +484,37 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
* the headers, even if we fill the entire length in the recv. */
char readbuf[AP_IOBUFSIZE + 1];
apr_size_t readbuflen;
- apr_size_t clen;
- int rid, type;
+ apr_uint16_t clen, rid;
apr_bucket *b;
- char plen;
+ unsigned char plen;
+ unsigned char type, version;
memset(readbuf, 0, sizeof(readbuf));
memset(farray, 0, sizeof(farray));
/* First, we grab the header... */
- readbuflen = FCGI_HEADER_LEN;
-
- rv = get_data(conn, (char *) farray, &readbuflen);
+ rv = get_data_full(conn, (char *) farray, AP_FCGI_HEADER_LEN);
if (rv != APR_SUCCESS) {
- break;
- }
-
- dump_header_to_log(r, farray, readbuflen);
-
- if (readbuflen != FCGI_HEADER_LEN) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01067)
- "Failed to read entire header "
- "got %" APR_SIZE_T_FMT " wanted %d",
- readbuflen, FCGI_HEADER_LEN);
- rv = APR_EINVAL;
+ "Failed to read FastCGI header");
break;
}
- fcgi_header_from_array(&header, farray);
+#ifdef FCGI_DUMP_HEADERS
+ ap_log_rdata(APLOG_MARK, APLOG_DEBUG, r, "FastCGI header",
+ farray, AP_FCGI_HEADER_LEN, 0);
+#endif
+
+ ap_fcgi_header_fields_from_array(&version, &type, &rid,
+ &clen, &plen, farray);
- if (header.version != FCGI_VERSION) {
+ if (version != AP_FCGI_VERSION_1) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01068)
"Got bogus version %d", (int) header.version);
rv = APR_EINVAL;
break;
}
- type = header.type;
-
- rid = header.requestIdB1 << 8;
- rid |= header.requestIdB0;
-
if (rid != request_id) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01069)
"Got bogus rid %d, expected %d",
@@ -701,11 +523,6 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
break;
}
- clen = header.contentLengthB1 << 8;
- clen |= header.contentLengthB0;
-
- plen = header.paddingLength;
-
recv_again:
if (clen > sizeof(readbuf) - 1) {
readbuflen = sizeof(readbuf) - 1;
@@ -725,7 +542,7 @@ recv_again:
}
switch (type) {
- case FCGI_STDOUT:
+ case AP_FCGI_STDOUT:
if (clen != 0) {
b = apr_bucket_transient_create(readbuf,
readbuflen,
@@ -825,7 +642,7 @@ recv_again:
}
break;
- case FCGI_STDERR:
+ case AP_FCGI_STDERR:
/* TODO: Should probably clean up this logging a bit... */
if (clen) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01071)
@@ -838,7 +655,7 @@ recv_again:
}
break;
- case FCGI_END_REQUEST:
+ case AP_FCGI_END_REQUEST:
done = 1;
break;
@@ -849,10 +666,10 @@ recv_again:
}
if (plen) {
- readbuflen = plen;
-
- rv = get_data(conn, readbuf, &readbuflen);
+ rv = get_data_full(conn, readbuf, plen);
if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ APLOGNO(02537) "Error occurred reading padding");
break;
}
}
@@ -884,10 +701,11 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
* multiple requests to the same FastCGI connection, but
* we don't support that, and always use a value of '1' to
* keep things simple. */
- int request_id = 1;
+ apr_uint16_t request_id = 1;
apr_status_t rv;
+ apr_pool_t *temp_pool;
- /* Step 1: Send FCGI_BEGIN_REQUEST */
+ /* Step 1: Send AP_FCGI_BEGIN_REQUEST */
rv = send_begin_request(conn, request_id);
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01073)
@@ -896,8 +714,10 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
return HTTP_SERVICE_UNAVAILABLE;
}
+ apr_pool_create(&temp_pool, r->pool);
+
/* Step 2: Send Environment via FCGI_PARAMS */
- rv = send_environment(conn, r, request_id);
+ rv = send_environment(conn, r, temp_pool, request_id);
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01074)
"Failed writing Environment to %s:", server_portstr);
@@ -906,7 +726,7 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
}
/* Step 3: Read records from the back end server and handle them. */
- rv = dispatch(conn, conf, r, request_id);
+ rv = dispatch(conn, conf, r, temp_pool, request_id);
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01075)
"Error dispatching request to %s:", server_portstr);
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index cffad2e7..714014de 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -1873,7 +1873,7 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
return DECLINED;
if ((u - url) > 14)
return HTTP_BAD_REQUEST;
- scheme = apr_pstrndup(p, url, u - url);
+ scheme = apr_pstrmemdup(p, url, u - url);
/* scheme is lowercase */
ap_str_tolower(scheme);
/* is it for us? */
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 67dc9394..d3dd0686 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -309,7 +309,7 @@ PROXY_DECLARE(char *)
url = "";
}
else {
- *(url++) = '\0'; /* skip seperating '/' */
+ *(url++) = '\0'; /* skip separating '/' */
}
/* find _last_ '@' since it might occur in user/password part */
@@ -386,7 +386,7 @@ PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *mes
static const char *
proxy_get_host_of_request(request_rec *r)
{
- char *url, *user = NULL, *password = NULL, *err, *host;
+ char *url, *user = NULL, *password = NULL, *err, *host = NULL;
apr_port_t port;
if (r->hostname != NULL) {
@@ -1080,7 +1080,6 @@ PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
int i;
proxy_hashes hash;
- ap_str_tolower(uri);
c = strchr(uri, ':');
if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
return NULL;
@@ -1089,6 +1088,7 @@ PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
if ((c = strchr(c + 3, '/'))) {
*c = '\0';
}
+ ap_str_tolower(uri);
hash.def = ap_proxy_hashfunc(uri, PROXY_HASHFUNC_DEFAULT);
hash.fnv = ap_proxy_hashfunc(uri, PROXY_HASHFUNC_FNV);
balancer = (proxy_balancer *)conf->balancers->elts;
@@ -2132,34 +2132,46 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
conn->port = uri->port;
}
socket_cleanup(conn);
- err = apr_sockaddr_info_get(&(conn->addr),
- conn->hostname, APR_UNSPEC,
- conn->port, 0,
- conn->pool);
- }
- else if (!worker->cp->addr) {
- if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
- return HTTP_INTERNAL_SERVER_ERROR;
+ if (!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.
+ */
+ err = apr_sockaddr_info_get(&(conn->addr),
+ conn->hostname, APR_UNSPEC,
+ conn->port, 0,
+ conn->pool);
}
-
+ }
+ if (worker->s->is_address_reusable && !worker->s->disablereuse) {
/*
- * Worker can have the single constant backend adress.
- * The single DNS lookup is used once per worker.
- * If dynamic change is needed then set the addr to NULL
- * inside dynamic config to force the lookup.
+ * Looking up the backend address for the worker only makes sense if
+ * we can reuse the address.
*/
- err = apr_sockaddr_info_get(&(worker->cp->addr),
- conn->hostname, APR_UNSPEC,
- conn->port, 0,
- worker->cp->pool);
- conn->addr = worker->cp->addr;
- if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
+ if (!worker->cp->addr) {
+ if ((err = PROXY_THREAD_LOCK(worker)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, APLOGNO(00945) "lock");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ /*
+ * Worker can have the single constant backend adress.
+ * The single DNS lookup is used once per worker.
+ * If dynamic change is needed then set the addr to NULL
+ * inside dynamic config to force the lookup.
+ */
+ err = apr_sockaddr_info_get(&(worker->cp->addr),
+ conn->hostname, APR_UNSPEC,
+ conn->port, 0,
+ worker->cp->pool);
+ conn->addr = worker->cp->addr;
+ if ((uerr = PROXY_THREAD_UNLOCK(worker)) != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, uerr, r, APLOGNO(00946) "unlock");
+ }
+ }
+ else {
+ conn->addr = worker->cp->addr;
}
- }
- else {
- conn->addr = worker->cp->addr;
}
/* Close a possible existing socket if we are told to do so */
if (conn->close) {
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c
index 7213eb3c..89c80747 100644
--- a/modules/session/mod_session.c
+++ b/modules/session/mod_session.c
@@ -144,9 +144,11 @@ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
}
}
- /* make sure the expiry is set, if present */
- if (!zz->expiry && dconf->maxage) {
- zz->expiry = now + dconf->maxage * APR_USEC_PER_SEC;
+ /* make sure the expiry and maxage are set, if present */
+ if (dconf->maxage) {
+ if (!zz->expiry) {
+ zz->expiry = now + dconf->maxage * APR_USEC_PER_SEC;
+ }
zz->maxage = dconf->maxage;
}
@@ -194,6 +196,11 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z)
z->maxage = dconf->maxage;
}
+ /* reset the expiry before saving if present */
+ if (z->dirty && z->maxage) {
+ z->expiry = now + z->maxage * APR_USEC_PER_SEC;
+ }
+
/* encode the session */
rv = ap_run_session_encode(r, z);
if (OK != rv) {
@@ -443,6 +450,8 @@ static apr_status_t session_output_filter(ap_filter_t * f,
override = apr_table_get(r->headers_out, conf->header);
}
if (override) {
+ apr_table_unset(r->err_headers_out, conf->header);
+ apr_table_unset(r->headers_out, conf->header);
z->encoded = override;
z->dirty = 1;
session_identity_decode(r, z);
diff --git a/modules/session/mod_session_crypto.c b/modules/session/mod_session_crypto.c
index 03dbba61..984a0487 100644
--- a/modules/session/mod_session_crypto.c
+++ b/modules/session/mod_session_crypto.c
@@ -534,11 +534,41 @@ static const char *set_crypto_driver(cmd_parms * cmd, void *config, const char *
static const char *set_crypto_passphrase(cmd_parms * cmd, void *config, const char *arg)
{
+ int arglen = strlen(arg);
+ char **argv;
+ char *result;
const char **passphrase;
session_crypto_dir_conf *dconf = (session_crypto_dir_conf *) config;
passphrase = apr_array_push(dconf->passphrases);
- *passphrase = arg;
+
+ if ((arglen > 5) && strncmp(arg, "exec:", 5) == 0) {
+ if (apr_tokenize_to_argv(arg+5, &argv, cmd->temp_pool) != APR_SUCCESS) {
+ return apr_pstrcat(cmd->pool,
+ "Unable to parse exec arguments from ",
+ arg+5, NULL);
+ }
+ argv[0] = ap_server_root_relative(cmd->temp_pool, argv[0]);
+
+ if (!argv[0]) {
+ return apr_pstrcat(cmd->pool,
+ "Invalid SessionCryptoPassphrase exec location:",
+ arg+5, NULL);
+ }
+ result = ap_get_exec_line(cmd->pool,
+ (const char*)argv[0], (const char * const *)argv);
+
+ if(!result) {
+ return apr_pstrcat(cmd->pool,
+ "Unable to get bind password from exec of ",
+ arg+5, NULL);
+ }
+ *passphrase = result;
+ }
+ else {
+ *passphrase = arg;
+ }
+
dconf->passphrases_set = 1;
return NULL;
diff --git a/modules/slotmem/mod_slotmem_shm.c b/modules/slotmem/mod_slotmem_shm.c
index aac96e23..1f7e557c 100644
--- a/modules/slotmem/mod_slotmem_shm.c
+++ b/modules/slotmem/mod_slotmem_shm.c
@@ -178,6 +178,7 @@ static void store_slotmem(ap_slotmem_instance_t *slotmem)
apr_status_t rv;
apr_size_t nbytes;
const char *storename;
+ unsigned char digest[APR_MD5_DIGESTSIZE];
storename = slotmem_filename(slotmem->gpool, slotmem->name, 1);
@@ -200,20 +201,27 @@ static void store_slotmem(ap_slotmem_instance_t *slotmem)
}
nbytes = (slotmem->desc.size * slotmem->desc.num) +
(slotmem->desc.num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET;
- /* XXX: Error handling */
- apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
+ apr_md5(digest, slotmem->persist, nbytes);
+ rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
+ if (rv == APR_SUCCESS) {
+ rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL);
+ }
apr_file_close(fp);
+ if (rv != APR_SUCCESS) {
+ apr_file_remove(storename, slotmem->gpool);
+ }
}
}
-/* should be apr_status_t really */
-static void restore_slotmem(void *ptr, const char *name, apr_size_t size,
- apr_pool_t *pool)
+static apr_status_t restore_slotmem(void *ptr, const char *name, apr_size_t size,
+ apr_pool_t *pool)
{
const char *storename;
apr_file_t *fp;
apr_size_t nbytes = size;
- apr_status_t rv;
+ apr_status_t rv = APR_SUCCESS;
+ unsigned char digest[APR_MD5_DIGESTSIZE];
+ unsigned char digest2[APR_MD5_DIGESTSIZE];
storename = slotmem_filename(pool, name, 1);
@@ -224,20 +232,42 @@ static void restore_slotmem(void *ptr, const char *name, apr_size_t size,
rv = apr_file_open(&fp, storename, APR_READ | APR_WRITE, APR_OS_DEFAULT,
pool);
if (rv == APR_SUCCESS) {
- apr_finfo_t fi;
- if (apr_file_info_get(&fi, APR_FINFO_SIZE, fp) == APR_SUCCESS) {
- if (fi.size == nbytes) {
- apr_file_read(fp, ptr, &nbytes);
+ rv = apr_file_read(fp, ptr, &nbytes);
+ if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) {
+ rv = APR_SUCCESS; /* for successful return @ EOF */
+ /*
+ * if at EOF, don't bother checking md5
+ * - backwards compatibility
+ * */
+ if (apr_file_eof(fp) != APR_EOF) {
+ apr_size_t ds = APR_MD5_DIGESTSIZE;
+ rv = apr_file_read(fp, digest, &ds);
+ if ((rv == APR_SUCCESS || rv == APR_EOF) &&
+ ds == APR_MD5_DIGESTSIZE) {
+ rv = APR_SUCCESS;
+ apr_md5(digest2, ptr, nbytes);
+ if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ APLOGNO(02551) "bad md5 match");
+ rv = APR_EGENERAL;
+ }
+ }
}
else {
- apr_file_close(fp);
- apr_file_remove(storename, pool);
- return;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)");
}
}
+ else if (nbytes != size) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT,
+ size, nbytes);
+ rv = APR_EGENERAL;
+ }
apr_file_close(fp);
}
}
+ return rv;
}
static apr_status_t cleanup_slotmem(void *param)
@@ -251,7 +281,12 @@ static apr_status_t cleanup_slotmem(void *param)
store_slotmem(next);
}
if (next->fbased) {
+ const char *name;
apr_shm_remove(next->name, next->gpool);
+ name = slotmem_filename(next->gpool, next->name, 0);
+ if (name) {
+ apr_file_remove(name, next->gpool);
+ }
}
apr_shm_destroy((apr_shm_t *)next->shm);
next = next->next;
@@ -390,8 +425,16 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
* sense if the restore fails? Any?
*/
if (type & AP_SLOTMEM_TYPE_PERSIST) {
- restore_slotmem(ptr, fname, dsize, pool);
- restored = 1;
+ rv = restore_slotmem(ptr, fname, dsize, pool);
+ if (rv == APR_SUCCESS) {
+ restored = 1;
+ }
+ else {
+ /* just in case, re-zero */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ APLOGNO(02554) "could not restore %s", fname);
+ memset(ptr, 0, dsize);
+ }
}
}
diff --git a/modules/ssl/config.m4 b/modules/ssl/config.m4
index 1b589d81..45eeb43d 100644
--- a/modules/ssl/config.m4
+++ b/modules/ssl/config.m4
@@ -20,7 +20,6 @@ dnl # list of module object files
ssl_objs="dnl
mod_ssl.lo dnl
ssl_engine_config.lo dnl
-ssl_engine_dh.lo dnl
ssl_engine_init.lo dnl
ssl_engine_io.lo dnl
ssl_engine_kernel.lo dnl
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index a43f656e..f0499405 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -139,7 +139,7 @@ static const command_rec ssl_config_cmds[] = {
SSL_CMD_SRV(HonorCipherOrder, FLAG,
"Use the server's cipher ordering preference")
SSL_CMD_SRV(Compression, FLAG,
- "Enable SSL level compression"
+ "Enable SSL level compression "
"(`on', `off')")
SSL_CMD_SRV(InsecureRenegotiation, FLAG,
"Enable support for insecure renegotiation")
@@ -148,7 +148,7 @@ static const command_rec ssl_config_cmds[] = {
SSL_CMD_SRV(StrictSNIVHostCheck, FLAG,
"Strict SNI virtual host checking")
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
SSL_CMD_SRV(SRPVerifierFile, TAKE1,
"SRP verifier file "
"('/path/to/file' - created by srptool)")
@@ -471,15 +471,6 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
sslconn->ssl = ssl;
- /*
- * Configure callbacks for SSL connection
- */
- SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
- SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
-#ifndef OPENSSL_NO_EC
- SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH);
-#endif
-
SSL_set_verify_result(ssl, X509_V_OK);
ssl_io_filter_init(c, r, ssl);
diff --git a/modules/ssl/mod_ssl.dsp b/modules/ssl/mod_ssl.dsp
index fc86a7b6..58b55456 100644
--- a/modules/ssl/mod_ssl.dsp
+++ b/modules/ssl/mod_ssl.dsp
@@ -112,10 +112,6 @@ SOURCE=.\ssl_engine_config.c
# End Source File
# Begin Source File
-SOURCE=.\ssl_engine_dh.c
-# End Source File
-# Begin Source File
-
SOURCE=.\ssl_engine_init.c
# End Source File
# Begin Source File
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 1ab5bf37..f519151e 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -75,8 +75,6 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
mc->stapling_mutex = NULL;
#endif
- memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys));
-
apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
apr_pool_cleanup_null,
pool);
@@ -150,7 +148,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)
mctx->stapling_force_url = NULL;
#endif
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
mctx->srp_vfile = NULL;
mctx->srp_unknown_user_seed = NULL;
mctx->srp_vbase = NULL;
@@ -208,7 +206,7 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
sc->proxy_ssl_check_peer_expire = SSL_ENABLED_UNSET;
sc->proxy_ssl_check_peer_cn = SSL_ENABLED_UNSET;
sc->proxy_ssl_check_peer_name = SSL_ENABLED_UNSET;
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
sc->strict_sni_vhost_check = SSL_ENABLED_UNSET;
#endif
#ifdef HAVE_FIPS
@@ -282,7 +280,7 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
cfgMerge(stapling_force_url, NULL);
#endif
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
cfgMergeString(srp_vfile);
cfgMergeString(srp_unknown_user_seed);
#endif
@@ -338,7 +336,7 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
cfgMerge(proxy_ssl_check_peer_expire, SSL_ENABLED_UNSET);
cfgMerge(proxy_ssl_check_peer_cn, SSL_ENABLED_UNSET);
cfgMerge(proxy_ssl_check_peer_name, SSL_ENABLED_UNSET);
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
cfgMerge(strict_sni_vhost_check, SSL_ENABLED_UNSET);
#endif
#ifdef HAVE_FIPS
@@ -601,7 +599,7 @@ const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
if (!strcasecmp(arg, "On")) {
sc->enabled = SSL_ENABLED_TRUE;
- return NULL;
+ return NULL;
}
else if (!strcasecmp(arg, "Off")) {
sc->enabled = SSL_ENABLED_FALSE;
@@ -645,6 +643,9 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
+ /* always disable null and export ciphers */
+ arg = apr_pstrcat(cmd->pool, "!aNULL:!eNULL:!EXP:", arg, NULL);
+
if (cmd->path) {
dc->szCipherSuite = arg;
}
@@ -1384,6 +1385,9 @@ const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *cmd,
{
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ /* always disable null and export ciphers */
+ arg = apr_pstrcat(cmd->pool, "!aNULL:!eNULL:!EXP:", arg, NULL);
+
sc->proxy->auth.cipher_suite = arg;
return NULL;
@@ -1645,7 +1649,7 @@ const char *ssl_cmd_SSLProxyCheckPeerName(cmd_parms *cmd, void *dcfg, int flag)
const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag)
{
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
sc->strict_sni_vhost_check = flag ? SSL_ENABLED_TRUE : SSL_ENABLED_FALSE;
@@ -1804,7 +1808,7 @@ const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg,
#endif /* HAVE_OCSP_STAPLING */
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
const char *arg)
@@ -1828,7 +1832,7 @@ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg,
return NULL;
}
-#endif /* OPENSSL_NO_SRP */
+#endif /* HAVE_SRP */
void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
{
diff --git a/modules/ssl/ssl_engine_dh.c b/modules/ssl/ssl_engine_dh.c
deleted file mode 100644
index 0cc74555..00000000
--- a/modules/ssl/ssl_engine_dh.c
+++ /dev/null
@@ -1,244 +0,0 @@
-#if 0
-=pod
-#endif
-
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* _ _
- * _ __ ___ ___ __| | ___ ___| | mod_ssl
- * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
- * | | | | | | (_) | (_| | \__ \__ \ |
- * |_| |_| |_|\___/ \__,_|___|___/___/_|
- * |_____|
- * ssl_engine_dh.c
- * Diffie-Hellman Built-in Temporary Parameters
- */
-
-#include "ssl_private.h"
-
-/* ----BEGIN GENERATED SECTION-------- */
-
-/*
-** Diffie-Hellman-Parameters: (512 bit)
-** prime:
-** 00:9f:db:8b:8a:00:45:44:f0:04:5f:17:37:d0:ba:
-** 2e:0b:27:4c:df:1a:9f:58:82:18:fb:43:53:16:a1:
-** 6e:37:41:71:fd:19:d8:d8:f3:7c:39:bf:86:3f:d6:
-** 0e:3e:30:06:80:a3:03:0c:6e:4c:37:57:d0:8f:70:
-** e6:aa:87:10:33
-** generator: 2 (0x2)
-** Diffie-Hellman-Parameters: (1024 bit)
-** prime:
-** 00:d6:7d:e4:40:cb:bb:dc:19:36:d6:93:d3:4a:fd:
-** 0a:d5:0c:84:d2:39:a4:5f:52:0b:b8:81:74:cb:98:
-** bc:e9:51:84:9f:91:2e:63:9c:72:fb:13:b4:b4:d7:
-** 17:7e:16:d5:5a:c1:79:ba:42:0b:2a:29:fe:32:4a:
-** 46:7a:63:5e:81:ff:59:01:37:7b:ed:dc:fd:33:16:
-** 8a:46:1a:ad:3b:72:da:e8:86:00:78:04:5b:07:a7:
-** db:ca:78:74:08:7d:15:10:ea:9f:cc:9d:dd:33:05:
-** 07:dd:62:db:88:ae:aa:74:7d:e0:f4:d6:e2:bd:68:
-** b0:e7:39:3e:0f:24:21:8e:b3
-** generator: 2 (0x2)
-*/
-
-static unsigned char dh512_p[] = {
- 0x9F, 0xDB, 0x8B, 0x8A, 0x00, 0x45, 0x44, 0xF0, 0x04, 0x5F, 0x17, 0x37,
- 0xD0, 0xBA, 0x2E, 0x0B, 0x27, 0x4C, 0xDF, 0x1A, 0x9F, 0x58, 0x82, 0x18,
- 0xFB, 0x43, 0x53, 0x16, 0xA1, 0x6E, 0x37, 0x41, 0x71, 0xFD, 0x19, 0xD8,
- 0xD8, 0xF3, 0x7C, 0x39, 0xBF, 0x86, 0x3F, 0xD6, 0x0E, 0x3E, 0x30, 0x06,
- 0x80, 0xA3, 0x03, 0x0C, 0x6E, 0x4C, 0x37, 0x57, 0xD0, 0x8F, 0x70, 0xE6,
- 0xAA, 0x87, 0x10, 0x33,
-};
-static unsigned char dh512_g[] = {
- 0x02,
-};
-
-static DH *get_dh512(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
- dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-
-static unsigned char dh1024_p[] = {
- 0xD6, 0x7D, 0xE4, 0x40, 0xCB, 0xBB, 0xDC, 0x19, 0x36, 0xD6, 0x93, 0xD3,
- 0x4A, 0xFD, 0x0A, 0xD5, 0x0C, 0x84, 0xD2, 0x39, 0xA4, 0x5F, 0x52, 0x0B,
- 0xB8, 0x81, 0x74, 0xCB, 0x98, 0xBC, 0xE9, 0x51, 0x84, 0x9F, 0x91, 0x2E,
- 0x63, 0x9C, 0x72, 0xFB, 0x13, 0xB4, 0xB4, 0xD7, 0x17, 0x7E, 0x16, 0xD5,
- 0x5A, 0xC1, 0x79, 0xBA, 0x42, 0x0B, 0x2A, 0x29, 0xFE, 0x32, 0x4A, 0x46,
- 0x7A, 0x63, 0x5E, 0x81, 0xFF, 0x59, 0x01, 0x37, 0x7B, 0xED, 0xDC, 0xFD,
- 0x33, 0x16, 0x8A, 0x46, 0x1A, 0xAD, 0x3B, 0x72, 0xDA, 0xE8, 0x86, 0x00,
- 0x78, 0x04, 0x5B, 0x07, 0xA7, 0xDB, 0xCA, 0x78, 0x74, 0x08, 0x7D, 0x15,
- 0x10, 0xEA, 0x9F, 0xCC, 0x9D, 0xDD, 0x33, 0x05, 0x07, 0xDD, 0x62, 0xDB,
- 0x88, 0xAE, 0xAA, 0x74, 0x7D, 0xE0, 0xF4, 0xD6, 0xE2, 0xBD, 0x68, 0xB0,
- 0xE7, 0x39, 0x3E, 0x0F, 0x24, 0x21, 0x8E, 0xB3,
-};
-static unsigned char dh1024_g[] = {
- 0x02,
-};
-
-static DH *get_dh1024(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-
-/* ----END GENERATED SECTION---------- */
-
-DH *ssl_dh_GetTmpParam(int nKeyLen)
-{
- DH *dh;
-
- if (nKeyLen == 512)
- dh = get_dh512();
- else if (nKeyLen == 1024)
- dh = get_dh1024();
- else
- dh = get_dh1024();
- return dh;
-}
-
-DH *ssl_dh_GetParamFromFile(char *file)
-{
- DH *dh = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(file, "r")) == NULL)
- return NULL;
- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- BIO_free(bio);
- return (dh);
-}
-
-/*
-=cut
-##
-## Embedded Perl script for generating the temporary DH parameters
-##
-
-require 5.003;
-use strict;
-
-# configuration
-my $file = $0;
-my $begin = '----BEGIN GENERATED SECTION--------';
-my $end = '----END GENERATED SECTION----------';
-
-# read ourself and keep a backup
-open(FP, "<$file") || die;
-my $source = '';
-$source .= $_ while (<FP>);
-close(FP);
-open(FP, ">$file.bak") || die;
-print FP $source;
-close(FP);
-
-# generate the DH parameters
-print "1. Generate 512 and 1024 bit Diffie-Hellman parameters (p, g)\n";
-my $rand = '';
-foreach $file (qw(/var/log/messages /var/adm/messages
- /kernel /vmunix /vmlinuz /etc/hosts /etc/resolv.conf)) {
- if (-f $file) {
- $rand = $file if ($rand eq '');
- $rand .= ":$file" if ($rand ne '');
- }
-}
-$rand = "-rand $rand" if ($rand ne '');
-system("openssl gendh $rand -out dh512.pem 512");
-system("openssl gendh $rand -out dh1024.pem 1024");
-
-# generate DH param info
-my $dhinfo = '';
-open(FP, "openssl dh -noout -text -in dh512.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -text -in dh1024.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-$dhinfo =~ s|^|** |mg;
-$dhinfo = "\n\/\*\n$dhinfo\*\/\n\n";
-
-my $indent_args = "-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1";
-
-# generate C source from DH params
-my $dhsource = '';
-open(FP, "openssl dh -noout -C -in dh512.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -C -in dh1024.pem | indent $indent_args | expand |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-$dhsource =~ s|(DH\s+\*get_dh)(\d+)[^}]*\n}|static $1$2(void)
-{
- DH *dh;
-
- if (!(dh = DH_new())) {
- return NULL;
- }
-
- dh->p = BN_bin2bn(dh$2_p, sizeof(dh$2_p), NULL);
- dh->g = BN_bin2bn(dh$2_g, sizeof(dh$2_g), NULL);
- if (!(dh->p && dh->g)) {
- DH_free(dh);
- return NULL;
- }
-
- return dh;
-}
-|sg;
-
-# generate output
-my $o = $dhinfo . $dhsource;
-
-# insert the generated code at the target location
-$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
-
-# and update the source on disk
-print "Updating file `$file'\n";
-open(FP, ">$file") || die;
-print FP $source;
-close(FP);
-
-# cleanup
-unlink("dh512.pem");
-unlink("dh1024.pem");
-
-=pod
-*/
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index 9f8dcc8f..f6e010de 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -35,7 +35,7 @@
** _________________________________________________________________
*/
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
#define KEYTYPES "RSA, DSA or ECC"
#else
#define KEYTYPES "RSA or DSA"
@@ -56,180 +56,6 @@ static void ssl_add_version_components(apr_pool_t *p,
modver, AP_SERVER_BASEVERSION, incver);
}
-
-/*
- * Handle the Temporary RSA Keys and DH Params
- */
-
-#define MODSSL_TMP_KEY_FREE(mc, type, idx) \
- if (mc->pTmpKeys[idx]) { \
- type##_free((type *)mc->pTmpKeys[idx]); \
- mc->pTmpKeys[idx] = NULL; \
- }
-
-#define MODSSL_TMP_KEYS_FREE(mc, type) \
- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_512); \
- MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_1024)
-
-static void ssl_tmp_keys_free(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
- MODSSL_TMP_KEYS_FREE(mc, RSA);
- MODSSL_TMP_KEYS_FREE(mc, DH);
-#ifndef OPENSSL_NO_EC
- MODSSL_TMP_KEY_FREE(mc, EC_KEY, SSL_TMP_KEY_EC_256);
-#endif
-}
-
-static int ssl_tmp_key_init_rsa(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
-#ifdef HAVE_FIPS
-
- if (FIPS_mode() && bits < 1024) {
- mc->pTmpKeys[idx] = NULL;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01877)
- "Init: Skipping generating temporary "
- "%d bit RSA private key in FIPS mode", bits);
- return OK;
- }
-
-#endif
-#ifdef HAVE_GENERATE_EX
- {
- RSA *tkey;
- BIGNUM *bn_f4;
- if (!(tkey = RSA_new())
- || !(bn_f4 = BN_new())
- || !BN_set_word(bn_f4, RSA_F4)
- || !RSA_generate_key_ex(tkey, bits, bn_f4, NULL))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01878)
- "Init: Failed to generate temporary "
- "%d bit RSA private key", bits);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- return !OK;
- }
- BN_free(bn_f4);
- mc->pTmpKeys[idx] = tkey;
- }
-#else
- if (!(mc->pTmpKeys[idx] =
- RSA_generate_key(bits, RSA_F4, NULL, NULL)))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01879)
- "Init: Failed to generate temporary "
- "%d bit RSA private key", bits);
- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
- return !OK;
- }
-#endif
-
- return OK;
-}
-
-static int ssl_tmp_key_init_dh(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
-
-#ifdef HAVE_FIPS
-
- if (FIPS_mode() && bits < 1024) {
- mc->pTmpKeys[idx] = NULL;
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01880)
- "Init: Skipping generating temporary "
- "%d bit DH parameters in FIPS mode", bits);
- return OK;
- }
-
-#endif
-
- if (!(mc->pTmpKeys[idx] =
- ssl_dh_GetTmpParam(bits)))
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01881)
- "Init: Failed to generate temporary "
- "%d bit DH parameters", bits);
- return !OK;
- }
-
- return OK;
-}
-
-#ifndef OPENSSL_NO_EC
-static int ssl_tmp_key_init_ec(server_rec *s,
- int bits, int idx)
-{
- SSLModConfigRec *mc = myModConfig(s);
- EC_KEY *ecdh = NULL;
-
- /* XXX: Are there any FIPS constraints we should enforce? */
-
- if (bits != 256) {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02298)
- "Init: Failed to generate temporary "
- "%d bit EC parameters, only 256 bits supported", bits);
- return !OK;
- }
-
- if ((ecdh = EC_KEY_new()) == NULL ||
- EC_KEY_set_group(ecdh, EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 1)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02299)
- "Init: Failed to generate temporary "
- "%d bit EC parameters", bits);
- return !OK;
- }
-
- mc->pTmpKeys[idx] = ecdh;
- return OK;
-}
-
-#define MODSSL_TMP_KEY_INIT_EC(s, bits) \
- ssl_tmp_key_init_ec(s, bits, SSL_TMP_KEY_EC_##bits)
-
-#endif
-
-#define MODSSL_TMP_KEY_INIT_RSA(s, bits) \
- ssl_tmp_key_init_rsa(s, bits, SSL_TMP_KEY_RSA_##bits)
-
-#define MODSSL_TMP_KEY_INIT_DH(s, bits) \
- ssl_tmp_key_init_dh(s, bits, SSL_TMP_KEY_DH_##bits)
-
-static int ssl_tmp_keys_init(server_rec *s)
-{
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary RSA private keys (512/1024 bits)");
-
- if (MODSSL_TMP_KEY_INIT_RSA(s, 512) ||
- MODSSL_TMP_KEY_INIT_RSA(s, 1024)) {
- return !OK;
- }
-
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary DH parameters (512/1024 bits)");
-
- if (MODSSL_TMP_KEY_INIT_DH(s, 512) ||
- MODSSL_TMP_KEY_INIT_DH(s, 1024)) {
- return !OK;
- }
-
-#ifndef OPENSSL_NO_EC
- ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
- "Init: Generating temporary EC parameters (256 bits)");
-
- if (MODSSL_TMP_KEY_INIT_EC(s, 256)) {
- return !OK;
- }
-#endif
-
- return OK;
-}
-
/*
* Per-module initialization
*/
@@ -294,7 +120,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
sc->enabled = SSL_ENABLED_TRUE;
}
- /* If sc->enabled is UNSET, then SSL is optional on this vhost */
+ /* If sc->enabled is UNSET, then SSL is optional on this vhost */
/* Fix up stuff that may not have been set */
if (sc->enabled == SSL_ENABLED_UNSET) {
sc->enabled = SSL_ENABLED_FALSE;
@@ -367,10 +193,6 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
*/
ssl_pphrase_Handle(base_server, ptemp);
- if (ssl_tmp_keys_init(base_server)) {
- return !OK;
- }
-
/*
* initialize the mutex handling
*/
@@ -481,7 +303,7 @@ static void ssl_init_server_check(server_rec *s,
*/
if (mctx->pks->certs[SSL_AIDX_RSA] ||
mctx->pks->certs[SSL_AIDX_DSA]
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
|| mctx->pks->certs[SSL_AIDX_ECC]
#endif
)
@@ -493,7 +315,7 @@ static void ssl_init_server_check(server_rec *s,
}
}
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
static void ssl_init_ctx_tls_extensions(server_rec *s,
apr_pool_t *p,
apr_pool_t *ptemp,
@@ -527,7 +349,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
}
#endif
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
/*
* TLS-SRP support
*/
@@ -660,7 +482,7 @@ static void ssl_init_ctx_protocol(server_rec *s,
#ifdef SSL_OP_NO_COMPRESSION
/* OpenSSL >= 1.0 only */
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
-#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
+#else
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
#endif
}
@@ -678,6 +500,9 @@ static void ssl_init_ctx_protocol(server_rec *s,
* Configure additional context ingredients
*/
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
+#ifdef HAVE_ECC
+ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
+#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
/*
@@ -718,11 +543,7 @@ static void ssl_init_ctx_callbacks(server_rec *s,
{
SSL_CTX *ctx = mctx->ssl_ctx;
- SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
-#ifndef OPENSSL_NO_EC
- SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH);
-#endif
SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
}
@@ -818,14 +639,16 @@ static void ssl_init_ctx_cipher_suite(server_rec *s,
modssl_ctx_t *mctx)
{
SSL_CTX *ctx = mctx->ssl_ctx;
- const char *suite = mctx->auth.cipher_suite;
+ const char *suite;
/*
- * Configure SSL Cipher Suite
+ * Configure SSL Cipher Suite. Always disable NULL and export ciphers,
+ * see also ssl_engine_config.c:ssl_cmd_SSLCipherSuite().
+ * OpenSSL's SSL_DEFAULT_CIPHER_LIST already includes !aNULL:!eNULL,
+ * so only prepend !EXP in this case.
*/
- if (!suite) {
- return;
- }
+ suite = mctx->auth.cipher_suite ? mctx->auth.cipher_suite :
+ apr_pstrcat(ptemp, "!EXP:", SSL_DEFAULT_CIPHER_LIST, NULL);
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
"Configuring permitted SSL ciphers [%s]",
@@ -988,7 +811,7 @@ static void ssl_init_ctx(server_rec *s,
if (mctx->pks) {
/* XXX: proxy support? */
ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
#endif
}
@@ -1001,7 +824,7 @@ static int ssl_server_import_cert(server_rec *s,
{
SSLModConfigRec *mc = myModConfig(s);
ssl_asn1_t *asn1;
- MODSSL_D2I_X509_CONST unsigned char *ptr;
+ const unsigned char *ptr;
const char *type = ssl_asn1_keystr(idx);
X509 *cert;
@@ -1048,12 +871,12 @@ static int ssl_server_import_key(server_rec *s,
{
SSLModConfigRec *mc = myModConfig(s);
ssl_asn1_t *asn1;
- MODSSL_D2I_PrivateKey_CONST unsigned char *ptr;
+ const unsigned char *ptr;
const char *type = ssl_asn1_keystr(idx);
int pkey_type;
EVP_PKEY *pkey;
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
if (idx == SSL_AIDX_ECC)
pkey_type = EVP_PKEY_EC;
else
@@ -1157,30 +980,34 @@ static void ssl_init_server_certs(server_rec *s,
modssl_ctx_t *mctx)
{
const char *rsa_id, *dsa_id;
-#ifndef OPENSSL_NO_EC
+#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;
-#ifndef OPENSSL_NO_EC
+ DH *dhparams;
+#ifdef HAVE_ECC
int have_ecc;
#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);
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC);
#endif
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);
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
#endif
if (!(have_rsa || have_dsa
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
|| have_ecc
#endif
)) {
@@ -1196,12 +1023,12 @@ static void ssl_init_server_certs(server_rec *s,
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);
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC);
#endif
if (!(have_rsa || have_dsa
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
|| have_ecc
#endif
)) {
@@ -1209,6 +1036,40 @@ static void ssl_init_server_certs(server_rec *s,
"Oops, no " KEYTYPES " server private key found?!");
ssl_die(s);
}
+
+ /*
+ * 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]))) {
+ 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]);
+ }
+
+#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])) &&
+ (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]);
+ }
+ /*
+ * ...otherwise, configure NIST P-256 (required to enable ECDHE)
+ */
+ else {
+ SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
+ EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ }
+#endif
}
#ifdef HAVE_TLS_SESSION_TICKETS
@@ -1516,7 +1377,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
klen = strlen(key);
if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
-#ifdef OPENSSL_NO_TLSEXT
+#ifndef HAVE_TLSEXT
int level = APLOG_WARNING;
const char *problem = "conflict";
#else
@@ -1540,7 +1401,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
}
if (conflict) {
-#ifdef OPENSSL_NO_TLSEXT
+#ifndef HAVE_TLSEXT
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01917)
"Init: You should not use name-based "
"virtual hosts in conjunction with SSL!!");
@@ -1689,7 +1550,7 @@ static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx)
{
MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx);
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
if (mctx->srp_vbase != NULL) {
SRP_VBASE_free(mctx->srp_vbase);
mctx->srp_vbase = NULL;
@@ -1745,11 +1606,6 @@ apr_status_t ssl_init_ModuleKill(void *data)
ssl_scache_kill(base_server);
/*
- * Destroy the temporary keys and params
- */
- ssl_tmp_keys_free(base_server);
-
- /*
* Free the non-pool allocated structures
* in the per-server configurations
*/
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index d135bd38..7f60cc27 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -775,6 +775,18 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
*/
outctx->rc = APR_EAGAIN;
}
+ else if (ssl_err == SSL_ERROR_WANT_READ) {
+ /*
+ * If OpenSSL wants to read during write, and we were
+ * nonblocking, set the sense explicitly to read and
+ * report as an EAGAIN.
+ *
+ * (This is usually the case when the client forces an SSL
+ * renegotiation which is handled implicitly by OpenSSL.)
+ */
+ outctx->c->cs->sense = CONN_SENSE_WANT_READ;
+ outctx->rc = APR_EAGAIN;
+ }
else if (ssl_err == SSL_ERROR_SYSCALL) {
ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01993)
"SSL output filter write failed.");
@@ -1048,7 +1060,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
server = sslconn->server;
if (sslconn->is_proxy) {
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
apr_ipsubnet_t *ip;
#endif
const char *hostname_note = apr_table_get(c->notes,
@@ -1056,7 +1068,7 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
BOOL proxy_ssl_check_peer_ok = TRUE;
sc = mySrvConfig(server);
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
/*
* Enable SNI for backend requests. Make sure we don't do it for
* pure SSLv3 connections, and also prevent IP addresses
@@ -1902,8 +1914,10 @@ void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
filter_ctx->pbioWrite = BIO_new(&bio_filter_out_method);
filter_ctx->pbioWrite->ptr = (void *)bio_filter_out_ctx_new(filter_ctx, c);
- /* We insert a clogging input filter. Let the core know. */
- c->clogging_input_filters = 1;
+ /* write is non blocking for the benefit of async mpm */
+ if (c->cs) {
+ BIO_set_nbio(filter_ctx->pbioWrite, 1);
+ }
ssl_io_input_add_filter(filter_ctx, c, r, ssl);
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index a088df16..6d93ac99 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -32,7 +32,7 @@
#include "util_md5.h"
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
#endif
@@ -119,7 +119,7 @@ int ssl_hook_ReadReq(request_rec *r)
SSLSrvConfigRec *sc = mySrvConfig(r->server);
SSLConnRec *sslconn;
const char *upgrade;
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
const char *servername;
#endif
SSL *ssl;
@@ -162,7 +162,7 @@ int ssl_hook_ReadReq(request_rec *r)
if (!ssl) {
return DECLINED;
}
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
char *host, *scope_id;
apr_port_t port;
@@ -329,7 +329,7 @@ int ssl_hook_Access(request_rec *r)
return DECLINED;
}
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
/*
* Support for per-directory reconfigured SSL connection parameters
*
@@ -1101,7 +1101,7 @@ static const char *ssl_hook_Fixup_vars[] = {
"SSL_SERVER_A_SIG",
"SSL_SESSION_ID",
"SSL_SESSION_RESUMED",
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
"SSL_SRP_USER",
"SSL_SRP_USERINFO",
#endif
@@ -1115,7 +1115,7 @@ int ssl_hook_Fixup(request_rec *r)
SSLDirConfigRec *dc = myDirConfig(r);
apr_table_t *env = r->subprocess_env;
char *var, *val = "";
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
const char *servername;
#endif
STACK_OF(X509) *peer_certs;
@@ -1144,7 +1144,7 @@ int ssl_hook_Fixup(request_rec *r)
/* the always present HTTPS (=HTTP over SSL) flag! */
apr_table_setn(env, "HTTPS", "on");
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
/* add content of SNI TLS extension (if supplied with ClientHello) */
if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
apr_table_set(env, "SSL_TLS_SNI", servername);
@@ -1287,117 +1287,70 @@ const authz_provider ssl_authz_provider_verify_client =
*/
/*
- * Handle out temporary RSA private keys on demand
- *
- * The background of this as the TLSv1 standard explains it:
- *
- * | D.1. Temporary RSA keys
- * |
- * | US Export restrictions limit RSA keys used for encryption to 512
- * | bits, but do not place any limit on lengths of RSA keys used for
- * | signing operations. Certificates often need to be larger than 512
- * | bits, since 512-bit RSA keys are not secure enough for high-value
- * | transactions or for applications requiring long-term security. Some
- * | certificates are also designated signing-only, in which case they
- * | cannot be used for key exchange.
- * |
- * | When the public key in the certificate cannot be used for encryption,
- * | the server signs a temporary RSA key, which is then exchanged. In
- * | exportable applications, the temporary RSA key should be the maximum
- * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are
- * | relatively insecure, they should be changed often. For typical
- * | electronic commerce applications, it is suggested that keys be
- * | changed daily or every 500 transactions, and more often if possible.
- * | Note that while it is acceptable to use the same temporary key for
- * | multiple transactions, it must be signed each time it is used.
- * |
- * | RSA key generation is a time-consuming process. In many cases, a
- * | low-priority process can be assigned the task of key generation.
- * | Whenever a new key is completed, the existing temporary key can be
- * | replaced with the new one.
- *
- * XXX: base on comment above, if thread support is enabled,
- * we should spawn a low-priority thread to generate new keys
- * on the fly.
- *
- * So we generated 512 and 1024 bit temporary keys on startup
- * which we now just hand out on demand....
+ * Grab well-defined DH parameters from OpenSSL, see <openssl/bn.h>
+ * (get_rfc*) for all available primes.
*/
-
-RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen)
-{
- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary %d bit RSA key", keylen);
-
- /* doesn't matter if export flag is on,
- * we won't be asked for keylen > 512 in that case.
- * if we are asked for a keylen > 1024, it is too expensive
- * to generate on the fly.
- * XXX: any reason not to generate 2048 bit keys at startup?
- */
-
- switch (keylen) {
- case 512:
- idx = SSL_TMP_KEY_RSA_512;
- break;
-
- case 1024:
- default:
- idx = SSL_TMP_KEY_RSA_1024;
- }
-
- return (RSA *)mc->pTmpKeys[idx];
+#define make_get_dh(rfc,size,gen) \
+static DH *get_dh##size(void) \
+{ \
+ DH *dh; \
+ if (!(dh = DH_new())) { \
+ return NULL; \
+ } \
+ dh->p = get_##rfc##_prime_##size(NULL); \
+ BN_dec2bn(&dh->g, #gen); \
+ if (!dh->p || !dh->g) { \
+ DH_free(dh); \
+ return NULL; \
+ } \
+ return dh; \
}
/*
- * Hand out the already generated DH parameters...
+ * Prepare DH parameters from 1024 to 4096 bits, in 1024-bit increments
+ */
+make_get_dh(rfc2409, 1024, 2)
+make_get_dh(rfc3526, 2048, 2)
+make_get_dh(rfc3526, 3072, 2)
+make_get_dh(rfc3526, 4096, 2)
+
+/*
+ * Hand out standard DH parameters, based on the authentication strength
*/
DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
{
conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary %d bit DH key", keylen);
-
- switch (keylen) {
- case 512:
- idx = SSL_TMP_KEY_DH_512;
- break;
+ EVP_PKEY *pkey = SSL_get_privatekey(ssl);
+ int type = pkey ? EVP_PKEY_type(pkey->type) : EVP_PKEY_NONE;
- case 1024:
- default:
- idx = SSL_TMP_KEY_DH_1024;
+ /*
+ * OpenSSL will call us with either keylen == 512 or keylen == 1024
+ * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
+ * Adjust the DH parameter length according to the size of the
+ * RSA/DSA private key used for the current connection, and always
+ * use at least 1024-bit parameters.
+ * Note: This may cause interoperability issues with implementations
+ * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
+ * In this case, SSLCertificateFile can be used to specify fixed
+ * 1024-bit DH parameters (with the effect that OpenSSL skips this
+ * callback).
+ */
+ if ((type == EVP_PKEY_RSA) || (type == EVP_PKEY_DSA)) {
+ keylen = EVP_PKEY_bits(pkey);
}
- return (DH *)mc->pTmpKeys[idx];
-}
-
-#ifndef OPENSSL_NO_EC
-EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen)
-{
- conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
- SSLModConfigRec *mc = myModConfigFromConn(c);
- int idx;
-
- /* XXX Uses 256-bit key for now. TODO: support other sizes. */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- "handing out temporary 256 bit ECC key");
-
- switch (keylen) {
- case 256:
- default:
- idx = SSL_TMP_KEY_EC_256;
- }
-
- return (EC_KEY *)mc->pTmpKeys[idx];
+ "handing out built-in DH parameters for %d-bit authenticated connection", keylen);
+
+ if (keylen >= 4096)
+ return get_dh4096();
+ else if (keylen >= 3072)
+ return get_dh3072();
+ else if (keylen >= 2048)
+ return get_dh2048();
+ else
+ return get_dh1024();
}
-#endif
/*
* This OpenSSL callback function is called when OpenSSL
@@ -1687,7 +1640,7 @@ static void ssl_session_log(server_rec *s,
if (timeout) {
apr_snprintf(timeout_str, sizeof(timeout_str),
- "timeout=%lds ", (timeout - time(NULL)));
+ "timeout=%lds ", timeout);
}
ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, s,
@@ -1938,7 +1891,7 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
}
}
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
/*
* This callback function is executed when OpenSSL encounters an extended
* client hello with a server name indication extension ("SNI", cf. RFC 4366).
@@ -2089,7 +2042,7 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
return 0;
}
-#endif /* OPENSSL_NO_TLSEXT */
+#endif /* HAVE_TLSEXT */
#ifdef HAVE_TLS_SESSION_TICKETS
/*
@@ -2161,7 +2114,7 @@ int ssl_callback_SessionTicket(SSL *ssl,
}
#endif /* HAVE_TLS_SESSION_TICKETS */
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
{
@@ -2185,4 +2138,4 @@ int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
return SSL_ERROR_NONE;
}
-#endif /* OPENSSL_NO_SRP */
+#endif /* HAVE_SRP */
diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c
index 23ccaf4a..ca8e130f 100644
--- a/modules/ssl/ssl_engine_pphrase.c
+++ b/modules/ssl/ssl_engine_pphrase.c
@@ -708,7 +708,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01966)
"Init: Failed to create pass phrase pipe '%s'",
sc->server->pphrase_dialog_path);
- PEMerr(PEM_F_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);
}
@@ -718,7 +718,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
}
else { /* sc->server->pphrase_dialog_type == SSL_PPTYPE_BUILTIN */
#ifdef WIN32
- PEMerr(PEM_F_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
@@ -769,7 +769,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
i = EVP_read_pw_string(buf, bufsize, "", FALSE);
}
if (i != 0) {
- PEMerr(PEM_F_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);
}
diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
index 536e6b1f..922bf7c1 100644
--- a/modules/ssl/ssl_engine_vars.c
+++ b/modules/ssl/ssl_engine_vars.c
@@ -382,7 +382,7 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r,
else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
result = ssl_var_lookup_ssl_compress_meth(ssl);
}
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
result = apr_pstrdup(p, SSL_get_servername(ssl,
TLSEXT_NAMETYPE_host_name));
@@ -395,7 +395,7 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r,
#endif
result = apr_pstrdup(p, flag ? "true" : "false");
}
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
else if (ssl != NULL && strcEQ(var, "SRP_USER")) {
if ((result = SSL_get_srp_username(ssl)) != NULL) {
result = apr_pstrdup(p, result);
@@ -879,7 +879,7 @@ void modssl_var_extract_dns(apr_table_t *t, SSL *ssl, apr_pool_t *p)
* success and writes the string to the given bio. */
static int dump_extn_value(BIO *bio, ASN1_OCTET_STRING *str)
{
- MODSSL_D2I_ASN1_type_bytes_CONST unsigned char *pp = str->data;
+ const unsigned char *pp = str->data;
ASN1_STRING *ret = ASN1_STRING_new();
int rv = 0;
@@ -975,7 +975,7 @@ apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer,
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl)
{
char *result = "NULL";
-#if (OPENSSL_VERSION_NUMBER >= 0x00908000) && !defined(OPENSSL_NO_COMP)
+#ifndef OPENSSL_NO_COMP
SSL_SESSION *pSession = SSL_get_session(ssl);
if (pSession) {
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 080ecef3..4ea924f3 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -105,65 +105,55 @@
#include <openssl/engine.h>
#endif
-#if (OPENSSL_VERSION_NUMBER < 0x0090700f)
-#error mod_ssl requires OpenSSL 0.9.7 or later
-#endif
-
-/* ...shifting sands of OpenSSL... */
-#if (OPENSSL_VERSION_NUMBER >= 0x0090707f)
-#define MODSSL_D2I_SSL_SESSION_CONST const
-#else
-#define MODSSL_D2I_SSL_SESSION_CONST
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x00908000)
-#define HAVE_GENERATE_EX
-#define MODSSL_D2I_ASN1_type_bytes_CONST const
-#define MODSSL_D2I_PrivateKey_CONST const
-#define MODSSL_D2I_X509_CONST const
-#else
-#define MODSSL_D2I_ASN1_type_bytes_CONST
-#define MODSSL_D2I_PrivateKey_CONST
-#define MODSSL_D2I_X509_CONST
-#endif
-
-#if OPENSSL_VERSION_NUMBER >= 0x00908080 && !defined(OPENSSL_NO_OCSP) \
- && !defined(OPENSSL_NO_TLSEXT)
-#define HAVE_OCSP_STAPLING
-#if (OPENSSL_VERSION_NUMBER < 0x10000000)
-#define sk_OPENSSL_STRING_pop sk_pop
-#endif
-#endif
-
-#if (OPENSSL_VERSION_NUMBER >= 0x009080a0) && defined(OPENSSL_FIPS)
-#define HAVE_FIPS
+#if (OPENSSL_VERSION_NUMBER < 0x0090801f)
+#error mod_ssl requires OpenSSL 0.9.8a or later
#endif
+/**
+ * ...shifting sands of OpenSSL...
+ * Note: when adding support for new OpenSSL features, avoid explicit
+ * version number checks whenever possible, and use "feature-based"
+ * detection instead (check for definitions of constants or functions)
+ */
#if (OPENSSL_VERSION_NUMBER >= 0x10000000)
#define MODSSL_SSL_CIPHER_CONST const
#define MODSSL_SSL_METHOD_CONST const
#else
#define MODSSL_SSL_CIPHER_CONST
#define MODSSL_SSL_METHOD_CONST
-/* ECC support came along in OpenSSL 1.0.0 */
-#define OPENSSL_NO_EC
#endif
-#ifndef PEM_F_DEF_CALLBACK
-#ifdef PEM_F_PEM_DEF_CALLBACK
-/** In OpenSSL 0.9.8 PEM_F_DEF_CALLBACK was renamed */
-#define PEM_F_DEF_CALLBACK PEM_F_PEM_DEF_CALLBACK
+#if defined(OPENSSL_FIPS)
+#define HAVE_FIPS
#endif
+
+#if defined(SSL_OP_NO_TLSv1_2)
+#define HAVE_TLSV1_X
#endif
-#ifndef OPENSSL_NO_TLSEXT
-#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
-#define OPENSSL_NO_TLSEXT
+/**
+ * The following features all depend on TLS extension support.
+ * Within this block, check again for features (not version numbers).
+ */
+#if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_set_tlsext_host_name)
+
+#define HAVE_TLSEXT
+
+/* ECC: make sure we have at least 1.0.0 */
+#if !defined(OPENSSL_NO_EC) && defined(TLSEXT_ECPOINTFORMAT_uncompressed)
+#define HAVE_ECC
+#endif
+
+/* OCSP stapling */
+#if !defined(OPENSSL_NO_OCSP) && defined(SSL_CTX_set_tlsext_status_cb)
+#define HAVE_OCSP_STAPLING
+#ifndef sk_OPENSSL_STRING_pop
+#define sk_OPENSSL_STRING_pop sk_pop
#endif
#endif
-#ifndef OPENSSL_NO_TLSEXT
-#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB
+/* TLS session tickets */
+#if defined(SSL_CTX_set_tlsext_ticket_key_cb)
#define HAVE_TLS_SESSION_TICKETS
#define TLSEXT_TICKET_KEY_LEN 48
#ifndef tlsext_tick_md
@@ -174,26 +164,15 @@
#endif
#endif
#endif
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
-#define HAVE_TLSV1_X
-#endif
-
-#if !defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION) \
- && OPENSSL_VERSION_NUMBER < 0x00908000L
-#define OPENSSL_NO_COMP
-#endif
-
-/* SRP support came in OpenSSL 1.0.1 */
-#ifndef OPENSSL_NO_SRP
-#ifdef SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB
+/* Secure Remote Password */
+#if !defined(OPENSSL_NO_SRP) && defined(SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB)
+#define HAVE_SRP
#include <openssl/srp.h>
-#else
-#define OPENSSL_NO_SRP
-#endif
#endif
+#endif /* !defined(OPENSSL_NO_TLSEXT) && defined(SSL_set_tlsext_host_name) */
+
/* mod_ssl headers */
#include "ssl_util_ssl.h"
@@ -287,7 +266,7 @@ typedef int ssl_algo_t;
#define SSL_ALGO_UNKNOWN (0)
#define SSL_ALGO_RSA (1<<0)
#define SSL_ALGO_DSA (1<<1)
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
#define SSL_ALGO_ECC (1<<2)
#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC)
#else
@@ -296,29 +275,13 @@ typedef int ssl_algo_t;
#define SSL_AIDX_RSA (0)
#define SSL_AIDX_DSA (1)
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
#define SSL_AIDX_ECC (2)
#define SSL_AIDX_MAX (3)
#else
#define SSL_AIDX_MAX (2)
#endif
-
-/**
- * Define IDs for the temporary RSA keys and DH params
- */
-
-#define SSL_TMP_KEY_RSA_512 (0)
-#define SSL_TMP_KEY_RSA_1024 (1)
-#define SSL_TMP_KEY_DH_512 (2)
-#define SSL_TMP_KEY_DH_1024 (3)
-#ifndef OPENSSL_NO_EC
-#define SSL_TMP_KEY_EC_256 (4)
-#define SSL_TMP_KEY_MAX (5)
-#else
-#define SSL_TMP_KEY_MAX (4)
-#endif
-
/**
* Define the SSL options
*/
@@ -534,7 +497,6 @@ typedef struct {
apr_global_mutex_t *pMutex;
apr_array_header_t *aRandSeed;
apr_hash_t *tVHostKeys;
- void *pTmpKeys[SSL_TMP_KEY_MAX];
/* Two hash tables of pointers to ssl_asn1_t structures. The
* structures are used to store certificates and private keys
@@ -656,7 +618,7 @@ typedef struct {
const char *stapling_force_url;
#endif
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
char *srp_vfile;
char *srp_unknown_user_seed;
SRP_VBASE *srp_vbase;
@@ -688,7 +650,7 @@ struct SSLSrvConfigRec {
ssl_enabled_t proxy_ssl_check_peer_expire;
ssl_enabled_t proxy_ssl_check_peer_cn;
ssl_enabled_t proxy_ssl_check_peer_name;
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
ssl_enabled_t strict_sni_vhost_check;
#endif
#ifdef HAVE_FIPS
@@ -792,7 +754,7 @@ 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);
-#ifndef OPENSSL_NO_SRP
+#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);
#endif
@@ -823,11 +785,7 @@ extern const authz_provider ssl_authz_provider_require_ssl;
extern const authz_provider ssl_authz_provider_verify_client;
/** OpenSSL callbacks */
-RSA *ssl_callback_TmpRSA(SSL *, int, int);
DH *ssl_callback_TmpDH(SSL *, int, int);
-#ifndef OPENSSL_NO_EC
-EC_KEY *ssl_callback_TmpECDH(SSL *, int, int);
-#endif
int ssl_callback_SSLVerify(int, X509_STORE_CTX *);
int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *);
int ssl_callback_proxy_cert(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
@@ -835,7 +793,7 @@ int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *);
SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
void ssl_callback_Info(const SSL *, int, int);
-#ifndef OPENSSL_NO_TLSEXT
+#ifdef HAVE_TLSEXT
int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
#endif
#ifdef HAVE_TLS_SESSION_TICKETS
@@ -873,7 +831,7 @@ void modssl_init_stapling(server_rec *, apr_pool_t *, apr_pool_t *, mods
void ssl_stapling_ex_init(void);
int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x);
#endif
-#ifndef OPENSSL_NO_SRP
+#ifdef HAVE_SRP
int ssl_callback_SRPServerParams(SSL *, int *, void *);
#endif
@@ -906,8 +864,10 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r);
void ssl_pphrase_Handle(server_rec *, apr_pool_t *);
/** Diffie-Hellman Parameter Support */
-DH *ssl_dh_GetTmpParam(int);
-DH *ssl_dh_GetParamFromFile(char *);
+DH *ssl_dh_GetParamFromFile(const char *);
+#ifdef HAVE_ECC
+EC_GROUP *ssl_ec_GetParamFromFile(const char *);
+#endif
unsigned char *ssl_asn1_table_set(apr_hash_t *table,
const char *key,
diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c
index d32f8e1d..bfed6e7c 100644
--- a/modules/ssl/ssl_scache.c
+++ b/modules/ssl/ssl_scache.c
@@ -148,7 +148,7 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen,
SSLModConfigRec *mc = myModConfig(s);
unsigned char dest[SSL_SESSION_MAX_DER];
unsigned int destlen = SSL_SESSION_MAX_DER;
- MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr;
+ const unsigned char *ptr;
apr_status_t rv;
if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) {
diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
index 475fe4d2..d2122784 100644
--- a/modules/ssl/ssl_util.c
+++ b/modules/ssl/ssl_util.c
@@ -151,7 +151,7 @@ ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
case EVP_PKEY_DSA:
t = SSL_ALGO_DSA;
break;
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
case EVP_PKEY_EC:
t = SSL_ALGO_ECC;
break;
@@ -177,7 +177,7 @@ char *ssl_util_algotypestr(ssl_algo_t t)
case SSL_ALGO_DSA:
cp = "DSA";
break;
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
case SSL_ALGO_ECC:
cp = "ECC";
break;
@@ -253,7 +253,7 @@ void ssl_asn1_table_unset(apr_hash_t *table,
apr_hash_set(table, key, klen, NULL);
}
-#ifndef OPENSSL_NO_EC
+#ifdef HAVE_ECC
static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"};
#else
static const char *ssl_asn1_key_types[] = {"RSA", "DSA"};
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
index a8c36adb..9f4cfa2c 100644
--- a/modules/ssl/ssl_util_ssl.c
+++ b/modules/ssl/ssl_util_ssl.c
@@ -483,6 +483,38 @@ BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp,
/* _________________________________________________________________
**
+** Custom (EC)DH parameter support
+** _________________________________________________________________
+*/
+
+DH *ssl_dh_GetParamFromFile(const char *file)
+{
+ DH *dh = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(file, "r")) == NULL)
+ return NULL;
+ dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return (dh);
+}
+
+#ifdef HAVE_ECC
+EC_GROUP *ssl_ec_GetParamFromFile(const char *file)
+{
+ EC_GROUP *group = NULL;
+ BIO *bio;
+
+ if ((bio = BIO_new_file(file, "r")) == NULL)
+ return NULL;
+ group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return (group);
+}
+#endif
+
+/* _________________________________________________________________
+**
** Extra Server Certificate Chain Support
** _________________________________________________________________
*/
diff --git a/modules/test/mod_optional_hook_export.h b/modules/test/mod_optional_hook_export.h
index 7af68620..223f5914 100644
--- a/modules/test/mod_optional_hook_export.h
+++ b/modules/test/mod_optional_hook_export.h
@@ -15,7 +15,7 @@
*/
#ifndef MOD_OPTIONAL_HOOK_EXPORT_H
-#define MOD_OPTOPNAL_HOOK_EXPORT_H
+#define MOD_OPTIONAL_HOOK_EXPORT_H
#include "ap_config.h"