1818
1919#include  <apr_base64.h> 
2020
21- 
2221/* Those are defined twice, lets keep it defined just once by `undef` 
2322 * the first one. 
2423 */ 
3130#define  NOTE_NGINX_REQUEST_CTX  "nginx-ctx"
3231#define  TXID_SIZE  25
3332
33+ /* 
34+  * If MOVE_REQUEST_CHAIN_TO_MODSEC is set, the chain will be moved into the 
35+  * ModSecurity brigade, after be processed by ModSecurity, it needs to be moved 
36+  * to nginx chains again, in order to be processed by other modules. It seems 
37+  * that this is not working well whenever the request body is delivered into 
38+  * chunks. Resulting in segfaults. 
39+  * 
40+  * If MOVE_REQUEST_CHAIN_TO_MODSEC is _not_ set, a copy of the request body 
41+  * will be delivered to ModSecurity and after processed it will be released, 
42+  * not modifying the nginx chain. 
43+  * 
44+  * The malfunctioning can be observer while running the following regression 
45+  * tests: 
46+  *  #15 - SecRequestBodyInMemoryLimit 
47+  *  #16 - SecRequestBodyInMemoryLimit (greater) 
48+  *  #19 - SecRequestBodyLimitAction ProcessPartial (multipart/greater - chunked) 
49+  *  (from: regression/config/10-request-directives.t) 
50+  */ 
51+ /* 
52+ #define MOVE_REQUEST_CHAIN_TO_MODSEC 
53+ */ 
54+ 
55+ 
3456#define  tuxb 
3557
3658/*  
@@ -492,8 +514,8 @@ ngx_http_modsecurity_save_headers_in_visitor(void *data, const char *key, const
492514static  ngx_inline  ngx_int_t 
493515ngx_http_modsecurity_load_request_body (ngx_http_request_t  * r )
494516{
495-     ngx_http_modsecurity_ctx_t      * ctx ;
496- 
517+     ngx_http_modsecurity_ctx_t  * ctx ;
518+      ngx_chain_t   * chain ; 
497519
498520    ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
499521        "ModSec: loading request body." );
@@ -502,33 +524,47 @@ ngx_http_modsecurity_load_request_body(ngx_http_request_t *r)
502524
503525    modsecSetBodyBrigade (ctx -> req , ctx -> brigade );
504526
505-     if  (r -> request_body  ==  NULL  ||  r -> request_body -> bufs  ==  NULL ) {
506-         ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
507-             "ModSec: request was null." );
508- 
509-         return  move_chain_to_brigade (NULL , ctx -> brigade , r -> pool , 1 );
527+     if  (r -> request_body  ==  NULL ) {
528+         chain  =  NULL ;
510529    }
530+     else  {
531+         chain  =  r -> request_body -> bufs ;
532+     }
533+ 
511534
512-     if  (move_chain_to_brigade (r -> request_body -> bufs , ctx -> brigade , r -> pool , 1 ) !=  NGX_OK ) {
535+ #ifdef  MOVE_REQUEST_CHAIN_TO_MODSEC 
536+     if  (move_chain_to_brigade (chain , ctx -> brigade , r -> pool , 1 ) !=  NGX_OK ) {
513537        ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
514538            "ModSec: failed to move chain to brigade." );
515539
516540        return  NGX_ERROR ;
517541    }
518542
519543    r -> request_body  =  NULL ;
544+ #else 
545+     if  (copy_chain_to_brigade (chain , ctx -> brigade , r -> pool , 1 ) !=  NGX_OK ) {
546+         ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
547+             "ModSec: failed to copy chain to brigade." );
548+ 
549+         return  NGX_ERROR ;
550+     }
551+ #endif 
520552
521553    return  NGX_OK ;
522554}
523555
524556static  ngx_inline  ngx_int_t 
525557ngx_http_modsecurity_save_request_body (ngx_http_request_t  * r )
526558{
527-     ngx_http_modsecurity_ctx_t     * ctx ;
528-     apr_off_t                       content_length ;
529-     ngx_buf_t                      * buf ;
530-     ctx  =  ngx_http_get_module_ctx (r , ngx_http_modsecurity );
559+     ngx_http_modsecurity_ctx_t  * ctx ;
560+ #ifdef  MOVE_REQUEST_CHAIN_TO_MODSEC 
561+     apr_off_t  content_length ;
562+     ngx_buf_t  * buf ;
563+ #endif 
564+ 
565+    ctx  =  ngx_http_get_module_ctx (r , ngx_http_modsecurity );
531566
567+ #ifdef  MOVE_REQUEST_CHAIN_TO_MODSEC 
532568    apr_brigade_length (ctx -> brigade , 0 , & content_length );
533569
534570    buf  =  ngx_create_temp_buf (ctx -> r -> pool , (size_t ) content_length );
@@ -550,10 +586,15 @@ ngx_http_modsecurity_save_request_body(ngx_http_request_t *r)
550586
551587    }
552588
553- 
554589    r -> headers_in .content_length_n  =  content_length ;
555590
556-     ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , "ModSec: Content length: %O, Content length n: %O" , content_length , r -> headers_in .content_length_n );
591+     ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
592+             "ModSec: Content length: %O, Content length n: %O" , content_length ,
593+             r -> headers_in .content_length_n );
594+ #else 
595+     apr_brigade_cleanup (ctx -> brigade );
596+ #endif 
597+ 
557598    return  NGX_OK ;
558599}
559600
@@ -787,7 +828,7 @@ ngx_http_modsecurity_status(ngx_http_request_t *r, int status)
787828 * @param r pointer to ngx_http_request_t. 
788829 * 
789830 */ 
790- static   void 
831+ ngx_int_t 
791832ngx_http_modsecurity_process_request (ngx_http_request_t  * r )
792833{
793834    ngx_int_t  rc  =  0 ;
@@ -802,23 +843,21 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
802843    if  (ngx_http_modsecurity_load_request (r ) !=  NGX_OK ) {
803844        ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
804845               "ModSec: failed while loading the request." );
805-         ngx_http_finalize_request (r , NGX_HTTP_INTERNAL_SERVER_ERROR );
806-         goto terminate ;
846+         return  NGX_HTTP_INTERNAL_SERVER_ERROR ;
807847    }
808848
809849    if  (ngx_http_modsecurity_load_headers_in (r ) !=  NGX_OK ) {
810850        ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
811851               "ModSec: failed while loading the headers." );
812-         ngx_http_finalize_request (r , NGX_HTTP_INTERNAL_SERVER_ERROR );
813-         goto terminate ;
852+         return  NGX_HTTP_INTERNAL_SERVER_ERROR ;
814853    }
815854
816855    rc  =  modsecProcessRequestHeaders (ctx -> req );
817856    rc  =  ngx_http_modsecurity_status (r , rc );
818857    if  (rc  !=  NGX_DECLINED ) {
819858        ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
820859               "ModSec: failed while processing the request headers" );
821-         ngx_http_finalize_request ( r ,  rc ) ;
860+         return  rc ;
822861    }
823862
824863    /* Here we check if ModSecurity is enabled or disabled again. 
@@ -841,12 +880,15 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
841880    }
842881
843882    if  (load_request_body  ==  1 ) {
883+         ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
884+             "ModSec: loading request body..." );
885+ 
844886        rc  =  ngx_http_modsecurity_load_request_body (r );
845887        if  (rc  !=  NGX_OK )
846888        {
847889            ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
848890                "ModSec: failed while loading the request body." );
849-             ngx_http_finalize_request ( r ,  NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
891+             return  NGX_HTTP_INTERNAL_SERVER_ERROR ;
850892        }
851893
852894
@@ -862,24 +904,23 @@ ngx_http_modsecurity_process_request(ngx_http_request_t *r)
862904            "ModSec: finalizing the connection after process the "  \
863905            "request body." );
864906
865-         ngx_http_finalize_request ( r ,  rc ) ;
907+         return  rc ;
866908    }
867909    if  (load_request_body  ==  1 ) {
868910        if  (ngx_http_modsecurity_save_request_body (r ) !=  NGX_OK )
869911        {
870912            ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
871913                "ModSec: failed while saving the request body" );
872-             ngx_http_finalize_request ( r ,  NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
914+             return  NGX_HTTP_INTERNAL_SERVER_ERROR ;
873915        }
874916        if  (ngx_http_modsecurity_save_headers_in (r ) !=  NGX_OK )
875917        {
876918            ngx_log_debug (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
877919                "ModSec: failed while saving the headers in" );
878-             ngx_http_finalize_request ( r ,  NGX_HTTP_INTERNAL_SERVER_ERROR ) ;
920+             return  NGX_HTTP_INTERNAL_SERVER_ERROR ;
879921        }
880922    }
881- terminate :
882-     return ;
923+     return  NGX_OK ;
883924}
884925
885926
@@ -1102,14 +1143,22 @@ ngx_http_modsecurity_handler(ngx_http_request_t *r) {
11021143
11031144        ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
11041145            "ModSec: request is ready to be processed." );
1105-         ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , 
1106-                 "ModSec: chuncked? %d" , r -> chunked );
1107-         ngx_http_modsecurity_process_request (r );
1146+         rc  =  ngx_http_modsecurity_process_request (r );
11081147        ctx -> request_processed  =  1 ;
1148+ 
1149+         if  (rc  ==  NGX_ERROR  ||  rc  >= NGX_HTTP_SPECIAL_RESPONSE ) {
1150+             ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
1151+                 "ModSec: returning a special response after process "  \
1152+                 "a request: %d" , rc );
1153+ 
1154+            return  rc ;
1155+         }
1156+ 
1157+ 
11091158    }
11101159
11111160    ngx_log_debug0 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
1112-         "ModSec: returning NGX_OK. Count++ :P "  );
1161+         "ModSec: returning NGX_DECLINED. "  );
11131162
11141163    return  NGX_DECLINED ;
11151164}
0 commit comments