Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adds a new rule type. It evaluates regular expressions against the

HTTP arguments. It can either check a specific parameter of all of
them. The cherokee-admin module is still to be committed.

git-svn-id: svn://cherokee-project.com/cherokee/trunk@3860 5dc97367-97f1-0310-9951-d761b3857238
  • Loading branch information...
commit 992ee8127eab59e3728f24574f8632e0a7baf82f 1 parent de4aa5e
@alobbs alobbs authored
View
19 cherokee/Makefile.am
@@ -198,6 +198,23 @@ endif
#
+# Rule http_arg
+#
+rule_http_arg = \
+rule_http_arg.c \
+rule_http_arg.h
+
+libplugin_http_arg_la_LDFLAGS = $(module_ldflags)
+libplugin_http_arg_la_SOURCES = $(rule_http_arg)
+
+if STATIC_RULE_HTTP_ARG
+static_rule_http_arg_src = $(rule_http_arg)
+else
+dynamic_rule_http_arg_lib = libplugin_http_arg.la
+endif
+
+
+#
# Rule fullpath
#
rule_fullpath = \
@@ -1422,6 +1439,7 @@ $(static_rule_extensions_src) \
$(static_rule_request_src) \
$(static_rule_header_src) \
$(static_rule_exists_src) \
+$(static_rule_http_arg_src) \
$(static_rule_fullpath_src) \
$(static_rule_bind_src) \
$(static_rule_method_src) \
@@ -1608,6 +1626,7 @@ $(dynamic_rule_extensions_lib) \
$(dynamic_rule_request_lib) \
$(dynamic_rule_header_lib) \
$(dynamic_rule_exists_lib) \
+$(dynamic_rule_http_arg_lib) \
$(dynamic_rule_fullpath_lib) \
$(dynamic_rule_bind_lib) \
$(dynamic_rule_method_lib) \
View
6 cherokee/connection.c
@@ -2315,9 +2315,11 @@ cherokee_connection_parse_args (cherokee_connection_t *conn)
{
ret_t ret;
- /* Sanity check
+ /* Parse arguments only once
*/
- return_if_fail (conn->arguments == NULL, ret_error);
+ if (conn->arguments != NULL) {
+ return ret_ok;
+ }
/* Build a new table
*/
View
205 cherokee/rule_http_arg.c
@@ -0,0 +1,205 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Cherokee
+ *
+ * Authors:
+ * Alvaro Lopez Ortega <alvaro@alobbs.com>
+ *
+ * Copyright (C) 2001-2009 Alvaro Lopez Ortega
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "common-internal.h"
+#include "rule_http_arg.h"
+
+#include "plugin_loader.h"
+#include "server-protected.h"
+#include "connection-protected.h"
+#include "util.h"
+#include "pcre/pcre.h"
+
+#define ENTRIES "rule,http_arg"
+
+PLUGIN_INFO_RULE_EASIEST_INIT(http_arg);
+
+
+static ret_t
+check_argument (cherokee_rule_http_arg_t *rule,
+ cherokee_buffer_t *value)
+{
+ int re;
+
+ /* Check whether it matches
+ */
+ re = pcre_exec (rule->pcre, NULL,
+ value->buf, value->len,
+ 0, 0, NULL, 0);
+
+ if (re < 0) {
+ TRACE (ENTRIES, "Parameter value '%s' didn't match with '%s'\n",
+ value->buf, rule->match.buf);
+ return ret_not_found;
+ }
+
+ TRACE (ENTRIES, "Parameter value '%s' matched with '%s'\n",
+ value->buf, rule->match.buf);
+
+ return ret_ok;
+}
+
+
+static ret_t
+match_avl_func (cherokee_buffer_t *key, void *value, void *param)
+{
+ ret_t ret;
+ cherokee_buffer_t fake;
+ cherokee_rule_http_arg_t *rule = RULE_HTTP_ARG(param);
+
+ UNUSED(key);
+
+ // Temporal until conn->arguments uses cherokee_buffer_t
+ cherokee_buffer_fake (&fake, (char *)value, strlen((char *)value));
+
+ ret = check_argument (rule, &fake);
+ if (ret == ret_not_found) {
+ return ret_ok;
+ }
+
+ /* Found */
+ return ret_eof;
+}
+
+
+static ret_t
+match (cherokee_rule_http_arg_t *rule,
+ cherokee_connection_t *conn,
+ cherokee_config_entry_t *ret_conf)
+{
+ ret_t ret;
+
+ UNUSED(ret_conf);
+
+ /* Parse HTTP arguments
+ */
+ ret = cherokee_connection_parse_args (conn);
+ if (ret != ret_ok) {
+ return ret_not_found;
+ }
+
+ if (conn->arguments == NULL) {
+ return ret_not_found;
+ }
+
+ /* Retrieve the right one
+ */
+ if (! cherokee_buffer_is_empty (&rule->arg)) {
+ cherokee_buffer_t fake;
+ char *value;
+
+ ret = cherokee_avl_get (conn->arguments, &rule->arg, (void **)&value);
+ if (ret != ret_ok) {
+ return ret_not_found;
+ }
+
+ // Temporal until conn->arguments uses cherokee_buffer_t
+ cherokee_buffer_fake (&fake, (char *)value, strlen((char *)value));
+
+ return check_argument (rule, &fake);
+ }
+
+ /* Check all arguments
+ */
+ else {
+ ret = cherokee_avl_while (conn->arguments, match_avl_func, rule, NULL, NULL);
+ if (ret == ret_eof) {
+ return ret_ok;
+ }
+ }
+
+ return ret_not_found;
+}
+
+
+static ret_t
+configure (cherokee_rule_http_arg_t *rule,
+ cherokee_config_node_t *conf,
+ cherokee_virtual_server_t *vsrv)
+{
+ ret_t ret;
+ cherokee_regex_table_t *regexs = VSERVER_SRV(vsrv)->regexs;
+
+ /* Read the matching reg-ex
+ */
+ ret = cherokee_config_node_copy (conf, "match", &rule->match);
+ if (ret != ret_ok) {
+ LOG_ERROR (CHEROKEE_ERROR_RULE_NO_PROPERTY,
+ RULE(rule)->priority, "match");
+ return ret_error;
+ }
+
+ /* Read the optional argument
+ */
+ cherokee_config_node_copy (conf, "arg", &rule->arg);
+
+ /* Compile the regular expression
+ */
+ ret = cherokee_regex_table_add (regexs, rule->match.buf);
+ if (ret != ret_ok)
+ return ret;
+
+ ret = cherokee_regex_table_get (regexs, rule->match.buf, &rule->pcre);
+ if (ret != ret_ok)
+ return ret;
+
+ return ret_ok;
+}
+
+
+static ret_t
+_free (void *p)
+{
+ cherokee_rule_http_arg_t *rule = RULE_HTTP_ARG(p);
+
+ cherokee_buffer_mrproper (&rule->arg);
+ cherokee_buffer_mrproper (&rule->match);
+ return ret_ok;
+}
+
+
+ret_t
+cherokee_rule_http_arg_new (cherokee_rule_http_arg_t **rule)
+{
+ CHEROKEE_NEW_STRUCT (n, rule_http_arg);
+
+ /* Parent class constructor
+ */
+ cherokee_rule_init_base (RULE(n), PLUGIN_INFO_PTR(http_arg));
+
+ /* Virtual methods
+ */
+ RULE(n)->match = (rule_func_match_t) match;
+ RULE(n)->configure = (rule_func_configure_t) configure;
+ MODULE(n)->free = (module_func_free_t) _free;
+
+ /* Properties
+ */
+ n->pcre = NULL;
+ cherokee_buffer_init (&n->arg);
+ cherokee_buffer_init (&n->match);
+
+ *rule = n;
+ return ret_ok;
+}
View
53 cherokee/rule_http_arg.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Cherokee
+ *
+ * Authors:
+ * Alvaro Lopez Ortega <alvaro@alobbs.com>
+ *
+ * Copyright (C) 2001-2009 Alvaro Lopez Ortega
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#if !defined (CHEROKEE_INSIDE_CHEROKEE_H) && !defined (CHEROKEE_COMPILATION)
+# error "Only <cherokee/cherokee.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef CHEROKEE_RULE_HTTP_ARG_H
+#define CHEROKEE_RULE_HTTP_ARG_H
+
+#include <cherokee/common.h>
+#include <cherokee/buffer.h>
+#include <cherokee/rule.h>
+#include <cherokee/regex.h>
+
+CHEROKEE_BEGIN_DECLS
+
+typedef struct {
+ cherokee_rule_t rule;
+ cherokee_buffer_t arg;
+ cherokee_buffer_t match;
+ void *pcre;
+
+} cherokee_rule_http_arg_t;
+
+#define RULE_HTTP_ARG(x) ((cherokee_rule_http_arg_t *)(x))
+
+ret_t cherokee_rule_http_arg_new (cherokee_rule_http_arg_t **rule);
+
+CHEROKEE_END_DECLS
+
+#endif /* CHEROKEE_RULE_HTTP_ARG_H */
View
3  configure.in
@@ -1344,7 +1344,7 @@ AC_ARG_ENABLE(static-module,
AC_HELP_STRING([--enable-static-module=MODULE][]),
[use_static_module="$use_static_module $enableval "],[])
-modules="error_redir error_nn server_info file admin dirlist fcgi fastcgi scgi uwsgi redir common cgi proxy ssi secdownload empty_gif custom_error dbslayer streaming gzip deflate ncsa combined custom pam ldap mysql htpasswd plain htdigest authlist round_robin ip_hash directory extensions request header exists fullpath method from bind geoip wildcard rehost target_ip evhost libssl render_rrd rrd not and or"
+modules="error_redir error_nn server_info file admin dirlist fcgi fastcgi scgi uwsgi redir common cgi proxy ssi secdownload empty_gif custom_error dbslayer streaming gzip deflate ncsa combined custom pam ldap mysql htpasswd plain htdigest authlist round_robin ip_hash directory extensions request header exists fullpath method from bind geoip http_arg wildcard rehost target_ip evhost libssl render_rrd rrd not and or"
# Remove modules that will not be compiles
#
@@ -1445,6 +1445,7 @@ AM_CONDITIONAL(STATIC_RULE_BIND, grep bind $conf_h >/dev/null
AM_CONDITIONAL(STATIC_RULE_METHOD, grep method $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_FROM, grep from $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_RULE_GEOIP, grep geoip $conf_h >/dev/null)
+AM_CONDITIONAL(STATIC_RULE_HTTP_ARG, grep http_arg $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_VRULE_WILDCARD, grep wildcard $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_VRULE_REHOST, grep rehost $conf_h >/dev/null)
AM_CONDITIONAL(STATIC_VRULE_TARGET_IP, grep target_ip $conf_h >/dev/null)
View
34 qa/235-HTTP-arg_match1.py
@@ -0,0 +1,34 @@
+from base import *
+
+DIR = "header_arg1_match"
+ARGS = "first=1&second=http://1.1.1.1&third=3"
+MAGIC = "magic string"
+
+CONF = """
+vserver!1!rule!2350!match = http_arg
+vserver!1!rule!2350!match!arg = second
+vserver!1!rule!2350!match!match = http://
+vserver!1!rule!2350!handler = cgi
+"""
+
+CGI = """#!/bin/sh
+
+echo "Content-Type: text/plain"
+echo
+echo "%s"
+""" % (MAGIC)
+
+class Test (TestBase):
+ def __init__ (self):
+ TestBase.__init__ (self, __file__)
+ self.name = "Rule http_arg: match"
+
+ self.request = "GET /%s/test?%s HTTP/1.0\r\n" % (DIR, ARGS)
+ self.conf = CONF
+ self.expected_error = 200
+ self.required_content = MAGIC
+ self.forbidden_content = ["/bin/sh", "echo"]
+
+ def Prepare (self, www):
+ d = self.Mkdir (www, DIR)
+ f = self.WriteFile (d, 'test', 0755, CGI)
View
33 qa/236-HTTP-arg_match2.py
@@ -0,0 +1,33 @@
+from base import *
+
+DIR = "header_arg2_match"
+ARGS = "first=1&second=http://1.1.1.1&third=3"
+MAGIC = "magic string"
+
+CONF = """
+vserver!1!rule!2360!match = http_arg
+vserver!1!rule!2360!match!arg = second
+vserver!1!rule!2360!match!match = isnt_there
+vserver!1!rule!2360!handler = cgi
+"""
+
+CGI = """#!/bin/sh
+
+echo "Content-Type: text/plain"
+echo
+echo "%s"
+""" % (MAGIC)
+
+class Test (TestBase):
+ def __init__ (self):
+ TestBase.__init__ (self, __file__)
+ self.name = "Rule http_arg: no match"
+
+ self.request = "GET /%s/test?%s HTTP/1.0\r\n" % (DIR, ARGS)
+ self.conf = CONF
+ self.expected_error = 200
+ self.required_content = ["/bin/sh", "echo", MAGIC]
+
+ def Prepare (self, www):
+ d = self.Mkdir (www, DIR)
+ f = self.WriteFile (d, 'test', 0755, CGI)
View
33 qa/237-HTTP-arg_match_all1.py
@@ -0,0 +1,33 @@
+from base import *
+
+DIR = "header_arg_match_all_1"
+ARGS = "first=1&second=http://1.1.1.1&third=3"
+MAGIC = "magic string"
+
+CONF = """
+vserver!1!rule!2370!match = http_arg
+vserver!1!rule!2370!match!match = http://
+vserver!1!rule!2370!handler = cgi
+"""
+
+CGI = """#!/bin/sh
+
+echo "Content-Type: text/plain"
+echo
+echo "%s"
+""" % (MAGIC)
+
+class Test (TestBase):
+ def __init__ (self):
+ TestBase.__init__ (self, __file__)
+ self.name = "Rule http_arg: match all"
+
+ self.request = "GET /%s/test?%s HTTP/1.0\r\n" % (DIR, ARGS)
+ self.conf = CONF
+ self.expected_error = 200
+ self.required_content = MAGIC
+ self.forbidden_content = ["/bin/sh", "echo"]
+
+ def Prepare (self, www):
+ d = self.Mkdir (www, DIR)
+ f = self.WriteFile (d, 'test', 0755, CGI)
View
32 qa/238-HTTP-arg_match_all2.py
@@ -0,0 +1,32 @@
+from base import *
+
+DIR = "header_arg_match_all_2"
+ARGS = "first=1&second=http://1.1.1.1&third=3"
+MAGIC = "magic string"
+
+CONF = """
+vserver!1!rule!2370!match = http_arg
+vserver!1!rule!2370!match!match = not_found
+vserver!1!rule!2370!handler = cgi
+"""
+
+CGI = """#!/bin/sh
+
+echo "Content-Type: text/plain"
+echo
+echo "%s"
+""" % (MAGIC)
+
+class Test (TestBase):
+ def __init__ (self):
+ TestBase.__init__ (self, __file__)
+ self.name = "Rule http_arg: no match all"
+
+ self.request = "GET /%s/test?%s HTTP/1.0\r\n" % (DIR, ARGS)
+ self.conf = CONF
+ self.expected_error = 200
+ self.required_content = ["/bin/sh", "echo", MAGIC]
+
+ def Prepare (self, www):
+ d = self.Mkdir (www, DIR)
+ f = self.WriteFile (d, 'test', 0755, CGI)
View
7 qa/Makefile.am
@@ -239,8 +239,11 @@ run-tests.py \
231-POST-4extra.py \
232-X-Real-IP-CGI.py \
233-X-Real-IP-CGI-2.py \
-234-X-Real-IP-CGI-3.py
-
+234-X-Real-IP-CGI-3.py \
+235-HTTP-arg_match1.py \
+236-HTTP-arg_match2.py \
+237-HTTP-arg_match_all1.py \
+238-HTTP-arg_match_all2.py
test:
./run-tests.py
Please sign in to comment.
Something went wrong with that request. Please try again.