@@ -37,8 +37,11 @@ ngx_http_modsecurity_body_filter_init(void)
3737ngx_int_t
3838ngx_http_modsecurity_body_filter (ngx_http_request_t * r , ngx_chain_t * in )
3939{
40- ngx_chain_t * chain = in ;
4140 ngx_http_modsecurity_ctx_t * ctx = NULL ;
41+ ngx_chain_t * chain = in ;
42+ ngx_int_t ret ;
43+ ngx_pool_t * old_pool ;
44+ ngx_int_t is_request_processed = 0 ;
4245#if defined(MODSECURITY_SANITY_CHECKS ) && (MODSECURITY_SANITY_CHECKS )
4346 ngx_http_modsecurity_conf_t * mcf ;
4447 ngx_list_part_t * part = & r -> headers_out .headers .part ;
@@ -47,14 +50,19 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
4750#endif
4851
4952 if (in == NULL ) {
53+ ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , "MDS input chain is null" );
5054 return ngx_http_next_body_filter (r , in );
5155 }
5256
57+ /* get context for request */
5358 ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity_module );
54-
5559 dd ("body filter, recovering ctx: %p" , ctx );
5660
57- if (ctx == NULL ) {
61+
62+ if (ctx == NULL || r -> filter_finalize || ctx -> response_body_filtered ) {
63+ if (ctx && ctx -> response_body_filtered ) {
64+ r -> filter_finalize = 1 ;
65+ }
5866 return ngx_http_next_body_filter (r , in );
5967 }
6068
@@ -140,47 +148,82 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
140148 }
141149#endif
142150
143- int is_request_processed = 0 ;
144- for (; chain != NULL ; chain = chain -> next )
145- {
146- u_char * data = chain -> buf -> pos ;
147- int ret ;
151+ for (chain = in ; chain != NULL ; chain = chain -> next ) {
148152
149- msc_append_response_body (ctx -> modsec_transaction , data , chain -> buf -> last - data );
150- ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 0 );
153+
154+ ngx_buf_t * copy_buf ;
155+ ngx_chain_t * copy_chain ;
156+ is_request_processed = chain -> buf -> last_buf ;
157+ u_char * data = chain -> buf -> pos ;
158+ msc_append_response_body (ctx -> modsec_transaction , data ,
159+ chain -> buf -> last - data );
160+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction ,
161+ r , 0 );
151162 if (ret > 0 ) {
152163 return ngx_http_filter_finalize_request (r ,
153164 & ngx_http_modsecurity_module , ret );
154165 }
155-
156- /* XXX: chain->buf->last_buf || chain->buf->last_in_chain */
157- is_request_processed = chain -> buf -> last_buf ;
158-
159- if (is_request_processed ) {
160- ngx_pool_t * old_pool ;
161-
162- old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
163- msc_process_response_body (ctx -> modsec_transaction );
164- ngx_http_modsecurity_pcre_malloc_done (old_pool );
165-
166- /* XXX: I don't get how body from modsec being transferred to nginx's buffer. If so - after adjusting of nginx's
167- XXX: body we can proceed to adjust body size (content-length). see xslt_body_filter() for example */
168- ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 0 );
169- if (ret > 0 ) {
170- return ret ;
166+ if (!chain -> buf -> last_buf ){
167+ copy_chain = ngx_alloc_chain_link (r -> pool );
168+ if (copy_chain == NULL ) {
169+ return NGX_ERROR ;
171170 }
172- else if (ret < 0 ) {
173- return ngx_http_filter_finalize_request (r ,
174- & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
175-
171+ copy_buf = ngx_calloc_buf (r -> pool );
172+ if (copy_buf == NULL ) {
173+ return NGX_ERROR ;
176174 }
175+ copy_buf -> pos = chain -> buf -> pos ;
176+ copy_buf -> end = chain -> buf -> end ;
177+ copy_buf -> last = chain -> buf -> last ;
178+ copy_buf -> temporary = (chain -> buf -> temporary == 1 ) ? 1 : 0 ;
179+ copy_buf -> memory = (chain -> buf -> memory == 1 ) ? 1 : 0 ;
180+ copy_chain -> buf = copy_buf ;
181+ copy_chain -> buf -> last_buf = chain -> buf -> last_buf ;
182+ copy_chain -> next = NULL ;
183+ //chain->buf->pos = chain->buf->last;
184+ }
185+ else {
186+ copy_chain = chain ;
187+ }
188+ if (ctx -> temp_chain == NULL ) {
189+ ctx -> temp_chain = copy_chain ;
190+ } else {
191+ if (ctx -> current_chain == NULL ) {
192+ ctx -> temp_chain -> next = copy_chain ;
193+ ctx -> temp_chain -> buf -> last_buf = 0 ;
194+ } else {
195+ ctx -> current_chain -> next = copy_chain ;
196+ ctx -> current_chain -> buf -> last_buf = 0 ;
197+ }
198+ ctx -> current_chain = copy_chain ;
177199 }
178- }
179- if (!is_request_processed )
180- {
181- dd ("buffer was not fully loaded! ctx: %p" , ctx );
182200 }
183201
184- /* XXX: xflt_filter() -- return NGX_OK here */
185- return ngx_http_next_body_filter (r , in );
202+ if (is_request_processed ) {
203+ old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
204+ msc_process_response_body (ctx -> modsec_transaction );
205+ ngx_http_modsecurity_pcre_malloc_done (old_pool );
206+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 0 );
207+ if (ret > 0 ) {
208+ if (ret < NGX_HTTP_BAD_REQUEST && ctx -> header_pt != NULL ){
209+ ctx -> header_pt (r );
210+ }
211+ else {
212+ ctx -> response_body_filtered = 1 ;
213+ return ngx_http_filter_finalize_request (r ,
214+ & ngx_http_modsecurity_module
215+ , ret );
216+ }
217+ } else if (ret < 0 ) {
218+ ctx -> response_body_filtered = 1 ;
219+ return ngx_http_filter_finalize_request (r ,
220+ & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
221+ }
222+ ctx -> response_body_filtered = 1 ;
223+ if (ctx -> header_pt != NULL )
224+ ctx -> header_pt (r );
225+ return ngx_http_next_body_filter (r , ctx -> temp_chain );
226+ } else {
227+ return NGX_AGAIN ;
228+ }
186229}
0 commit comments