Skip to content

Commit

Permalink
mod_allowhandlers: New module to forbid specific handlers for specific
Browse files Browse the repository at this point in the history
directories.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1406617 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Stefan Fritsch committed Nov 7, 2012
1 parent cd2e3c9 commit 5be4ad3
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 2 deletions.
5 changes: 4 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0

*) Be more correct about rejecting directives that cannot work in <If>
*) mod_allowhandlers: New module to forbid specific handlers for specific
directories. [Stefan Fritsch]

*) core: Be more correct about rejecting directives that cannot work in <If>
sections. [Stefan Fritsch]

*) core: Fix directives like LogLevel that need to know if they are invoked
Expand Down
2 changes: 1 addition & 1 deletion docs/log-message-tags/next-number
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2398
2401
87 changes: 87 additions & 0 deletions docs/manual/mod/mod_allowhandlers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
<!-- $LastChangedRevision$ -->

<!--
Upon adding a new module XML doc, you will need to:
svn ps svn:eol-style native <alltextfiles>
svn ps svn:keywords LastChangedRevision mod_allowhandlers.xml
in order for it to rebuild correctly.
-->

<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<modulesynopsis metafile="mod_allowhandlers.xml.meta">
<name>mod_allowhandlers</name>
<description>Easily restrict what HTTP handlers can be used on the server</description>
<status>Experimental</status>
<sourcefile>mod_allowhandlers.c</sourcefile>
<identifier>allowhandlers_module</identifier>


<summary>
<p>This module makes it easy to restrict which handlers may be used for a
request. A possible configuration would be:</p>

<highlight language="config">
&lt;Location /&gt;
AllowHandlers not server-info server-status balancer-manager ldap-status
&lt;/Location&gt;
</highlight>

<p>It also registers a handler named <code>forbidden</code> that simply
returns 403 FORBIDDEN to the client. This can be used with directives like
<directive module="mod_mime">AddHandler</directive>.</p>

</summary>

<seealso><directive module="core">SetHandler</directive></seealso>
<seealso><directive module="mime">AddHandler</directive></seealso>

<directivesynopsis>
<name>AllowHandlers</name>
<description>Restrict access to the listed handlers</description>
<syntax>AllowHandlers [not] none|<em>handler-name</em>
[none|<em>handler-name</em>]...</syntax>
<default>AllowHandlers all</default>
<contextlist><context>directory</context></contextlist>
<status>Experimental</status>

<usage>

<p>The handler names are case sensitive. The special name
<code>none</code> can be used to match the case where no handler has been
set. The special vallue <code>all</code> can be used to allow all
handlers again in a later config section, even if some headers were denied
earlier in the configuration merge order:</p>

<highlight language="config">
&lt;Location /server-status&gt;
AllowHandlers all
SetHandler server-status
&lt;/Location&gt;
</highlight>

</usage>
</directivesynopsis>

</modulesynopsis>
1 change: 1 addition & 0 deletions modules/aaa/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ APACHE_MODULE(auth_digest, RFC2617 Digest authentication, , , most, [
])

APACHE_MODULE(allowmethods, restrict allowed HTTP methods, , , most)
APACHE_MODULE(allowhandlers, restrict allowed handlers, , , most)

APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])

Expand Down
143 changes: 143 additions & 0 deletions modules/aaa/mod_allowhandlers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_log.h"

module AP_MODULE_DECLARE_DATA allowhandlers_module;

typedef enum {
AH_ALLOW = 0,
AH_DENY = 1,
} ah_op_e;
typedef struct {
apr_table_t *handlers;
ah_op_e op;
} ah_conf_t;

static const char * const forbidden_handler = "forbidden";
static const char * const no_handler = "none";

static int ah_fixups(request_rec *r)
{
ah_conf_t *conf = ap_get_module_config(r->per_dir_config,
&allowhandlers_module);
int match = 0;
const char *handler_name;
if (!r->handler || r->handler[0] == '\0') {
handler_name = no_handler;
}
else if (strcasecmp(r->handler, forbidden_handler) == 0) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
APLOGNO(02398) "Handler 'forbidden' denied by "
"server configuration: URI %s (file %s)",
r->uri, r->filename);
return HTTP_FORBIDDEN;
}
else {
handler_name = r->handler;
}

if (!conf)
return DECLINED;
if (conf->handlers && apr_table_get(conf->handlers, handler_name))
match = 1;

if ((match && conf->op == AH_ALLOW) || (!match && conf->op == AH_DENY)) {
return DECLINED;
}
else {
if (handler_name != no_handler) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
APLOGNO(02399) "Handler '%s' denied by "
"server configuration: URI %s (file %s)",
r->handler, r->uri, r->filename);
}
else {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
APLOGNO(02400) "Handler denied by server "
"configuration: No handler set for URI %s (file %s)",
r->uri, r->filename);
}
return HTTP_FORBIDDEN;
}
}

static void *ah_create_conf(apr_pool_t * p, char *dummy)
{
ah_conf_t *conf = apr_pcalloc(p, sizeof(ah_conf_t));
conf->op = AH_DENY;
return conf;
}

static const char *set_allowed_handlers(cmd_parms *cmd, void *d, int argc, char *const argv[])
{
int i;
ah_conf_t* conf = (ah_conf_t*) d;
const char *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS);
if (err)
return err;
if (argc == 0)
return "AllowHandlers: No handler name given";
conf->op = AH_ALLOW;
if (conf->handlers)
apr_table_clear(conf->handlers);
for (i = 0; i < argc; i++) {
if (strcasecmp(argv[i], forbidden_handler) == 0 && conf->op != AH_DENY)
return "Handler name 'forbidden' cannot be changed.";
if (strcasecmp(argv[i], "all") == 0) {
if (argc != 1)
return "'all' not possible with specific handler names";
conf->op = AH_DENY;
return NULL;
}
else if (strcasecmp(argv[i], "not") == 0) {
if (i != 0 || argc == 1)
return "'not' must come before specific handler names";
conf->op = AH_DENY;
}
else {
if (!conf->handlers)
conf->handlers = apr_table_make(cmd->pool, 4);
apr_table_setn(conf->handlers, argv[i], "1");
}
}
return NULL;
}

static void ah_register_hooks(apr_pool_t * p)
{
ap_hook_fixups(ah_fixups, NULL, NULL, APR_HOOK_REALLY_LAST);
}

static const command_rec ah_cmds[] = {
AP_INIT_TAKE_ARGV("AllowHandlers", set_allowed_handlers, NULL, ACCESS_CONF,
"only allow specific handlers (use 'not' to negate)"),
{NULL}
};

AP_DECLARE_MODULE(allowhandlers) = {
STANDARD20_MODULE_STUFF,
ah_create_conf,
NULL,
NULL,
NULL,
ah_cmds,
ah_register_hooks,
};

0 comments on commit 5be4ad3

Please sign in to comment.