@@ -32,6 +32,19 @@ static char *ngx_http_modsecurity_merge_srv_conf(ngx_conf_t *cf, void *parent, v
32
32
static void ngx_http_modsecurity_config_cleanup (void * data );
33
33
static char * ngx_http_modsecurity_init_main_conf (ngx_conf_t * cf , void * conf );
34
34
35
+ static ngx_int_t ngx_http_modsecurity_add_variables (ngx_conf_t * cf );
36
+ static ngx_int_t ngx_http_intervention_variable (ngx_http_request_t * r , ngx_http_variable_value_t * v , uintptr_t data );
37
+ static ngx_int_t ngx_http_rules_variable (ngx_http_request_t * r , ngx_http_variable_value_t * v , uintptr_t data );
38
+
39
+ ngx_http_variable_t ngx_http_modsecurity_vars [] = {
40
+ { ngx_string ("intervention_done" ), NULL ,
41
+ ngx_http_intervention_variable , 0 ,
42
+ NGX_HTTP_VAR_NOCACHEABLE , 0 },
43
+ { ngx_string ("rules" ), NULL ,
44
+ ngx_http_rules_variable , 0 ,
45
+ NGX_HTTP_VAR_NOCACHEABLE , 0 },
46
+ { ngx_null_string , NULL , NULL , 0 , 0 , 0 }
47
+ };
35
48
36
49
/*
37
50
* PCRE malloc/free workaround, based on
@@ -137,14 +150,12 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re
137
150
intervention .url = NULL ;
138
151
intervention .log = NULL ;
139
152
intervention .disruptive = 0 ;
140
- ngx_http_modsecurity_ctx_t * ctx = NULL ;
141
153
142
154
dd ("processing intervention" );
143
155
144
- ctx = ngx_http_get_module_ctx (r , ngx_http_modsecurity_module );
145
- if (ctx == NULL )
146
- {
147
- return NGX_HTTP_INTERNAL_SERVER_ERROR ;
156
+ if (ngx_http_get_intervention_status (r )) {
157
+ dd ("already done earlier" );
158
+ return 0 ;
148
159
}
149
160
150
161
if (msc_intervention (transaction , & intervention ) == 0 ) {
@@ -201,8 +212,7 @@ ngx_http_modsecurity_process_intervention (Transaction *transaction, ngx_http_re
201
212
202
213
if (intervention .status != 200 )
203
214
{
204
- ngx_http_modsecurity_log_handler (r );
205
- ctx -> logged = 1 ;
215
+ ngx_http_set_intervention_status_done (r );
206
216
207
217
if (r -> header_sent )
208
218
{
@@ -257,7 +267,7 @@ ngx_http_modsecurity_create_ctx(ngx_http_request_t *r)
257
267
ctx -> modsec_transaction = msc_new_transaction (cf -> modsec , loc_cf -> rules_set , r -> connection -> log );
258
268
259
269
dd ("transaction created" );
260
-
270
+
261
271
ctx -> response_body_filtered = 0 ;
262
272
ngx_http_set_ctx (r , ctx , ngx_http_modsecurity_module );
263
273
@@ -395,7 +405,7 @@ static ngx_command_t ngx_http_modsecurity_commands[] = {
395
405
396
406
397
407
static ngx_http_module_t ngx_http_modsecurity_ctx = {
398
- NULL , /* preconfiguration */
408
+ ngx_http_modsecurity_add_variables , /* preconfiguration */
399
409
ngx_http_modsecurity_init , /* postconfiguration */
400
410
401
411
ngx_http_modsecurity_create_main_conf , /* create main configuration */
@@ -672,3 +682,137 @@ ngx_http_modsecurity_config_cleanup(void *data)
672
682
673
683
674
684
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
685
+
686
+ static ngx_int_t
687
+ ngx_http_modsecurity_add_variables (ngx_conf_t * cf )
688
+ {
689
+ ngx_http_variable_t * var , * v ;
690
+ ngx_int_t index ;
691
+
692
+ dd ("adding variable" );
693
+
694
+ for (v = ngx_http_modsecurity_vars ; v -> name .len ; v ++ ) {
695
+ var = ngx_http_add_variable (cf , & v -> name , v -> flags );
696
+ if (var == NULL ) {
697
+ return NGX_ERROR ;
698
+ }
699
+ var -> get_handler = v -> get_handler ;
700
+
701
+ // initialization a variable
702
+ index = ngx_http_get_variable_index (cf , & v -> name );
703
+ if (index == NGX_ERROR ) {
704
+ return NGX_ERROR ;
705
+ }
706
+ dd ("variable %s, index %d" , v -> name .data , index );
707
+ }
708
+
709
+ return NGX_OK ;
710
+ }
711
+
712
+ static ngx_int_t
713
+ ngx_http_intervention_variable (ngx_http_request_t * r , ngx_http_variable_value_t * v , uintptr_t data )
714
+ {
715
+ if (v -> data == NULL ) {
716
+ dd ("initialize variable at first time" );
717
+ ngx_str_t str = ngx_string ("no" );
718
+ v -> valid = 1 ;
719
+ v -> not_found = 0 ;
720
+ v -> no_cacheable = 0 ;
721
+ v -> data = str .data ;
722
+ v -> len = str .len ;
723
+ }
724
+ return NGX_OK ;
725
+ }
726
+
727
+ static ngx_int_t
728
+ ngx_http_rules_variable (ngx_http_request_t * r , ngx_http_variable_value_t * v , uintptr_t data )
729
+ {
730
+ return NGX_OK ;
731
+ }
732
+
733
+ ngx_int_t
734
+ ngx_http_get_intervention_status (ngx_http_request_t * r )
735
+ {
736
+ ngx_http_variable_value_t * vv = NULL ;
737
+ ngx_uint_t key ;
738
+ ngx_str_t str = ngx_string ("yes" );
739
+ u_char * buf ;
740
+
741
+ buf = ngx_palloc (r -> pool , ngx_http_modsecurity_vars [0 ].name .len );
742
+ key = ngx_hash_strlow (buf , ngx_http_modsecurity_vars [0 ].name .data , ngx_http_modsecurity_vars [0 ].name .len );
743
+ vv = ngx_http_get_variable (r , & ngx_http_modsecurity_vars [0 ].name , key );
744
+ if (vv == NULL ) {
745
+ return NGX_ERROR ;
746
+ }
747
+
748
+ if (ngx_strncasecmp (vv -> data , str .data , str .len ) == 0 ) {
749
+ return 1 ;
750
+ }
751
+
752
+ return 0 ;
753
+ }
754
+
755
+ ngx_int_t
756
+ ngx_http_set_intervention_status_done (ngx_http_request_t * r )
757
+ {
758
+ ngx_http_variable_value_t * vv = NULL ;
759
+ ngx_uint_t key ;
760
+ ngx_str_t str = ngx_string ("yes" );
761
+ u_char * buf ;
762
+
763
+ buf = ngx_palloc (r -> pool , ngx_http_modsecurity_vars [0 ].name .len );
764
+ key = ngx_hash_strlow (buf , ngx_http_modsecurity_vars [0 ].name .data , ngx_http_modsecurity_vars [0 ].name .len );
765
+ vv = ngx_http_get_variable (r , & ngx_http_modsecurity_vars [0 ].name , key );
766
+ if (vv == NULL ) {
767
+ return NGX_ERROR ;
768
+ }
769
+
770
+ vv -> data = str .data ;
771
+ vv -> len = str .len ;
772
+
773
+ return 1 ;
774
+ }
775
+
776
+ ngx_http_variable_t *
777
+ ngx_http_get_variable_by_name (ngx_http_request_t * r , ngx_str_t * name )
778
+ {
779
+ ngx_http_core_main_conf_t * cmcf ;
780
+ ngx_http_variable_t * v ;
781
+ ngx_uint_t i ;
782
+
783
+ if (name -> len == 0 ) {
784
+ ngx_log_error (NGX_LOG_EMERG , r -> connection -> log , 0 , "invalid variable name" );
785
+ return NULL ;
786
+ }
787
+
788
+ cmcf = ngx_http_get_module_main_conf (r , ngx_http_core_module );
789
+
790
+ v = cmcf -> variables .elts ;
791
+
792
+ for (i = 0 ; i < cmcf -> variables .nelts ; i ++ ) {
793
+ if (name -> len != v [i ].name .len || ngx_strncasecmp (name -> data , v [i ].name .data , name -> len ) != 0 ) {
794
+ continue ;
795
+ }
796
+ return v ;
797
+ }
798
+
799
+ return NULL ;
800
+ }
801
+
802
+ void
803
+ ngx_http_restore_ruleset_from_variable (ngx_http_request_t * r , ngx_http_modsecurity_conf_t * cf )
804
+ {
805
+ ngx_http_variable_t * v ;
806
+
807
+ // saving the ruleset pointer to make it available for the cleanup callback that invoked when the config pool will be destroyed
808
+ dd ("backup ruleset %p for current location" , cf -> rules_set );
809
+ cf -> rules_backup = cf -> rules_set ;
810
+
811
+ v = ngx_http_get_variable_by_name (r , & ngx_http_modsecurity_vars [1 ].name );
812
+ if (v != NULL ) {
813
+ dd ("restore ruleset %p from variable" , (void * )v -> data );
814
+ cf -> rules_set = (Rules * )v -> data ;
815
+ } else {
816
+ dd ("failed to restore ruleset from varibale" );
817
+ }
818
+ }
0 commit comments