see https://issues.apache.org/bugzilla/show_bug.cgi?id=44262
The docs for 2.0 say about AllowOverride Options:
(http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride)
"
Options Allow use of the directives controlling specific directory
features (Options and XBitHack).
"
and for 2.2 (http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride)
"
Options[=Option,...]Allow use of the directives controlling specific
directory features (Options and XBitHack). An equal sign may be given
followed by a comma (but no spaces) separated lists of options that
may be set using the Options command.
"
In 2.0 they don't specify which Options can be overwritten and in 2.2
=Option,.. is optional so I expect Options without =Option,... be
compatible with old AllowOverride Options.
The catch is that Option All isn't really all the options.
from includes/http_core.h
"
/** No directives */
#define OPT_NONE 0
/** Indexes directive */
#define OPT_INDEXES 1
/** Includes directive */
#define OPT_INCLUDES 2
/** FollowSymLinks directive */
#define OPT_SYM_LINKS 4
/** ExecCGI directive */
#define OPT_EXECCGI 8
/** directive unset */
#define OPT_UNSET 16
/** IncludesNOEXEC directive */
#define OPT_INCNOEXEC 32
/** SymLinksIfOwnerMatch directive */
#define OPT_SYM_OWNER 64
/** MultiViews directive */
#define OPT_MULTI 128
/** All directives */
#define OPT_ALL (OPT_INDEXES | OPT_INCLUDES | OPT_SYM_LINKS | OPT_EXECCGI)
"
so OPT_INCNOEXEC OPT_SYM_OWNER OPT_MULTI are omitted from All.
in 2.2.x
AllowOverride Options=
allows everything including Multiviews and others
AllowOverride Options
allows only All and this is only OPT_INDEXES | OPT_INCLUDES |
OPT_SYM_LINKS | OPT_EXECCGI
The bug is in server/core.c:1286
l is the string after "Options=", in this case its just an empty string.
static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts,
const char *l)
{
allow_options_t opt;
int first = 1;
char *w, *p = (char *) l;
char *tok_state;
while ((w = apr_strtok(p, ",", &tok_state)) != NULL) {
if (first) {
p = NULL;
*opts = OPT_NONE;
first = 0;
}
if (!strcasecmp(w, "Indexes")) {
opt = OPT_INDEXES;
}
else if (!strcasecmp(w, "Includes")) {
opt = OPT_INCLUDES;
}
...
else if (!strcasecmp(w, "None")) {
opt = OPT_NONE;
}
else if (!strcasecmp(w, "All")) {
opt = OPT_ALL;
}
else {
return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
}
*opts |= opt;
}
(*opts) &= (~OPT_UNSET);
return NULL;
}
In case of Options= the while loop isn't executed and options are set to
(*opts) &= (~OPT_UNSET);
which is previous options & 0xffffffff . Probably in case if OPT_UNSET is not 0.
opts by default are
server/core.c:99 static void *create_core_dir_config(apr_pool_t *a, char *dir)
...
conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER
| OPT_MULTI;
and in server/core.c set_override()
.. d->override = OR_NONE;
while (l[0]) {
w = ap_getword_conf(cmd->pool, &l);
k = w;
v = strchr(k, '=');
if (v) {
*v++ = '\0';
}
if (!strcasecmp(w, "Limit")) {
d->override |= OR_LIMIT;
}
else if (!strcasecmp(k, "Options")) {
// in case of Options= v=""
d->override |= OR_OPTIONS;
if (v)
//in case of "AllowOverride Options=" set_allow_opts() leavs
d->override_opts unchanged
set_allow_opts(cmd, &(d->override_opts), v);
else
// in case of "AllowOverride Options" sets ONLY!!! OPT_ALL ommiting
OPT_MULTIVIEWS and others
d->override_opts = OPT_ALL;
This is at least inconsistent, Options= should be a syntax error, or
OPT_NONE + warning.
In pre Options= releases (it bit me hard when I upgraded to 2.2.8 from
2.0.61) AllovOverride Options
allowed overriding any options not only those in OPT_ALL, and now
suddenly it stopped but allowed old behavior
if I set AllowOverride Options=. We might even call it an regression
because old correct config (new docs don't mention
any changes so I expect new versions to be compatible) stops to work.
I will produce a patch when it get's decided what to do with an empty
"Options=" (in docs defined as Options[=Option,] so there must be at
least 1 option set)
--
Michał Grzędzicki
|