/usr/share/modsecurity-crs/util/rule-management/verify.rb is in modsecurity-crs 2.2.8-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #!/usr/bin/env ruby
# -*- coding: utf-8 -*-
#
# Copyright © 2012 Diego Elio Pettenò <flameeyes@flameeyes.eu>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
require 'set'
seen_ids = Set.new
res = 0
# read reserved id range from the id-range file so that it can be
# configured on a per-repository basis.
range = Range.new(*File.read('id-range').rstrip.split('-').map(&:to_i))
# open all the rule files
Dir.chdir("../../")
Dir["**/*.conf"].each do |rulefile|
# read the content
content = File.read(rulefile)
lineno = 0
this_chained = next_chained = false
prevline = nil
# for each line in the rule file
content.each_line do |line|
lineno += 1
# handle continuation lines
line = (prevline + line) unless prevline.nil?
# remove comments
line.gsub!(/^([^'"]|'[^']+'|"[^"]+")#.*/) { $1 }
if line =~ /\\\n$/
prevline = line.gsub(/\\\n/, '')
next
else
prevline = nil
end
# skip if it's an empty line (this also skip comment-only lines)
next if line =~ /(?:^\s+$|^#)/
this_chained = next_chained
next_chained = false
# split the directive in its components, considering quoted strings
directive = line.scan(/([^'"\s][^\s]*[^'"\s]|'(?:[^']|\\')*[^\\]'|"(?:[^"]|\\")*[^\\]")(?:\s+|$)/).flatten
directive.map! do |piece|
# then make sure to split the quoting out of the quoted strings
(piece[0] == '"' || piece[0] == "'") ? piece[1..-2] : piece
end
# skip if it's not a SecRule or SecAction
case directive[0]
when "SecRule"
rawrule = directive[3]
when "SecAction"
rawrule = directive[1]
else
next
end
# get the rule and split in its components
rule = (rawrule || "").gsub(/(?:^"|"$)/, '').split(/\s*,\s*/)
if rule.include?("chain")
next_chained = true
end
ids = rule.find_all { |piece| piece =~ /^id:/ }
if ids.size > 1
$stderr.puts "#{rulefile}:#{lineno} rule with multiple ids"
next
elsif ids.size == 0
id = nil
else
id = ids[0].sub(/^id:/, '').gsub(/(?:^'|'$)/, '').to_i
end
if this_chained
unless id.nil?
$stderr.puts "#{rulefile}:#{lineno} chained rule with id"
res = 1
end
next
elsif id.nil?
$stderr.puts "#{rulefile}:#{lineno} rule missing id (#{rule.join(',')})"
res = 1
next
elsif ! range.include?(id)
$stderr.puts "#{rulefile}:#{lineno} rule with id #{id} outside of reserved range #{range}"
res = 1
elsif seen_ids.include?(id)
$stderr.puts "#{rulefile}:#{lineno} rule with duplicated id #{id}"
res = 1
end
seen_ids << id
end
end
exit res
|