Added experiemental support for content injection.

This commit is contained in:
ivanr 2007-05-02 11:22:09 +00:00
parent 20c0b11dd9
commit e0a8602929
5 changed files with 164 additions and 2 deletions

View File

@ -2,6 +2,12 @@
?? ??? 2007 - 2.2.0-trunk
-------------------------
* Added experimental support for content injection. Directive SecContentInjection
(On|Off) controls whether injection is taking place. Actions "prepend"
and "append" inject content when executed. Do note that it is your
responsibility to make sure the response is of the appropriate
content type (e.g. HTML, plain text, etc).
* Added string comparison operators with support for macro expansion:
@contains, @is, @beginsWith and @endsWith.

View File

@ -81,6 +81,9 @@ void *create_directory_config(apr_pool_t *mp, char *path) {
dcfg->data_dir = NOT_SET_P;
dcfg->webappid = NOT_SET_P;
/* Content injection. */
dcfg->content_injection_enabled = NOT_SET;
return dcfg;
}
@ -356,6 +359,10 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) {
merged->webappid = (child->webappid == NOT_SET_P
? parent->webappid : child->webappid);
/* Content injection. */
merged->content_injection_enabled = (child->content_injection_enabled == NOT_SET
? parent->content_injection_enabled : child->content_injection_enabled);
return merged;
}
@ -414,6 +421,9 @@ void init_directory_config(directory_config *dcfg) {
/* Misc */
if (dcfg->data_dir == NOT_SET_P) dcfg->data_dir = NULL;
if (dcfg->webappid == NOT_SET_P) dcfg->webappid = "default";
/* Content injection. */
if (dcfg->content_injection_enabled == NOT_SET) dcfg->content_injection_enabled = 0;
}
/**
@ -696,6 +706,13 @@ static const char *cmd_chroot_dir(cmd_parms *cmd, void *_dcfg, const char *p1) {
return NULL;
}
static const char *cmd_content_injection(cmd_parms *cmd, void *_dcfg, int flag) {
directory_config *dcfg = (directory_config *)_dcfg;
if (dcfg == NULL) return NULL;
dcfg->content_injection_enabled = flag;
return NULL;
}
static const char *cmd_data_dir(cmd_parms *cmd, void *_dcfg, const char *p1) {
directory_config *dcfg = (directory_config *)_dcfg;
@ -1175,6 +1192,14 @@ const command_rec module_directives[] = {
"Path of the directory to which server will be chrooted"
),
AP_INIT_FLAG (
"SecContentInjection",
cmd_content_injection,
NULL,
CMD_SCOPE_ANY,
"On or Off"
),
AP_INIT_TAKE1 (
"SecCookieFormat",
cmd_cookie_format,

View File

@ -384,7 +384,7 @@ static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
request_rec *r = f->r;
modsec_rec *msr = (modsec_rec *)f->ctx;
apr_bucket *bucket;
apr_bucket *bucket = NULL, *eos_bucket = NULL;
apr_status_t rc;
if (msr == NULL) {
@ -445,6 +445,40 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
/* Continue (observe the response body). */
break;
}
// If injecting content unset headers now.
if (msr->txcfg->content_injection_enabled == 0) {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content Injection: Not enabled.");
}
} else {
if ((msr->content_prepend) || (msr->content_append)) {
apr_table_unset(msr->r->headers_out, "Content-Length");
apr_table_unset(msr->r->headers_out, "Last-Modified");
apr_table_unset(msr->r->headers_out, "ETag");
apr_table_unset(msr->r->headers_out, "Expires");
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content Injection: Removing headers (C-L, L-M, Etag, Expires).");
}
} else {
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content Injection: Nothing to inject.");
}
}
}
// Content injection (prepend & non-buffering).
if (msr->txcfg->content_injection_enabled && msr->content_prepend) {
apr_bucket *bucket_ci = apr_bucket_heap_create(msr->content_prepend,
msr->content_prepend_len, NULL, f->r->connection->bucket_alloc);
APR_BRIGADE_INSERT_HEAD(bb_in, bucket_ci);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content Injection (nb): Added content to top: %s",
log_escape_nq_ex(msr->mp, msr->content_prepend, msr->content_prepend_len));
}
}
} else
if (msr->of_status == OF_STATUS_COMPLETE) {
msr_log(msr, 1, "Output filter: Internal error: output filtering complete yet filter was invoked.");
@ -452,6 +486,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
return APR_EGENERAL;
}
/* Loop through the buckets in the brigade in order
* to extract the size of the data available.
*/
@ -490,6 +525,22 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
}
if (APR_BUCKET_IS_EOS(bucket)) {
eos_bucket = bucket;
// Inject content (append & non-buffering).
if (msr->txcfg->content_injection_enabled && msr->content_append) {
apr_bucket *bucket_ci = NULL;
bucket_ci = apr_bucket_heap_create(msr->content_append,
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
APR_BUCKET_INSERT_BEFORE(bucket, bucket_ci);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content-Injection (nb): Added content to bottom: %s",
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
}
}
msr->of_done_reading = 1;
}
}
@ -541,7 +592,6 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
}
// TODO Why does the function below take pointer to length? Will it modify it?
rc = apr_brigade_flatten(msr->of_brigade, msr->resbody_data, &msr->resbody_length);
if (rc != APR_SUCCESS) {
msr_log(msr, 1, "Output filter: Failed to flatten brigade (%i): %s", rc,
@ -567,6 +617,34 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
if (msr->of_skipping == 0) {
record_time_checkpoint(msr, 3);
// Inject content into response (prepend & buffering).
if (msr->txcfg->content_injection_enabled && msr->content_prepend) {
apr_bucket *bucket_ci = NULL;
bucket_ci = apr_bucket_heap_create(msr->content_prepend,
msr->content_prepend_len, NULL, f->r->connection->bucket_alloc);
APR_BRIGADE_INSERT_HEAD(msr->of_brigade, bucket_ci);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content Injection (b): Added content to top: %s",
log_escape_nq_ex(msr->mp, msr->content_prepend, msr->content_prepend_len));
}
}
// Inject content into response (append & buffering).
if (msr->txcfg->content_injection_enabled && msr->content_append) {
apr_bucket *bucket_ci = NULL;
bucket_ci = apr_bucket_heap_create(msr->content_append,
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
APR_BUCKET_INSERT_BEFORE(eos_bucket, bucket_ci);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Content-Injection (b): Added content to bottom: %s",
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
}
}
rc = ap_pass_brigade(f->next, msr->of_brigade);
if (rc != APR_SUCCESS) {
int log_level = 1;

View File

@ -309,6 +309,12 @@ struct modsec_rec {
/* rule processing temp pool */
apr_pool_t *msc_rule_mptmp;
/* content injection */
const char *content_prepend;
apr_off_t content_prepend_len;
const char *content_append;
apr_off_t content_append_len;
};
struct directory_config {
@ -386,6 +392,9 @@ struct directory_config {
/* Misc */
const char *data_dir;
const char *webappid;
/* Content injection. */
int content_injection_enabled;
};
struct error_message {

View File

@ -1363,6 +1363,26 @@ static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
return 1;
}
/* prepend */
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);
return 1;
}
/* append */
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);
return 1;
}
/* -- */
/**
@ -1813,4 +1833,28 @@ void msre_engine_register_default_actions(msre_engine *engine) {
NULL,
NULL
);
/* prepend */
msre_engine_action_register(engine,
"prepend",
ACTION_NON_DISRUPTIVE,
1, 1,
NO_PLUS_MINUS,
ACTION_CARDINALITY_ONE,
NULL,
NULL,
msre_action_prepend_execute
);
/* append */
msre_engine_action_register(engine,
"append",
ACTION_NON_DISRUPTIVE,
1, 1,
NO_PLUS_MINUS,
ACTION_CARDINALITY_ONE,
NULL,
NULL,
msre_action_append_execute
);
}