@@ -33,12 +33,14 @@ ngx_http_modsecurity_body_filter_init(void)
3333
3434 return NGX_OK ;
3535}
36-
3736ngx_int_t
3837ngx_http_modsecurity_body_filter (ngx_http_request_t * r , ngx_chain_t * in )
3938{
40- ngx_chain_t * chain = in ;
4139 ngx_http_modsecurity_ctx_t * ctx = NULL ;
40+ ngx_chain_t * chain = in ;
41+ ngx_int_t ret ;
42+ ngx_pool_t * old_pool ;
43+ ngx_int_t is_request_processed = 0 ;
4244#if defined(MODSECURITY_SANITY_CHECKS ) && (MODSECURITY_SANITY_CHECKS )
4345 ngx_http_modsecurity_conf_t * mcf ;
4446 ngx_list_part_t * part = & r -> headers_out .headers .part ;
@@ -47,14 +49,18 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
4749#endif
4850
4951 if (in == NULL ) {
52+ ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , "MDS input chain is null" );
53+
5054 return ngx_http_next_body_filter (r , in );
5155 }
5256
53- ctx = ngx_http_get_module_ctx ( r , ngx_http_modsecurity_module );
54-
57+ /* get context for request */
58+ ctx = ngx_http_modsecurity_get_module_ctx ( r );
5559 dd ("body filter, recovering ctx: %p" , ctx );
5660
57- if (ctx == NULL ) {
61+ if (ctx == NULL || r -> filter_finalize || ctx -> response_body_filtered ) {
62+ if (ctx && ctx -> response_body_filtered )
63+ r -> filter_finalize = 1 ;
5864 return ngx_http_next_body_filter (r , in );
5965 }
6066
@@ -140,47 +146,81 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
140146 }
141147#endif
142148
143- int is_request_processed = 0 ;
144- for (; chain != NULL ; chain = chain -> next )
145- {
146- u_char * data = chain -> buf -> pos ;
147- int ret ;
149+ for (chain = in ; chain != NULL ; chain = chain -> next ) {
148150
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 );
151+ ngx_buf_t * copy_buf ;
152+ ngx_chain_t * copy_chain ;
153+ is_request_processed = chain -> buf -> last_buf ;
154+ u_char * data = chain -> buf -> pos ;
155+ msc_append_response_body (ctx -> modsec_transaction , data ,
156+ chain -> buf -> last - data );
157+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction ,
158+ r , 0 );
151159 if (ret > 0 ) {
152160 return ngx_http_filter_finalize_request (r ,
153161 & ngx_http_modsecurity_module , ret );
154162 }
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 ;
163+ if (!chain -> buf -> last_buf ){
164+ copy_chain = ngx_alloc_chain_link (r -> pool );
165+ if (copy_chain == NULL ) {
166+ return NGX_ERROR ;
171167 }
172- else if (ret < 0 ) {
173- return ngx_http_filter_finalize_request (r ,
174- & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
175-
168+ copy_buf = ngx_calloc_buf (r -> pool );
169+ if (copy_buf == NULL ) {
170+ return NGX_ERROR ;
176171 }
172+ copy_buf -> pos = chain -> buf -> pos ;
173+ copy_buf -> end = chain -> buf -> end ;
174+ copy_buf -> last = chain -> buf -> last ;
175+ copy_buf -> temporary = (chain -> buf -> temporary == 1 ) ? 1 : 0 ;
176+ copy_buf -> memory = (chain -> buf -> memory == 1 ) ? 1 : 0 ;
177+ copy_chain -> buf = copy_buf ;
178+ copy_chain -> buf -> last_buf = chain -> buf -> last_buf ;
179+ copy_chain -> next = NULL ;
180+ chain -> buf -> pos = chain -> buf -> last ;
177181 }
178- }
179- if (!is_request_processed )
180- {
181- dd ("buffer was not fully loaded! ctx: %p" , ctx );
182+ else
183+ copy_chain = chain ;
184+ if (ctx -> temp_chain == NULL ) {
185+ ctx -> temp_chain = copy_chain ;
186+ } else {
187+ if (ctx -> current_chain == NULL ) {
188+ ctx -> temp_chain -> next = copy_chain ;
189+ ctx -> temp_chain -> buf -> last_buf = 0 ;
190+ } else {
191+ ctx -> current_chain -> next = copy_chain ;
192+ ctx -> current_chain -> buf -> last_buf = 0 ;
193+ }
194+ ctx -> current_chain = copy_chain ;
195+ }
196+
182197 }
183198
184- /* XXX: xflt_filter() -- return NGX_OK here */
185- return ngx_http_next_body_filter (r , in );
199+ if (is_request_processed ) {
200+ old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
201+ msc_process_response_body (ctx -> modsec_transaction );
202+ ngx_http_modsecurity_pcre_malloc_done (old_pool );
203+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 0 );
204+ if (ret > 0 ) {
205+ if (ret < NGX_HTTP_BAD_REQUEST && ctx -> header_pt != NULL ){
206+ ctx -> header_pt (r );
207+ }
208+ else {
209+ ctx -> response_body_filtered = 1 ;
210+ return ngx_http_filter_finalize_request (r ,
211+ & ngx_http_modsecurity_module
212+ , ret );
213+ }
214+ } else if (ret < 0 ) {
215+ ctx -> response_body_filtered = 1 ;
216+ return ngx_http_filter_finalize_request (r ,
217+ & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
218+ }
219+ ctx -> response_body_filtered = 1 ;
220+ if (ctx -> header_pt != NULL )
221+ ctx -> header_pt (r );
222+ return ngx_http_next_body_filter (r , ctx -> temp_chain );
223+ } else {
224+ return NGX_AGAIN ;
225+ }
186226}
0 commit comments