@@ -539,26 +539,49 @@ static void format_performance_variables_json(modsec_rec *msr, yajl_gen g) {
539539 * Write detailed information about a rule and its actionset into a JSON generator
540540 */
541541static void write_rule_json (modsec_rec * msr ,const msre_rule * rule ,yajl_gen g ) {
542- int present = 0 ;
542+ const apr_array_header_t * tarr ;
543+ const apr_table_entry_t * telts ;
544+ int been_opened = 0 ;
545+ int k ;
543546
544547yajl_gen_map_open (g );
545548
546549yajl_string (g ,"actionset" );
547550yajl_gen_map_open (g );
548551if (rule -> actionset -> id ) {
549- yajl_kv_string (g ,"id" ,rule -> actionset -> id );
552+ yajl_kv_string (g ,"id" ,log_escape ( msr -> mp , rule -> actionset -> id ) );
550553 }
551554if (rule -> actionset -> rev ) {
552- yajl_kv_string (g ,"rev" ,rule -> actionset -> rev );
555+ yajl_kv_string (g ,"rev" ,log_escape ( msr -> mp , rule -> actionset -> rev ) );
553556 }
554557if (rule -> actionset -> msg ) {
555- yajl_kv_string (g ,"msg" ,rule -> actionset -> msg );
558+ msc_string * var = (msc_string * )apr_palloc (msr -> mp ,sizeof (msc_string ));
559+ var -> value = (char * )rule -> actionset -> msg ;
560+ var -> value_len = strlen (rule -> actionset -> msg );
561+ expand_macros (msr ,var ,NULL ,msr -> mp );
562+
563+ yajl_kv_string (g ,"msg" ,log_escape_ex (msr -> mp ,var -> value ,var -> value_len ));
556564 }
557565if (rule -> actionset -> version ) {
558- yajl_kv_string (g ,"version" ,rule -> actionset -> version );
566+ yajl_kv_string (g ,"version" ,log_escape ( msr -> mp , rule -> actionset -> version ) );
559567 }
560568if (rule -> actionset -> logdata ) {
561- yajl_kv_string (g ,"logdata" ,rule -> actionset -> logdata );
569+ msc_string * var = (msc_string * )apr_pcalloc (msr -> mp ,sizeof (msc_string ));
570+ var -> value = (char * )rule -> actionset -> logdata ;
571+ var -> value_len = strlen (rule -> actionset -> logdata );
572+ expand_macros (msr ,var ,NULL ,msr -> mp );
573+
574+ char * logdata = apr_pstrdup (msr -> mp ,log_escape_hex (msr -> mp , (unsignedchar * )var -> value ,var -> value_len ));
575+
576+ // if it is > 512 bytes, then truncate at 512 with ellipsis.
577+ if (strlen (logdata )> 515 ) {
578+ logdata [512 ]= '.' ;
579+ logdata [513 ]= '.' ;
580+ logdata [514 ]= '.' ;
581+ logdata [515 ]= '\0' ;
582+ }
583+
584+ yajl_kv_string (g ,"logdata" ,logdata );
562585 }
563586if (rule -> actionset -> severity != NOT_SET ) {
564587yajl_kv_int (g ,"severity" ,rule -> actionset -> severity );
@@ -576,13 +599,41 @@ static void write_rule_json(modsec_rec *msr, const msre_rule *rule, yajl_gen g)
576599if (rule -> actionset -> is_chained && (rule -> chain_starter == NULL )) {
577600yajl_kv_bool (g ,"chain_starter" ,1 );
578601 }
602+
603+ // tags, lazily opened
604+ tarr = apr_table_elts (rule -> actionset -> actions );
605+ telts = (const apr_table_entry_t * )tarr -> elts ;
606+ for (k = 0 ;k < tarr -> nelts ;k ++ ) {
607+ msre_action * action = (msre_action * )telts [k ].val ;
608+ if (strcmp (telts [k ].key ,"tag" )== 0 ) {
609+ if (been_opened == 0 ) {
610+ yajl_string (g ,"tags" );
611+ yajl_gen_array_open (g );
612+ been_opened = 1 ;
613+ }
614+
615+ // expand variables in the tag
616+ msc_string * var = (msc_string * )apr_pcalloc (msr -> mp ,sizeof (msc_string ));
617+ var -> value = (char * )action -> param ;
618+ var -> value_len = strlen (action -> param );
619+ expand_macros (msr ,var ,NULL ,msr -> mp );
620+
621+ yajl_string (g ,log_escape (msr -> mp ,var -> value ));
622+ }
623+ }
624+
625+ if (been_opened == 1 ) {
626+ yajl_gen_array_close (g );
627+ }
628+
579629yajl_gen_map_close (g );
580630
581631yajl_string (g ,"operator" );
582632yajl_gen_map_open (g );
583633yajl_kv_string (g ,"operator" ,rule -> op_name );
584634yajl_kv_string (g ,"operator_param" ,rule -> op_param );
585635yajl_kv_string (g ,"target" ,rule -> p1 );
636+ yajl_kv_bool (g ,"negated" ,rule -> op_negated );
586637yajl_gen_map_close (g );
587638
588639yajl_string (g ,"config" );
@@ -591,6 +642,7 @@ static void write_rule_json(modsec_rec *msr, const msre_rule *rule, yajl_gen g)
591642yajl_kv_int (g ,"line_num" ,rule -> line_num );
592643yajl_gen_map_close (g );
593644
645+ yajl_kv_string (g ,"unparsed" ,rule -> unparsed );
594646yajl_kv_bool (g ,"is_matched" ,chained_is_matched (msr ,rule ));
595647
596648yajl_gen_map_close (g );