diff --git a/CHANGES b/CHANGES
index d0480e2c..0bd0210a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
05 Mar 2009 - 2.5.9-dev1
------------------------
+ * Added macro expansion for append/prepend action.
+
* Fixed race condition in concurrent updates of persistent counters. Updates
are now atomic.
diff --git a/apache2/re_actions.c b/apache2/re_actions.c
index d18df4ae..b15f568c 100644
--- a/apache2/re_actions.c
+++ b/apache2/re_actions.c
@@ -1803,8 +1803,18 @@ static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
static apr_status_t msre_action_prepend_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
- msr->content_prepend = action->param;
- msr->content_prepend_len = strlen(action->param);
+ msc_string *var = NULL;
+
+ /* Expand any macros in the text */
+ var = apr_pcalloc(mptmp, sizeof(msc_string));
+ if (var == NULL) return -1;
+ var->value = (char *)action->param;
+ var->value_len = strlen(var->value);
+ expand_macros(msr, var, rule, mptmp);
+
+ /* ENH: Verify we really have to dup the data here. */
+ msr->content_prepend = apr_pstrndup(msr->mp, var->value, var->value_len);
+ msr->content_prepend_len = var->value_len;
return 1;
}
@@ -1813,8 +1823,18 @@ static apr_status_t msre_action_prepend_execute(modsec_rec *msr, apr_pool_t *mpt
static apr_status_t msre_action_append_execute(modsec_rec *msr, apr_pool_t *mptmp,
msre_rule *rule, msre_action *action)
{
- msr->content_append = action->param;
- msr->content_append_len = strlen(action->param);
+ msc_string *var = NULL;
+
+ /* Expand any macros in the text */
+ var = apr_pcalloc(mptmp, sizeof(msc_string));
+ if (var == NULL) return -1;
+ var->value = (char *)action->param;
+ var->value_len = strlen(var->value);
+ expand_macros(msr, var, rule, mptmp);
+
+ /* ENH: Verify we really have to dup the data here. */
+ msr->content_append = apr_pstrndup(msr->mp, var->value, var->value_len);
+ msr->content_append_len = var->value_len;
return 1;
}
diff --git a/apache2/t/regression/action/00-misc.t b/apache2/t/regression/action/00-misc.t
index 0a99b4c5..1629d697 100644
--- a/apache2/t/regression/action/00-misc.t
+++ b/apache2/t/regression/action/00-misc.t
@@ -1,6 +1,5 @@
### Test misc actions
-# TODO: append
# TODO: block
# TODO: capture
# TODO: chain
@@ -10,7 +9,6 @@
# TODO: initcol
# TODO: multiMatch
# TODO: pause
-# TODO: prepend
# TODO: sanitiseArg
# TODO: sanitiseMatched
# TODO: sanitiseRequestHeader
diff --git a/apache2/t/regression/action/10-append-prepend.t b/apache2/t/regression/action/10-append-prepend.t
new file mode 100644
index 00000000..97f28685
--- /dev/null
+++ b/apache2/t/regression/action/10-append-prepend.t
@@ -0,0 +1,49 @@
+# TODO: Need more tests here
+
+### append
+{
+ type => "action",
+ comment => "append content",
+ conf => qq(
+ SecRuleEngine On
+ SecContentInjection On
+ SecDebugLog "$ENV{DEBUG_LOG}"
+ SecDebugLogLevel 9
+ SecAction "phase:1,setvar:tx.test=test"
+ SecAction "phase:2,append:'APPEND: \%{tx.test}'"
+ ),
+ match_log => {
+ debug => [ "Added content to bottom: APPEND: test", 1 ],
+ },
+ match_response => {
+ status => qr/^200$/,
+ content => qr/APPEND: test$/,
+ },
+ request => new HTTP::Request(
+ GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
+ ),
+},
+
+### prepend
+{
+ type => "action",
+ comment => "prepend content",
+ conf => qq(
+ SecRuleEngine On
+ SecContentInjection On
+ SecDebugLog "$ENV{DEBUG_LOG}"
+ SecDebugLogLevel 9
+ SecAction "phase:1,setvar:tx.test=test"
+ SecAction "phase:2,prepend:'PREPEND: \%{tx.test}'"
+ ),
+ match_log => {
+ debug => [ "Added content to top: PREPEND: test", 1 ],
+ },
+ match_response => {
+ status => qr/^200$/,
+ content => qr/^PREPEND: test/,
+ },
+ request => new HTTP::Request(
+ GET => "http://$ENV{SERVER_NAME}:$ENV{SERVER_PORT}/test.txt",
+ ),
+},
diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml
index fff38f8b..421c33f6 100644
--- a/doc/modsecurity2-apache-reference.xml
+++ b/doc/modsecurity2-apache-reference.xml
@@ -4270,6 +4270,12 @@ SecAction phase:3,allow
Example:
SecRule RESPONSE_CONTENT_TYPE "^text/html" "nolog,pass,append:'<hr>Footer'"
+
+
+ While macro expansion is allowed in the additional content,
+ you are strongly cautioned against inserting user defined data
+ fields.
+
@@ -4923,6 +4929,12 @@ SecRule REQUEST_HEADERS:User-Agent "Test" log,deny,status:403
Example:
SecRule RESPONSE_CONTENT_TYPE ^text/html "phase:3,nolog,pass,prepend:'Header<br>'"
+
+
+ While macro expansion is allowed in the additional content,
+ you are strongly cautioned against inserting user defined data
+ fields.
+