Skip to content

Commit 972d9e2

Browse files
committed
Added Response Phase for Nginx
1 parent 48bd099 commit 972d9e2

File tree

7 files changed

+761
-338
lines changed

7 files changed

+761
-338
lines changed

nginx/modsecurity/apr_bucket_nginx.c

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
2+
#include <apr_bucket_nginx.h>
3+
4+
static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
5+
apr_size_t *len, apr_read_type_e block);
6+
static void nginx_bucket_destroy(void *data);
7+
8+
static const apr_bucket_type_t apr_bucket_type_nginx = {
9+
"NGINX", 5, APR_BUCKET_DATA,
10+
nginx_bucket_destroy,
11+
nginx_bucket_read,
12+
apr_bucket_setaside_noop,
13+
apr_bucket_shared_split,
14+
apr_bucket_shared_copy
15+
};
16+
17+
18+
typedef struct apr_bucket_nginx {
19+
apr_bucket_refcount refcount;
20+
ngx_buf_t *buf;
21+
} apr_bucket_nginx;
22+
23+
/* ngx_buf_t to apr_bucket */
24+
apr_bucket * apr_bucket_nginx_create(ngx_buf_t *buf,
25+
apr_pool_t *p,
26+
apr_bucket_alloc_t *list)
27+
{
28+
29+
apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
30+
31+
APR_BUCKET_INIT(b); /* link */
32+
b->free = apr_bucket_free;
33+
b->list = list;
34+
return apr_bucket_nginx_make(b, buf, p);
35+
}
36+
37+
apr_bucket * apr_bucket_nginx_make(apr_bucket *b, ngx_buf_t *buf,
38+
apr_pool_t *pool)
39+
{
40+
apr_bucket_nginx *n;
41+
42+
n = apr_bucket_alloc(sizeof(*n), b->list);
43+
44+
n->buf = buf;
45+
46+
b = apr_bucket_shared_make(b, n, 0, ngx_buf_size(buf));
47+
b->type = &apr_bucket_type_nginx;
48+
return b;
49+
}
50+
51+
static apr_status_t nginx_bucket_read(apr_bucket *b, const char **str,
52+
apr_size_t *len, apr_read_type_e block)
53+
{
54+
apr_bucket_nginx *n = b->data;
55+
ngx_buf_t *buf = n->buf;
56+
u_char *data;
57+
ssize_t size;
58+
59+
if (buf->pos == NULL && ngx_buf_size(buf) != 0) {
60+
data = apr_bucket_alloc(ngx_buf_size(buf), b->list);
61+
if (data == NULL) {
62+
return APR_EGENERAL;
63+
}
64+
65+
size = ngx_read_file(buf->file, data, ngx_buf_size(buf), buf->file_pos);
66+
if (size != ngx_buf_size(buf)) {
67+
apr_bucket_free(data);
68+
return APR_EGENERAL;
69+
}
70+
buf->pos = data;
71+
}
72+
73+
*str = (char *)buf->pos + b->start;
74+
*len = b->length;
75+
76+
return APR_SUCCESS;
77+
}
78+
79+
80+
static void nginx_bucket_destroy(void *data)
81+
{
82+
apr_bucket_nginx *n = data;
83+
ngx_buf_t *buf = n->buf;
84+
85+
if (apr_bucket_shared_destroy(n)) {
86+
if (!ngx_buf_in_memory(buf) && buf->pos != NULL) {
87+
apr_bucket_free(buf->pos);
88+
buf->pos = NULL;
89+
}
90+
apr_bucket_free(n);
91+
}
92+
}
93+
94+
ngx_buf_t * apr_bucket_to_ngx_buf(apr_bucket *e, ngx_pool_t *pool) {
95+
ngx_buf_t *buf, *b;
96+
apr_bucket_nginx *n;
97+
ngx_uint_t len;
98+
u_char *data;
99+
100+
if (e->type->is_metadata) {
101+
return NULL;
102+
}
103+
104+
if (e->type == &apr_bucket_type_nginx) {
105+
n = e->data;
106+
b = n->buf;
107+
108+
/* whole buf */
109+
if (e->length == (apr_size_t)ngx_buf_size(b)) {
110+
b->last_buf = 0;
111+
return b;
112+
}
113+
114+
buf = ngx_palloc(pool, sizeof(ngx_buf_t));
115+
if (buf == NULL) {
116+
return NULL;
117+
}
118+
ngx_memcpy(buf, b, sizeof(ngx_buf_t));
119+
120+
if (ngx_buf_in_memory(buf)) {
121+
buf->start = buf->pos = buf->pos + e->start;
122+
buf->end = buf->last = buf->pos + e->length;
123+
} else {
124+
buf->pos = NULL;
125+
buf->file_pos += e->start;
126+
buf->file_last = buf->file_pos + e->length;
127+
}
128+
129+
buf->last_buf = 0;
130+
return buf;
131+
}
132+
133+
if (apr_bucket_read(e, (const char **)&data,
134+
&len, APR_BLOCK_READ) != APR_SUCCESS) {
135+
return NULL;
136+
}
137+
138+
buf = ngx_calloc_buf(pool);
139+
if (buf == NULL) {
140+
return NULL;
141+
}
142+
143+
if (e->type == &apr_bucket_type_pool) {
144+
buf->start = data;
145+
} else if (len != 0) {
146+
buf->start = ngx_palloc(pool, len);
147+
ngx_memcpy(buf->start, data, len);
148+
}
149+
150+
buf->pos = buf->start;
151+
buf->end = buf->last = buf->start + len;
152+
buf->temporary = 1;
153+
return buf;
154+
}
155+
156+
ngx_int_t
157+
move_chain_to_brigade(ngx_chain_t *chain, apr_bucket_brigade *bb, ngx_pool_t *pool) {
158+
apr_bucket *e;
159+
ngx_chain_t *cl;
160+
161+
while (chain) {
162+
e = ngx_buf_to_apr_bucket(chain->buf, bb->p, bb->bucket_alloc);
163+
if (e == NULL) {
164+
return NGX_ERROR;
165+
}
166+
167+
APR_BRIGADE_INSERT_TAIL(bb, e);
168+
if (chain->buf->last_buf) {
169+
e = apr_bucket_eos_create(bb->bucket_alloc);
170+
APR_BRIGADE_INSERT_TAIL(bb, e);
171+
chain->buf->last_buf = 0;
172+
return NGX_OK;
173+
}
174+
cl = chain;
175+
chain = chain->next;
176+
ngx_free_chain(pool, cl);
177+
}
178+
return NGX_AGAIN;
179+
}
180+
181+
ngx_int_t
182+
move_brigade_to_chain(apr_bucket_brigade *bb, ngx_chain_t **ll, ngx_pool_t *pool) {
183+
apr_bucket *e;
184+
ngx_buf_t *buf;
185+
ngx_chain_t *cl;
186+
187+
cl = NULL;
188+
189+
if (APR_BRIGADE_EMPTY(bb)) {
190+
*ll = NULL;
191+
return NGX_OK;
192+
}
193+
194+
for (e = APR_BRIGADE_FIRST(bb);
195+
e != APR_BRIGADE_SENTINEL(bb);
196+
e = APR_BUCKET_NEXT(e)) {
197+
198+
if (APR_BUCKET_IS_EOS(e)) {
199+
if (cl == NULL) {
200+
*ll = cl;
201+
} else {
202+
cl->buf->last_buf = 1;
203+
}
204+
apr_brigade_cleanup(bb);
205+
return NGX_OK;
206+
}
207+
208+
if (APR_BUCKET_IS_METADATA(e)) {
209+
continue;
210+
}
211+
212+
buf = apr_bucket_to_ngx_buf(e, pool);
213+
if (buf == NULL) {
214+
break;
215+
}
216+
217+
cl = ngx_alloc_chain_link(pool);
218+
if (cl == NULL) {
219+
break;
220+
}
221+
222+
cl->buf = buf;
223+
cl->next = NULL;
224+
*ll = cl;
225+
ll = &cl->next;
226+
}
227+
228+
apr_brigade_cleanup(bb);
229+
/* no eos or error */
230+
return NGX_ERROR;
231+
}
232+

nginx/modsecurity/apr_bucket_nginx.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
#include <ngx_core.h>
3+
#include "apr_buckets.h"
4+
5+
apr_bucket * apr_bucket_nginx_create(ngx_buf_t *buf,
6+
apr_pool_t *p,
7+
apr_bucket_alloc_t *list);
8+
9+
apr_bucket * apr_bucket_nginx_make(apr_bucket *e, ngx_buf_t *buf,
10+
apr_pool_t *pool);
11+
12+
#define ngx_buf_to_apr_bucket apr_bucket_nginx_create
13+
14+
ngx_buf_t * apr_bucket_to_ngx_buf(apr_bucket *e, ngx_pool_t *pool);
15+
16+
ngx_int_t move_chain_to_brigade(ngx_chain_t *chain, apr_bucket_brigade *bb, ngx_pool_t *pool);
17+
ngx_int_t move_brigade_to_chain(apr_bucket_brigade *bb, ngx_chain_t **chain, ngx_pool_t *pool);
18+

nginx/modsecurity/config

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
ngx_addon_name=ngx_http_modsecurity
2-
HTTP_MODULES="$HTTP_MODULES ngx_http_modsecurity"
3-
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_modsecurity.c"
2+
# HTTP_MODULES="$HTTP_MODULES ngx_http_modsecurity"
3+
HTTP_HEADERS_FILTER_MODULE="ngx_http_modsecurity $HTTP_HEADERS_FILTER_MODULE"
4+
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_modsecurity.c $ngx_addon_dir/apr_bucket_nginx.c"
45
NGX_ADDON_DEPS="$NGX_ADDON_DEPS"
56
CORE_LIBS="$CORE_LIBS $ngx_addon_dir/../../standalone/.libs/standalone.a -lapr-1 -laprutil-1 -lxml2 -lm"
6-
CORE_INCS="$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2"
7+
CORE_INCS="$CORE_INCS /usr/include/apache2 /usr/include/apr-1.0 /usr/include/httpd /usr/include/apr-1 $ngx_addon_dir $ngx_addon_dir/../../standalone $ngx_addon_dir/../../apache2 /usr/include/libxml2"
8+
have=REQUEST_EARLY . auto/have
9+

0 commit comments

Comments
 (0)