@@ -45,19 +45,248 @@ ngx_http_modsecurity_request_read(ngx_http_request_t *r)
45
45
ngx_int_t
46
46
ngx_http_modsecurity_access_handler (ngx_http_request_t * r )
47
47
{
48
- #if 1
48
+
49
49
ngx_pool_t * old_pool ;
50
50
ngx_http_modsecurity_ctx_t * ctx ;
51
51
ngx_http_modsecurity_conf_t * mcf ;
52
52
53
- dd ("catching a new _access_ phase handler" );
54
-
55
53
mcf = ngx_http_get_module_loc_conf (r , ngx_http_modsecurity_module );
56
- if (mcf == NULL || mcf -> enable != 1 )
57
- {
54
+ if (mcf == NULL || mcf -> enable != 1 ) {
58
55
dd ("ModSecurity not enabled... returning" );
59
56
return NGX_DECLINED ;
60
57
}
58
+
59
+ /*
60
+ if (r->method != NGX_HTTP_GET &&
61
+ r->method != NGX_HTTP_POST && r->method != NGX_HTTP_HEAD) {
62
+ dd("ModSecurity is not ready to deal with anything different from " \
63
+ "POST, GET or HEAD");
64
+ return NGX_DECLINED;
65
+ }
66
+ */
67
+
68
+ dd ("catching a new _rewrite_ phase handler" );
69
+
70
+ ctx = ngx_http_modsecurity_get_module_ctx (r );
71
+
72
+ dd ("recovering ctx: %p" , ctx );
73
+
74
+ if (ctx == NULL )
75
+ {
76
+ int ret = 0 ;
77
+
78
+ ngx_connection_t * connection = r -> connection ;
79
+ /**
80
+ * FIXME: We may want to use struct sockaddr instead of addr_text.
81
+ *
82
+ */
83
+ ngx_str_t addr_text = connection -> addr_text ;
84
+
85
+ ctx = ngx_http_modsecurity_create_ctx (r );
86
+
87
+ dd ("ctx was NULL, creating new context: %p" , ctx );
88
+
89
+ if (ctx == NULL ) {
90
+ dd ("ctx still null; Nothing we can do, returning an error." );
91
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
92
+ }
93
+
94
+ /**
95
+ * FIXME: Check if it is possible to hook on nginx on a earlier phase.
96
+ *
97
+ * At this point we are doing an late connection process. Maybe
98
+ * we have to hook into NGX_HTTP_FIND_CONFIG_PHASE, it seems to be the
99
+ * erliest phase that nginx allow us to attach those kind of hooks.
100
+ *
101
+ */
102
+ int client_port = ngx_inet_get_port (connection -> sockaddr );
103
+ int server_port = ngx_inet_get_port (connection -> local_sockaddr );
104
+
105
+ const char * client_addr = ngx_str_to_char (addr_text , r -> pool );
106
+ if (client_addr == (char * )-1 ) {
107
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
108
+ }
109
+
110
+ #if defined(MODSECURITY_CHECK_VERSION )
111
+ #if MODSECURITY_VERSION_NUM >= 30130100
112
+ ngx_str_t hostname ;
113
+ hostname .len = 0 ;
114
+ // first check if Nginx received a Host header and it's usable
115
+ // (i.e. not empty)
116
+ // if yes, we can use that
117
+ if (r -> headers_in .server .len > 0 ) {
118
+ hostname .len = r -> headers_in .server .len ;
119
+ hostname .data = r -> headers_in .server .data ;
120
+ }
121
+ else {
122
+ // otherwise we try to use the server config, namely the
123
+ // server_name $SERVER_NAME
124
+ // directive
125
+ // for eg. in default config, server_name is "_"
126
+ // possible all requests without a Host header will be
127
+ // handled by this server block
128
+ ngx_http_core_srv_conf_t * cscf ;
129
+ cscf = ngx_http_get_module_srv_conf (r , ngx_http_core_module );
130
+ if (cscf -> server_name .len > 0 ) {
131
+ hostname .len = cscf -> server_name .len ;
132
+ hostname .data = cscf -> server_name .data ;
133
+ }
134
+ }
135
+ if (hostname .len > 0 ) {
136
+ const char * host_name = ngx_str_to_char (hostname , r -> pool );
137
+ if (host_name == (char * )-1 || host_name == NULL ) {
138
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
139
+ }
140
+ else {
141
+ // set the hostname in the transaction
142
+ // this function is only available in ModSecurity 3.0.13 and later
143
+ msc_set_request_hostname (ctx -> modsec_transaction , (const unsigned char * )host_name );
144
+ }
145
+ }
146
+ #endif
147
+ #endif
148
+
149
+ ngx_str_t s ;
150
+ u_char addr [NGX_SOCKADDR_STRLEN ];
151
+ s .len = NGX_SOCKADDR_STRLEN ;
152
+ s .data = addr ;
153
+ if (ngx_connection_local_sockaddr (r -> connection , & s , 0 ) != NGX_OK ) {
154
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
155
+ }
156
+
157
+ const char * server_addr = ngx_str_to_char (s , r -> pool );
158
+ if (server_addr == (char * )-1 ) {
159
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
160
+ }
161
+
162
+ old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
163
+ ret = msc_process_connection (ctx -> modsec_transaction ,
164
+ client_addr , client_port ,
165
+ server_addr , server_port );
166
+ ngx_http_modsecurity_pcre_malloc_done (old_pool );
167
+ if (ret != 1 ){
168
+ dd ("Was not able to extract connection information." );
169
+ }
170
+ /**
171
+ *
172
+ * FIXME: Check how we can finalize a request without crash nginx.
173
+ *
174
+ * I don't think nginx is expecting to finalize a request at that
175
+ * point as it seems that it clean the ngx_http_request_t information
176
+ * and try to use it later.
177
+ *
178
+ */
179
+ dd ("Processing intervention with the connection information filled in" );
180
+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 1 );
181
+ if (ret > 0 ) {
182
+ ctx -> intervention_triggered = 1 ;
183
+ return ret ;
184
+ }
185
+
186
+ const char * http_version ;
187
+ switch (r -> http_version ) {
188
+ case NGX_HTTP_VERSION_9 :
189
+ http_version = "0.9" ;
190
+ break ;
191
+ case NGX_HTTP_VERSION_10 :
192
+ http_version = "1.0" ;
193
+ break ;
194
+ case NGX_HTTP_VERSION_11 :
195
+ http_version = "1.1" ;
196
+ break ;
197
+ #if defined(nginx_version ) && nginx_version >= 1009005
198
+ case NGX_HTTP_VERSION_20 :
199
+ http_version = "2.0" ;
200
+ break ;
201
+ #endif
202
+ default :
203
+ http_version = ngx_str_to_char (r -> http_protocol , r -> pool );
204
+ if (http_version == (char * )-1 ) {
205
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
206
+ }
207
+ if ((http_version != NULL ) && (strlen (http_version ) > 5 ) && (!strncmp ("HTTP/" , http_version , 5 ))) {
208
+ http_version += 5 ;
209
+ } else {
210
+ http_version = "1.0" ;
211
+ }
212
+ break ;
213
+ }
214
+
215
+ const char * n_uri = ngx_str_to_char (r -> unparsed_uri , r -> pool );
216
+ const char * n_method = ngx_str_to_char (r -> method_name , r -> pool );
217
+ if (n_uri == (char * )-1 || n_method == (char * )-1 ) {
218
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
219
+ }
220
+ if (n_uri == NULL ) {
221
+ dd ("uri is of length zero" );
222
+ return NGX_HTTP_INTERNAL_SERVER_ERROR ;
223
+ }
224
+ old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
225
+ msc_process_uri (ctx -> modsec_transaction , n_uri , n_method , http_version );
226
+ ngx_http_modsecurity_pcre_malloc_done (old_pool );
227
+
228
+ dd ("Processing intervention with the transaction information filled in (uri, method and version)" );
229
+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 1 );
230
+ if (ret > 0 ) {
231
+ ctx -> intervention_triggered = 1 ;
232
+ return ret ;
233
+ }
234
+
235
+ /**
236
+ * Since incoming request headers are already in place, lets send it to ModSecurity
237
+ *
238
+ */
239
+ ngx_list_part_t * part = & r -> headers_in .headers .part ;
240
+ ngx_table_elt_t * data = part -> elts ;
241
+ ngx_uint_t i = 0 ;
242
+ for (i = 0 ; /* void */ ; i ++ ) {
243
+ if (i >= part -> nelts ) {
244
+ if (part -> next == NULL ) {
245
+ break ;
246
+ }
247
+
248
+ part = part -> next ;
249
+ data = part -> elts ;
250
+ i = 0 ;
251
+ }
252
+
253
+ /**
254
+ * By using u_char (utf8_t) I believe nginx is hoping to deal
255
+ * with utf8 strings.
256
+ * Casting those into to unsigned char * in order to pass
257
+ * it to ModSecurity, it will handle with those later.
258
+ *
259
+ */
260
+
261
+ dd ("Adding request header: %.*s with value %.*s" , (int )data [i ].key .len , data [i ].key .data , (int ) data [i ].value .len , data [i ].value .data );
262
+ msc_add_n_request_header (ctx -> modsec_transaction ,
263
+ (const unsigned char * ) data [i ].key .data ,
264
+ data [i ].key .len ,
265
+ (const unsigned char * ) data [i ].value .data ,
266
+ data [i ].value .len );
267
+ }
268
+
269
+ /**
270
+ * Since ModSecurity already knew about all headers, i guess it is safe
271
+ * to process this information.
272
+ */
273
+
274
+ old_pool = ngx_http_modsecurity_pcre_malloc_init (r -> pool );
275
+ msc_process_request_headers (ctx -> modsec_transaction );
276
+ ngx_http_modsecurity_pcre_malloc_done (old_pool );
277
+ dd ("Processing intervention with the request headers information filled in" );
278
+ ret = ngx_http_modsecurity_process_intervention (ctx -> modsec_transaction , r , 1 );
279
+ if (r -> error_page ) {
280
+ return NGX_DECLINED ;
281
+ }
282
+ if (ret > 0 ) {
283
+ ctx -> intervention_triggered = 1 ;
284
+ return ret ;
285
+ }
286
+ }
287
+
288
+ #if 1
289
+
61
290
/*
62
291
* FIXME:
63
292
* In order to perform some tests, let's accept everything.
0 commit comments