[Remove entries to the current 2.0 section below, when backported]
+ *) core: Add Options= syntax to AllowOverride to specify which options
+ may be overridden in .htaccess files. PR 29310.
+ [Tom Alsberg <alsbergt cs.huji.ac.il>, Paul Querna]
+
*) ab: Handle long URLs with an error instead of an buffer overflow.
PR 28204. [Erik Weide <erik.weidel mplus-technologies.de>, Paul Querna]
<?xml version="1.0"?>
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
-<!-- $Revision: 1.88 $ -->
+<!-- $Revision: 1.89 $ -->
<!--
Copyright 2002-2004 The Apache Software Foundation
module="mod_authz_host">Deny</directive> and <directive
module="mod_authz_host">Order</directive>).</dd>
- <dt>Options</dt>
+ <dt>Options[=<var>Option</var>,...]</dt>
<dd>
Allow use of the directives controlling specific directory
features (<directive module="core">Options</directive> and
- <directive module="mod_include">XBitHack</directive>).</dd>
+ <directive module="mod_include">XBitHack</directive>).
+ 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.</dd>
</dl>
<p>Example:</p>
struct ap_conf_vector_t *context;
/** directive with syntax error */
const ap_directive_t *err_directive;
+
+ /** Which allow-override-opts bits are set */
+ int override_opts;
};
/**
*/
AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
request_rec *r, int override,
+ int override_opts,
const char *path,
const char *access_name);
allow_options_t opts_add;
allow_options_t opts_remove;
overrides_t override;
+ allow_options_t override_opts;
/* MIME typing --- the core doesn't do anything at all with this,
* but it does know what to slap on a request for a document which
const char *dir;
/** the overrides allowed for the .htaccess file */
int override;
+ /** the override options allowed for the .htaccess file */
+ int override_opts;
/** the configuration directives */
struct ap_conf_vector_t *htaccess;
/** the next one, or NULL if no more; N.B. never change this */
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
+ parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
&arr_parms, NULL,
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
+ parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
if (ap_pcfg_openfile(&cfp, p, fname) != APR_SUCCESS) {
return apr_pstrcat(p, "Could not open document config file ",
parms.temp_pool = ptemp;
parms.server = s;
parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
+ parms.override_opts = OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI;
parms.limited = -1;
errmsg = ap_walk_config(conftree, &parms, s->lookup_defaults);
AP_CORE_DECLARE(int) ap_parse_htaccess(ap_conf_vector_t **result,
request_rec *r, int override,
+ int override_opts,
const char *d, const char *access_name)
{
ap_configfile_t *f = NULL;
parms = default_parms;
parms.override = override;
+ parms.override_opts = override_opts;
parms.pool = r->pool;
parms.temp_pool = r->pool;
parms.server = r->server;
new = apr_palloc(r->pool, sizeof(struct htaccess_result));
new->dir = parms.path;
new->override = override;
+ new->override_opts = override_opts;
new->htaccess = dc;
/* add to head of list */
conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
conf->opts_add = conf->opts_remove = OPT_NONE;
conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
+ conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER
+ | OPT_MULTI;
conf->content_md5 = 2;
conf->accept_path_info = 3;
conf->override = new->override;
}
+ if (!(new->override_opts & OPT_UNSET)) {
+ conf->override_opts = new->override_opts;
+ }
+
if (new->ap_default_type) {
conf->ap_default_type = new->ap_default_type;
}
return NULL;
}
+static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts,
+ const char *l)
+{
+ allow_options_t opt;
+ int first = 1;
+
+ char *p = (char *) l;
+
+ while (p && *p) {
+ char *w = strsep(&p, ",");
+
+ if (first) {
+ *opts = OPT_NONE;
+ first = 0;
+ }
+
+ if (!w)
+ continue;
+
+ if (!strcasecmp(w, "Indexes")) {
+ opt = OPT_INDEXES;
+ }
+ else if (!strcasecmp(w, "Includes")) {
+ opt = OPT_INCLUDES;
+ }
+ else if (!strcasecmp(w, "IncludesNOEXEC")) {
+ opt = (OPT_INCLUDES | OPT_INCNOEXEC);
+ }
+ else if (!strcasecmp(w, "FollowSymLinks")) {
+ opt = OPT_SYM_LINKS;
+ }
+ else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
+ opt = OPT_SYM_OWNER;
+ }
+ else if (!strcasecmp(w, "ExecCGI")) {
+ opt = OPT_EXECCGI;
+ }
+ else if (!strcasecmp(w, "MultiViews")) {
+ opt = OPT_MULTI;
+ }
+ else if (!strcasecmp(w, "RunScripts")) { /* AI backcompat. Yuck */
+ opt = OPT_MULTI|OPT_EXECCGI;
+ }
+ 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;
+}
+
static const char *set_override(cmd_parms *cmd, void *d_, const char *l)
{
core_dir_config *d = d_;
char *w;
+ char *k, *v;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
if (err != NULL) {
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(w, "Options")) {
+ else if (!strcasecmp(k, "Options")) {
d->override |= OR_OPTIONS;
+ if (v)
+ set_allow_opts(cmd, &(d->override_opts), v);
+ else
+ d->override_opts = OPT_ALL;
}
else if (!strcasecmp(w, "FileInfo")) {
d->override |= OR_FILEINFO;
else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) {
opt = OPT_SYM_OWNER;
}
- else if (!strcasecmp(w, "execCGI")) {
+ else if (!strcasecmp(w, "ExecCGI")) {
opt = OPT_EXECCGI;
}
else if (!strcasecmp(w, "MultiViews")) {
return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
}
- /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
- if (action == '-') {
+ if (!(cmd->override_opts & opt) && opt != OPT_NONE) {
+ return apr_pstrcat(cmd->pool, "Option ", w, " not allowed here", NULL);
+ }
+ else if (action == '-') {
+ /* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
d->opts_remove |= opt;
d->opts_add &= ~opt;
d->opts &= ~opt;
allow_options_t add;
allow_options_t remove;
overrides_t override;
+ overrides_t override_opts;
} core_opts_t;
static void core_opts_merge(const ap_conf_vector_t *sec, core_opts_t *opts)
if (!(this_dir->override & OR_UNSET)) {
opts->override = this_dir->override;
}
+ if (!(this_dir->override_opts & OR_UNSET)) {
+ opts->override_opts = this_dir->override_opts;
+ }
}
}
res = ap_parse_htaccess(&htaccess_conf, r, opts.override,
+ opts.override_opts,
apr_pstrdup(r->pool, r->filename),
sconf->access_name);
if (res) {