recog 3.1.1 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Gemfile +6 -0
  4. data/Rakefile +7 -5
  5. data/lib/recog/db.rb +67 -68
  6. data/lib/recog/db_manager.rb +22 -21
  7. data/lib/recog/fingerprint/regexp_factory.rb +10 -13
  8. data/lib/recog/fingerprint/test.rb +9 -8
  9. data/lib/recog/fingerprint.rb +252 -262
  10. data/lib/recog/fingerprint_parse_error.rb +3 -1
  11. data/lib/recog/formatter.rb +41 -39
  12. data/lib/recog/match_reporter.rb +82 -83
  13. data/lib/recog/matcher.rb +37 -40
  14. data/lib/recog/matcher_factory.rb +7 -6
  15. data/lib/recog/nizer.rb +218 -224
  16. data/lib/recog/verifier.rb +30 -28
  17. data/lib/recog/verify_reporter.rb +69 -73
  18. data/lib/recog/version.rb +3 -1
  19. data/lib/recog.rb +2 -0
  20. data/recog/bin/recog_match +21 -20
  21. data/recog/xml/apache_modules.xml +2 -0
  22. data/recog/xml/dhcp_vendor_class.xml +1 -1
  23. data/recog/xml/favicons.xml +133 -1
  24. data/recog/xml/ftp_banners.xml +1 -1
  25. data/recog/xml/html_title.xml +140 -1
  26. data/recog/xml/http_cookies.xml +20 -2
  27. data/recog/xml/http_servers.xml +38 -17
  28. data/recog/xml/http_wwwauth.xml +17 -4
  29. data/recog/xml/mdns_device-info_txt.xml +49 -15
  30. data/recog/xml/sip_banners.xml +0 -2
  31. data/recog/xml/sip_user_agents.xml +1 -1
  32. data/recog/xml/snmp_sysdescr.xml +1 -2
  33. data/recog/xml/ssh_banners.xml +8 -0
  34. data/recog/xml/telnet_banners.xml +3 -2
  35. data/recog/xml/tls_jarm.xml +1 -1
  36. data/recog/xml/x11_banners.xml +1 -0
  37. data/recog/xml/x509_issuers.xml +1 -1
  38. data/recog/xml/x509_subjects.xml +0 -1
  39. data/recog.gemspec +14 -13
  40. data/spec/lib/recog/db_spec.rb +37 -36
  41. data/spec/lib/recog/fingerprint/regexp_factory_spec.rb +19 -20
  42. data/spec/lib/recog/fingerprint_spec.rb +44 -42
  43. data/spec/lib/recog/formatter_spec.rb +20 -18
  44. data/spec/lib/recog/match_reporter_spec.rb +35 -30
  45. data/spec/lib/recog/nizer_spec.rb +85 -101
  46. data/spec/lib/recog/verify_reporter_spec.rb +45 -44
  47. data/spec/spec_helper.rb +2 -1
  48. data.tar.gz.sig +1 -3
  49. metadata +3 -3
  50. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adbba4275e0d4b8b6c41541ea76d522529d17525f1f1fcce5147625d2a8adb59
4
- data.tar.gz: 71929660f907cd74dfcd3f74ea0f3761efd33992821333059b50e5e6e5d52629
3
+ metadata.gz: 06e7e85a8a5531bf315f482708ed3ada966be06efea9d09d85add533d098c2f9
4
+ data.tar.gz: e683dd6e7c529d95eef78cf1ebf32a19594449a2105593234860619393643aa0
5
5
  SHA512:
6
- metadata.gz: e37368c659cbeadbc38cd90e9a71b41825a02d2e060d88b19f06bab86f791474033b0a26c0481be4a89ab46dc9ddbc5f151241f45bdf96eeb0644edd19be548b
7
- data.tar.gz: c7d438651a3b40f1586793ce60d1589c00541fd8fe587e480d477af6f02618d013c2edd5afeafff010931aa495ef6c417ba980072c8667e5e41a1a25efe585c6
6
+ metadata.gz: 69bc3fe5c446de07ee4234f668293839c902eb7df8dbd89e5e5b410a8d43bcddecd4cda0d0acb513c3f262d6aa5496e3ade0a2ad4df02b724a6b5b21edc37f9c
7
+ data.tar.gz: 2fb2209fcc598a8a592e4f81ced771dc5520e4cb46f06277e8e9a47e3827f7d0f4d0348a6c41bb759eb538943e06694c3b1f34d04fe09c235ac375110c2cedb1
checksums.yaml.gz.sig CHANGED
Binary file
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec name: 'recog'
@@ -8,3 +10,7 @@ group :test do
8
10
  gem 'rake'
9
11
  gem 'regexp_parser'
10
12
  end
13
+
14
+ group :rubocop do
15
+ gem 'rubocop'
16
+ end
data/Rakefile CHANGED
@@ -1,15 +1,17 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
2
4
 
3
5
  require 'rspec/core/rake_task'
4
6
  RSpec::Core::RakeTask.new do |t|
5
- t.pattern = ['spec/**/*_spec.rb', 'recog/spec/**/*_spec.rb']
7
+ t.pattern = ['spec/**/*_spec.rb', 'recog/spec/**/*_spec.rb']
6
8
  end
7
9
 
8
10
  require 'yard'
9
11
  require 'yard/rake/yardoc_task'
10
12
  YARD::Rake::YardocTask.new do |t|
11
- t.files = ['lib/**/*.rb', '-', 'README.md']
13
+ t.files = ['lib/**/*.rb', '-', 'README.md']
12
14
  end
13
15
 
14
- task :default => [ :tests, :yard ]
15
- task :tests => [ :spec ]
16
+ task default: %i[tests yard]
17
+ task tests: [:spec]
data/lib/recog/db.rb CHANGED
@@ -1,79 +1,78 @@
1
- module Recog
2
-
3
- # A collection of {Fingerprint fingerprints} for matching against a particular
4
- # kind of fingerprintable data, e.g. an HTTP `Server` header
5
- class DB
6
- require 'nokogiri'
7
- require 'recog/fingerprint'
8
-
9
- # @return [String]
10
- attr_reader :path
11
-
12
- # @return [Array<Fingerprint>] {Fingerprint} objects that can be matched
13
- # against strings that make sense for the {#match_key}
14
- attr_reader :fingerprints
15
-
16
- # @return [String] Taken from the `fingerprints/matches` attribute, or
17
- # defaults to the basename of {#path} without the `.xml` extension.
18
- attr_reader :match_key
19
-
20
- # @return [String] Taken from the `fingerprints/protocol` attribute, or
21
- # defaults to an empty string
22
- attr_reader :protocol
23
-
24
- # @return [String] Taken from the `fingerprints/database_type` attribute
25
- # defaults to an empty string
26
- attr_reader :database_type
27
-
28
- # @return [Float] Taken from the `fingerprints/preference` attribute,
29
- # defaults to 0.10. Used when ordering databases, highest numbers
30
- # are given priority and are processed first.
31
- attr_reader :preference
32
-
33
- # Default Fingerprint database preference when it isn't specified in file
34
- # Do not use a value below 0.10 so as to allow users to specify lower
35
- # values in their own custom XML that will always run last.
36
- DEFAULT_FP_PREFERENCE = 0.10
37
-
38
- # @param path [String]
39
- def initialize(path)
40
- @match_key = nil
41
- @protocol = ''
42
- @database_type = ''
43
- @preference = DEFAULT_FP_PREFERENCE.to_f
44
- @path = path
45
- @fingerprints = []
46
-
47
- parse_fingerprints
48
- end
1
+ # frozen_string_literal: true
49
2
 
50
- # @return [void]
51
- def parse_fingerprints
52
- xml = nil
53
-
54
- File.open(self.path, 'rb') do |fd|
55
- xml = Nokogiri::XML(fd.read(fd.stat.size))
3
+ module Recog
4
+ # A collection of {Fingerprint fingerprints} for matching against a particular
5
+ # kind of fingerprintable data, e.g. an HTTP `Server` header
6
+ class DB
7
+ require 'nokogiri'
8
+ require 'recog/fingerprint'
9
+
10
+ # @return [String]
11
+ attr_reader :path
12
+
13
+ # @return [Array<Fingerprint>] {Fingerprint} objects that can be matched
14
+ # against strings that make sense for the {#match_key}
15
+ attr_reader :fingerprints
16
+
17
+ # @return [String] Taken from the `fingerprints/matches` attribute, or
18
+ # defaults to the basename of {#path} without the `.xml` extension.
19
+ attr_reader :match_key
20
+
21
+ # @return [String] Taken from the `fingerprints/protocol` attribute, or
22
+ # defaults to an empty string
23
+ attr_reader :protocol
24
+
25
+ # @return [String] Taken from the `fingerprints/database_type` attribute
26
+ # defaults to an empty string
27
+ attr_reader :database_type
28
+
29
+ # @return [Float] Taken from the `fingerprints/preference` attribute,
30
+ # defaults to 0.10. Used when ordering databases, highest numbers
31
+ # are given priority and are processed first.
32
+ attr_reader :preference
33
+
34
+ # Default Fingerprint database preference when it isn't specified in file
35
+ # Do not use a value below 0.10 so as to allow users to specify lower
36
+ # values in their own custom XML that will always run last.
37
+ DEFAULT_FP_PREFERENCE = 0.10
38
+
39
+ # @param path [String]
40
+ def initialize(path)
41
+ @match_key = nil
42
+ @protocol = ''
43
+ @database_type = ''
44
+ @preference = DEFAULT_FP_PREFERENCE.to_f
45
+ @path = path
46
+ @fingerprints = []
47
+
48
+ parse_fingerprints
56
49
  end
57
50
 
58
- raise "#{self.path} is invalid XML: #{xml.errors.join(',')}" unless xml.errors.empty?
51
+ # @return [void]
52
+ def parse_fingerprints
53
+ xml = nil
59
54
 
60
- xml.xpath('/fingerprints').each do |fbase|
55
+ File.open(path, 'rb') do |fd|
56
+ xml = Nokogiri::XML(fd.read(fd.stat.size))
57
+ end
61
58
 
62
- @match_key = fbase['matches'].to_s if fbase['matches']
63
- @protocol = fbase['protocol'].to_s if fbase['protocol']
64
- @database_type = fbase['database_type'].to_s if fbase['database_type']
65
- @preference = fbase['preference'].to_f if fbase['preference']
59
+ raise "#{path} is invalid XML: #{xml.errors.join(',')}" unless xml.errors.empty?
66
60
 
67
- end
61
+ xml.xpath('/fingerprints').each do |fbase|
62
+ @match_key = fbase['matches'].to_s if fbase['matches']
63
+ @protocol = fbase['protocol'].to_s if fbase['protocol']
64
+ @database_type = fbase['database_type'].to_s if fbase['database_type']
65
+ @preference = fbase['preference'].to_f if fbase['preference']
66
+ end
68
67
 
69
- filepath = self.path.sub(/\.xml$/, '')
70
- @match_key = File.basename(self.path).sub(/\.xml$/, '') unless @match_key
68
+ filepath = path.sub(/\.xml$/, '')
69
+ @match_key ||= File.basename(path).sub(/\.xml$/, '')
71
70
 
72
- xml.xpath('/fingerprints/fingerprint').each do |fprint|
73
- @fingerprints << Fingerprint.new(fprint, @match_key, @protocol, filepath)
74
- end
71
+ xml.xpath('/fingerprints/fingerprint').each do |fprint|
72
+ @fingerprints << Fingerprint.new(fprint, @match_key, @protocol, filepath)
73
+ end
75
74
 
76
- xml = nil
75
+ xml = nil
76
+ end
77
77
  end
78
78
  end
79
- end
@@ -1,31 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Recog
2
- class DBManager
3
- require 'nokogiri'
4
- require 'recog/db'
4
+ class DBManager
5
+ require 'nokogiri'
6
+ require 'recog/db'
5
7
 
6
- attr_accessor :path, :databases
8
+ attr_accessor :path, :databases
7
9
 
8
- DefaultDatabasePath = File.expand_path(File.join(File.expand_path(__dir__), ["..", "..", "recog", "xml"]))
10
+ DefaultDatabasePath = File.expand_path(File.join(File.expand_path(__dir__), ['..', '..', 'recog', 'xml']))
9
11
 
10
- def initialize(path = DefaultDatabasePath)
11
- self.path = path
12
- reload
13
- end
12
+ def initialize(path = DefaultDatabasePath)
13
+ self.path = path
14
+ reload
15
+ end
14
16
 
15
- def load_databases
16
- if File.directory?(self.path)
17
- Dir[self.path + "/*.xml"].each do |dbxml|
18
- self.databases << DB.new(dbxml)
17
+ def load_databases
18
+ if File.directory?(path)
19
+ Dir["#{path}/*.xml"].each do |dbxml|
20
+ databases << DB.new(dbxml)
21
+ end
22
+ else
23
+ databases << DB.new(path)
19
24
  end
20
- else
21
- self.databases << DB.new(self.path)
22
25
  end
23
- end
24
26
 
25
- def reload
26
- self.databases = []
27
- load_databases
27
+ def reload
28
+ self.databases = []
29
+ load_databases
30
+ end
28
31
  end
29
-
30
- end
31
32
  end
@@ -1,14 +1,13 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Recog
3
4
  class Fingerprint
4
-
5
5
  #
6
6
  # @example
7
7
  # r = RegexpFactory.build("^Apache[ -]Coyote/(\d\.\d)$", "REG_ICASE")
8
8
  # r.match("Apache-Coyote/1.1")
9
9
  #
10
10
  module RegexpFactory
11
-
12
11
  # Currently, only options relating to case insensitivity and
13
12
  # multiline/newline are supported. Because Recog's data is used by tools
14
13
  # written in different languages like Ruby and Java, we currently support
@@ -19,13 +18,13 @@ module Recog
19
18
  # that use Recog data translate accordingly
20
19
  FLAG_MAP = {
21
20
  # multiline variations
22
- 'REG_DOT_NEWLINE' => Regexp::MULTILINE,
21
+ 'REG_DOT_NEWLINE' => Regexp::MULTILINE,
23
22
  'REG_LINE_ANY_CRLF' => Regexp::MULTILINE,
24
- 'REG_MULTILINE' => Regexp::MULTILINE,
23
+ 'REG_MULTILINE' => Regexp::MULTILINE,
25
24
  # case variations
26
- 'REG_ICASE' => Regexp::IGNORECASE,
27
- 'IGNORECASE' => Regexp::IGNORECASE
28
- }
25
+ 'REG_ICASE' => Regexp::IGNORECASE,
26
+ 'IGNORECASE' => Regexp::IGNORECASE
27
+ }.freeze
29
28
 
30
29
  DEFAULT_FLAGS = 0
31
30
 
@@ -42,15 +41,13 @@ module Recog
42
41
  # @param flags [Array<String>]
43
42
  # @return [Fixnum] Flags for creating a regular expression object
44
43
  def self.build_options(flags)
45
- unsupported_flags = flags.select { |flag| !FLAG_MAP.key?(flag) }
46
- unless unsupported_flags.empty?
47
- fail "Unsupported regular expression flags found: #{unsupported_flags.join(',')}. Must be one of: #{FLAG_MAP.keys.join(',')}"
48
- end
44
+ unsupported_flags = flags.reject { |flag| FLAG_MAP.key?(flag) }
45
+ raise "Unsupported regular expression flags found: #{unsupported_flags.join(',')}. Must be one of: #{FLAG_MAP.keys.join(',')}" unless unsupported_flags.empty?
46
+
49
47
  flags.reduce(DEFAULT_FLAGS) do |sum, flag|
50
- sum |= (FLAG_MAP[flag] || 0)
48
+ sum | (FLAG_MAP[flag] || 0)
51
49
  end
52
50
  end
53
51
  end
54
52
  end
55
53
  end
56
-
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  class Recog::Fingerprint::Test
3
- attr_accessor :content
4
- attr_accessor :attributes
5
- def initialize(content, attributes=[])
4
+ attr_accessor :content, :attributes
5
+
6
+ def initialize(content, attributes = [])
6
7
  @attributes = attributes
7
8
 
8
- if @attributes['_encoding'] && @attributes['_encoding'] == 'base64'
9
- @content = content.to_s.unpack('m*').first
10
- else
11
- @content = content
12
- end
9
+ @content = if @attributes['_encoding'] && @attributes['_encoding'] == 'base64'
10
+ content.to_s.unpack1('m*')
11
+ else
12
+ content
13
+ end
13
14
  end
14
15
 
15
16
  def to_s