diff options
| author | Arno Töll <arno@debian.org> | 2012-10-20 02:58:14 +0200 |
|---|---|---|
| committer | Arno Töll <arno@debian.org> | 2012-10-20 02:58:14 +0200 |
| commit | 5c4fba3ffbe778bdffe10a93d04821579601a020 (patch) | |
| tree | 91be9a7f99d3988ba48b0a619479aa46a3234191 /modules | |
| parent | 8f9c15530d0bc387af114619b3ff3f930eb23d3c (diff) | |
| download | apache2-upstream/2.4.3.tar.gz | |
Imported Upstream version 2.4.3upstream/2.4.3
Diffstat (limited to 'modules')
69 files changed, 1230 insertions, 781 deletions
diff --git a/modules/NWGNUmakefile b/modules/NWGNUmakefile index b929d01a..0ec061ef 100644 --- a/modules/NWGNUmakefile +++ b/modules/NWGNUmakefile @@ -13,8 +13,12 @@ include $(AP_WORK)/build/NWGNUenvironment.inc ifeq "$(wildcard $(APRUTIL)/include/apr_ldap.h)" "$(APRUTIL)/include/apr_ldap.h" WITH_LDAP = $(shell $(AWK) '/^\#define APR_HAS_LDAP /{print $$3}' $(APRUTIL)/include/apr_ldap.h) else +ifeq "$(MAKECMDGOALS)" "clean" +WITH_LDAP = 1 +else WITH_LDAP = 0 endif +endif # If USE_STDSOCKETS is defined we allways build mod_ssl ifdef USE_STDSOCKETS diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 460619b0..65183160 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -267,26 +267,17 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) { unsigned long idx; apr_status_t sts; - const char *tempdir; /* set up client list */ - sts = apr_temp_dir_get(&tempdir, ctx); - if (APR_SUCCESS != sts) { - ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, APLOGNO(01761) - "Failed to find temporary directory"); - log_error_and_cleanup("failed to find temp dir", sts, s); - return HTTP_INTERNAL_SERVER_ERROR; - } - /* Create the shared memory segment */ /* * Create a unique filename using our pid. This information is * stashed in the global variable so the children inherit it. */ - client_shm_filename = apr_psprintf(ctx, "%s/authdigest_shm.%"APR_PID_T_FMT, tempdir, - getpid()); + client_shm_filename = ap_runtime_dir_relative(ctx, "authdigest_shm"); + client_shm_filename = ap_append_pid(ctx, client_shm_filename, "."); /* Now create that segment */ sts = apr_shm_create(&client_shm, shmem_size, diff --git a/modules/aaa/mod_authn_dbd.c b/modules/aaa/mod_authn_dbd.c index 5819abd4..db5b05f6 100644 --- a/modules/aaa/mod_authn_dbd.c +++ b/modules/aaa/mod_authn_dbd.c @@ -100,6 +100,7 @@ static authn_status authn_dbd_password(request_rec *r, const char *user, apr_dbd_prepared_t *statement; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; + int ret; authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config, &authn_dbd_module); @@ -124,11 +125,12 @@ static authn_status authn_dbd_password(request_rec *r, const char *user, "AuthDBDUserPWQuery with the key '%s'", conf->user); return AUTH_GENERAL_ERROR; } - if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, statement, - 0, user, NULL) != 0) { + if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, + statement, 0, user, NULL) != 0)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01656) "Query execution error looking up '%s' " - "in database", user); + "in database [%s]", + user, apr_dbd_error(dbd->driver, dbd->handle, ret)); return AUTH_GENERAL_ERROR; } for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); @@ -193,6 +195,7 @@ static authn_status authn_dbd_realm(request_rec *r, const char *user, apr_dbd_prepared_t *statement; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; + int ret; authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config, &authn_dbd_module); @@ -215,11 +218,13 @@ static authn_status authn_dbd_realm(request_rec *r, const char *user, "AuthDBDUserRealmQuery with the key '%s'", conf->realm); return AUTH_GENERAL_ERROR; } - if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, statement, - 0, user, realm, NULL) != 0) { + if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, + statement, 0, user, realm, NULL) != 0)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01661) "Query execution error looking up '%s:%s' " - "in database", user, realm); + "in database [%s]", + user, realm, + apr_dbd_error(dbd->driver, dbd->handle, ret)); return AUTH_GENERAL_ERROR; } for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); diff --git a/modules/aaa/mod_authnz_ldap.c b/modules/aaa/mod_authnz_ldap.c index 689d5b76..d55b57f5 100644 --- a/modules/aaa/mod_authnz_ldap.c +++ b/modules/aaa/mod_authnz_ldap.c @@ -870,6 +870,7 @@ static authz_status ldapgroup_check_authorization(request_rec *r, "membership in \"%s\"", t); + /* PR52464 exhaust attrs in base group before checking subgroups */ for (i = 0; i < sec->groupattr->nelts; i++) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01714) "auth_ldap authorize: require group: testing for %s: " @@ -879,64 +880,62 @@ static authz_status ldapgroup_check_authorization(request_rec *r, result = util_ldap_cache_compare(r, ldc, sec->url, t, ent[i].name, sec->group_attrib_is_dn ? req->dn : req->user); - switch(result) { - case LDAP_COMPARE_TRUE: { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01715) - "auth_ldap authorize: require group: " - "authorization successful (attribute %s) " - "[%s][%d - %s]", - ent[i].name, ldc->reason, result, - ldap_err2string(result)); - set_request_vars(r, LDAP_AUTHZ); - return AUTHZ_GRANTED; - } - case LDAP_NO_SUCH_ATTRIBUTE: - case LDAP_COMPARE_FALSE: { - /* nested groups need searches and compares, so grab a new handle */ - authnz_ldap_cleanup_connection_close(ldc); - apr_pool_cleanup_kill(r->pool, ldc,authnz_ldap_cleanup_connection_close); - - ldc = get_connection_for_authz(r, LDAP_COMPARE_AND_SEARCH); - apr_pool_cleanup_register(r->pool, ldc, - authnz_ldap_cleanup_connection_close, - apr_pool_cleanup_null); - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01716) - "auth_ldap authorise: require group \"%s\": " - "failed [%s][%d - %s], checking sub-groups", - t, ldc->reason, result, ldap_err2string(result)); - - result = util_ldap_cache_check_subgroups(r, ldc, sec->url, t, ent[i].name, - sec->group_attrib_is_dn ? req->dn : req->user, - sec->sgAttributes[0] ? sec->sgAttributes : default_attributes, - sec->subgroupclasses, - 0, sec->maxNestingDepth); - if(result == LDAP_COMPARE_TRUE) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01717) - "auth_ldap authorise: require group " - "(sub-group): authorisation successful " - "(attribute %s) [%s][%d - %s]", - ent[i].name, ldc->reason, result, - ldap_err2string(result)); - set_request_vars(r, LDAP_AUTHZ); - return AUTHZ_GRANTED; - } - else { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01718) - "auth_ldap authorise: require group " - "(sub-group) \"%s\": authorisation failed " - "[%s][%d - %s]", - t, ldc->reason, result, - ldap_err2string(result)); - } - break; - } - default: { + if (result == LDAP_COMPARE_TRUE) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01715) + "auth_ldap authorize: require group: " + "authorization successful (attribute %s) " + "[%s][%d - %s]", + ent[i].name, ldc->reason, result, + ldap_err2string(result)); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01719) "auth_ldap authorize: require group \"%s\": " - "authorization failed [%s][%d - %s]", - t, ldc->reason, result, ldap_err2string(result)); - } + "didn't match with attr %s [%s][%d - %s]", + t, ldc->reason, ent[i].name, result, + ldap_err2string(result)); + } + } + + for (i = 0; i < sec->groupattr->nelts; i++) { + /* nested groups need searches and compares, so grab a new handle */ + authnz_ldap_cleanup_connection_close(ldc); + apr_pool_cleanup_kill(r->pool, ldc,authnz_ldap_cleanup_connection_close); + + ldc = get_connection_for_authz(r, LDAP_COMPARE_AND_SEARCH); + apr_pool_cleanup_register(r->pool, ldc, + authnz_ldap_cleanup_connection_close, + apr_pool_cleanup_null); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01716) + "auth_ldap authorise: require group \"%s\": " + "failed [%s][%d - %s], checking sub-groups", + t, ldc->reason, result, ldap_err2string(result)); + + result = util_ldap_cache_check_subgroups(r, ldc, sec->url, t, ent[i].name, + sec->group_attrib_is_dn ? req->dn : req->user, + sec->sgAttributes[0] ? sec->sgAttributes : default_attributes, + sec->subgroupclasses, + 0, sec->maxNestingDepth); + if (result == LDAP_COMPARE_TRUE) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01717) + "auth_ldap authorise: require group " + "(sub-group): authorisation successful " + "(attribute %s) [%s][%d - %s]", + ent[i].name, ldc->reason, result, + ldap_err2string(result)); + set_request_vars(r, LDAP_AUTHZ); + return AUTHZ_GRANTED; + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01718) + "auth_ldap authorise: require group " + "(sub-group) \"%s\": didn't match with attr %s " + "[%s][%d - %s]", + t, ldc->reason, ent[i].name, result, + ldap_err2string(result)); } } diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c index fb286e20..9b7173c8 100644 --- a/modules/aaa/mod_authz_core.c +++ b/modules/aaa/mod_authz_core.c @@ -221,6 +221,14 @@ static authz_status authz_alias_check_authorization(request_rec *r, r->per_dir_config = orig_dir_config; } + else { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02305) + "no alias provider found for '%s' (BUG?)", + provider_name); + } + } + else { + ap_assert(provider_name != NULL); } return ret; @@ -305,6 +313,14 @@ static const char *authz_require_alias_section(cmd_parms *cmd, void *mconfig, "Unknown Authz provider: %s", provider_name); } + if (prvdraliasrec->provider->parse_require_line) { + const char *err = prvdraliasrec->provider->parse_require_line(cmd, + provider_args, &prvdraliasrec->provider_parsed_args); + if (err) + return apr_psprintf(cmd->pool, + "Can't parse 'Require %s %s': %s", + provider_name, provider_args, err); + } authcfg = ap_get_module_config(cmd->server->module_config, &authz_core_module); @@ -397,8 +413,14 @@ static const char *add_authz_provider(cmd_parms *cmd, void *config, section->limited = cmd->limited; if (section->provider->parse_require_line) { - const char *err = section->provider->parse_require_line(cmd, args, - §ion->provider_parsed_args); + const char *err; + apr_pool_userdata_setn(section->provider_name, + AUTHZ_PROVIDER_NAME_NOTE, + apr_pool_cleanup_null, + cmd->temp_pool); + err = section->provider->parse_require_line(cmd, args, + §ion->provider_parsed_args); + if (err) return err; } @@ -607,12 +629,9 @@ static int authz_core_check_section(apr_pool_t *p, server_rec *s, if (ret != OK) { ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, APR_SUCCESS, s, APLOGNO(01624) - "%s", - apr_pstrcat(p, (is_conf - ? "<Directory>, <Location>, or similar" - : format_authz_command(p, section)), - " directive contains only negative " - "authorization directives", NULL)); + "%s directive contains only negative authorization directives", + is_conf ? "<Directory>, <Location>, or similar" + : format_authz_command(p, section)); } return ret; @@ -1015,36 +1034,74 @@ static const authz_provider authz_method_provider = &method_parse_config, }; -static authz_status expr_check_authorization(request_rec *r, - const char *require_line, - const void *parsed_require_line) -{ - const char *err = NULL; - const ap_expr_info_t *expr = parsed_require_line; - int rc = ap_expr_exec(r, expr, &err); +/* + * expr authz provider + */ - if (rc <= 0) - /* XXX: real error handling? */ - return AUTHZ_DENIED; - else - return AUTHZ_GRANTED; +#define REQUIRE_EXPR_NOTE "Require_expr_info" +struct require_expr_info { + ap_expr_info_t *expr; + int want_user; +}; + +static int expr_lookup_fn(ap_expr_lookup_parms *parms) +{ + if (parms->type == AP_EXPR_FUNC_VAR + && strcasecmp(parms->name, "REMOTE_USER") == 0) { + struct require_expr_info *info; + apr_pool_userdata_get((void**)&info, REQUIRE_EXPR_NOTE, parms->ptemp); + AP_DEBUG_ASSERT(info != NULL); + info->want_user = 1; + } + return ap_expr_lookup_default(parms); } static const char *expr_parse_config(cmd_parms *cmd, const char *require_line, const void **parsed_require_line) { const char *expr_err = NULL; - ap_expr_info_t *expr = ap_expr_parse_cmd(cmd, require_line, 0, &expr_err, - NULL); + struct require_expr_info *info = apr_pcalloc(cmd->pool, sizeof(*info)); + + apr_pool_userdata_setn(info, REQUIRE_EXPR_NOTE, apr_pool_cleanup_null, + cmd->temp_pool); + info->expr = ap_expr_parse_cmd(cmd, require_line, 0, &expr_err, + expr_lookup_fn); if (expr_err) - return "Cannot parse expression in require line"; + return apr_pstrcat(cmd->temp_pool, + "Cannot parse expression in require line: ", + expr_err, NULL); - *parsed_require_line = expr; + *parsed_require_line = info; return NULL; } +static authz_status expr_check_authorization(request_rec *r, + const char *require_line, + const void *parsed_require_line) +{ + const char *err = NULL; + const struct require_expr_info *info = parsed_require_line; + int rc = ap_expr_exec(r, info->expr, &err); + + if (rc < 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02320) + "Error evaluating expression in 'Require expr': %s", + err); + return AUTHZ_GENERAL_ERROR; + } + else if (rc == 0) { + if (info->want_user) + return AUTHZ_DENIED_NO_USER; + else + return AUTHZ_DENIED; + } + else { + return AUTHZ_GRANTED; + } +} + static const authz_provider authz_expr_provider = { &expr_check_authorization, diff --git a/modules/aaa/mod_authz_dbd.c b/modules/aaa/mod_authz_dbd.c index 59ca2b34..86d3b561 100644 --- a/modules/aaa/mod_authz_dbd.c +++ b/modules/aaa/mod_authz_dbd.c @@ -162,8 +162,8 @@ static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg, "authz_dbd: no redirect query!"); /* OK, this is non-critical; we can just not-redirect */ } - else if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, - query, 0, r->user, NULL) == 0) { + else if ((rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, + &res, query, 0, r->user, NULL) == 0)) { for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); rv != -1; rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { diff --git a/modules/arch/win32/mod_isapi.c b/modules/arch/win32/mod_isapi.c index d77ff688..f6cb99a2 100644 --- a/modules/arch/win32/mod_isapi.c +++ b/modules/arch/win32/mod_isapi.c @@ -894,7 +894,7 @@ static int APR_THREAD_FUNC regfnServerSupportFunction(isapi_cid *cid, } /* Reset the method to GET */ - r->method = apr_pstrdup(r->pool, "GET"); + r->method = "GET"; r->method_number = M_GET; /* Don't let anyone think there's still data */ diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c index bad438ac..1e5098d5 100644 --- a/modules/cache/cache_util.c +++ b/modules/cache/cache_util.c @@ -172,7 +172,7 @@ cache_provider_list *cache_get_providers(request_rec *r, cache_server_conf *conf, apr_uri_t uri) { - cache_dir_conf *dconf = dconf = ap_get_module_config(r->per_dir_config, &cache_module); + cache_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &cache_module); cache_provider_list *providers = NULL; int i; diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index 720d81a5..e75f01d3 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -1655,6 +1655,9 @@ static void cache_insert_error_filter(request_rec *r) r->err_headers_out = cache->stale_handle->resp_hdrs; + ap_set_content_type(r, apr_table_get( + cache->stale_handle->resp_hdrs, "Content-Type")); + /* add a revalidation warning */ warn_head = apr_table_get(r->err_headers_out, "Warning"); if ((warn_head == NULL) || ((warn_head != NULL) diff --git a/modules/cache/mod_socache_dbm.c b/modules/cache/mod_socache_dbm.c index 70fe28bf..0d7c302b 100644 --- a/modules/cache/mod_socache_dbm.c +++ b/modules/cache/mod_socache_dbm.c @@ -53,7 +53,7 @@ struct ap_socache_instance_t { */ #define DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) -#define DEFAULT_DBM_PREFIX DEFAULT_REL_RUNTIMEDIR "/socache-dbm-" +#define DEFAULT_DBM_PREFIX "socache-dbm-" /* ### this should use apr_dbm_usednames. */ #if !defined(DBM_FILE_SUFFIX_DIR) && !defined(DBM_FILE_SUFFIX_PAG) @@ -127,7 +127,7 @@ static apr_status_t socache_dbm_init(ap_socache_instance_t *ctx, const char *path = apr_pstrcat(p, DEFAULT_DBM_PREFIX, namespace, NULL); - ctx->data_file = ap_server_root_relative(p, path); + ctx->data_file = ap_runtime_dir_relative(p, path); if (ctx->data_file == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00803) diff --git a/modules/cache/mod_socache_dc.c b/modules/cache/mod_socache_dc.c index 9739a97b..7d09408d 100644 --- a/modules/cache/mod_socache_dc.c +++ b/modules/cache/mod_socache_dc.c @@ -140,7 +140,8 @@ static apr_status_t socache_dc_remove(ap_socache_instance_t *ctx, if (!DC_CTX_remove_session(ctx->dc, id, idlen)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00745) "distributed scache 'remove' MISS"); return APR_NOTFOUND; - } else { + } + else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00746) "distributed scache 'remove' HIT"); return APR_SUCCESS; } diff --git a/modules/cache/mod_socache_shmcb.c b/modules/cache/mod_socache_shmcb.c index ff4defd3..4d4246b3 100644 --- a/modules/cache/mod_socache_shmcb.c +++ b/modules/cache/mod_socache_shmcb.c @@ -32,10 +32,14 @@ #define SHMCB_MAX_SIZE (64 * 1024 * 1024) -#define DEFAULT_SHMCB_PREFIX DEFAULT_REL_RUNTIMEDIR "/socache-shmcb-" +#define DEFAULT_SHMCB_PREFIX "socache-shmcb-" #define DEFAULT_SHMCB_SUFFIX ".cache" +#define ALIGNED_HEADER_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBHeader)) +#define ALIGNED_SUBCACHE_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBSubcache)) +#define ALIGNED_INDEX_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBIndex)) + /* * Header structure - the start of the shared-mem segment */ @@ -141,7 +145,7 @@ struct ap_socache_instance_t { * a pointer to the corresponding subcache. */ #define SHMCB_SUBCACHE(pHeader, num) \ (SHMCBSubcache *)(((unsigned char *)(pHeader)) + \ - sizeof(SHMCBHeader) + \ + ALIGNED_HEADER_SIZE + \ (num) * ((pHeader)->subcache_size)) /* This macro takes a pointer to the header and an id and returns a @@ -157,8 +161,9 @@ struct ap_socache_instance_t { /* This macro takes a pointer to a subcache and a zero-based index and returns * a pointer to the corresponding SHMCBIndex. */ #define SHMCB_INDEX(pSubcache, num) \ - ((SHMCBIndex *)(((unsigned char *)pSubcache) + \ - sizeof(SHMCBSubcache)) + num) + (SHMCBIndex *)(((unsigned char *)pSubcache) + \ + ALIGNED_SUBCACHE_SIZE + \ + (num) * ALIGNED_INDEX_SIZE) /* This macro takes a pointer to the header and a subcache and returns a * pointer to the corresponding data area. */ @@ -194,7 +199,8 @@ static void shmcb_cyclic_ntoc_memcpy(unsigned int buf_size, unsigned char *data, } } -/* A "cyclic-to-normal" memcpy. */static void shmcb_cyclic_cton_memcpy(unsigned int buf_size, unsigned char *dest, +/* A "cyclic-to-normal" memcpy. */ +static void shmcb_cyclic_cton_memcpy(unsigned int buf_size, unsigned char *dest, const unsigned char *data, unsigned int src_offset, unsigned int src_len) { @@ -341,7 +347,7 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, const char *path = apr_pstrcat(p, DEFAULT_SHMCB_PREFIX, namespace, DEFAULT_SHMCB_SUFFIX, NULL); - ctx->data_file = ap_server_root_relative(p, path); + ctx->data_file = ap_runtime_dir_relative(p, path); } /* Use anonymous shm by default, fall back on name-based. */ @@ -373,7 +379,7 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, shm_segment = apr_shm_baseaddr_get(ctx->shm); shm_segsize = apr_shm_size_get(ctx->shm); - if (shm_segsize < (5 * sizeof(SHMCBHeader))) { + if (shm_segsize < (5 * ALIGNED_HEADER_SIZE)) { /* the segment is ridiculously small, bail out */ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00820) "shared memory segment too small"); @@ -384,7 +390,7 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, " bytes of shared memory", shm_segsize); /* Discount the header */ - shm_segsize -= sizeof(SHMCBHeader); + shm_segsize -= ALIGNED_HEADER_SIZE; /* Select index size based on average object size hints, if given. */ avg_obj_size = hints && hints->avg_obj_size ? hints->avg_obj_size : 150; avg_id_len = hints && hints->avg_id_len ? hints->avg_id_len : 30; @@ -397,7 +403,8 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, "for %" APR_SIZE_T_FMT " bytes (%" APR_SIZE_T_FMT " including header), recommending %u subcaches, " "%u indexes each", shm_segsize, - shm_segsize + sizeof(SHMCBHeader), num_subcache, num_idx); + shm_segsize + ALIGNED_HEADER_SIZE, + num_subcache, num_idx); if (num_idx < 5) { /* we're still too small, bail out */ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00823) @@ -416,13 +423,14 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, header->stat_removes_miss = 0; header->subcache_num = num_subcache; /* Convert the subcache size (in bytes) to a value that is suitable for - * structure alignment on the host platform, by rounding down if necessary. - * This assumes that sizeof(unsigned long) provides an appropriate - * alignment unit. */ - header->subcache_size = ((size_t)(shm_segsize / num_subcache) & - ~(size_t)(sizeof(unsigned long) - 1)); - header->subcache_data_offset = sizeof(SHMCBSubcache) + - num_idx * sizeof(SHMCBIndex); + * structure alignment on the host platform, by rounding down if necessary. */ + header->subcache_size = (size_t)(shm_segsize / num_subcache); + if (header->subcache_size != APR_ALIGN_DEFAULT(header->subcache_size)) { + header->subcache_size = APR_ALIGN_DEFAULT(header->subcache_size) - + APR_ALIGN_DEFAULT(1); + } + header->subcache_data_offset = ALIGNED_SUBCACHE_SIZE + + num_idx * ALIGNED_INDEX_SIZE; header->subcache_data_size = header->subcache_size - header->subcache_data_offset; header->index_num = num_idx; diff --git a/modules/core/mod_so.c b/modules/core/mod_so.c index 13ecd963..6df596a9 100644 --- a/modules/core/mod_so.c +++ b/modules/core/mod_so.c @@ -143,6 +143,37 @@ static apr_status_t unload_module(void *data) return APR_SUCCESS; } +static const char *dso_load(cmd_parms *cmd, apr_dso_handle_t **modhandlep, + const char *filename, const char **used_filename) +{ + int retry = 0; + const char *fullname = ap_server_root_relative(cmd->temp_pool, filename); + char my_error[256]; + if (filename != NULL && ap_strchr_c(filename, '/') == NULL) { + /* retry on error without path to use dlopen()'s search path */ + retry = 1; + } + + if (fullname == NULL && !retry) { + return apr_psprintf(cmd->temp_pool, "Invalid %s path %s", + cmd->cmd->name, filename); + } + *used_filename = fullname; + if (apr_dso_load(modhandlep, fullname, cmd->pool) == APR_SUCCESS) { + return NULL; + } + if (retry) { + *used_filename = filename; + if (apr_dso_load(modhandlep, filename, cmd->pool) == APR_SUCCESS) + return NULL; + } + + return apr_pstrcat(cmd->temp_pool, "Cannot load ", filename, + " into server: ", + apr_dso_error(*modhandlep, my_error, sizeof(my_error)), + NULL); +} + /* * This is called for the directive LoadModule and actually loads * a shared object file into the address space of the server process. @@ -154,7 +185,7 @@ static const char *load_module(cmd_parms *cmd, void *dummy, apr_dso_handle_t *modhandle; apr_dso_handle_sym_t modsym; module *modp; - const char *szModuleFile = ap_server_root_relative(cmd->pool, filename); + const char *module_file; so_server_conf *sconf; ap_module_symbol_t *modi; ap_module_symbol_t *modie; @@ -167,11 +198,6 @@ static const char *load_module(cmd_parms *cmd, void *dummy, */ *(ap_directive_t **)dummy = NULL; - if (!szModuleFile) { - return apr_pstrcat(cmd->pool, "Invalid LoadModule path ", - filename, NULL); - } - /* * check for already existing module * If it already exists, we have nothing to do @@ -234,16 +260,11 @@ static const char *load_module(cmd_parms *cmd, void *dummy, /* * Load the file into the Apache address space */ - if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) { - char my_error[256]; - - return apr_pstrcat(cmd->pool, "Cannot load ", szModuleFile, - " into server: ", - apr_dso_error(modhandle, my_error, sizeof(my_error)), - NULL); - } + error = dso_load(cmd, &modhandle, filename, &module_file); + if (error) + return error; ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, cmd->pool, APLOGNO(01575) - "loaded module %s", modname); + "loaded module %s from %s", modname, module_file); /* * Retrieve the pointer to the module structure through the module name: @@ -254,7 +275,7 @@ static const char *load_module(cmd_parms *cmd, void *dummy, char my_error[256]; return apr_pstrcat(cmd->pool, "Can't locate API module structure `", - modname, "' in file ", szModuleFile, ": ", + modname, "' in file ", module_file, ": ", apr_dso_error(modhandle, my_error, sizeof(my_error)), NULL); } @@ -271,7 +292,7 @@ static const char *load_module(cmd_parms *cmd, void *dummy, "is garbled - expected signature %08lx but saw " "%08lx - perhaps this is not an Apache module DSO, " "or was compiled for a different Apache version?", - modname, szModuleFile, + modname, module_file, MODULE_MAGIC_COOKIE, modp->magic); } @@ -306,26 +327,14 @@ static const char *load_module(cmd_parms *cmd, void *dummy, static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename) { apr_dso_handle_t *handle; - const char *file; - - file = ap_server_root_relative(cmd->pool, filename); + const char *used_file, *error; - if (!file) { - return apr_pstrcat(cmd->pool, "Invalid LoadFile path ", - filename, NULL); - } - - if (apr_dso_load(&handle, file, cmd->pool) != APR_SUCCESS) { - char my_error[256]; - - return apr_pstrcat(cmd->pool, "Cannot load ", filename, - " into server: ", - apr_dso_error(handle, my_error, sizeof(my_error)), - NULL); - } + error = dso_load(cmd, &handle, filename, &used_file); + if (error) + return error; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01576) - "loaded file %s", filename); + "loaded file %s", used_file); return NULL; } diff --git a/modules/filters/NWGNUdeflate b/modules/filters/NWGNUdeflate index 579d1386..7f7204d1 100644 --- a/modules/filters/NWGNUdeflate +++ b/modules/filters/NWGNUdeflate @@ -30,6 +30,7 @@ XINCDIRS += \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(STDMOD)/ssl \ $(NWOS) \ $(EOLIST) diff --git a/modules/filters/config.m4 b/modules/filters/config.m4 index 4ef2d3a5..966f77a5 100644 --- a/modules/filters/config.m4 +++ b/modules/filters/config.m4 @@ -16,7 +16,13 @@ APACHE_MODULE(reflector, Reflect request through the output filter stack, , , ) APACHE_MODULE(substitute, response content rewrite-like filtering, , , most) sed_obj="mod_sed.lo sed0.lo sed1.lo regexp.lo" -APACHE_MODULE(sed, filter request and/or response bodies through sed, $sed_obj, , most) +APACHE_MODULE(sed, filter request and/or response bodies through sed, $sed_obj, , most, [ + if test "x$enable_sed" = "xshared"; then + # The only symbol which needs to be exported is the module + # structure, so ask libtool to hide libsed internals: + APR_ADDTO(MOD_SED_LDADD, [-export-symbols-regex sed_module]) + fi +]) if test "$ac_cv_ebcdic" = "yes"; then # mod_charset_lite can be very useful on an ebcdic system, diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c index 0876cb4e..48d37b13 100644 --- a/modules/filters/mod_deflate.c +++ b/modules/filters/mod_deflate.c @@ -45,6 +45,7 @@ #include "http_request.h" #define APR_WANT_STRFUNC #include "apr_want.h" +#include "mod_ssl.h" #include "zlib.h" @@ -83,6 +84,7 @@ static const char deflate_magic[2] = { '\037', '\213' }; #define DEFAULT_MEMLEVEL 9 #define DEFAULT_BUFFERSIZE 8096 +static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *mod_deflate_ssl_var = NULL; /* Check whether a request is gzipped, so we can un-gzip it. * If a request has multiple encodings, we need the gzip @@ -419,6 +421,18 @@ static void deflate_check_etag(request_rec *r, const char *transform) } } +static int have_ssl_compression(request_rec *r) +{ + const char *comp; + if (mod_deflate_ssl_var == NULL) + return 0; + comp = mod_deflate_ssl_var(r->pool, r->server, r->connection, r, + "SSL_COMPRESS_METHOD"); + if (comp == NULL || *comp == '\0' || strcmp(comp, "NULL") == 0) + return 0; + return 1; +} + static apr_status_t deflate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { @@ -448,6 +462,14 @@ static apr_status_t deflate_out_filter(ap_filter_t *f, char *token; const char *encoding; + if (have_ssl_compression(r)) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + "Compression enabled at SSL level; not compressing " + "at HTTP level."); + ap_remove_output_filter(f); + return ap_pass_brigade(f->next, bb); + } + /* We have checked above that bb is not empty */ e = APR_BRIGADE_LAST(bb); if (APR_BUCKET_IS_EOS(e)) { @@ -1474,6 +1496,14 @@ static apr_status_t inflate_out_filter(ap_filter_t *f, return APR_SUCCESS; } +static int mod_deflate_post_config(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ + mod_deflate_ssl_var = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); + return OK; +} + + #define PROTO_FLAGS AP_FILTER_PROTO_CHANGE|AP_FILTER_PROTO_CHANGE_LENGTH static void register_hooks(apr_pool_t *p) { @@ -1483,6 +1513,7 @@ static void register_hooks(apr_pool_t *p) AP_FTYPE_RESOURCE-1); ap_register_input_filter(deflateFilterName, deflate_in_filter, NULL, AP_FTYPE_CONTENT_SET); + ap_hook_post_config(mod_deflate_post_config, NULL, NULL, APR_HOOK_MIDDLE); } static const command_rec deflate_filter_cmds[] = { diff --git a/modules/filters/mod_deflate.dsp b/modules/filters/mod_deflate.dsp index 06ce9683..f990c976 100644 --- a/modules/filters/mod_deflate.dsp +++ b/modules/filters/mod_deflate.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c -# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/zlib" /D "NDEBUG" /D "ZLIB_DLL" /D "HAVE_ZUTIL_H" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_deflate_src" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../ssl" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/zlib" /D "NDEBUG" /D "ZLIB_DLL" /D "HAVE_ZUTIL_H" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_deflate_src" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" @@ -75,7 +75,7 @@ PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).ma # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c -# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/zlib" /D "_DEBUG" /D "ZLIB_DLL" /D "HAVE_ZUTIL_H" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_deflate_src" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../ssl" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/zlib" /D "_DEBUG" /D "ZLIB_DLL" /D "HAVE_ZUTIL_H" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_deflate_src" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" diff --git a/modules/filters/mod_ext_filter.c b/modules/filters/mod_ext_filter.c index 76ddbc8a..fc1ed2ce 100644 --- a/modules/filters/mod_ext_filter.c +++ b/modules/filters/mod_ext_filter.c @@ -66,7 +66,7 @@ typedef struct ef_ctx_t { apr_procattr_t *procattr; ef_dir_t *dc; ef_filter_t *filter; - int noop; + int noop, hit_eos; #if APR_FILES_AS_SOCKETS apr_pollset_t *pollset; #endif @@ -827,6 +827,7 @@ static int ef_unified_filter(ap_filter_t *f, apr_bucket_brigade *bb) if (eos) { b = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); + ctx->hit_eos = 1; } return APR_SUCCESS; @@ -910,6 +911,14 @@ static apr_status_t ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, ctx = f->ctx; } + if (ctx->hit_eos) { + /* Match behaviour of HTTP_IN if filter is re-invoked after + * hitting EOS: give back another EOS. */ + apr_bucket *e = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + return APR_SUCCESS; + } + if (ctx->noop) { ap_remove_input_filter(f); return ap_get_brigade(f->next, bb, mode, block, readbytes); diff --git a/modules/filters/mod_filter.c b/modules/filters/mod_filter.c index 7dd7db1a..67cfd6bb 100644 --- a/modules/filters/mod_filter.c +++ b/modules/filters/mod_filter.c @@ -165,13 +165,21 @@ static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) const char **type = provider->types; size_t len = strcspn(r->content_type, "; \t"); AP_DEBUG_ASSERT(type != NULL); + ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, + "Content-Type '%s' ...", r->content_type); while (*type) { /* Handle 'content-type;charset=...' correctly */ if (strncmp(*type, r->content_type, len) == 0 && (*type)[len] == '\0') { + ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, + "... matched '%s'", *type); match = 1; break; } + else { + ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, + "... did not match '%s'", *type); + } type++; } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, @@ -179,6 +187,11 @@ static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) provider->frec->name, match ? "matched" : "did not match"); } + else { + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, + "Content-Type condition for '%s' did not match: " + "no Content-Type", provider->frec->name); + } if (match) { /* condition matches this provider */ diff --git a/modules/filters/sed1.c b/modules/filters/sed1.c index ddca3bdb..739e1ce9 100644 --- a/modules/filters/sed1.c +++ b/modules/filters/sed1.c @@ -25,7 +25,7 @@ #include "apr_strings.h" #include "regexp.h" -char *trans[040] = { +static const char *const trans[040] = { "\\01", "\\02", "\\03", @@ -58,7 +58,7 @@ char *trans[040] = { "\\36", "\\37" }; -char rub[] = {"\\177"}; +static const char rub[] = {"\\177"}; extern int sed_step(char *p1, char *p2, int circf, step_vars_storage *vars); static int substitute(sed_eval_t *eval, sed_reptr_t *ipc, @@ -692,7 +692,8 @@ static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc, step_vars_storage *step_vars) { int i; - char *p1, *p2, *p3; + char *p1, *p2; + const char *p3; int length; char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */ apr_status_t rv = APR_SUCCESS; diff --git a/modules/generators/mod_asis.c b/modules/generators/mod_asis.c index 1fc14389..c947e303 100644 --- a/modules/generators/mod_asis.c +++ b/modules/generators/mod_asis.c @@ -70,7 +70,7 @@ static int asis_handler(request_rec *r) /* This redirect needs to be a GET no matter what the original * method was. */ - r->method = apr_pstrdup(r->pool, "GET"); + r->method = "GET"; r->method_number = M_GET; ap_internal_redirect_handler(location, r); diff --git a/modules/generators/mod_cgi.c b/modules/generators/mod_cgi.c index 385bb364..a6096545 100644 --- a/modules/generators/mod_cgi.c +++ b/modules/generators/mod_cgi.c @@ -993,7 +993,7 @@ static int cgi_handler(request_rec *r) /* This redirect needs to be a GET no matter what the original * method was. */ - r->method = apr_pstrdup(r->pool, "GET"); + r->method = "GET"; r->method_number = M_GET; /* We already read the message body (if any), so don't allow diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c index 1e4aaf67..1155bd75 100644 --- a/modules/generators/mod_cgid.c +++ b/modules/generators/mod_cgid.c @@ -135,7 +135,7 @@ static int is_scriptaliased(request_rec *r) #define DEFAULT_LOGBYTES 10385760 #define DEFAULT_BUFBYTES 1024 -#define DEFAULT_SOCKET DEFAULT_REL_RUNTIMEDIR "/cgisock" +#define DEFAULT_SOCKET "cgisock" #define CGI_REQ 1 #define SSI_REQ 2 @@ -910,6 +910,7 @@ static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, procnew->err = procnew->in = procnew->out = NULL; apr_pool_userdata_set((const void *)procnew, userdata_key, apr_pool_cleanup_null, main_server->process->pool); + return ret; } else { procnew = data; @@ -922,7 +923,7 @@ static int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, total_modules++; parent_pid = getpid(); - tmp_sockname = ap_server_root_relative(p, sockname); + tmp_sockname = ap_runtime_dir_relative(p, sockname); if (strlen(tmp_sockname) > sizeof(server_addr->sun_path) - 1) { tmp_sockname[sizeof(server_addr->sun_path)] = '\0'; ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, APLOGNO(01254) @@ -1016,7 +1017,7 @@ static const char *set_script_socket(cmd_parms *cmd, void *dummy, const char *ar /* Make sure the pid is appended to the sockname */ sockname = ap_append_pid(cmd->pool, arg, "."); - sockname = ap_server_root_relative(cmd->pool, sockname); + sockname = ap_runtime_dir_relative(cmd->pool, sockname); if (!sockname) { return apr_pstrcat(cmd->pool, "Invalid ScriptSock path", @@ -1593,7 +1594,7 @@ static int cgid_handler(request_rec *r) /* This redirect needs to be a GET no matter what the original * method was. */ - r->method = apr_pstrdup(r->pool, "GET"); + r->method = "GET"; r->method_number = M_GET; /* We already read the message body (if any), so don't allow diff --git a/modules/generators/mod_info.c b/modules/generators/mod_info.c index 360290c7..75c37782 100644 --- a/modules/generators/mod_info.c +++ b/modules/generators/mod_info.c @@ -62,6 +62,7 @@ #include "util_script.h" #include "ap_mpm.h" #include "mpm_common.h" +#include "ap_provider.h" #include <stdio.h> #include <stdlib.h> @@ -688,6 +689,57 @@ static int show_active_hooks(request_rec * r) return 0; } +static int cmp_provider_groups(const void *a_, const void *b_) +{ + const ap_list_provider_groups_t *a = a_, *b = b_; + int ret = strcmp(a->provider_group, b->provider_group); + if (!ret) + ret = strcmp(a->provider_version, b->provider_version); + return ret; +} + +static int cmp_provider_names(const void *a_, const void *b_) +{ + const ap_list_provider_names_t *a = a_, *b = b_; + return strcmp(a->provider_name, b->provider_name); +} + +static void show_providers(request_rec *r) +{ + apr_array_header_t *groups = ap_list_provider_groups(r->pool); + ap_list_provider_groups_t *group; + apr_array_header_t *names; + ap_list_provider_names_t *name; + int i,j; + const char *cur_group = NULL; + + qsort(groups->elts, groups->nelts, sizeof(ap_list_provider_groups_t), + cmp_provider_groups); + ap_rputs("<h2><a name=\"providers\">Providers</a></h2>\n<dl>", r); + + for (i = 0; i < groups->nelts; i++) { + group = &APR_ARRAY_IDX(groups, i, ap_list_provider_groups_t); + if (!cur_group || strcmp(cur_group, group->provider_group) != 0) { + if (cur_group) + ap_rputs("\n</dt>\n", r); + cur_group = group->provider_group; + ap_rprintf(r, "<dt><strong>%s</strong> (version <tt>%s</tt>):" + "\n <br />\n", cur_group, group->provider_version); + } + names = ap_list_provider_names(r->pool, group->provider_group, + group->provider_version); + qsort(names->elts, names->nelts, sizeof(ap_list_provider_names_t), + cmp_provider_names); + for (j = 0; j < names->nelts; j++) { + name = &APR_ARRAY_IDX(names, j, ap_list_provider_names_t); + ap_rprintf(r, "<tt> %s</tt><br/>", name->provider_name); + } + } + if (cur_group) + ap_rputs("\n</dt>\n", r); + ap_rputs("</dl>\n<hr />\n", r); +} + static int cmp_module_name(const void *a_, const void *b_) { const module * const *a = a_; @@ -737,8 +789,9 @@ static int display_info(request_rec * r) ap_rputs("<dl><dt><tt>Subpages:<br />", r); ap_rputs("<a href=\"?config\">Configuration Files</a>, " "<a href=\"?server\">Server Settings</a>, " - "<a href=\"?list\">Module List</a>, " - "<a href=\"?hooks\">Active Hooks</a>", r); + "<a href=\"?list\">Module List</a>, " + "<a href=\"?hooks\">Active Hooks</a>, " + "<a href=\"?providers\">Available Providers</a>", r); ap_rputs("</tt></dt></dl><hr />", r); ap_rputs("<dl><dt><tt>Sections:<br />", r); @@ -746,7 +799,8 @@ static int display_info(request_rec * r) "<a href=\"#server\">Server Settings</a>, " "<a href=\"#startup_hooks\">Startup Hooks</a>, " "<a href=\"#request_hooks\">Request Hooks</a>, " - "<a href=\"#other_hooks\">Other Hooks</a>", r); + "<a href=\"#other_hooks\">Other Hooks</a>, " + "<a href=\"#providers\">Providers</a>", r); ap_rputs("</tt></dt></dl><hr />", r); ap_rputs("<h2><a name=\"modules\">Loaded Modules</a></h2>" @@ -772,6 +826,10 @@ static int display_info(request_rec * r) show_active_hooks(r); } + if (!r->args || !strcasecmp(r->args, "providers")) { + show_providers(r); + } + if (r->args && 0 == strcasecmp(r->args, "config")) { ap_rputs("<dl><dt><strong>Configuration:</strong>\n", r); mod_info_module_cmds(r, NULL, ap_conftree, 0, 0); diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c index ced19edb..50bcb272 100644 --- a/modules/generators/mod_status.c +++ b/modules/generators/mod_status.c @@ -582,7 +582,7 @@ static int status_handler(request_rec *r) "\"<b><code>L</code></b>\" Logging, \n" "\"<b><code>G</code></b>\" Gracefully finishing,<br /> \n" "\"<b><code>I</code></b>\" Idle cleanup of worker, \n" - "\"<b><code>.</code></b>\" Open slot with no current process,<br />\n" + "\"<b><code>.</code></b>\" Open slot with no current process<br />\n" "<p />\n", r); if (!ap_extended_status) { int j; diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 10165478..2f786123 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -62,8 +62,12 @@ APLOG_USE_MODULE(http); /* New Apache routine to map status codes into array indicies * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ... - * The number of status lines must equal the value of RESPONSE_CODES (httpd.h) - * and must be listed in order. + * The number of status lines must equal the value of + * RESPONSE_CODES (httpd.h) and must be listed in order. + * No gaps are allowed between X00 and the largest Xnn + * for any X (see ap_index_of_response). + * When adding a new code here, add a define to httpd.h + * as well. */ static const char * const status_lines[RESPONSE_CODES] = @@ -80,58 +84,81 @@ static const char * const status_lines[RESPONSE_CODES] = "205 Reset Content", "206 Partial Content", "207 Multi-Status", -#define LEVEL_300 11 + "208 Already Reported", + NULL, /* 209 */ + NULL, /* 210 */ + NULL, /* 211 */ + NULL, /* 212 */ + NULL, /* 213 */ + NULL, /* 214 */ + NULL, /* 215 */ + NULL, /* 216 */ + NULL, /* 217 */ + NULL, /* 218 */ + NULL, /* 219 */ + NULL, /* 220 */ + NULL, /* 221 */ + NULL, /* 222 */ + NULL, /* 223 */ + NULL, /* 224 */ + NULL, /* 225 */ + "226 IM Used", +#define LEVEL_300 30 "300 Multiple Choices", "301 Moved Permanently", "302 Found", "303 See Other", "304 Not Modified", "305 Use Proxy", - "306 unused", + NULL, /* 306 */ "307 Temporary Redirect", -#define LEVEL_400 19 + "308 Permanent Redirect", +#define LEVEL_400 39 "400 Bad Request", - "401 Authorization Required", + "401 Unauthorized", "402 Payment Required", "403 Forbidden", "404 Not Found", "405 Method Not Allowed", "406 Not Acceptable", "407 Proxy Authentication Required", - "408 Request Time-out", + "408 Request Timeout", "409 Conflict", "410 Gone", "411 Length Required", "412 Precondition Failed", "413 Request Entity Too Large", - "414 Request-URI Too Large", + "414 Request-URI Too Long", "415 Unsupported Media Type", "416 Requested Range Not Satisfiable", "417 Expectation Failed", - "418 unused", - "419 unused", - "420 unused", - "421 unused", + NULL, /* 418 */ + NULL, /* 419 */ + NULL, /* 420 */ + NULL, /* 421 */ "422 Unprocessable Entity", "423 Locked", "424 Failed Dependency", - /* This is a hack, but it is required for ap_index_of_response - * to work with 426. - */ - "425 No code", + NULL, /* 425 */ "426 Upgrade Required", -#define LEVEL_500 46 + NULL, /* 427 */ + "428 Precondition Required", + "429 Too Many Requests", + NULL, /* 430 */ + "431 Request Header Fields Too Large", +#define LEVEL_500 71 "500 Internal Server Error", - "501 Method Not Implemented", + "501 Not Implemented", "502 Bad Gateway", - "503 Service Temporarily Unavailable", - "504 Gateway Time-out", + "503 Service Unavailable", + "504 Gateway Timeout", "505 HTTP Version Not Supported", "506 Variant Also Negotiates", "507 Insufficient Storage", - "508 unused", - "509 unused", - "510 Not Extended" + "508 Loop Detected", + NULL, /* 509 */ + "510 Not Extended", + "511 Network Authentication Required" }; APR_HOOK_STRUCT( @@ -739,6 +766,7 @@ AP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum) * decides to define a high-numbered code before the lower numbers. * If that sad event occurs, replace the code below with a linear search * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1]; + * or use NULL to fill the gaps. */ AP_DECLARE(int) ap_index_of_response(int status) { @@ -754,7 +782,7 @@ AP_DECLARE(int) ap_index_of_response(int status) status -= 100; if (status < 100) { pos = (status + shortcut[i]); - if (pos < shortcut[i + 1]) { + if (pos < shortcut[i + 1] && status_lines[pos] != NULL) { return pos; } else { @@ -771,11 +799,9 @@ AP_DECLARE(const char *) ap_get_status_line(int status) } /* Build the Allow field-value from the request handler method mask. - * Note that we always allow TRACE, since it is handled below. */ static char *make_allow(request_rec *r) { - char *list; apr_int64_t mask; apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *)); apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry); @@ -803,25 +829,15 @@ static char *make_allow(request_rec *r) if (conf->trace_enable != AP_TRACE_DISABLE) *(const char **)apr_array_push(allow) = "TRACE"; - list = apr_array_pstrcat(r->pool, allow, ','); - /* ### this is rather annoying. we should enforce registration of ### these methods */ if ((mask & (AP_METHOD_BIT << M_INVALID)) && (r->allowed_methods->method_list != NULL) && (r->allowed_methods->method_list->nelts != 0)) { - int i; - char **xmethod = (char **) r->allowed_methods->method_list->elts; - - /* - * Append all of the elements of r->allowed_methods->method_list - */ - for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) { - list = apr_pstrcat(r->pool, list, ",", xmethod[i], NULL); - } + apr_array_cat(allow, r->allowed_methods->method_list); } - return list; + return apr_array_pstrcat(r->pool, allow, ','); } AP_DECLARE(int) ap_send_http_options(request_rec *r) @@ -887,6 +903,7 @@ static const char *get_canned_error_string(int status, case HTTP_MOVED_PERMANENTLY: case HTTP_MOVED_TEMPORARILY: case HTTP_TEMPORARY_REDIRECT: + case HTTP_PERMANENT_REDIRECT: return(apr_pstrcat(p, "<p>The document has moved <a href=\"", ap_escape_html(r->pool, location), @@ -1048,6 +1065,14 @@ static const char *get_canned_error_string(int status, "connection to SSL, but your client doesn't support it.\n" "Either upgrade your client, or try requesting the page\n" "using https://\n"); + case HTTP_PRECONDITION_REQUIRED: + return("<p>The request is required to be conditional.</p>\n"); + case HTTP_TOO_MANY_REQUESTS: + return("<p>The user has sent too many requests\n" + "in a given amount of time.</p>\n"); + case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE: + return("<p>The server refused this request because\n" + "the request header fields are too large.</p>\n"); case HTTP_INSUFFICIENT_STORAGE: return("<p>The method could not be performed on the resource\n" "because the server is unable to store the\n" @@ -1061,9 +1086,15 @@ static const char *get_canned_error_string(int status, case HTTP_GATEWAY_TIME_OUT: return("<p>The gateway did not receive a timely response\n" "from the upstream server or application.</p>\n"); + case HTTP_LOOP_DETECTED: + return("<p>The server terminated an operation because\n" + "it encountered an infinite loop.</p>\n"); case HTTP_NOT_EXTENDED: return("<p>A mandatory extension policy in the request is not\n" "accepted by the server for this resource.</p>\n"); + case HTTP_NETWORK_AUTHENTICATION_REQUIRED: + return("<p>The client needs to authenticate to gain\n" + "network access.</p>\n"); default: /* HTTP_INTERNAL_SERVER_ERROR */ /* * This comparison to expose error-notes could be modified to diff --git a/modules/http/http_request.c b/modules/http/http_request.c index ce16de92..21c6debd 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -197,7 +197,7 @@ AP_DECLARE(void) ap_die(int type, request_rec *r) "error-notes")) != NULL) { apr_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes); } - r->method = apr_pstrdup(r->pool, "GET"); + r->method = "GET"; r->method_number = M_GET; ap_internal_redirect(custom_response, r); return; diff --git a/modules/ldap/util_ldap.c b/modules/ldap/util_ldap.c index 46840ad6..c7f7b93d 100644 --- a/modules/ldap/util_ldap.c +++ b/modules/ldap/util_ldap.c @@ -2110,7 +2110,7 @@ static const char *util_ldap_set_cache_file(cmd_parms *cmd, void *dummy, } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01298) - "LDAP cache: Setting shared memory cache file to %s bytes.", + "LDAP cache: Setting shared memory cache file to %s.", st->cache_file); return NULL; diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 026a6cf6..bc225cee 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -544,10 +544,10 @@ static const char *log_cookie(request_rec *r, char *a) while ((cookie = apr_strtok(cookies, ";", &last1))) { char *name = apr_strtok(cookie, "=", &last2); if (name) { - char *value; + char *value = name + strlen(name) + 1; apr_collapse_spaces(name, name); - if (!strcasecmp(name, a) && (value = apr_strtok(NULL, "=", &last2))) { + if (!strcasecmp(name, a)) { char *last; value += strspn(value, " \t"); /* Move past leading WS */ last = value + strlen(value) - 1; diff --git a/modules/loggers/mod_log_debug.c b/modules/loggers/mod_log_debug.c index 0361cba7..9111b119 100644 --- a/modules/loggers/mod_log_debug.c +++ b/modules/loggers/mod_log_debug.c @@ -35,8 +35,8 @@ typedef struct { apr_array_header_t *entries; } log_debug_dirconf; -const char *allhooks = "all"; -const char * const hooks[] = { +static const char *allhooks = "all"; +static const char * const hooks[] = { "log_transaction", /* 0 */ "quick_handler", /* 1 */ "handler", /* 2 */ diff --git a/modules/lua/README b/modules/lua/README index 4efa9cd6..c614b3e2 100644 --- a/modules/lua/README +++ b/modules/lua/README @@ -54,6 +54,13 @@ ** TODO apw_rgetvm needs to handle connection scoped vms ** TODO options in server scoped vms (ie, min and max vm counts) ** TODO provide means to implement authn and authz providers +** TODO: Flatten LuaHook* to LuaHook phase file fn ? +** TODO: Lua and ap_expr integration in one or both directions +** TODO: document or remove block sections +** TODO: test per-dir behavior of block sections +** TODO: Catch-up documentation on r: methods +** TODO: 500 errors instead of 404 with AddHandler lua-script +** TODO: Suppress internal details (fs path to scripts, etc) in error responses * License Apache License, Version 2.0, diff --git a/modules/lua/lua_config.c b/modules/lua/lua_config.c index 0e675652..07dd932b 100644 --- a/modules/lua/lua_config.c +++ b/modules/lua/lua_config.c @@ -154,14 +154,6 @@ static const struct luaL_Reg cfg_methods[] = { {NULL, NULL} }; - -static int cmd_foo(lua_State *L) -{ - cmd_parms *cmd = check_cmd_parms(L, 1); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server, APLOGNO(01479) "FOO!"); - return 0; -} - /* helper function for the logging functions below */ static int cmd_log_at(lua_State *L, int level) { @@ -181,88 +173,70 @@ static int cmd_log_at(lua_State *L, int level) /* r:debug(String) and friends which use apache logging */ static int cmd_emerg(lua_State *L) { - cmd_log_at(L, APLOG_EMERG); - return 0; + return cmd_log_at(L, APLOG_EMERG); } static int cmd_alert(lua_State *L) { - cmd_log_at(L, APLOG_ALERT); - return 0; + return cmd_log_at(L, APLOG_ALERT); } static int cmd_crit(lua_State *L) { - cmd_log_at(L, APLOG_CRIT); - return 0; + return cmd_log_at(L, APLOG_CRIT); } static int cmd_err(lua_State *L) { - cmd_log_at(L, APLOG_ERR); - return 0; + return cmd_log_at(L, APLOG_ERR); } static int cmd_warn(lua_State *L) { - cmd_log_at(L, APLOG_WARNING); - return 0; + return cmd_log_at(L, APLOG_WARNING); } static int cmd_notice(lua_State *L) { - cmd_log_at(L, APLOG_NOTICE); - return 0; + return cmd_log_at(L, APLOG_NOTICE); } static int cmd_info(lua_State *L) { - cmd_log_at(L, APLOG_INFO); - return 0; + return cmd_log_at(L, APLOG_INFO); } static int cmd_debug(lua_State *L) { - cmd_log_at(L, APLOG_DEBUG); - return 0; + return cmd_log_at(L, APLOG_DEBUG); } static int cmd_trace1(lua_State *L) { - cmd_log_at(L, APLOG_TRACE1); - return 0; + return cmd_log_at(L, APLOG_TRACE1); } static int cmd_trace2(lua_State *L) { - cmd_log_at(L, APLOG_TRACE2); - return 0; + return cmd_log_at(L, APLOG_TRACE2); } static int cmd_trace3(lua_State *L) { - cmd_log_at(L, APLOG_TRACE3); - return 0; + return cmd_log_at(L, APLOG_TRACE3); } static int cmd_trace4(lua_State *L) { - cmd_log_at(L, APLOG_TRACE4); - return 0; + return cmd_log_at(L, APLOG_TRACE4); } static int cmd_trace5(lua_State *L) { - cmd_log_at(L, APLOG_TRACE5); - return 0; + return cmd_log_at(L, APLOG_TRACE5); } static int cmd_trace6(lua_State *L) { - cmd_log_at(L, APLOG_TRACE6); - return 0; + return cmd_log_at(L, APLOG_TRACE6); } static int cmd_trace7(lua_State *L) { - cmd_log_at(L, APLOG_TRACE7); - return 0; + return cmd_log_at(L, APLOG_TRACE7); } static int cmd_trace8(lua_State *L) { - cmd_log_at(L, APLOG_TRACE8); - return 0; + return cmd_log_at(L, APLOG_TRACE8); } static const struct luaL_Reg cmd_methods[] = { - {"foo", cmd_foo}, - {"trace8", cmd_trace8}, {"trace7", cmd_trace7}, {"trace6", cmd_trace6}, diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index 91bd3b75..9a1cdf8c 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -164,6 +164,34 @@ static int req_parseargs(lua_State *L) return 2; /* [table<string, string>, table<string, array<string>>] */ } +/* r:parsebody() returning a lua table */ +static int req_parsebody(lua_State *L) +{ + apr_array_header_t *pairs; + apr_off_t len; + int res; + apr_size_t size; + apr_size_t max_post_size; + char *buffer; + request_rec *r = ap_lua_check_request_rec(L, 1); + max_post_size = (apr_size_t) luaL_optint(L, 2, MAX_STRING_LEN); + lua_newtable(L); + lua_newtable(L); /* [table, table] */ + res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size); + if (res == OK) { + while(pairs && !apr_is_empty_array(pairs)) { + ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs); + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + req_aprtable2luatable_cb(L, pair->name, buffer); + } + } + return 2; /* [table<string, string>, table<string, array<string>>] */ +} + /* wrap ap_rputs as r:puts(String) */ static int req_puts(lua_State *L) { @@ -235,6 +263,16 @@ static const char *req_document_root(request_rec *r) return ap_document_root(r); } +static const char *req_context_prefix(request_rec *r) +{ + return ap_context_prefix(r); +} + +static const char *req_context_document_root(request_rec *r) +{ + return ap_context_document_root(r); +} + static char *req_uri_field(request_rec *r) { return r->uri; @@ -323,6 +361,16 @@ static const char *req_the_request_field(request_rec *r) return r->the_request; } +static const char *req_log_id_field(request_rec *r) +{ + return r->log_id; +} + +static const char *req_useragent_ip_field(request_rec *r) +{ + return r->useragent_ip; +} + static int req_status_field(request_rec *r) { return r->status; @@ -452,49 +500,40 @@ static int req_log_at(lua_State *L, int level) /* r:debug(String) and friends which use apache logging */ static int req_emerg(lua_State *L) { - req_log_at(L, APLOG_EMERG); - return 0; + return req_log_at(L, APLOG_EMERG); } static int req_alert(lua_State *L) { - req_log_at(L, APLOG_ALERT); - return 0; + return req_log_at(L, APLOG_ALERT); } static int req_crit(lua_State *L) { - req_log_at(L, APLOG_CRIT); - return 0; + return req_log_at(L, APLOG_CRIT); } static int req_err(lua_State *L) { - req_log_at(L, APLOG_ERR); - return 0; + return req_log_at(L, APLOG_ERR); } static int req_warn(lua_State *L) { - req_log_at(L, APLOG_WARNING); - return 0; + return req_log_at(L, APLOG_WARNING); } static int req_notice(lua_State *L) { - req_log_at(L, APLOG_NOTICE); - return 0; + return req_log_at(L, APLOG_NOTICE); } static int req_info(lua_State *L) { - req_log_at(L, APLOG_INFO); - return 0; + return req_log_at(L, APLOG_INFO); } static int req_debug(lua_State *L) { - req_log_at(L, APLOG_DEBUG); - return 0; + return req_log_at(L, APLOG_DEBUG); } #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \ { \ - req_log_at(L, APLOG_TRACE##lev); \ - return 0; \ + return req_log_at(L, APLOG_TRACE##lev); \ } APLUA_REQ_TRACE(1) @@ -608,8 +647,14 @@ AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&req_write, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "document_root", APR_HASH_KEY_STRING, makefun(&req_document_root, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "context_prefix", APR_HASH_KEY_STRING, + makefun(&req_context_prefix, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "context_document_root", APR_HASH_KEY_STRING, + makefun(&req_context_document_root, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "parseargs", APR_HASH_KEY_STRING, makefun(&req_parseargs, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "parsebody", APR_HASH_KEY_STRING, + makefun(&req_parsebody, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "debug", APR_HASH_KEY_STRING, makefun(&req_debug, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "info", APR_HASH_KEY_STRING, @@ -688,6 +733,10 @@ AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&req_uri_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "the_request", APR_HASH_KEY_STRING, makefun(&req_the_request_field, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "log_id", APR_HASH_KEY_STRING, + makefun(&req_log_id_field, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "useragent_ip", APR_HASH_KEY_STRING, + makefun(&req_useragent_ip_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "method", APR_HASH_KEY_STRING, makefun(&req_method_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "proxyreq", APR_HASH_KEY_STRING, @@ -744,7 +793,7 @@ AP_LUA_DECLARE(void) ap_lua_push_connection(lua_State *L, conn_rec *c) lua_setfield(L, -2, "notes"); lua_pushstring(L, c->client_ip); - lua_setfield(L, -2, "remote_ip"); + lua_setfield(L, -2, "client_ip"); lua_pop(L, 1); } diff --git a/modules/lua/lua_vmprep.c b/modules/lua/lua_vmprep.c index 7c383ca9..e821fee3 100644 --- a/modules/lua/lua_vmprep.c +++ b/modules/lua/lua_vmprep.c @@ -19,6 +19,7 @@ #include "apr_uuid.h" #include "lua_config.h" #include "apr_file_info.h" +#include "mod_auth.h" APLOG_USE_MODULE(lua); @@ -96,6 +97,8 @@ static void pstack_dump(lua_State *L, apr_pool_t *r, int level, /* BEGIN apache lmodule */ +#define makeintegerfield(L, n) lua_pushinteger(L, n); lua_setfield(L, -2, #n) + AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) { lua_getglobal(L, "package"); @@ -106,130 +109,83 @@ AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) lua_pop(L, 1); /* empty stack */ lua_getglobal(L, "apache2"); - lua_pushinteger(L, OK); - lua_setfield(L, -2, "OK"); - - lua_pushinteger(L, DECLINED); - lua_setfield(L, -2, "DECLINED"); - - lua_pushinteger(L, DONE); - lua_setfield(L, -2, "DONE"); lua_pushstring(L, ap_get_server_banner()); lua_setfield(L, -2, "version"); - lua_pushinteger(L, HTTP_MOVED_TEMPORARILY); - lua_setfield(L, -2, "HTTP_MOVED_TEMPORARILY"); - - lua_pushinteger(L, PROXYREQ_NONE); - lua_setfield(L, -2, "PROXYREQ_NONE"); - - lua_pushinteger(L, PROXYREQ_PROXY); - lua_setfield(L, -2, "PROXYREQ_PROXY"); - - lua_pushinteger(L, PROXYREQ_REVERSE); - lua_setfield(L, -2, "PROXYREQ_REVERSE"); - - lua_pushinteger(L, PROXYREQ_RESPONSE); - lua_setfield(L, -2, "PROXYREQ_RESPONSE"); + makeintegerfield(L, OK); + makeintegerfield(L, DECLINED); + makeintegerfield(L, DONE); + makeintegerfield(L, HTTP_MOVED_TEMPORARILY); + makeintegerfield(L, PROXYREQ_NONE); + makeintegerfield(L, PROXYREQ_PROXY); + makeintegerfield(L, PROXYREQ_REVERSE); + makeintegerfield(L, PROXYREQ_RESPONSE); + makeintegerfield(L, PROXYREQ_RESPONSE); + makeintegerfield(L, AUTHZ_DENIED); + makeintegerfield(L, AUTHZ_GRANTED); + makeintegerfield(L, AUTHZ_NEUTRAL); + makeintegerfield(L, AUTHZ_GENERAL_ERROR); + makeintegerfield(L, AUTHZ_DENIED_NO_USER); /* - lua_pushinteger(L, HTTP_CONTINUE); - lua_setfield(L, -2, "HTTP_CONTINUE"); - lua_pushinteger(L, HTTP_SWITCHING_PROTOCOLS); - lua_setfield(L, -2, "HTTP_SWITCHING_PROTOCOLS"); - lua_pushinteger(L, HTTP_PROCESSING); - lua_setfield(L, -2, "HTTP_PROCESSING"); - lua_pushinteger(L, HTTP_OK); - lua_setfield(L, -2, "HTTP_OK"); - lua_pushinteger(L, HTTP_CREATED); - lua_setfield(L, -2, "HTTP_CREATED"); - lua_pushinteger(L, HTTP_ACCEPTED); - lua_setfield(L, -2, "HTTP_ACCEPTED"); - lua_pushinteger(L, HTTP_NON_AUTHORITATIVE); - lua_setfield(L, -2, "HTTP_NON_AUTHORITATIVE"); - lua_pushinteger(L, HTTP_NO_CONTENT); - lua_setfield(L, -2, "HTTP_NO_CONTENT"); - lua_pushinteger(L, HTTP_RESET_CONTENT); - lua_setfield(L, -2, "HTTP_RESET_CONTENT"); - lua_pushinteger(L, HTTP_PARTIAL_CONTENT); - lua_setfield(L, -2, "HTTP_PARTIAL_CONTENT"); - lua_pushinteger(L, HTTP_MULTI_STATUS); - lua_setfield(L, -2, "HTTP_MULTI_STATUS"); - lua_pushinteger(L, HTTP_MULTIPLE_CHOICES); - lua_setfield(L, -2, "HTTP_MULTIPLE_CHOICES"); - lua_pushinteger(L, HTTP_MOVED_PERMANENTLY); - lua_setfield(L, -2, "HTTP_MOVED_PERMANENTLY"); - lua_pushinteger(L, HTTP_SEE_OTHER); - lua_setfield(L, -2, "HTTP_SEE_OTHER"); - lua_pushinteger(L, HTTP_NOT_MODIFIED); - lua_setfield(L, -2, "HTTP_NOT_MODIFIED"); - lua_pushinteger(L, HTTP_USE_PROXY); - lua_setfield(L, -2, "HTTP_USE_PROXY"); - lua_pushinteger(L, HTTP_TEMPORARY_REDIRECT); - lua_setfield(L, -2, "HTTP_TEMPORARY_REDIRECT"); - lua_pushinteger(L, HTTP_BAD_REQUEST); - lua_setfield(L, -2, "HTTP_BAD_REQUEST"); - lua_pushinteger(L, HTTP_UNAUTHORIZED); - lua_setfield(L, -2, "HTTP_UNAUTHORIZED"); - lua_pushinteger(L, HTTP_PAYMENT_REQUIRED); - lua_setfield(L, -2, "HTTP_PAYMENT_REQUIRED"); - lua_pushinteger(L, HTTP_FORBIDDEN); - lua_setfield(L, -2, "HTTP_FORBIDDEN"); - lua_pushinteger(L, HTTP_NOT_FOUND); - lua_setfield(L, -2, "HTTP_NOT_FOUND"); - lua_pushinteger(L, HTTP_METHOD_NOT_ALLOWED); - lua_setfield(L, -2, "HTTP_METHOD_NOT_ALLOWED"); - lua_pushinteger(L, HTTP_NOT_ACCEPTABLE); - lua_setfield(L, -2, "HTTP_NOT_ACCEPTABLE"); - lua_pushinteger(L, HTTP_PROXY_AUTHENTICATION_REQUIRED); - lua_setfield(L, -2, "HTTP_PROXY_AUTHENTICATION_REQUIRED"); - lua_pushinteger(L, HTTP_REQUEST_TIME_OUT); - lua_setfield(L, -2, "HTTP_REQUEST_TIME_OUT"); - lua_pushinteger(L, HTTP_CONFLICT); - lua_setfield(L, -2, "HTTP_CONFLICT"); - lua_pushinteger(L, HTTP_GONE); - lua_setfield(L, -2, "HTTP_GONE"); - lua_pushinteger(L, HTTP_LENGTH_REQUIRED); - lua_setfield(L, -2, "HTTP_LENGTH_REQUIRED"); - lua_pushinteger(L, HTTP_PRECONDITION_FAILED); - lua_setfield(L, -2, "HTTP_PRECONDITION_FAILED"); - lua_pushinteger(L, HTTP_REQUEST_ENTITY_TOO_LARGE); - lua_setfield(L, -2, "HTTP_REQUEST_ENTITY_TOO_LARGE"); - lua_pushinteger(L, HTTP_REQUEST_URI_TOO_LARGE); - lua_setfield(L, -2, "HTTP_REQUEST_URI_TOO_LARGE"); - lua_pushinteger(L, HTTP_UNSUPPORTED_MEDIA_TYPE); - lua_setfield(L, -2, "HTTP_UNSUPPORTED_MEDIA_TYPE"); - lua_pushinteger(L, HTTP_RANGE_NOT_SATISFIABLE); - lua_setfield(L, -2, "HTTP_RANGE_NOT_SATISFIABLE"); - lua_pushinteger(L, HTTP_EXPECTATION_FAILED); - lua_setfield(L, -2, "HTTP_EXPECTATION_FAILED"); - lua_pushinteger(L, HTTP_UNPROCESSABLE_ENTITY); - lua_setfield(L, -2, "HTTP_UNPROCESSABLE_ENTITY"); - lua_pushinteger(L, HTTP_LOCKED); - lua_setfield(L, -2, "HTTP_LOCKED"); - lua_pushinteger(L, HTTP_FAILED_DEPENDENCY); - lua_setfield(L, -2, "HTTP_FAILED_DEPENDENCY"); - lua_pushinteger(L, HTTP_UPGRADE_REQUIRED); - lua_setfield(L, -2, "HTTP_UPGRADE_REQUIRED"); - lua_pushinteger(L, HTTP_INTERNAL_SERVER_ERROR); - lua_setfield(L, -2, "HTTP_INTERNAL_SERVER_ERROR"); - lua_pushinteger(L, HTTP_NOT_IMPLEMENTED); - lua_setfield(L, -2, "HTTP_NOT_IMPLEMENTED"); - lua_pushinteger(L, HTTP_BAD_GATEWAY); - lua_setfield(L, -2, "HTTP_BAD_GATEWAY"); - lua_pushinteger(L, HTTP_SERVICE_UNAVAILABLE); - lua_setfield(L, -2, "HTTP_SERVICE_UNAVAILABLE"); - lua_pushinteger(L, HTTP_GATEWAY_TIME_OUT); - lua_setfield(L, -2, "HTTP_GATEWAY_TIME_OUT"); - lua_pushinteger(L, HTTP_VERSION_NOT_SUPPORTED); - lua_setfield(L, -2, "HTTP_VERSION_NOT_SUPPORTED"); - lua_pushinteger(L, HTTP_VARIANT_ALSO_VARIES); - lua_setfield(L, -2, "HTTP_VARIANT_ALSO_VARIES"); - lua_pushinteger(L, HTTP_INSUFFICIENT_STORAGE); - lua_setfield(L, -2, "HTTP_INSUFFICIENT_STORAGE"); - lua_pushinteger(L, HTTP_NOT_EXTENDED); - lua_setfield(L, -2, "HTTP_NOT_EXTENDED"); + makeintegerfield(L, HTTP_CONTINUE); + makeintegerfield(L, HTTP_SWITCHING_PROTOCOLS); + makeintegerfield(L, HTTP_PROCESSING); + makeintegerfield(L, HTTP_OK); + makeintegerfield(L, HTTP_CREATED); + makeintegerfield(L, HTTP_ACCEPTED); + makeintegerfield(L, HTTP_NON_AUTHORITATIVE); + makeintegerfield(L, HTTP_NO_CONTENT); + makeintegerfield(L, HTTP_RESET_CONTENT); + makeintegerfield(L, HTTP_PARTIAL_CONTENT); + makeintegerfield(L, HTTP_MULTI_STATUS); + makeintegerfield(L, HTTP_ALREADY_REPORTED); + makeintegerfield(L, HTTP_IM_USED); + makeintegerfield(L, HTTP_MULTIPLE_CHOICES); + makeintegerfield(L, HTTP_MOVED_PERMANENTLY); + makeintegerfield(L, HTTP_MOVED_TEMPORARILY); + makeintegerfield(L, HTTP_SEE_OTHER); + makeintegerfield(L, HTTP_NOT_MODIFIED); + makeintegerfield(L, HTTP_USE_PROXY); + makeintegerfield(L, HTTP_TEMPORARY_REDIRECT); + makeintegerfield(L, HTTP_PERMANENT_REDIRECT); + makeintegerfield(L, HTTP_BAD_REQUEST); + makeintegerfield(L, HTTP_UNAUTHORIZED); + makeintegerfield(L, HTTP_PAYMENT_REQUIRED); + makeintegerfield(L, HTTP_FORBIDDEN); + makeintegerfield(L, HTTP_NOT_FOUND); + makeintegerfield(L, HTTP_METHOD_NOT_ALLOWED); + makeintegerfield(L, HTTP_NOT_ACCEPTABLE); + makeintegerfield(L, HTTP_PROXY_AUTHENTICATION_REQUIRED); + makeintegerfield(L, HTTP_REQUEST_TIME_OUT); + makeintegerfield(L, HTTP_CONFLICT); + makeintegerfield(L, HTTP_GONE); + makeintegerfield(L, HTTP_LENGTH_REQUIRED); + makeintegerfield(L, HTTP_PRECONDITION_FAILED); + makeintegerfield(L, HTTP_REQUEST_ENTITY_TOO_LARGE); + makeintegerfield(L, HTTP_REQUEST_URI_TOO_LARGE); + makeintegerfield(L, HTTP_UNSUPPORTED_MEDIA_TYPE); + makeintegerfield(L, HTTP_RANGE_NOT_SATISFIABLE); + makeintegerfield(L, HTTP_EXPECTATION_FAILED); + makeintegerfield(L, HTTP_UNPROCESSABLE_ENTITY); + makeintegerfield(L, HTTP_LOCKED); + makeintegerfield(L, HTTP_FAILED_DEPENDENCY); + makeintegerfield(L, HTTP_UPGRADE_REQUIRED); + makeintegerfield(L, HTTP_PRECONDITION_REQUIRED); + makeintegerfield(L, HTTP_TOO_MANY_REQUESTS); + makeintegerfield(L, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE); + makeintegerfield(L, HTTP_INTERNAL_SERVER_ERROR); + makeintegerfield(L, HTTP_NOT_IMPLEMENTED); + makeintegerfield(L, HTTP_BAD_GATEWAY); + makeintegerfield(L, HTTP_SERVICE_UNAVAILABLE); + makeintegerfield(L, HTTP_GATEWAY_TIME_OUT); + makeintegerfield(L, HTTP_VERSION_NOT_SUPPORTED); + makeintegerfield(L, HTTP_VARIANT_ALSO_VARIES); + makeintegerfield(L, HTTP_INSUFFICIENT_STORAGE); + makeintegerfield(L, HTTP_LOOP_DETECTED); + makeintegerfield(L, HTTP_NOT_EXTENDED); + makeintegerfield(L, HTTP_NETWORK_AUTHENTICATION_REQUIRED); */ } @@ -240,6 +196,7 @@ AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) /* callback for cleaning up a lua vm when pool is closed */ static apr_status_t cleanup_lua(void *l) { + AP_DEBUG_ASSERT(l != NULL); lua_close((lua_State *) l); return APR_SUCCESS; } @@ -319,7 +276,7 @@ static int loadjitmodule(lua_State *L, apr_pool_t *lifecycle_pool) { #endif -static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_pool) +static apr_status_t vm_construct(lua_State **vm, void *params, apr_pool_t *lifecycle_pool) { lua_State* L; @@ -357,24 +314,10 @@ static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_ "loading lua file %s", spec->file); rc = luaL_loadfile(L, spec->file); if (rc != 0) { - char *err; - switch (rc) { - case LUA_ERRSYNTAX: - err = "syntax error"; - break; - case LUA_ERRMEM: - err = "memory allocation error"; - break; - case LUA_ERRFILE: - err = "error opening or reading file"; - break; - default: - err = "unknown error"; - break; - } ap_log_perror(APLOG_MARK, APLOG_ERR, 0, lifecycle_pool, APLOGNO(01482) - "Loading lua file %s: %s", - spec->file, err); + "Error loading %s: %s", spec->file, + rc == LUA_ERRMEM ? "memory allocation error" + : lua_tostring(L, 0)); return APR_EBADF; } lua_pcall(L, 0, LUA_MULTRET, 0); @@ -407,7 +350,8 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool, "creating lua_State with file %s", spec->file); /* not available, so create */ - if(!vm_construct((void **)&L, spec, lifecycle_pool)) { + if(!vm_construct(&L, spec, lifecycle_pool)) { + AP_DEBUG_ASSERT(L != NULL); apr_pool_userdata_set(L, spec->file, cleanup_lua, diff --git a/modules/lua/lua_vmprep.h b/modules/lua/lua_vmprep.h index be1750df..1d3758ca 100644 --- a/modules/lua/lua_vmprep.h +++ b/modules/lua/lua_vmprep.h @@ -54,7 +54,7 @@ typedef struct apr_array_header_t *package_cpaths; /* name of base file to load in the vm */ - char *file; + const char *file; /* APL_SCOPE_ONCE | APL_SCOPE_REQUEST | APL_SCOPE_CONN | APL_SCOPE_THREAD */ int scope; @@ -75,8 +75,8 @@ typedef struct typedef struct { - char *function_name; - char *file_name; + const char *function_name; + const char *file_name; int scope; ap_regex_t *uri_pattern; const char *bytecode; diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c index 095e54fd..b5b626d1 100644 --- a/modules/lua/mod_lua.c +++ b/modules/lua/mod_lua.c @@ -24,6 +24,7 @@ #include "lua_config.h" #include "apr_optional.h" #include "mod_ssl.h" +#include "mod_auth.h" #ifdef APR_HAS_THREADS #include "apr_thread_proc.h" @@ -39,11 +40,22 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ap_lua, AP_LUA, int, lua_request, static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *lua_ssl_val = NULL; static APR_OPTIONAL_FN_TYPE(ssl_is_https) *lua_ssl_is_https = NULL; - module AP_MODULE_DECLARE_DATA lua_module; +module AP_MODULE_DECLARE_DATA lua_module; #define AP_LUA_HOOK_FIRST (APR_HOOK_FIRST - 1) #define AP_LUA_HOOK_LAST (APR_HOOK_LAST + 1) +typedef struct { + const char *name; + const char *file_name; + const char *function_name; + ap_lua_vm_spec *spec; + apr_array_header_t *args; +} lua_authz_provider_spec; + +apr_hash_t *lua_authz_providers; + + /** * error reporting if lua has an error. * Extracts the error from lua stack and prints @@ -78,73 +90,114 @@ static int lua_open_hook(lua_State *L, apr_pool_t *p) return OK; } +static const char *scope_to_string(unsigned int scope) +{ + switch (scope) { + case AP_LUA_SCOPE_ONCE: + case AP_LUA_SCOPE_UNSET: + return "once"; + case AP_LUA_SCOPE_REQUEST: + return "request"; + case AP_LUA_SCOPE_CONN: + return "conn"; +#if APR_HAS_THREADS + case AP_LUA_SCOPE_THREAD: + return "thread"; +#endif + default: + ap_assert(0); + } +} + +static ap_lua_vm_spec *create_vm_spec(apr_pool_t **lifecycle_pool, + request_rec *r, + const ap_lua_dir_cfg *cfg, + const ap_lua_server_cfg *server_cfg, + const char *filename, + const char *bytecode, + apr_size_t bytecode_len, + const char *function, + const char *what) +{ + apr_pool_t *pool; + ap_lua_vm_spec *spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); + + spec->scope = cfg->vm_scope; + spec->pool = r->pool; + spec->package_paths = cfg->package_paths; + spec->package_cpaths = cfg->package_cpaths; + spec->cb = &lua_open_callback; + spec->cb_arg = NULL; + spec->bytecode = bytecode; + spec->bytecode_len = bytecode_len; + + if (filename) { + char *file; + apr_filepath_merge(&file, server_cfg->root_path, + filename, APR_FILEPATH_NOTRELATIVE, r->pool); + spec->file = file; + } + else { + spec->file = r->filename; + } + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, APLOGNO(02313) + "%s details: scope: %s, file: %s, func: %s", + what, scope_to_string(spec->scope), spec->file, + function ? function : "-"); + + switch (spec->scope) { + case AP_LUA_SCOPE_ONCE: + case AP_LUA_SCOPE_UNSET: + apr_pool_create(&pool, r->pool); + break; + case AP_LUA_SCOPE_REQUEST: + pool = r->pool; + break; + case AP_LUA_SCOPE_CONN: + pool = r->connection->pool; + break; +#if APR_HAS_THREADS + case AP_LUA_SCOPE_THREAD: + pool = apr_thread_pool_get(r->connection->current_thread); + break; +#endif + default: + ap_assert(0); + } + + *lifecycle_pool = pool; + return spec; +} + /** * "main" */ static int lua_handler(request_rec *r) { - ap_lua_dir_cfg *dcfg; - apr_pool_t *pool; if (strcmp(r->handler, "lua-script")) { return DECLINED; } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01472) "handling [%s] in mod_lua", - r->filename); - dcfg = ap_get_module_config(r->per_dir_config, &lua_module); + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(01472) + "handling [%s] in mod_lua", r->filename); + /* XXX: This seems wrong because it may generate wrong headers for HEAD requests */ if (!r->header_only) { lua_State *L; + apr_pool_t *pool; const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, &lua_module); - ap_lua_vm_spec *spec = NULL; + ap_lua_vm_spec *spec = create_vm_spec(&pool, r, cfg, NULL, NULL, NULL, + 0, "handle", "request handler"); - spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); - spec->scope = dcfg->vm_scope; - spec->pool = r->pool; - spec->file = r->filename; - spec->package_paths = cfg->package_paths; - spec->package_cpaths = cfg->package_cpaths; - spec->cb = &lua_open_callback; - spec->cb_arg = NULL; - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01473) - "request details scope:%u, filename:%s, function:%s", - spec->scope, - spec->file, - "handle"); - - switch (spec->scope) { - case AP_LUA_SCOPE_ONCE: - case AP_LUA_SCOPE_UNSET: - apr_pool_create(&pool, r->pool); - break; - case AP_LUA_SCOPE_REQUEST: - pool = r->pool; - break; - case AP_LUA_SCOPE_CONN: - pool = r->connection->pool; - break; - case AP_LUA_SCOPE_THREAD: - #if APR_HAS_THREADS - pool = apr_thread_pool_get(r->connection->current_thread); - break; - #endif - default: - ap_assert(0); - } - - L = ap_lua_get_lua_state(pool, - spec); - + L = ap_lua_get_lua_state(pool, spec); if (!L) { /* TODO annotate spec with failure reason */ r->status = HTTP_INTERNAL_SERVER_ERROR; ap_rputs("Unable to compile VM, see logs", r); return HTTP_INTERNAL_SERVER_ERROR; } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01474) "got a vm!"); + ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, APLOGNO(01474) "got a vm!"); lua_getglobal(L, "handle"); if (!lua_isfunction(L, -1)) { ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01475) @@ -163,7 +216,6 @@ static int lua_handler(request_rec *r) - /* ---------------- Configury stuff --------------- */ /** harnesses for magic hooks **/ @@ -190,46 +242,12 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap if (hook_spec == NULL) { continue; } - spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); - - spec->file = hook_spec->file_name; - spec->scope = cfg->vm_scope; - spec->bytecode = hook_spec->bytecode; - spec->bytecode_len = hook_spec->bytecode_len; - spec->pool = r->pool; - spec->package_paths = cfg->package_paths; - spec->package_cpaths = cfg->package_cpaths; - spec->cb = &lua_open_callback; - spec->cb_arg = NULL; - - apr_filepath_merge(&spec->file, server_cfg->root_path, - spec->file, APR_FILEPATH_NOTRELATIVE, r->pool); - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01476) - "request details scope:%u, filename:%s, function:%s", - spec->scope, - spec->file, - hook_spec->function_name ? hook_spec->function_name : "-"); - - switch (spec->scope) { - case AP_LUA_SCOPE_ONCE: - case AP_LUA_SCOPE_UNSET: - apr_pool_create(&pool, r->pool); - break; - case AP_LUA_SCOPE_REQUEST: - pool = r->pool; - break; - case AP_LUA_SCOPE_CONN: - pool = r->connection->pool; - break; - case AP_LUA_SCOPE_THREAD: - #if APR_HAS_THREADS - pool = apr_thread_pool_get(r->connection->current_thread); - break; - #endif - default: - ap_assert(0); - } + spec = create_vm_spec(&pool, r, cfg, server_cfg, + hook_spec->file_name, + hook_spec->bytecode, + hook_spec->bytecode_len, + hook_spec->function_name, + "request hook"); L = ap_lua_get_lua_state(pool, spec); @@ -450,16 +468,15 @@ static const char *register_named_block_function_hook(const char *name, { cr_ctx ctx; - char buf[32]; lua_State *lvm; char *tmp; int rv; ap_directive_t **current; hack_section_baton *baton; - apr_snprintf(buf, sizeof(buf), "%u", cmd->config_file->line_number); - spec->file_name = apr_pstrcat(cmd->pool, cmd->config_file->name, ":", - buf, NULL); + spec->file_name = apr_psprintf(cmd->pool, "%s:%u", + cmd->config_file->name, + cmd->config_file->line_number); if (function) { spec->function_name = (char *) function; } @@ -959,6 +976,131 @@ AP_LUA_DECLARE(int) ap_lua_ssl_is_https(conn_rec *c) /*******************************/ +static const char *lua_authz_parse(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *provider_name; + lua_authz_provider_spec *spec; + + apr_pool_userdata_get((void**)&provider_name, AUTHZ_PROVIDER_NAME_NOTE, + cmd->temp_pool); + ap_assert(provider_name != NULL); + + spec = apr_hash_get(lua_authz_providers, provider_name, APR_HASH_KEY_STRING); + ap_assert(spec != NULL); + + if (require_line && *require_line) { + const char *arg; + spec->args = apr_array_make(cmd->pool, 2, sizeof(const char *)); + while ((arg = ap_getword_conf(cmd->pool, &require_line)) && *arg) { + APR_ARRAY_PUSH(spec->args, const char *) = arg; + } + } + + *parsed_require_line = spec; + return NULL; +} + +static authz_status lua_authz_check(request_rec *r, const char *require_line, + const void *parsed_require_line) +{ + apr_pool_t *pool; + ap_lua_vm_spec *spec; + lua_State *L; + ap_lua_server_cfg *server_cfg = ap_get_module_config(r->server->module_config, + &lua_module); + const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, + &lua_module); + const lua_authz_provider_spec *prov_spec = parsed_require_line; + int result; + int nargs = 0; + + spec = create_vm_spec(&pool, r, cfg, server_cfg, prov_spec->file_name, + NULL, 0, prov_spec->function_name, "authz provider"); + + L = ap_lua_get_lua_state(pool, spec); + if (L == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02314) + "Unable to compile VM for authz provider %s", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + lua_getglobal(L, prov_spec->function_name); + if (!lua_isfunction(L, -1)) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(02319) + "Unable to find function %s in %s", + prov_spec->function_name, prov_spec->file_name); + return AUTHZ_GENERAL_ERROR; + } + ap_lua_run_lua_request(L, r); + if (prov_spec->args) { + int i; + if (!lua_checkstack(L, prov_spec->args->nelts)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02315) + "Error: authz provider %s: too many arguments", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + for (i = 0; i < prov_spec->args->nelts; i++) { + const char *arg = APR_ARRAY_IDX(prov_spec->args, i, const char *); + lua_pushstring(L, arg); + } + nargs = prov_spec->args->nelts; + } + if (lua_pcall(L, 1 + nargs, 1, 0)) { + const char *err = lua_tostring(L, -1); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02316) + "Error executing authz provider %s: %s", prov_spec->name, err); + return AUTHZ_GENERAL_ERROR; + } + if (!lua_isnumber(L, -1)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02317) + "Error: authz provider %s did not return integer", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + result = lua_tointeger(L, -1); + switch (result) { + case AUTHZ_DENIED: + case AUTHZ_GRANTED: + case AUTHZ_NEUTRAL: + case AUTHZ_GENERAL_ERROR: + case AUTHZ_DENIED_NO_USER: + return result; + default: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02318) + "Error: authz provider %s: invalid return value %d", + prov_spec->name, result); + } + return AUTHZ_GENERAL_ERROR; +} + +static const authz_provider lua_authz_provider = +{ + &lua_authz_check, + &lua_authz_parse, +}; + +static const char *register_authz_provider(cmd_parms *cmd, void *_cfg, + const char *name, const char *file, + const char *function) +{ + lua_authz_provider_spec *spec; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err) + return err; + + spec = apr_pcalloc(cmd->pool, sizeof(*spec)); + spec->name = name; + spec->file_name = file; + spec->function_name = function; + + apr_hash_set(lua_authz_providers, name, APR_HASH_KEY_STRING, spec); + ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, name, + AUTHZ_PROVIDER_VERSION, + &lua_authz_provider, + AP_AUTH_INTERNAL_PER_CONF); + return NULL; +} + + command_rec lua_commands[] = { AP_INIT_TAKE1("LuaRoot", register_lua_root, NULL, OR_ALL, @@ -970,6 +1112,8 @@ command_rec lua_commands[] = { AP_INIT_TAKE1("LuaPackageCPath", register_package_cdir, NULL, OR_ALL, "Add a directory to lua's package.cpath"), + AP_INIT_TAKE3("LuaAuthzProvider", register_authz_provider, NULL, RSRC_CONF|EXEC_ON_READ, + "Provide an authorization provider"), AP_INIT_TAKE23("LuaHookTranslateName", register_translate_name_hook, NULL, OR_ALL, @@ -1202,6 +1346,9 @@ static void lua_register_hooks(apr_pool_t *p) APR_OPTIONAL_HOOK(ap_lua, lua_request, lua_request_hook, NULL, NULL, APR_HOOK_REALLY_FIRST); + + /* providers */ + lua_authz_providers = apr_hash_make(p); } AP_DECLARE_MODULE(lua) = { diff --git a/modules/lua/mod_lua.h b/modules/lua/mod_lua.h index 5394f7a4..52ff96ad 100644 --- a/modules/lua/mod_lua.h +++ b/modules/lua/mod_lua.h @@ -40,6 +40,9 @@ #include "apr_time.h" #include "apr_hooks.h" +/* Allow for Lua 5.2 backwards compatibility */ +#define LUA_COMPAT_ALL + #include "lua.h" #include "lauxlib.h" #include "lualib.h" @@ -113,7 +116,7 @@ typedef struct apr_hash_t *hooks; /* <wombat_hook_info> */ /* the actual directory being configured */ - char *dir; + const char *dir; /* Whether Lua scripts in a sub-dir are run before parents */ ap_lua_inherit_t inherit; @@ -131,7 +134,7 @@ typedef struct typedef struct { - char *function_name; + const char *function_name; ap_lua_vm_spec *spec; } mapped_request_details; @@ -144,7 +147,7 @@ typedef struct typedef struct { lua_State *L; - char *function; + const char *function; } ap_lua_filter_ctx; extern module AP_MODULE_DECLARE_DATA lua_module; diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index cba118c6..5f3232b8 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -2656,9 +2656,9 @@ static char *make_variant_list(request_rec *r, negotiation_state *neg) * need to change the calculation of max_vlist_array above. */ *((const char **) apr_array_push(arr)) = "<li><a href=\""; - *((const char **) apr_array_push(arr)) = filename; + *((const char **) apr_array_push(arr)) = ap_escape_path_segment(r->pool, filename); *((const char **) apr_array_push(arr)) = "\">"; - *((const char **) apr_array_push(arr)) = filename; + *((const char **) apr_array_push(arr)) = ap_escape_html(r->pool, filename); *((const char **) apr_array_push(arr)) = "</a> "; *((const char **) apr_array_push(arr)) = description; diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 8f5d3972..9823a7fa 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -190,6 +190,7 @@ static const char* really_last_key = "rewrite_really_last"; #define OPTION_INHERIT 1<<1 #define OPTION_INHERIT_BEFORE 1<<2 #define OPTION_NOSLASH 1<<3 +#define OPTION_ANYURI 1<<4 #ifndef RAND_MAX #define RAND_MAX 32767 @@ -401,7 +402,7 @@ static int proxy_available; /* Locks/Mutexes */ static apr_global_mutex_t *rewrite_mapr_lock_acquire = NULL; -const char *rewritemap_mutex_type = "rewrite-map"; +static const char *rewritemap_mutex_type = "rewrite-map"; /* Optional functions imported from mod_ssl when loaded: */ static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *rewrite_ssl_lookup = NULL; @@ -2893,6 +2894,9 @@ static const char *cmd_rewriteoptions(cmd_parms *cmd, "LimitInternalRecursion directive and will be " "ignored."); } + else if (!strcasecmp(w, "allowanyuri")) { + options |= OPTION_ANYURI; + } else { return apr_pstrcat(cmd->pool, "RewriteOptions: unknown option '", w, "'", NULL); @@ -2932,8 +2936,7 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1, sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); - newmap = apr_palloc(cmd->pool, sizeof(rewritemap_entry)); - newmap->func = NULL; + newmap = apr_pcalloc(cmd->pool, sizeof(rewritemap_entry)); if (strncasecmp(a2, "txt:", 4) == 0) { if ((fname = ap_server_root_relative(cmd->pool, a2+4)) == NULL) { @@ -2944,7 +2947,6 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1, newmap->type = MAPTYPE_TXT; newmap->datafile = fname; newmap->checkfile = fname; - newmap->checkfile2= NULL; newmap->cachename = apr_psprintf(cmd->pool, "%pp:%s", (void *)cmd->server, a1); } @@ -2957,7 +2959,6 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1, newmap->type = MAPTYPE_RND; newmap->datafile = fname; newmap->checkfile = fname; - newmap->checkfile2= NULL; newmap->cachename = apr_psprintf(cmd->pool, "%pp:%s", (void *)cmd->server, a1); } @@ -3031,17 +3032,10 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1, } newmap->type = MAPTYPE_PRG; - newmap->datafile = NULL; newmap->checkfile = newmap->argv[0]; - newmap->checkfile2= NULL; - newmap->cachename = NULL; } else if (strncasecmp(a2, "int:", 4) == 0) { newmap->type = MAPTYPE_INT; - newmap->datafile = NULL; - newmap->checkfile = NULL; - newmap->checkfile2= NULL; - newmap->cachename = NULL; newmap->func = (char *(*)(request_rec *,char *)) apr_hash_get(mapfunc_hash, a2+4, strlen(a2+4)); if (newmap->func == NULL) { @@ -3058,12 +3052,9 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1, newmap->type = MAPTYPE_TXT; newmap->datafile = fname; newmap->checkfile = fname; - newmap->checkfile2= NULL; newmap->cachename = apr_psprintf(cmd->pool, "%pp:%s", (void *)cmd->server, a1); } - newmap->fpin = NULL; - newmap->fpout = NULL; if (newmap->checkfile && (apr_stat(&st, newmap->checkfile, APR_FINFO_MIN, @@ -3243,37 +3234,60 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf, newcond->ptype = CONDPAT_AP_EXPR; } else if (*a2 && a2[1]) { - if (!a2[2] && *a2 == '-') { - switch (a2[1]) { - case 'f': newcond->ptype = CONDPAT_FILE_EXISTS; break; - case 's': newcond->ptype = CONDPAT_FILE_SIZE; break; - case 'd': newcond->ptype = CONDPAT_FILE_DIR; break; - case 'x': newcond->ptype = CONDPAT_FILE_XBIT; break; - case 'h': newcond->ptype = CONDPAT_FILE_LINK; break; - case 'L': newcond->ptype = CONDPAT_FILE_LINK; break; - case 'U': newcond->ptype = CONDPAT_LU_URL; break; - case 'F': newcond->ptype = CONDPAT_LU_FILE; break; - case 'l': if (a2[2] == 't') - a2 += 3, newcond->ptype = CONDPAT_INT_LT; - else if (a2[2] == 'e') - a2 += 3, newcond->ptype = CONDPAT_INT_LE; - else /* Historical; prefer -L or -h instead */ - newcond->ptype = CONDPAT_FILE_LINK; - break; - case 'g': if (a2[2] == 't') - a2 += 3, newcond->ptype = CONDPAT_INT_GT; - else if (a2[2] == 'e') - a2 += 3, newcond->ptype = CONDPAT_INT_GE; - break; - case 'e': if (a2[2] == 'q') - a2 += 3, newcond->ptype = CONDPAT_INT_EQ; - break; - case 'n': if (a2[2] == 'e') { - /* Inversion, ensure !-ne == -eq */ - a2 += 3, newcond->ptype = CONDPAT_INT_EQ; - newcond->flags ^= CONDFLAG_NOTMATCH; - } - break; + if (*a2 == '-') { + if (!a2[2]) { + switch (a2[1]) { + case 'f': newcond->ptype = CONDPAT_FILE_EXISTS; break; + case 's': newcond->ptype = CONDPAT_FILE_SIZE; break; + case 'd': newcond->ptype = CONDPAT_FILE_DIR; break; + case 'x': newcond->ptype = CONDPAT_FILE_XBIT; break; + case 'h': newcond->ptype = CONDPAT_FILE_LINK; break; + case 'L': newcond->ptype = CONDPAT_FILE_LINK; break; + case 'l': newcond->ptype = CONDPAT_FILE_LINK; break; + case 'U': newcond->ptype = CONDPAT_LU_URL; break; + case 'F': newcond->ptype = CONDPAT_LU_FILE; break; + } + } + else if (a2[3]) { + switch (a2[1]) { + case 'l': + if (a2[2] == 't') { + a2 += 3; + newcond->ptype = CONDPAT_INT_LT; + } + else if (a2[2] == 'e') { + a2 += 3; + newcond->ptype = CONDPAT_INT_LE; + } + break; + + case 'g': + if (a2[2] == 't') { + a2 += 3; + newcond->ptype = CONDPAT_INT_GT; + } + else if (a2[2] == 'e') { + a2 += 3; + newcond->ptype = CONDPAT_INT_GE; + } + break; + + case 'e': + if (a2[2] == 'q') { + a2 += 3; + newcond->ptype = CONDPAT_INT_EQ; + } + break; + + case 'n': + if (a2[2] == 'e') { + /* Inversion, ensure !-ne == -eq */ + a2 += 3; + newcond->ptype = CONDPAT_INT_EQ; + newcond->flags ^= CONDFLAG_NOTMATCH; + } + break; + } } } else { @@ -4419,8 +4433,16 @@ static int hook_uri2file(request_rec *r) return DECLINED; } - if ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0') - || !r->uri || r->uri[0] != '/') { + /* Unless the anyuri option is set, ensure that the input to the + * first rule really is a URL-path, avoiding security issues with + * poorly configured rules. See CVE-2011-3368, CVE-2011-4317. */ + if ((dconf->options & OPTION_ANYURI) == 0 + && ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0') + || !r->uri || r->uri[0] != '/')) { + rewritelog((r, 8, NULL, "Declining, request-URI '%s' is not a URL-path. " + "Consult the manual entry for the RewriteOptions directive " + "for options and caveats about matching other strings.", + r->uri)); return DECLINED; } diff --git a/modules/metadata/mod_setenvif.c b/modules/metadata/mod_setenvif.c index 80825cce..65214cd4 100644 --- a/modules/metadata/mod_setenvif.c +++ b/modules/metadata/mod_setenvif.c @@ -165,17 +165,15 @@ static void *merge_setenvif_config(apr_pool_t *p, void *basev, void *overridesv) #define ICASE_MAGIC ((void *)(&setenvif_module)) #define SEI_MAGIC_HEIRLOOM "setenvif-phase-flag" +static ap_regex_t *is_header_regex_regex; + static int is_header_regex(apr_pool_t *p, const char* name) { /* If a Header name contains characters other than: * -,_,[A-Z\, [a-z] and [0-9]. * assume the header name is a regular expression. */ - ap_regex_t *preg = ap_pregcomp(p, "^[-A-Za-z0-9_]*$", - (AP_REG_EXTENDED | AP_REG_NOSUB )); - ap_assert(preg != NULL); - - if (ap_regexec(preg, name, 0, NULL, 0)) { + if (ap_regexec(is_header_regex_regex, name, 0, NULL, 0)) { return 1; } @@ -633,6 +631,10 @@ static void register_hooks(apr_pool_t *p) { ap_hook_header_parser(match_headers, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_MIDDLE); + + is_header_regex_regex = ap_pregcomp(p, "^[-A-Za-z0-9_]*$", + (AP_REG_EXTENDED | AP_REG_NOSUB )); + ap_assert(is_header_regex_regex != NULL); } AP_DECLARE_MODULE(setenvif) = diff --git a/modules/proxy/NWGNUproxy b/modules/proxy/NWGNUproxy index cade4acb..6342e613 100644 --- a/modules/proxy/NWGNUproxy +++ b/modules/proxy/NWGNUproxy @@ -277,6 +277,7 @@ $(OBJDIR)/mod_proxy.imp: @echo $(DL) ap_proxy_canon_netloc,$(DL)>> $@ @echo $(DL) ap_proxy_canonenc,$(DL)>> $@ @echo $(DL) ap_proxy_checkproxyblock,$(DL)>> $@ + @echo $(DL) ap_proxy_checkproxyblock2,$(DL)>> $@ @echo $(DL) ap_proxy_conn_is_https,$(DL)>> $@ @echo $(DL) ap_proxy_connect_backend,$(DL)>> $@ @echo $(DL) ap_proxy_connect_to_backend,$(DL)>> $@ diff --git a/modules/proxy/NWGNUproxylbm_busy b/modules/proxy/NWGNUproxylbm_busy index 394af7a6..c1b91f6b 100644 --- a/modules/proxy/NWGNUproxylbm_busy +++ b/modules/proxy/NWGNUproxylbm_busy @@ -19,6 +19,7 @@ XINCDIRS += \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(AP_WORK)/modules/proxy \ $(AP_WORK)/modules/http \ $(NWOS) \ $(EOLIST) diff --git a/modules/proxy/NWGNUproxylbm_hb b/modules/proxy/NWGNUproxylbm_hb index 80f2f822..19563da6 100644 --- a/modules/proxy/NWGNUproxylbm_hb +++ b/modules/proxy/NWGNUproxylbm_hb @@ -19,6 +19,7 @@ XINCDIRS += \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(AP_WORK)/modules/proxy \ $(AP_WORK)/modules/http \ $(NWOS) \ $(EOLIST) diff --git a/modules/proxy/NWGNUproxylbm_req b/modules/proxy/NWGNUproxylbm_req index 0170056c..6a2c4cd0 100644 --- a/modules/proxy/NWGNUproxylbm_req +++ b/modules/proxy/NWGNUproxylbm_req @@ -19,6 +19,7 @@ XINCDIRS += \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(AP_WORK)/modules/proxy \ $(AP_WORK)/modules/http \ $(NWOS) \ $(EOLIST) diff --git a/modules/proxy/NWGNUproxylbm_traf b/modules/proxy/NWGNUproxylbm_traf index 1960453b..1927d626 100644 --- a/modules/proxy/NWGNUproxylbm_traf +++ b/modules/proxy/NWGNUproxylbm_traf @@ -19,6 +19,7 @@ XINCDIRS += \ $(APR)/include \ $(APRUTIL)/include \ $(AP_WORK)/include \ + $(AP_WORK)/modules/proxy \ $(AP_WORK)/modules/http \ $(NWOS) \ $(EOLIST) diff --git a/modules/proxy/ajp_header.c b/modules/proxy/ajp_header.c index dc86defa..3e906514 100644 --- a/modules/proxy/ajp_header.c +++ b/modules/proxy/ajp_header.c @@ -139,7 +139,7 @@ static const unsigned char sc_for_req_method_table[] = { SC_M_PUT, SC_M_POST, SC_M_DELETE, - 0, /* M_DELETE */ + 0, /* M_CONNECT */ SC_M_OPTIONS, SC_M_TRACE, 0, /* M_PATCH */ diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index f9a80090..431efb87 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -44,7 +44,6 @@ APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup, * can't trust directory_walk/file_walk since these are * not in our filesystem. Prevents mod_http from serving * the TRACE request we will set aside to handle later. - * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy: * fix_ups: convert the URL stored in the filename to the * canonical form. * handler: handle proxy requests diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 5ad91fb5..0bce5065 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -534,6 +534,18 @@ PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, cha char **passwordp, char **hostp, apr_port_t *port); PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message); PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); + +/** Test whether the hostname/address of the request are blocked by the ProxyBlock + * configuration. + * @param r request + * @param conf server configuration + * @param hostname hostname from request URI + * @param addr resolved address of hostname, or NULL if not known + * @return OK on success, or else an errro + */ +PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf, + const char *hostname, apr_sockaddr_t *addr); + PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r); /* DEPRECATED (will be replaced with ap_proxy_connect_backend */ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, request_rec *); diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c index 93cb1530..3736156a 100644 --- a/modules/proxy/mod_proxy_ajp.c +++ b/modules/proxy/mod_proxy_ajp.c @@ -207,7 +207,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, /* send request headers */ status = ajp_send_header(conn->sock, r, maxsize, uri); if (status != APR_SUCCESS) { - conn->close++; + conn->close = 1; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00868) "request failed to %pI (%s)", conn->worker->cp->addr, @@ -234,7 +234,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, status = ajp_alloc_data_msg(r->pool, &buff, &bufsiz, &msg); if (status != APR_SUCCESS) { /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00869) "ajp_alloc_data_msg failed"); return HTTP_INTERNAL_SERVER_ERROR; @@ -255,7 +255,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, if (status != APR_SUCCESS) { /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00871) "ap_get_brigade failed"); apr_brigade_destroy(input_brigade); @@ -275,7 +275,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, status = apr_brigade_flatten(input_brigade, buff, &bufsiz); if (status != APR_SUCCESS) { /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; apr_brigade_destroy(input_brigade); ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00874) "apr_brigade_flatten"); @@ -290,7 +290,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, ajp_msg_log(r, msg, "First ajp_send_data_msg: ajp_ilink_send packet dump"); if (status != APR_SUCCESS) { /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; apr_brigade_destroy(input_brigade); ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00876) "send failed to %pI (%s)", @@ -319,7 +319,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, * for later resusage by the next request again. * Close it to clean things up. */ - conn->close++; + conn->close = 1; return HTTP_BAD_REQUEST; } } @@ -330,7 +330,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, (ajp_msg_t **)&(conn->data)); if (status != APR_SUCCESS) { /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; apr_brigade_destroy(input_brigade); ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00878) "read response failed from %pI (%s)", @@ -559,7 +559,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, * But: Close this connection to the backend. */ if (r->connection->aborted) { - conn->close++; + conn->close = 1; output_failed = 0; result = CMD_AJP13_END_RESPONSE; request_ended = 1; @@ -597,7 +597,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, "Processing of request failed backend: %i, " "output: %i", backend_failed, output_failed); /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; /* Return DONE to avoid error messages being added to the stream */ if (data_sent) { rv = DONE; @@ -607,7 +607,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00891) "Processing of request didn't terminate cleanly"); /* We had a failure: Close connection to backend */ - conn->close++; + conn->close = 1; backend_failed = 1; /* Return DONE to avoid error messages being added to the stream */ if (data_sent) { @@ -616,7 +616,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, } else if (!conn_reuse) { /* Our backend signalled connection close */ - conn->close++; + conn->close = 1; } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00892) @@ -679,7 +679,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r, apr_brigade_destroy(output_brigade); if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) { - conn->close++; + conn->close = 1; } return rv; @@ -701,29 +701,15 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker, int retry; proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_module); - - /* - * Note: Memory pool allocation. - * A downstream keepalive connection is always connected to the existence - * (or not) of an upstream keepalive connection. If this is not done then - * load balancing against multiple backend servers breaks (one backend - * server ends up taking 100% of the load), and the risk is run of - * downstream keepalive connections being kept open unnecessarily. This - * keeps webservers busy and ties up resources. - * - * As a result, we allocate all sockets out of the upstream connection - * pool, and when we want to reuse a socket, we check first whether the - * connection ID of the current upstream connection is the same as that - * of the connection when the socket was opened. - */ - apr_pool_t *p = r->connection->pool; - apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri)); - + apr_pool_t *p = r->pool; + apr_uri_t *uri; if (strncasecmp(url, "ajp:", 4) != 0) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00894) "declining URL %s", url); return DECLINED; } + + uri = apr_palloc(p, sizeof(*uri)); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00895) "serving URL %s", url); /* create space for state information */ @@ -772,7 +758,7 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker, * TCP connection gets closed and try it once again. */ if (status != APR_SUCCESS) { - backend->close++; + backend->close = 1; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00897) "cping/cpong failed to %pI (%s)", worker->cp->addr, worker->s->hostname); diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index 96e0901e..1feb2d7c 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -437,6 +437,17 @@ static void force_recovery(proxy_balancer *balancer, server_rec *s) } } +static apr_status_t decrement_busy_count(void *worker_) +{ + proxy_worker *worker = worker_; + + if (worker->s->busy) { + worker->s->busy--; + } + + return APR_SUCCESS; +} + static int proxy_balancer_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, @@ -570,6 +581,8 @@ static int proxy_balancer_pre_request(proxy_worker **worker, } (*worker)->s->busy++; + apr_pool_cleanup_register(r->pool, *worker, decrement_busy_count, + apr_pool_cleanup_null); /* Add balancer/worker info to env. */ apr_table_setn(r->subprocess_env, @@ -623,7 +636,7 @@ static int proxy_balancer_post_request(proxy_worker *worker, for (i = 0; i < balancer->errstatuses->nelts; i++) { int val = ((int *)balancer->errstatuses->elts)[i]; if (r->status == val) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01174) + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01174) "%s: Forcing worker (%s) into error state " "due to status code %d matching 'failonstatus' " "balancer parameter", @@ -642,11 +655,7 @@ static int proxy_balancer_post_request(proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01176) "proxy_balancer_post_request for (%s)", balancer->s->name); - if (worker && worker->s->busy) - worker->s->busy--; - return OK; - } static void recalc_factors(proxy_balancer *balancer) @@ -744,7 +753,6 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, s = s->next; continue; } - if (conf->balancers->nelts) { conf->max_balancers = conf->balancers->nelts + conf->bgrowth; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01178) "Doing balancers create: %d, %d (%d)", diff --git a/modules/proxy/mod_proxy_connect.c b/modules/proxy/mod_proxy_connect.c index 9a14eb71..0cf5693c 100644 --- a/modules/proxy/mod_proxy_connect.c +++ b/modules/proxy/mod_proxy_connect.c @@ -205,7 +205,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, conn_rec *backconn; apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc); - apr_status_t err, rv; + apr_status_t rv; apr_size_t nbytes; char buffer[HUGE_STRING_LEN]; apr_socket_t *client_socket = ap_get_conn_socket(c); @@ -216,7 +216,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, const apr_pollfd_t *signalled; apr_int32_t pollcnt, pi; apr_int16_t pollevent; - apr_sockaddr_t *uri_addr, *connect_addr; + apr_sockaddr_t *nexthop; apr_uri_t uri; const char *connectname; @@ -246,37 +246,32 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01019) "connecting %s to %s:%d", url, uri.hostname, uri.port); - /* do a DNS lookup for the destination host */ - err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, - 0, p); - if (APR_SUCCESS != err) { + /* Determine host/port of next hop; from request URI or of a proxy. */ + connectname = proxyname ? proxyname : uri.hostname; + connectport = proxyname ? proxyport : uri.port; + + /* Do a DNS lookup for the next hop */ + rv = apr_sockaddr_info_get(&nexthop, connectname, APR_UNSPEC, + connectport, 0, p); + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO() + "failed to resolve hostname '%s'", connectname); return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, "DNS lookup failure for: ", - uri.hostname, NULL)); + connectname, NULL)); } - /* are we connecting directly, or via a proxy? */ - if (proxyname) { - connectname = proxyname; - connectport = proxyport; - err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, - proxyport, 0, p); - } - else { - connectname = uri.hostname; - connectport = uri.port; - connect_addr = uri_addr; + /* Check ProxyBlock directive on the hostname/address. */ + if (ap_proxy_checkproxyblock2(r, conf, uri.hostname, + proxyname ? NULL : nexthop) != OK) { + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); } + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "connecting to remote proxy %s on port %d", connectname, connectport); - /* check if ProxyBlock directive on this host */ - if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) { - return ap_proxyerror(r, HTTP_FORBIDDEN, - "Connect to remote machine blocked"); - } - /* Check if it is an allowed port */ if(!allowed_port(c_conf, uri.port)) { return ap_proxyerror(r, HTTP_FORBIDDEN, @@ -289,15 +284,6 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, * We have determined who to connect to. Now make the connection. */ - /* get all the possible IP addresses for the destname and loop through them - * until we get a successful connection - */ - if (APR_SUCCESS != err) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - apr_pstrcat(p, "DNS lookup failure for: ", - connectname, NULL)); - } - /* * At this point we have a list of one or more IP addresses of * the machine to connect to. If configured, reorder this @@ -308,7 +294,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, * For now we do nothing, ie we get DNS round robin. * XXX FIXME */ - failed = ap_proxy_connect_to_backend(&sock, "CONNECT", connect_addr, + failed = ap_proxy_connect_to_backend(&sock, "CONNECT", nexthop, connectname, conf, r); /* handle a permanent error from the above loop */ @@ -355,7 +341,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, /* peer reset */ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021) "an error occurred creating a new connection " - "to %pI (%s)", connect_addr, connectname); + "to %pI (%s)", nexthop, connectname); apr_socket_close(sock); return HTTP_INTERNAL_SERVER_ERROR; } @@ -370,7 +356,7 @@ static int proxy_connect_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, "connection complete to %pI (%s)", - connect_addr, connectname); + nexthop, connectname); apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu", backconn->local_addr->port)); diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c index d0df5fa1..0f844163 100644 --- a/modules/proxy/mod_proxy_fcgi.c +++ b/modules/proxy/mod_proxy_fcgi.c @@ -748,10 +748,10 @@ recv_again: apr_brigade_cleanup(ob); tmp_b = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ob, tmp_b); + r->status = status; ap_pass_brigade(r->output_filters, ob); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01070) "Error parsing script headers"); - r->status = status; rv = APR_EINVAL; break; } diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c index d5aabd69..33237d6f 100644 --- a/modules/proxy/mod_proxy_ftp.c +++ b/modules/proxy/mod_proxy_ftp.c @@ -1143,7 +1143,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, } /* check if ProxyBlock directive on this host */ - if (OK != ap_proxy_checkproxyblock(r, conf, connect_addr)) { + if (OK != ap_proxy_checkproxyblock2(r, conf, connectname, connect_addr)) { return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } @@ -1725,7 +1725,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, if (len != 0) buf = apr_pstrcat(p, "LIST ", path, CRLF, NULL); else if (cwd == NULL || strchr(cwd, '/') != NULL) - buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL); + buf = "LIST -lag" CRLF; else buf = "LIST" CRLF; } diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 64b95a2f..243c9a5e 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -795,14 +795,14 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r, } buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL); force10 = 1; - p_conn->close++; + p_conn->close = 1; } else { buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL); force10 = 0; } if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) { origin->keepalive = AP_CONN_CLOSE; - p_conn->close++; + p_conn->close = 1; } ap_xlate_proto_to_ascii(buf, strlen(buf)); e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc); @@ -1019,7 +1019,7 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r, */ if (!r->kept_body && r->main) { /* XXX: Why DON'T sub-requests use keepalives? */ - p_conn->close++; + p_conn->close = 1; if (old_cl_val) { old_cl_val = NULL; apr_table_unset(r->headers_in, "Content-Length"); @@ -1056,7 +1056,7 @@ int ap_proxy_http_request(apr_pool_t *p, request_rec *r, apr_table_unset(r->headers_in, "Content-Length"); old_cl_val = NULL; origin->keepalive = AP_CONN_CLOSE; - p_conn->close++; + p_conn->close = 1; } /* Prefetch MAX_MEM_SPOOL bytes @@ -1705,7 +1705,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01106) "bad HTTP/%d.%d header returned by %s (%s)", major, minor, r->uri, r->method); - backend->close += 1; + backend->close = 1; /* * ap_send_error relies on a headers_out to be present. we * are in a bad position here.. so force everything we send out @@ -1746,7 +1746,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, "server %s:%d returned Transfer-Encoding" " and Content-Length", backend->hostname, backend->port); - backend->close += 1; + backend->close = 1; } /* @@ -1755,8 +1755,9 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, */ te = apr_table_get(r->headers_out, "Transfer-Encoding"); /* strip connection listed hop-by-hop headers from response */ - backend->close += ap_find_token(p, - apr_table_get(r->headers_out, "Connection"), "close"); + if (ap_find_token(p, apr_table_get(r->headers_out, "Connection"), + "close")) + backend->close = 1; ap_proxy_clear_connection(p, r->headers_out); if ((buf = apr_table_get(r->headers_out, "Content-Type"))) { ap_set_content_type(r, apr_pstrdup(p, buf)); @@ -1801,7 +1802,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* cancel keepalive if HTTP/1.0 or less */ if ((major < 1) || (minor < 1)) { - backend->close += 1; + backend->close = 1; origin->keepalive = AP_CONN_CLOSE; } } else { @@ -1809,7 +1810,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, backasswards = 1; r->status = 200; r->status_line = "200 OK"; - backend->close += 1; + backend->close = 1; } if (ap_is_HTTP_INFO(proxy_status)) { @@ -1964,8 +1965,9 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* ap_get_brigade will return success with an empty brigade * for a non-blocking read which would block: */ - if (APR_STATUS_IS_EAGAIN(rv) - || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) { + if (mode == APR_NONBLOCK_READ + && (APR_STATUS_IS_EAGAIN(rv) + || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) { /* flush to the client and switch to blocking mode */ e = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); @@ -2236,8 +2238,24 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker, * so. */ if (is_ssl) { + proxy_dir_conf *dconf; + const char *ssl_hostname; + + /* + * In the case of ProxyPreserveHost on use the hostname of + * the request if present otherwise use the one from the + * backend request URI. + */ + dconf = ap_get_module_config(r->per_dir_config, &proxy_module); + if ((dconf->preserve_host != 0) && (r->hostname != NULL)) { + ssl_hostname = r->hostname; + } + else { + ssl_hostname = uri->hostname; + } + apr_table_set(backend->connection->notes, "proxy-request-hostname", - uri->hostname); + ssl_hostname); } } diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index fe2ac43e..4aaaf9bc 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -373,7 +373,7 @@ PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *mes NULL)); /* Allow "error-notes" string to be printed by ap_send_error_response() */ - apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*")); + apr_table_setn(r->notes, "verbose-error-to", "*"); r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00898) "%s returned by %s", message, @@ -759,48 +759,63 @@ static int proxy_match_word(struct dirconn_entry *This, request_rec *r) return host != NULL && ap_strstr_c(host, This->name) != NULL; } -/* checks whether a host in uri_addr matches proxyblock */ +/* Backwards-compatible interface. */ PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr) { + return ap_proxy_checkproxyblock2(r, conf, uri_addr->hostname, uri_addr); +} + +#define MAX_IP_STR_LEN (46) + +PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf, + const char *hostname, apr_sockaddr_t *addr) +{ int j; - apr_sockaddr_t * src_uri_addr = uri_addr; + /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */ for (j = 0; j < conf->noproxies->nelts; j++) { struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; - struct apr_sockaddr_t *conf_addr = npent[j].addr; - uri_addr = src_uri_addr; + struct apr_sockaddr_t *conf_addr; + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "checking remote machine [%s] against [%s]", - uri_addr->hostname, npent[j].name); - if (ap_strstr_c(uri_addr->hostname, npent[j].name) - || npent[j].name[0] == '*') { + hostname, npent[j].name); + if (ap_strstr_c(hostname, npent[j].name) || npent[j].name[0] == '*') { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00916) "connect to remote machine %s blocked: name %s " - "matched", uri_addr->hostname, npent[j].name); + "matched", hostname, npent[j].name); return HTTP_FORBIDDEN; } - while (conf_addr) { - uri_addr = src_uri_addr; - while (uri_addr) { - char *conf_ip; - char *uri_ip; - apr_sockaddr_ip_get(&conf_ip, conf_addr); - apr_sockaddr_ip_get(&uri_ip, uri_addr); + + /* No IP address checks if no IP address was passed in, + * i.e. the forward address proxy case, where this server does + * not resolve the hostname. */ + if (!addr) + continue; + + for (conf_addr = npent[j].addr; conf_addr; conf_addr = conf_addr->next) { + char caddr[MAX_IP_STR_LEN], uaddr[MAX_IP_STR_LEN]; + apr_sockaddr_t *uri_addr; + + if (apr_sockaddr_ip_getbuf(caddr, sizeof caddr, conf_addr)) + continue; + + for (uri_addr = addr; uri_addr; uri_addr = uri_addr->next) { + if (apr_sockaddr_ip_getbuf(uaddr, sizeof uaddr, uri_addr)) + continue; ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, - "ProxyBlock comparing %s and %s", conf_ip, - uri_ip); - if (!apr_strnatcasecmp(conf_ip, uri_ip)) { + "ProxyBlock comparing %s and %s", caddr, uaddr); + if (!strcmp(caddr, uaddr)) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00917) - "connect to remote machine %s blocked: " - "IP %s matched", uri_addr->hostname, conf_ip); + "connect to remote machine %s blocked: " + "IP %s matched", hostname, caddr); return HTTP_FORBIDDEN; } - uri_addr = uri_addr->next; } - conf_addr = conf_addr->next; } } + return OK; } @@ -852,7 +867,7 @@ PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, (balancer = ap_proxy_get_balancer(r->pool, sconf, real, 1))) { int n, l3 = 0; proxy_worker **worker = (proxy_worker **)balancer->workers->elts; - const char *urlpart = ap_strchr_c(real, '/'); + const char *urlpart = ap_strchr_c(real + sizeof(BALANCER_PREFIX) - 1, '/'); if (urlpart) { if (!urlpart[1]) urlpart = NULL; @@ -2128,7 +2143,8 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, } } /* check if ProxyBlock directive on this host */ - if (OK != ap_proxy_checkproxyblock(r, conf, conn->addr)) { + if (OK != ap_proxy_checkproxyblock2(r, conf, uri->hostname, + proxyname ? NULL : conn->addr)) { return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } diff --git a/modules/session/config.m4 b/modules/session/config.m4 index 719fe915..7a38185d 100644 --- a/modules/session/config.m4 +++ b/modules/session/config.m4 @@ -47,7 +47,7 @@ if test "$session_mods_enable_crypto" != "no"; then ], [ap_HAVE_APR_CRYPTO="yes"], [ap_HAVE_APR_CRYPTO="no"]) CPPFLAGS="$saved_CPPFLAGS" if test $ap_HAVE_APR_CRYPTO = "no"; then - AC_MSG_WARN([Your APR does not include SSL/EVP support.]) + AC_MSG_WARN([Your APR does not include SSL/EVP support. To enable it: configure --with-crypto]) if test "$enable_session_crypto" != "" -a "$enable_session_crypto" != "no"; then AC_MSG_ERROR([mod_session_crypto cannot be enabled]) fi diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c index e053619a..7f855c72 100644 --- a/modules/session/mod_session.c +++ b/modules/session/mod_session.c @@ -373,7 +373,7 @@ static apr_status_t session_identity_decode(request_rec * r, session_rec * z) } /* decode what we have */ - encoded = apr_pstrcat(r->pool, z->encoded, NULL); + encoded = apr_pstrdup(r->pool, z->encoded); pair = apr_strtok(encoded, sep, &last); while (pair && pair[0]) { char *plast = NULL; diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index fe7aeae5..0872da8a 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -138,6 +138,9 @@ static const command_rec ssl_config_cmds[] = { "('[+-][" SSL_PROTOCOLS "] ...' - see manual)") SSL_CMD_SRV(HonorCipherOrder, FLAG, "Use the server's cipher ordering preference") + SSL_CMD_SRV(Compression, FLAG, + "Enable SSL level compression" + "(`on', `off')") SSL_CMD_SRV(InsecureRenegotiation, FLAG, "Enable support for insecure renegotiation") SSL_CMD_ALL(UserName, TAKE1, diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 6aab7641..15993f16 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -207,6 +207,9 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p) #ifdef HAVE_FIPS sc->fips = UNSET; #endif +#ifndef OPENSSL_NO_COMP + sc->compression = UNSET; +#endif modssl_ctx_init_proxy(sc, p); @@ -328,6 +331,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv) #ifdef HAVE_FIPS cfgMergeBool(fips); #endif +#ifndef OPENSSL_NO_COMP + cfgMergeBool(compression); +#endif modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy); @@ -663,6 +669,23 @@ static const char *ssl_cmd_check_file(cmd_parms *parms, } +const char *ssl_cmd_SSLCompression(cmd_parms *cmd, void *dcfg, int flag) +{ +#if !defined(OPENSSL_NO_COMP) + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); +#ifndef SSL_OP_NO_COMPRESSION + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err) + return "This version of openssl does not support configuring " + "compression within <VirtualHost> sections."; +#endif + sc->compression = flag ? TRUE : FALSE; + return NULL; +#else + return "Setting Compression mode unsupported; not implemented by the SSL library"; +#endif +} + const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag) { #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 5d816478..7c121737 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -349,7 +349,7 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, else { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01885) "FIPS mode failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } } } @@ -438,7 +438,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) "Init: Failed to load Crypto Device API `%s'", mc->szCryptoDevice); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } if (strEQ(mc->szCryptoDevice, "chil")) { @@ -450,7 +450,7 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) "Init: Failed to enable Crypto Device API `%s'", mc->szCryptoDevice); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890) "Init: loaded Crypto Device API `%s'", @@ -473,7 +473,7 @@ static void ssl_init_server_check(server_rec *s, if (!mctx->pks->cert_files[0] && !mctx->pkcs7) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01891) "No SSL Certificate set [hint: SSLCertificateFile]"); - ssl_die(); + ssl_die(s); } /* @@ -489,7 +489,7 @@ static void ssl_init_server_check(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01892) "Illegal attempt to re-initialise SSL for server " "(SSLEngine On should go in the VirtualHost, not in global scope.)"); - ssl_die(); + ssl_die(s); } } @@ -515,7 +515,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s, "Unable to initialize TLS servername extension " "callback (incompatible OpenSSL version?)"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } #ifdef HAVE_OCSP_STAPLING @@ -546,7 +546,7 @@ static void ssl_init_ctx_protocol(server_rec *s, if (protocol == SSL_PROTOCOL_NONE) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02231) "No SSL protocols available [hint: SSLProtocol]"); - ssl_die(); + ssl_die(s); } cp = apr_pstrcat(p, @@ -622,6 +622,18 @@ static void ssl_init_ctx_protocol(server_rec *s, } #endif + +#ifndef OPENSSL_NO_COMP + if (sc->compression == FALSE) { +#ifdef SSL_OP_NO_COMPRESSION + /* OpenSSL >= 1.0 only */ + SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); +#elif OPENSSL_VERSION_NUMBER >= 0x00908000L + sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); +#endif + } +#endif + #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION if (sc->insecure_reneg == TRUE) { SSL_CTX_set_options(ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); @@ -731,7 +743,7 @@ static void ssl_init_ctx_verify(server_rec *s, "Unable to configure verify locations " "for client authentication"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } if (mctx->pks && (mctx->pks->ca_name_file || mctx->pks->ca_name_path)) { @@ -746,7 +758,7 @@ static void ssl_init_ctx_verify(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01896) "Unable to determine list of acceptable " "CA certificates for client authentication"); - ssl_die(); + ssl_die(s); } SSL_CTX_set_client_CA_list(ctx, ca_list); @@ -791,7 +803,7 @@ static void ssl_init_ctx_cipher_suite(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01898) "Unable to configure permitted SSL ciphers"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } } @@ -815,7 +827,7 @@ static void ssl_init_ctx_crl(server_rec *s, "Host %s: CRL checking has been enabled, but " "neither %sCARevocationFile nor %sCARevocationPath " "is configured", mctx->sc->vhost_id, cfgp, cfgp); - ssl_die(); + ssl_die(s); } return; } @@ -829,7 +841,7 @@ static void ssl_init_ctx_crl(server_rec *s, "Host %s: unable to configure X.509 CRL storage " "for certificate revocation", mctx->sc->vhost_id); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } switch (mctx->crl_check_mode) { @@ -915,7 +927,7 @@ static void ssl_init_ctx_cert_chain(server_rec *s, if (n < 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01903) "Failed to configure CA certificate chain!"); - ssl_die(); + ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01904) @@ -973,14 +985,14 @@ static int ssl_server_import_cert(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02233) "Unable to import %s server certificate", type); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) <= 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02234) "Unable to configure %s server certificate", type); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } #ifdef HAVE_OCSP_STAPLING @@ -1029,14 +1041,14 @@ static int ssl_server_import_key(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237) "Unable to import %s server private key", type); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02238) "Unable to configure %s server private key", type); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } /* @@ -1188,7 +1200,7 @@ static void ssl_init_server_certs(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01910) "Oops, no " KEYTYPES " server certificate found " "for '%s:%d'?!", s->server_hostname, s->port); - ssl_die(); + ssl_die(s); } for (i = 0; i < SSL_AIDX_MAX; i++) { @@ -1208,7 +1220,7 @@ static void ssl_init_server_certs(server_rec *s, )) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01911) "Oops, no " KEYTYPES " server private key found?!"); - ssl_die(); + ssl_die(s); } } @@ -1238,7 +1250,7 @@ static void ssl_init_ticket_key(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02286) "Failed to open ticket key file %s: (%d) %pm", path, rv, &rv); - ssl_die(); + ssl_die(s); } rv = apr_file_read_full(fp, &buf[0], TLSEXT_TICKET_KEY_LEN, &len); @@ -1247,7 +1259,7 @@ static void ssl_init_ticket_key(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02287) "Failed to read %d bytes from %s: (%d) %pm", TLSEXT_TICKET_KEY_LEN, path, rv, &rv); - ssl_die(); + ssl_die(s); } memcpy(ticket_key->key_name, buf, 16); @@ -1260,7 +1272,7 @@ static void ssl_init_ticket_key(server_rec *s, "Unable to initialize TLS session ticket key callback " "(incompatible OpenSSL version?)"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(02288) @@ -1315,7 +1327,7 @@ static void ssl_init_proxy_certs(server_rec *s, ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252) "incomplete client cert configured for SSL proxy " "(missing or encrypted private key?)"); - ssl_die(); + ssl_die(s); return; } } @@ -1338,7 +1350,7 @@ static void ssl_init_proxy_certs(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02208) "SSL proxy client cert initialization failed"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } X509_STORE_load_locations(store, pkp->ca_cert_file, NULL); @@ -1628,7 +1640,7 @@ STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02211) "Failed to open Certificate Path `%s'", ca_path); - ssl_die(); + ssl_die(s); } while ((apr_dir_read(&direntry, finfo_flags, dir)) == APR_SUCCESS) { diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index 2ffe21f4..510e1606 100644 --- a/modules/ssl/ssl_engine_io.c +++ b/modules/ssl/ssl_engine_io.c @@ -813,12 +813,12 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, /* Just use a simple request. Any request will work for this, because * we use a flag in the conn_rec->conn_vector now. The fake request just * gets the request back to the Apache core so that a response can be sent. - * - * To avoid calling back for more data from the socket, use an HTTP/0.9 - * request, and tack on an EOS bucket. + * Since we use an HTTP/1.x request, we also have to inject the empty line + * that terminates the headers, or the core will read more data from the + * socket. */ #define HTTP_ON_HTTPS_PORT \ - "GET /" CRLF + "GET / HTTP/1.0" CRLF #define HTTP_ON_HTTPS_PORT_BUCKET(alloc) \ apr_bucket_immortal_create(HTTP_ON_HTTPS_PORT, \ @@ -848,6 +848,7 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, { SSLConnRec *sslconn = myConnConfig(f->c); apr_bucket *bucket; + int send_eos = 1; switch (status) { case MODSSL_ERROR_HTTP_ON_HTTPS: @@ -857,11 +858,12 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, "trying to send HTML error page"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server); - sslconn->non_ssl_request = 1; + sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP; ssl_io_filter_disable(sslconn, f); /* fake the request line */ bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); + send_eos = 0; break; case MODSSL_ERROR_BAD_GATEWAY: @@ -877,9 +879,10 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, } APR_BRIGADE_INSERT_TAIL(bb, bucket); - bucket = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); - + if (send_eos) { + bucket = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, bucket); + } return APR_SUCCESS; } @@ -1282,6 +1285,13 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, } if (!inctx->ssl) { + SSLConnRec *sslconn = myConnConfig(f->c); + if (sslconn->non_ssl_request == NON_SSL_SEND_HDR_SEP) { + apr_bucket *bucket = apr_bucket_immortal_create(CRLF, 2, f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, bucket); + sslconn->non_ssl_request = NON_SSL_SET_ERROR_MSG; + return APR_SUCCESS; + } return ap_get_brigade(f->next, bb, mode, block, readbytes); } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 35b2a854..e514a74b 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -140,37 +140,16 @@ int ssl_hook_ReadReq(request_rec *r) return DECLINED; } - if (sslconn->non_ssl_request) { - const char *errmsg; - char *thisurl; - char *thisport = ""; - int port = ap_get_server_port(r); - - if (!ap_is_default_port(port, r)) { - thisport = apr_psprintf(r->pool, ":%u", port); - } - - thisurl = ap_escape_html(r->pool, - apr_psprintf(r->pool, "https://%s%s/", - ap_get_server_name_for_url(r), - thisport)); - - errmsg = apr_psprintf(r->pool, - "Reason: You're speaking plain HTTP " - "to an SSL-enabled server port.<br />\n" - "Instead use the HTTPS scheme to access " - "this URL, please.<br />\n" - "<blockquote>Hint: " - "<a href=\"%s\"><b>%s</b></a></blockquote>", - thisurl, thisurl); - - apr_table_setn(r->notes, "error-notes", errmsg); + if (sslconn->non_ssl_request == NON_SSL_SET_ERROR_MSG) { + apr_table_setn(r->notes, "error-notes", + "Reason: You're speaking plain HTTP to an SSL-enabled " + "server port.<br />\n Instead use the HTTPS scheme to " + "access this URL, please.<br />\n"); /* Now that we have caught this error, forget it. we are done * with using SSL on this request. */ - sslconn->non_ssl_request = 0; - + sslconn->non_ssl_request = NON_SSL_OK; return HTTP_BAD_REQUEST; } diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c index 31861ca7..3f6d6edc 100644 --- a/modules/ssl/ssl_engine_log.c +++ b/modules/ssl/ssl_engine_log.c @@ -63,12 +63,23 @@ static const char *ssl_log_annotation(const char *error) return ssl_log_annotate[i].cpAnnotation; } -void ssl_die(void) +void ssl_die(server_rec *s) { + if (s != NULL && s->is_virtual && s->error_fname != NULL) + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02311) + "Fatal error initialising mod_ssl, exiting. " + "See %s for more information", + ap_server_root_relative(s->process->pool, + s->error_fname)); + else + ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02312) + "Fatal error initialising mod_ssl, exiting."); + /* * This is used for fatal errors and here * it is common module practice to really * exit from the complete program. + * XXX: The config hooks should return errors instead of calling exit(). */ exit(1); } diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c index 1fa4a2ef..23ccaf4a 100644 --- a/modules/ssl/ssl_engine_pphrase.c +++ b/modules/ssl/ssl_engine_pphrase.c @@ -196,7 +196,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) "Server should be SSL-aware but has no certificate " "configured [Hint: SSLCertificateFile] (%s:%d)", pServ->defn_name, pServ->defn_line_number); - ssl_die(); + ssl_die(pServ); } /* Bitmasks for all key algorithms configured for this server; @@ -225,14 +225,14 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201) "Init: Can't open server certificate file %s", szPath); - ssl_die(); + ssl_die(s); } if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241) "Init: Unable to read server certificate from" " file %s", szPath); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202) "Init: Read server certificate from '%s'", @@ -249,7 +249,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) "Init: Multiple %s server certificates not " "allowed", an); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } algoCert |= at; @@ -328,7 +328,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243) "Init: Can't open server private key file " "%s",szPath); - ssl_die(); + ssl_die(s); } /* @@ -425,7 +425,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) "Init: SSLPassPhraseDialog builtin is not " "supported on Win32 (key file " "%s)", szPath); - ssl_die(); + ssl_die(s); } #endif /* WIN32 */ @@ -464,7 +464,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) apr_file_printf(writetty, "**Stopped\n"); } } - ssl_die(); + ssl_die(pServ); } /* If a cached private key was found, nothing more to do @@ -479,7 +479,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) "file %s [Hint: Perhaps it is in a separate file? " " See SSLCertificateKeyFile]", szPath); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } /* @@ -493,7 +493,7 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) "Init: Multiple %s server private keys not " "allowed", an); ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); - ssl_die(); + ssl_die(s); } algoKey |= at; diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 1b5d0428..f2fb7d52 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -180,6 +180,11 @@ #define HAVE_TLSV1_X #endif +#if !defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION) \ + && OPENSSL_VERSION_NUMBER < 0x00908000L +#define OPENSSL_NO_COMP +#endif + /* mod_ssl headers */ #include "ssl_util_ssl.h" @@ -454,7 +459,11 @@ typedef struct { int verify_depth; int is_proxy; int disabled; - int non_ssl_request; + enum { + NON_SSL_OK = 0, /* is SSL request, or error handling completed */ + NON_SSL_SEND_HDR_SEP, /* Need to send the header separator */ + NON_SSL_SET_ERROR_MSG /* Need to set the error message */ + } non_ssl_request; /* Track the handshake/renegotiation state for the connection so * that all client-initiated renegotiations can be rejected, as a @@ -669,6 +678,9 @@ struct SSLSrvConfigRec { #ifdef HAVE_FIPS BOOL fips; #endif +#ifndef OPENSSL_NO_COMP + BOOL compression; +#endif }; /** @@ -723,6 +735,7 @@ const char *ssl_cmd_SSLCARevocationPath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCARevocationFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLHonorCipherOrder(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLCompression(cmd_parms *, void *, int flag); const char *ssl_cmd_SSLVerifyClient(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLVerifyDepth(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLSessionCache(cmd_parms *, void *, const char *); @@ -902,7 +915,7 @@ int ssl_stapling_mutex_reinit(server_rec *, apr_pool_t *); #define SSL_STAPLING_MUTEX_TYPE "ssl-stapling" /** Logfile Support */ -void ssl_die(void); +void ssl_die(server_rec *); void ssl_log_ssl_error(const char *, int, int, server_rec *); /* ssl_log_xerror, ssl_log_cxerror and ssl_log_rxerror are wrappers for the diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c index 2c8d1bc8..d32f8e1d 100644 --- a/modules/ssl/ssl_scache.c +++ b/modules/ssl/ssl_scache.c @@ -63,7 +63,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) if (rv) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01872) "Could not initialize stapling cache. Exiting."); - ssl_die(); + ssl_die(s); } } #endif @@ -88,7 +88,7 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p) if (rv) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01874) "Could not initialize session cache. Exiting."); - ssl_die(); + ssl_die(s); } } diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index 6b5a7de6..475fe4d2 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -76,8 +76,7 @@ apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd, return NULL; if (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS) return NULL; - if ((proc = (apr_proc_t *)apr_pcalloc(p, sizeof(apr_proc_t))) == NULL) - return NULL; + proc = apr_pcalloc(p, sizeof(apr_proc_t)); if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS) return NULL; return proc->out; @@ -287,7 +286,7 @@ STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7) f = fopen(pkcs7, "r"); if (!f) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02212) "Can't open %s", pkcs7); - ssl_die(); + ssl_die(s); } p7 = PEM_read_PKCS7(f, NULL, NULL, NULL); @@ -314,13 +313,13 @@ STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7) default: ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02213) "Don't understand PKCS7 file %s", pkcs7); - ssl_die(); + ssl_die(s); } if (!certs) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02214) "No certificates in %s", pkcs7); - ssl_die(); + ssl_die(s); } fclose(f); @@ -376,24 +375,11 @@ static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file, * allocated memory from a pool, create a subpool that we can blow * away in the destruction callback. */ - rv = apr_pool_create(&p, dynlockpool); - if (rv != APR_SUCCESS) { - ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, dynlockpool, - APLOGNO(02183) "Failed to create subpool for dynamic lock"); - return NULL; - } - + apr_pool_create(&p, dynlockpool); ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, p, "Creating dynamic lock"); - value = (struct CRYPTO_dynlock_value *)apr_palloc(p, - sizeof(struct CRYPTO_dynlock_value)); - if (!value) { - ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, 0, p, - APLOGNO(02185) "Failed to allocate dynamic lock structure"); - return NULL; - } - + value = apr_palloc(p, sizeof(struct CRYPTO_dynlock_value)); value->pool = p; /* Keep our own copy of the place from which we were created, using our own pool. */ diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c index 94ef4cd0..e5c5e58d 100644 --- a/modules/ssl/ssl_util_ocsp.c +++ b/modules/ssl/ssl_util_ocsp.c @@ -153,7 +153,13 @@ static char *get_line(apr_bucket_brigade *bbout, apr_bucket_brigade *bbin, return NULL; } - if (len && line[len-1] != APR_ASCII_LF) { + if (len == 0) { + ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(02321) + "empty response from OCSP server"); + return NULL; + } + + if (line[len-1] != APR_ASCII_LF) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01979) "response header line too long from OCSP server"); return NULL; diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c index 3ff08dcc..89be7f53 100644 --- a/modules/ssl/ssl_util_stapling.c +++ b/modules/ssl/ssl_util_stapling.c @@ -662,12 +662,12 @@ void modssl_init_stapling(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, if (mc->stapling_cache == NULL) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01958) "SSLStapling: no stapling cache available"); - ssl_die(); + ssl_die(s); } if (ssl_stapling_mutex_init(s, ptemp) == FALSE) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01959) "SSLStapling: cannot initialise stapling mutex"); - ssl_die(); + ssl_die(s); } /* Set some default values for parameters if they are not set */ if (mctx->stapling_resptime_skew == UNSET) { |
