@@ -37,8 +37,11 @@ ngx_http_modsecurity_body_filter_init(void)
37
37
ngx_int_t
38
38
ngx_http_modsecurity_body_filter (ngx_http_request_t * r , ngx_chain_t * in )
39
39
{
40
- ngx_chain_t * chain = in ;
41
40
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 ;
42
45
#if defined(MODSECURITY_SANITY_CHECKS ) && (MODSECURITY_SANITY_CHECKS )
43
46
ngx_http_modsecurity_conf_t * mcf ;
44
47
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)
47
50
#endif
48
51
49
52
if (in == NULL ) {
53
+ ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , "MDS input chain is null" );
50
54
return ngx_http_next_body_filter (r , in );
51
55
}
52
56
57
+ /* get context for request */
53
58
ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity_module );
54
-
55
59
dd ("body filter, recovering ctx: %p" , ctx );
56
60
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
+ }
58
66
return ngx_http_next_body_filter (r , in );
59
67
}
60
68
@@ -140,47 +148,82 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
140
148
}
141
149
#endif
142
150
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 ) {
148
152
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 );
151
162
if (ret > 0 ) {
152
163
return ngx_http_filter_finalize_request (r ,
153
164
& ngx_http_modsecurity_module , ret );
154
165
}
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 ;
171
170
}
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 ;
176
174
}
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 ;
177
199
}
178
- }
179
- if (!is_request_processed )
180
- {
181
- dd ("buffer was not fully loaded! ctx: %p" , ctx );
182
200
}
183
201
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
+ }
186
229
}
0 commit comments