Class: Recog::Fingerprint
- Inherits:
-
Object
- Object
- Recog::Fingerprint
- Defined in:
- lib/recog/fingerprint.rb,
lib/recog/fingerprint/regexp_factory.rb
Overview
A fingerprint that can be matched against a particular kind of
fingerprintable data, e.g. an HTTP Server
header
Defined Under Namespace
Modules: RegexpFactory Classes: Test
Instance Attribute Summary collapse
-
#name ⇒ String
readonly
A human readable name describing this fingerprint.
-
#params ⇒ Hash<String,Array>
readonly
Collection of indexes for capture groups created by #match.
-
#regex ⇒ Regexp
readonly
Regular expression pulled from the DB xml file.
- #tests ⇒ void readonly
Instance Method Summary collapse
-
#initialize(xml, match_key = nil, protocol = nil) ⇒ Fingerprint
constructor
A new instance of Fingerprint.
-
#match(match_string) ⇒ Hash?
Attempt to match the given string.
- #output_diag_data(message, data, exception) ⇒ Object
-
#verify_params {|status, message| ... } ⇒ Object
Ensure all the #params are valid.
-
#verify_tests {|status, message| ... } ⇒ Object
Ensure all the #tests actually match the fingerprint and return the expected capture groups.
Constructor Details
#initialize(xml, match_key = nil, protocol = nil) ⇒ Fingerprint
Returns a new instance of Fingerprint.
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/recog/fingerprint.rb', line 32 def initialize(xml, match_key=nil, protocol=nil) @match_key = match_key @protocol = protocol @name = parse_description(xml) @regex = create_regexp(xml) @params = {} @tests = [] @protocol.downcase! if @protocol parse_examples(xml) parse_params(xml) end |
Instance Attribute Details
#name ⇒ String (readonly)
A human readable name describing this fingerprint
11 12 13 |
# File 'lib/recog/fingerprint.rb', line 11 def name @name end |
#params ⇒ Hash<String,Array> (readonly)
Collection of indexes for capture groups created by #match
22 23 24 |
# File 'lib/recog/fingerprint.rb', line 22 def params @params end |
#regex ⇒ Regexp (readonly)
Regular expression pulled from the DB xml file.
17 18 19 |
# File 'lib/recog/fingerprint.rb', line 17 def regex @regex end |
Instance Method Details
#match(match_string) ⇒ Hash?
Attempt to match the given string.
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 |
# File 'lib/recog/fingerprint.rb', line 58 def match(match_string) # match_string.force_encoding('BINARY') if match_string begin match_data = @regex.match(match_string) rescue Encoding::CompatibilityError => e begin # Replace invalid UTF-8 characters with spaces, just as DAP does. encoded_str = match_string.encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => '') match_data = @regex.match(encoded_str) rescue Exception => e output_diag_data('Exception while re-encoding match_string to UTF-8', match_string, e) end rescue Exception => e output_diag_data('Exception while running regex against match_string', match_string, e) end return if match_data.nil? result = { 'matched' => @name } @params.each_pair do |k,v| pos = v[0] if pos == 0 # A match offset of 0 means this param has a hardcoded value result[k] = v[1] else # A match offset other than 0 means the value should come from # the corresponding match result index result[k] = match_data[ pos ] end end # Use the protocol specified in the XML database if there isn't one # provided as part of this fingerprint. if @protocol unless result['service.protocol'] result['service.protocol'] = @protocol end end result['fingerprint_db'] = @match_key if @match_key return result end |
#output_diag_data(message, data, exception) ⇒ Object
45 46 47 48 49 50 51 52 |
# File 'lib/recog/fingerprint.rb', line 45 def output_diag_data(, data, exception) STDERR.puts STDERR.puts exception.inspect STDERR.puts "Length: #{data.length}" STDERR.puts "Encoding: #{data.encoding}" STDERR.puts "Problematic data:\n#{data}" STDERR.puts "Raw bytes:\n#{data.pretty_inspect}\n" end |
#verify_params {|status, message| ... } ⇒ Object
Ensure all the #params are valid
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/recog/fingerprint.rb', line 107 def verify_params(&block) return if params.empty? params.each do |param_name, pos_value| pos, value = pos_value if pos > 0 && !value.to_s.empty? yield :fail, "'#{@name}'s #{param_name} is a non-zero pos but specifies a value of '#{value}'" elsif pos == 0 && value.to_s.empty? yield :fail, "'#{@name}'s #{param_name} is not a capture (pos=0) but doesn't specify a value" end end end |
#verify_tests {|status, message| ... } ⇒ Object
Ensure all the #tests actually match the fingerprint and return the expected capture groups.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/recog/fingerprint.rb', line 126 def verify_tests(&block) if tests.size == 0 yield :warn, "'#{@name}' has no test cases" end tests.each do |test| result = match(test.content) if result.nil? yield :fail, "'#{@name}' failed to match #{test.content.inspect} with #{@regex}'" next end = test status = :success # Ensure that all the attributes as provided by the example were parsed # out correctly and match the capture group values we expect. test.attributes.each do |k, v| next if k == '_encoding' if !result.has_key?(k) || result[k] != v = "'#{@name}' failed to find expected capture group #{k} '#{v}'. Result was #{result[k]}" status = :fail break end end yield status, end end |