read client body in a better manner

This commit is contained in:
chaizhenhua 2012-12-25 09:34:13 +08:00
parent 77ccd0b7b5
commit 5f97bec8d3

View File

@ -49,6 +49,7 @@ typedef struct ngx_http_modsecurity_ctx_s {
request_rec *req; request_rec *req;
ngx_chain_t *chain; ngx_chain_t *chain;
ngx_buf_t buf; ngx_buf_t buf;
void **loc_conf;
unsigned request_body_in_single_buf:1; unsigned request_body_in_single_buf:1;
unsigned request_body_in_file_only:1; unsigned request_body_in_file_only:1;
} ngx_http_modsecurity_ctx_t; } ngx_http_modsecurity_ctx_t;
@ -393,7 +394,7 @@ modsecurity_read_body_cb(request_rec *r, char *outpos, unsigned int length,
rest -= size; rest -= size;
buf->file_pos += size; buf->file_pos += size;
} else { } else {
return APR_ERROR; return -1;
} }
} }
@ -443,14 +444,13 @@ static ngx_int_t
ngx_http_modsecurity_handler(ngx_http_request_t *r) ngx_http_modsecurity_handler(ngx_http_request_t *r)
{ {
ngx_http_modsecurity_loc_conf_t *cf; ngx_http_modsecurity_loc_conf_t *cf;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf, *lcf;
ngx_http_modsecurity_ctx_t *ctx; ngx_http_modsecurity_ctx_t *ctx;
ngx_buf_t *buf;
size_t preread;
ngx_list_part_t *part; ngx_list_part_t *part;
ngx_table_elt_t *h; ngx_table_elt_t *h;
ngx_uint_t i; ngx_uint_t i;
ngx_int_t rc; ngx_int_t rc;
void **loc_conf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler"); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: handler");
@ -545,35 +545,37 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r)
/* Processing POST request body, should we process PUT? */ /* Processing POST request body, should we process PUT? */
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: method POST"); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "modSecurity: method POST");
/*
* read client request body TODO: chunked request body
*/
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf == NULL) { if (clcf == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
preread = r->header_in->last - r->header_in->pos; ctx->loc_conf = r->loc_conf;
/* hijack loc_conf so that we can receive any body length
* TODO: nonblocking process & chuncked body
*/
if (clcf->client_body_buffer_size < r->headers_in.content_length_n) {
/* force read_client_request_body to use r->header_in as body buffer */ loc_conf = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
r->headers_in.content_length_n ++; if (loc_conf == NULL) {
if ( (r->header_in->end - r->header_in->pos) < r->headers_in.content_length_n) {
buf = ngx_create_temp_buf(r->pool, r->headers_in.content_length_n);
if (buf == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR; return NGX_HTTP_INTERNAL_SERVER_ERROR;
} }
ngx_memcpy(buf->pos + 1, r->header_in->pos, preread); lcf = ngx_pcalloc(r->pool, sizeof(ngx_http_core_loc_conf_t));
buf->last += preread + 1; if (lcf == NULL) {
r->header_in = buf; return NGX_HTTP_INTERNAL_SERVER_ERROR;
*r->header_in->pos = 0xff; }
} else {
ngx_memmove(r->header_in->pos + 1, r->header_in->pos, preread); ngx_memcpy(loc_conf, r->loc_conf, sizeof(void *) * ngx_http_max_module);
r->header_in->last ++; ngx_memcpy(lcf, clcf, sizeof(ngx_http_core_loc_conf_t));
*r->header_in->pos = 0xff;
ctx->loc_conf = r->loc_conf;
r->loc_conf = loc_conf;
ngx_http_get_module_loc_conf(r, ngx_http_core_module) = lcf;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
clcf->client_body_buffer_size = r->headers_in.content_length_n;
} }
ctx->request_body_in_single_buf = r->request_body_in_single_buf; ctx->request_body_in_single_buf = r->request_body_in_single_buf;
@ -582,7 +584,7 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r)
r->request_body_in_file_only = 0; r->request_body_in_file_only = 0;
rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_request_body_handler); rc = ngx_http_read_client_request_body(r, ngx_http_modsecurity_request_body_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc; return rc;
} }
@ -608,18 +610,17 @@ ngx_http_modsecurity_request_body_handler(ngx_http_request_t *r)
if (ctx == NULL if (ctx == NULL
|| r->request_body->bufs == NULL || r->request_body->bufs == NULL
|| *r->request_body->bufs->buf->pos != 0xff) { || r->request_body->bufs->next != NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return; return;
} }
r->request_body_in_single_buf = ctx->request_body_in_single_buf; r->request_body_in_single_buf = ctx->request_body_in_single_buf;
r->request_body_in_file_only = ctx->request_body_in_file_only; r->request_body_in_file_only = ctx->request_body_in_file_only;
r->header_in = r->request_body->bufs->buf;
r->request_body->bufs->buf->pos ++;
r->headers_in.content_length_n --;
ctx->chain = r->request_body->bufs; ctx->chain = r->request_body->bufs;
r->request_body = NULL;
r->loc_conf = ctx->loc_conf;
ngx_http_finalize_request(r, ngx_http_modsecurity_pass_to_backend(r)); ngx_http_finalize_request(r, ngx_http_modsecurity_pass_to_backend(r));
return; return;