@@ -31,13 +31,15 @@ ngx_http_modsecurity_body_filter_init(void)
31
31
32
32
return NGX_OK ;
33
33
}
34
-
35
34
ngx_int_t
36
35
ngx_http_modsecurity_body_filter (ngx_http_request_t * r , ngx_chain_t * in )
37
36
{
38
- int buffer_fully_loadead = 0 ;
39
- ngx_chain_t * chain = in ;
37
+
40
38
ngx_http_modsecurity_ctx_t * ctx = NULL ;
39
+ ngx_chain_t * chain = in ;
40
+ ngx_int_t ret ;
41
+ ngx_pool_t * old_pool ;
42
+ ngx_int_t is_request_processed = 0 ;
41
43
#if defined(MODSECURITY_SANITY_CHECKS ) && (MODSECURITY_SANITY_CHECKS )
42
44
ngx_http_modsecurity_conf_t * loc_cf = NULL ;
43
45
ngx_list_part_t * part = & r -> headers_out .headers .part ;
@@ -49,11 +51,11 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
49
51
return ngx_http_next_body_filter (r , in );
50
52
}
51
53
54
+ /* get context for request */
52
55
ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity_module );
53
-
54
56
dd ("body filter, recovering ctx: %p" , ctx );
55
-
56
- if (ctx == NULL ) {
57
+
58
+ if (ctx == NULL || r -> filter_finalize ) {
57
59
return ngx_http_next_body_filter (r , in );
58
60
}
59
61
@@ -130,56 +132,82 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
130
132
{
131
133
dd ("%d header(s) were not inspected by ModSecurity, so exiting" , worth_to_fail );
132
134
return ngx_http_filter_finalize_request (r ,
133
- & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
135
+ & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
134
136
}
135
137
}
136
138
#endif
137
139
138
- for (; chain != NULL ; chain = chain -> next )
139
- {
140
- /* XXX: chain->buf->last_buf || chain->buf->last_in_chain */
141
- if (chain -> buf -> last_buf ) {
142
- buffer_fully_loadead = 1 ;
140
+ for (chain = in ; chain != NULL ; chain = chain -> next ) {
141
+
142
+ ngx_buf_t * copy_buf ;
143
+ ngx_chain_t * copy_chain ;
144
+ is_request_processed = chain -> buf -> last_buf ;
145
+ ngx_int_t data_size = chain -> buf -> end - chain -> buf -> start ;
146
+ ngx_int_t data_offset = chain -> buf -> pos - chain -> buf -> start ;
147
+ u_char * data = chain -> buf -> start ;
148
+ msc_append_response_body (ctx -> modsec_transaction , data ,
149
+ chain -> buf -> end - data );
150
+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction ,
151
+ r );
152
+ if (ret > 0 ) {
153
+ return ngx_http_filter_finalize_request (r ,
154
+ & ngx_http_modsecurity_module , ret );
143
155
}
144
- }
145
156
146
- if (buffer_fully_loadead == 1 )
147
- {
148
- int ret ;
149
- ngx_pool_t * old_pool ;
150
-
151
- for (chain = in ; chain != NULL ; chain = chain -> next )
152
- {
153
- u_char * data = chain -> buf -> start ;
157
+ copy_chain = ngx_alloc_chain_link (r -> pool );
158
+ if (copy_chain == NULL ) {
159
+ return NGX_ERROR ;
160
+ }
154
161
155
- msc_append_response_body (ctx -> modsec_transaction , data , chain -> buf -> end - data );
156
- ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r );
157
- if (ret > 0 ) {
158
- return ngx_http_filter_finalize_request (r ,
159
- & ngx_http_modsecurity_module , ret );
162
+ copy_buf = ngx_calloc_buf (r -> pool );
163
+ if (copy_buf == NULL ) {
164
+ return NGX_ERROR ;
165
+ }
166
+ copy_buf -> start = ngx_pcalloc (r -> pool , data_size );
167
+ if (copy_buf -> start == NULL ) {
168
+ return NGX_ERROR ;
169
+ }
170
+ ngx_memcpy (copy_buf -> start , chain -> buf -> start , data_size );
171
+ copy_buf -> pos = copy_buf -> start + data_offset ;
172
+ copy_buf -> end = copy_buf -> start + data_size ;
173
+ copy_buf -> last = copy_buf -> pos + ngx_buf_size (chain -> buf );
174
+ copy_buf -> temporary = (chain -> buf -> temporary == 1 ) ? 1 : 0 ;
175
+ copy_buf -> memory = (chain -> buf -> memory == 1 ) ? 1 : 0 ;
176
+ copy_chain -> buf = copy_buf ;
177
+ copy_chain -> buf -> last_buf = 1 ;
178
+ copy_chain -> next = NULL ;
179
+ chain -> buf -> pos = chain -> buf -> last ;
180
+
181
+ if (ctx -> temp_chain == NULL ) {
182
+ ctx -> temp_chain = copy_chain ;
183
+ } else {
184
+ if (ctx -> current_chain == NULL ) {
185
+ ctx -> temp_chain -> next = copy_chain ;
186
+ ctx -> temp_chain -> buf -> last_buf = 0 ;
187
+ } else {
188
+ ctx -> current_chain -> next = copy_chain ;
189
+ ctx -> current_chain -> buf -> last_buf = 0 ;
160
190
}
191
+ ctx -> current_chain = copy_chain ;
161
192
}
193
+ }
162
194
195
+ if (is_request_processed ) {
163
196
old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
164
197
msc_process_response_body (ctx -> modsec_transaction );
165
198
ngx_http_modsecurity_pcre_malloc_done (old_pool );
166
-
167
- /* XXX: I don't get how body from modsec being transferred to nginx's buffer. If so - after adjusting of nginx's
168
- XXX: body we can proceed to adjust body size (content-length). see xslt_body_filter() for example */
169
199
ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r );
170
200
if (ret > 0 ) {
171
- return ret ;
172
- }
173
- else if (ret < 0 ) {
174
201
return ngx_http_filter_finalize_request (r ,
175
- & ngx_http_modsecurity_module , NGX_HTTP_INTERNAL_SERVER_ERROR );
202
+ & ngx_http_modsecurity_module , ret );
203
+ } else if (ret < 0 ) {
204
+ return ngx_http_filter_finalize_request (r ,
205
+ & ngx_http_modsecurity_module , ret );
176
206
}
207
+ ctx -> response_body_filtered = 1 ;
208
+ ctx -> header_pt (r );
209
+ return ngx_http_next_body_filter (r , ctx -> temp_chain );
210
+ } else {
211
+ return NGX_AGAIN ;
177
212
}
178
- else
179
- {
180
- dd ("buffer was not fully loaded! ctx: %p" , ctx );
181
- }
182
-
183
- /* XXX: xflt_filter() -- return NGX_OK here */
184
- return ngx_http_next_body_filter (r , in );
185
213
}
0 commit comments