All;
I am attaching a patch that will allow for a comma separated list of
directives permissable for override. I am doing this because the
existing AllowOverride list of override-able directives sometimes has
too many things, sometimes allows more than is documented and it also
forces third party modules into one of the four predefined lists. With
this patch, an AllowOverrideList directive is added for the server admin
to specify individual directives for override. No other functionality
changes. FWIW, In my particular use case, I would like to grant a
content admin the ability to implement a server-side redirect in
.htacess, but would NOT like to grant them the ability to stand up a
proxy via "RewriteRule / http://someOtherLocation/ [P]" (which is what
would happen if FileInfo was set in AllowOverride). Note how Redirect
and friends are not documented as directives in core.html#allowoverride
for FileInfo... another patch, another day :) .
With that in mind, I'd like to request comments on the idea and the
implementation supplied. I can see that there could be efficiency gained
without having to "tolower" each directive before comparison in
invoke_cmd, but I could not find a way outside of server/config.c
(server/core.c constructs the list I am using) to look up a directive's
normal case like ReDiREcT becomes "Redirect" before the call to
invoke_cmd as a result of ml = apr_hash_get(ap_config_hash, dir,
APR_HASH_KEY_STRING);.
The second thing I'd like to bring up is that I see a lot of use in
backporting this, but I have made a change that I think would be
considered an API change (added param to ap_parse_htaccess in
include/http_config.h). Since I know this is not allowed, would it be
acceptable to rename the new ap_parse_htaccess function and implement a
wrapper as ap_parse_htaccess? I would foresee that such a wrapper would
issue a deprecation warning when called, but will call ap_parse_htaccess
with a NULL in place of the (new) override_list.
cheers!
--
--
Daniel Ruggeri
diff -ru httpd-2.3.12-beta/include/http_config.h
httpd-2.3.12-beta.AllowOverrideList/include/http_config.h
--- httpd-2.3.12-beta/include/http_config.h 2011-05-09 10:36:32.000000000
-0500
+++ httpd-2.3.12-beta.AllowOverrideList/include/http_config.h 2011-07-19
18:23:10.000000000 -0500
@@ -28,6 +28,7 @@
#include "util_cfgtree.h"
#include "ap_config.h"
+#include "apr_tables.h"
#ifdef __cplusplus
extern "C" {
@@ -282,6 +283,8 @@
int override;
/** Which allow-override-opts bits are set */
int override_opts;
+ /** Table of directives allowed per AllowOverrideList */
+ apr_table_t *override_list;
/** Which methods are <Limit>ed */
apr_int64_t limited;
/** methods which are limited */
@@ -1064,6 +1067,7 @@
* @param r The request currently being served
* @param override Which overrides are active
* @param override_opts Which allow-override-opts bits are set
+ * @param override_list Table of directives allowed for override
* @param path The path to the htaccess file
* @param access_name The list of possible names for .htaccess files
* int The status of the current request
@@ -1072,6 +1076,7 @@
request_rec *r,
int override,
int override_opts,
+ apr_table_t *override_list,
const char *path,
const char *access_name);
diff -ru httpd-2.3.12-beta/include/http_core.h
httpd-2.3.12-beta.AllowOverrideList/include/http_core.h
--- httpd-2.3.12-beta/include/http_core.h 2011-05-09 13:43:50.000000000
-0500
+++ httpd-2.3.12-beta.AllowOverrideList/include/http_core.h 2011-07-19
18:23:10.000000000 -0500
@@ -31,6 +31,7 @@
#include "apr_optional.h"
#include "util_filter.h"
#include "ap_expr.h"
+#include "apr_tables.h"
#include "http_config.h"
@@ -542,6 +543,9 @@
struct ap_logconf *log;
unsigned int decode_encoded_slashes : 1; /* whether to decode encoded
slashes in URLs */
+
+ /** Table of directives allowed per AllowOverrideList */
+ apr_table_t *override_list;
} core_dir_config;
/* macro to implement off by default behaviour */
diff -ru httpd-2.3.12-beta/include/httpd.h
httpd-2.3.12-beta.AllowOverrideList/include/httpd.h
--- httpd-2.3.12-beta/include/httpd.h 2011-04-25 17:49:59.000000000 -0500
+++ httpd-2.3.12-beta.AllowOverrideList/include/httpd.h 2011-07-19
18:23:10.000000000 -0500
@@ -706,6 +706,8 @@
int override;
/** the override options allowed for the .htaccess file */
int override_opts;
+ /** Table of allowed directives for override */
+ apr_table_t *override_list;
/** the configuration directives */
struct ap_conf_vector_t *htaccess;
/** the next one, or NULL if no more; N.B. never change this */
diff -ru httpd-2.3.12-beta/server/config.c
httpd-2.3.12-beta.AllowOverrideList/server/config.c
--- httpd-2.3.12-beta/server/config.c 2011-05-10 17:52:45.000000000 -0500
+++ httpd-2.3.12-beta.AllowOverrideList/server/config.c 2011-07-19
18:23:10.000000000 -0500
@@ -836,10 +836,20 @@
static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
void *mconfig, const char *args)
{
+ int override_list_ok = 0;
char *w, *w2, *w3;
const char *errmsg = NULL;
- if ((parms->override & cmd->req_override) == 0)
+ /** Have we been provided a list of acceptable directives? */
+ if(parms->override_list != NULL) {
+ char *directivelc=apr_pstrdup(parms->pool,cmd->name);
+ ap_str_tolower(directivelc);
+
+ if(apr_table_get(parms->override_list, directivelc) != NULL)
+ override_list_ok = 1;
+ }
+
+ if ((parms->override & cmd->req_override) == 0 && !override_list_ok)
return apr_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
parms->info = cmd->cmd_data;
@@ -1504,7 +1514,7 @@
*/
static cmd_parms default_parms =
-{NULL, 0, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+{NULL, 0, 0, NULL, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
AP_DECLARE(char *) ap_server_root_relative(apr_pool_t *p, const char *file)
{
@@ -2006,7 +2016,7 @@
AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
request_rec *r, int override,
- int override_opts,
+ int override_opts, apr_table_t
*override_list,
const char *d, const char *access_name)
{
ap_configfile_t *f = NULL;
@@ -2028,6 +2038,7 @@
parms = default_parms;
parms.override = override;
parms.override_opts = override_opts;
+ parms.override_list = override_list;
parms.pool = r->pool;
parms.temp_pool = r->pool;
parms.server = r->server;
diff -ru httpd-2.3.12-beta/server/core.c
httpd-2.3.12-beta.AllowOverrideList/server/core.c
--- httpd-2.3.12-beta/server/core.c 2011-05-09 10:36:32.000000000 -0500
+++ httpd-2.3.12-beta.AllowOverrideList/server/core.c 2011-07-19
18:23:10.000000000 -0500
@@ -228,6 +228,10 @@
conf->override_opts = new->override_opts;
}
+ if (conf->override_list == NULL) {
+ conf->override_list = new->override_list;
+ }
+
if (conf->response_code_strings == NULL) {
conf->response_code_strings = new->response_code_strings;
}
@@ -1556,6 +1560,33 @@
return NULL;
}
+static const char *set_override_list(cmd_parms *cmd, void *d_, const char *arg)
+{
+ core_dir_config *d = d_;
+
+ /* Throw a warning if we're in <Location> or <Files> */
+ if (ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_FILES)) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
+ "Useless use of AllowOverrideList in line %d of %s.",
+ cmd->directive->line_num, cmd->directive->filename);
+ }
+
+ char *directive;
+ char *tok_state;
+ char *arglc=apr_pstrdup(cmd->temp_pool, arg);
+
+ ap_str_tolower(arglc);
+ d->override_list = apr_table_make(cmd->pool, 1);
+
+ directive = apr_strtok(arglc, ", ", &tok_state);
+ while (directive != NULL) {
+ apr_table_set(d->override_list, directive, "1");
+ directive = apr_strtok(NULL, ", ", &tok_state);
+ }
+
+ return NULL;
+}
+
static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
{
core_dir_config *d = d_;
@@ -3669,6 +3700,9 @@
AP_INIT_RAW_ARGS("AllowOverride", set_override, NULL, ACCESS_CONF,
"Controls what groups of directives can be configured by per-directory "
"config files"),
+AP_INIT_TAKE1("AllowOverrideList", set_override_list, NULL, ACCESS_CONF,
+ "Controls what individual directives can be configured by per-directory "
+ "config files as a comma-separated list"),
AP_INIT_RAW_ARGS("Options", set_options, NULL, OR_OPTIONS,
"Set a number of attributes for a given directory"),
AP_INIT_TAKE1("DefaultType", set_default_type, NULL, OR_FILEINFO,
diff -ru httpd-2.3.12-beta/server/request.c
httpd-2.3.12-beta.AllowOverrideList/server/request.c
--- httpd-2.3.12-beta/server/request.c 2011-03-16 11:45:25.000000000 -0500
+++ httpd-2.3.12-beta.AllowOverrideList/server/request.c 2011-07-19
18:23:10.000000000 -0500
@@ -484,6 +484,7 @@
allow_options_t remove;
overrides_t override;
overrides_t override_opts;
+ apr_table_t *override_list;
} core_opts_t;
static void core_opts_merge(const ap_conf_vector_t *sec, core_opts_t *opts)
@@ -511,6 +512,11 @@
opts->override = this_dir->override;
opts->override_opts = this_dir->override_opts;
}
+
+ if (this_dir->override_list != NULL) {
+ opts->override_list = this_dir->override_list;
+ }
+
}
@@ -738,6 +744,7 @@
opts.remove = this_dir->opts_remove;
opts.override = this_dir->override;
opts.override_opts = this_dir->override_opts;
+ opts.override_list = this_dir->override_list;
/* Set aside path_info to merge back onto path_info later.
* If r->filename is a directory, we must remerge the path_info,
@@ -949,7 +956,7 @@
}
res = ap_parse_htaccess(&htaccess_conf, r, opts.override,
- opts.override_opts,
+ opts.override_opts, opts.override_list,
apr_pstrdup(r->pool, r->filename),
sconf->access_name);
if (res) {