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

@@ -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
);
}