ronin-db-activerecord 0.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +165 -0
  9. data/ChangeLog.md +39 -0
  10. data/Gemfile +27 -0
  11. data/README.md +143 -0
  12. data/Rakefile +72 -0
  13. data/db/migrate/0001_create_ronin_ip_address_mac_addresses_table.rb +43 -0
  14. data/db/migrate/0002_create_ronin_vulnerabilities_table.rb +61 -0
  15. data/db/migrate/0003_create_ronin_url_schemes_table.rb +32 -0
  16. data/db/migrate/0004_create_ronin_url_query_param_names_table.rb +32 -0
  17. data/db/migrate/0005_create_ronin_user_names_table.rb +33 -0
  18. data/db/migrate/0006_create_ronin_software_vendors_table.rb +32 -0
  19. data/db/migrate/0007_create_ronin_advisories_table.rb +42 -0
  20. data/db/migrate/0008_create_ronin_host_name_ip_addresses_table.rb +43 -0
  21. data/db/migrate/0009_create_ronin_host_names_table.rb +34 -0
  22. data/db/migrate/0010_create_ronin_arches_table.rb +37 -0
  23. data/db/migrate/0011_create_ronin_email_addresses_table.rb +44 -0
  24. data/db/migrate/0012_create_ronin_oses_table.rb +36 -0
  25. data/db/migrate/0013_create_ronin_organizations_table.rb +31 -0
  26. data/db/migrate/0014_create_ronin_ip_addresses_table.rb +35 -0
  27. data/db/migrate/0015_create_ronin_os_guesses_table.rb +40 -0
  28. data/db/migrate/0016_create_ronin_url_query_params_table.rb +42 -0
  29. data/db/migrate/0017_create_ronin_passwords_table.rb +32 -0
  30. data/db/migrate/0018_create_ronin_open_ports_table.rb +46 -0
  31. data/db/migrate/0019_create_ronin_urls_table.rb +50 -0
  32. data/db/migrate/0020_create_ronin_softwares_table.rb +39 -0
  33. data/db/migrate/0021_create_ronin_mac_addresses_table.rb +33 -0
  34. data/db/migrate/0022_create_ronin_countries_table.rb +34 -0
  35. data/db/migrate/0023_create_ronin_services_table.rb +32 -0
  36. data/db/migrate/0024_create_ronin_credentials_table.rb +44 -0
  37. data/db/migrate/0025_create_ronin_ports_table.rb +33 -0
  38. data/db/migrate/0026_create_ronin_asns_table.rb +44 -0
  39. data/db/migrate/0027_create_ronin_http_query_param_names_table.rb +32 -0
  40. data/db/migrate/0028_create_ronin_http_query_params_table.rb +42 -0
  41. data/db/migrate/0029_create_ronin_http_header_names_table.rb +31 -0
  42. data/db/migrate/0030_create_ronin_http_request_headers_table.rb +41 -0
  43. data/db/migrate/0031_create_ronin_http_response_headers_table.rb +41 -0
  44. data/db/migrate/0032_create_ronin_http_requests_table.rb +41 -0
  45. data/db/migrate/0033_create_ronin_http_responses_table.rb +36 -0
  46. data/db/migrate/0034_create_ronin_service_credentials_table.rb +41 -0
  47. data/db/migrate/0035_create_ronin_web_credentials_table.rb +41 -0
  48. data/gemspec.yml +28 -0
  49. data/lib/ronin/db/address.rb +105 -0
  50. data/lib/ronin/db/advisory.rb +169 -0
  51. data/lib/ronin/db/arch.rb +160 -0
  52. data/lib/ronin/db/asn.rb +212 -0
  53. data/lib/ronin/db/credential.rb +248 -0
  54. data/lib/ronin/db/email_address.rb +225 -0
  55. data/lib/ronin/db/host_name.rb +224 -0
  56. data/lib/ronin/db/host_name_ip_address.rb +65 -0
  57. data/lib/ronin/db/http_header_name.rb +75 -0
  58. data/lib/ronin/db/http_query_param.rb +79 -0
  59. data/lib/ronin/db/http_query_param_name.rb +76 -0
  60. data/lib/ronin/db/http_request.rb +120 -0
  61. data/lib/ronin/db/http_request_header.rb +78 -0
  62. data/lib/ronin/db/http_response.rb +91 -0
  63. data/lib/ronin/db/http_response_header.rb +78 -0
  64. data/lib/ronin/db/ip_address.rb +351 -0
  65. data/lib/ronin/db/ip_address_mac_address.rb +62 -0
  66. data/lib/ronin/db/mac_address.rb +91 -0
  67. data/lib/ronin/db/migrations.rb +137 -0
  68. data/lib/ronin/db/model/has_name.rb +102 -0
  69. data/lib/ronin/db/model/has_unique_name.rb +82 -0
  70. data/lib/ronin/db/model/importable.rb +85 -0
  71. data/lib/ronin/db/model/last_scanned_at.rb +48 -0
  72. data/lib/ronin/db/model.rb +37 -0
  73. data/lib/ronin/db/models.rb +108 -0
  74. data/lib/ronin/db/open_port.rb +148 -0
  75. data/lib/ronin/db/organization.rb +50 -0
  76. data/lib/ronin/db/os.rb +183 -0
  77. data/lib/ronin/db/os_guess.rb +67 -0
  78. data/lib/ronin/db/password.rb +167 -0
  79. data/lib/ronin/db/port.rb +123 -0
  80. data/lib/ronin/db/root.rb +28 -0
  81. data/lib/ronin/db/schema_migration.rb +34 -0
  82. data/lib/ronin/db/service.rb +48 -0
  83. data/lib/ronin/db/service_credential.rb +66 -0
  84. data/lib/ronin/db/software.rb +85 -0
  85. data/lib/ronin/db/software_vendor.rb +42 -0
  86. data/lib/ronin/db/url.rb +497 -0
  87. data/lib/ronin/db/url_query_param.rb +79 -0
  88. data/lib/ronin/db/url_query_param_name.rb +76 -0
  89. data/lib/ronin/db/url_scheme.rb +80 -0
  90. data/lib/ronin/db/user_name.rb +96 -0
  91. data/lib/ronin/db/vulnerability.rb +81 -0
  92. data/lib/ronin/db/web_credential.rb +69 -0
  93. data/ronin-db-activerecord.gemspec +61 -0
  94. data/spec/advisory_spec.rb +277 -0
  95. data/spec/arch_spec.rb +228 -0
  96. data/spec/asn_spec.rb +504 -0
  97. data/spec/credential_spec.rb +362 -0
  98. data/spec/email_address_spec.rb +372 -0
  99. data/spec/host_name_ip_address_spec.rb +8 -0
  100. data/spec/host_name_spec.rb +207 -0
  101. data/spec/http_header_name_spec.rb +25 -0
  102. data/spec/http_query_param_name_spec.rb +25 -0
  103. data/spec/http_query_param_spec.rb +104 -0
  104. data/spec/http_request_header_spec.rb +72 -0
  105. data/spec/http_request_spec.rb +168 -0
  106. data/spec/http_response_header_spec.rb +74 -0
  107. data/spec/http_response_spec.rb +103 -0
  108. data/spec/ip_address_mac_addresses_spec.rb +8 -0
  109. data/spec/ip_address_spec.rb +386 -0
  110. data/spec/mac_address_spec.rb +67 -0
  111. data/spec/migrations_spec.rb +122 -0
  112. data/spec/model/has_name_spec.rb +65 -0
  113. data/spec/model/has_unique_name_spec.rb +61 -0
  114. data/spec/model/importable_spec.rb +105 -0
  115. data/spec/models_spec.rb +60 -0
  116. data/spec/open_port_spec.rb +87 -0
  117. data/spec/organization_spec.rb +10 -0
  118. data/spec/os_guess_spec.rb +43 -0
  119. data/spec/os_spec.rb +114 -0
  120. data/spec/password_spec.rb +81 -0
  121. data/spec/port_spec.rb +102 -0
  122. data/spec/schema_migration_spec.rb +8 -0
  123. data/spec/service_credential_spec.rb +43 -0
  124. data/spec/service_spec.rb +39 -0
  125. data/spec/software_spec.rb +76 -0
  126. data/spec/software_vendor_spec.rb +33 -0
  127. data/spec/spec_helper.rb +13 -0
  128. data/spec/url_query_param_name_spec.rb +25 -0
  129. data/spec/url_query_param_spec.rb +110 -0
  130. data/spec/url_scheme_spec.rb +39 -0
  131. data/spec/url_spec.rb +951 -0
  132. data/spec/user_name_spec.rb +54 -0
  133. data/spec/vulnerability_spec.rb +8 -0
  134. data/spec/web_credential_spec.rb +72 -0
  135. metadata +266 -0
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/model'
22
+ require 'ronin/db/model/importable'
23
+ require 'ronin/db/model/last_scanned_at'
24
+
25
+ require 'active_record'
26
+
27
+ module Ronin
28
+ module DB
29
+ #
30
+ # A base model which represents an Internet Address, such as:
31
+ #
32
+ # * {MACAddress}
33
+ # * {IPAddress}
34
+ # * {HostName}
35
+ #
36
+ class Address < ActiveRecord::Base
37
+
38
+ include Model
39
+ include Model::Importable
40
+ include Model::LastScannedAt
41
+
42
+ self.abstract_class = true
43
+
44
+ # @!attribute [rw] id
45
+ # The primary key of the Address
46
+ #
47
+ # @return [Integer]
48
+ attribute :id, :integer
49
+
50
+ # @!attribute [rw] address
51
+ # The Address
52
+ #
53
+ # @return [String]
54
+ attribute :address, :string
55
+ validates :address, presence: true, uniqueness: true
56
+
57
+ # @!attribute [rw] created_at
58
+ # Tracks when the IP Address was first created
59
+ #
60
+ # @return [Time]
61
+ attribute :created_at, :time
62
+
63
+ #
64
+ # Looks up the address.
65
+ #
66
+ # @param [String] address
67
+ # The address to query.
68
+ #
69
+ # @return [Address, nil]
70
+ # The found address.
71
+ #
72
+ def self.lookup(address)
73
+ find_by(address: address)
74
+ end
75
+
76
+ #
77
+ # Imports an address.
78
+ #
79
+ # @param [String] address
80
+ # The address to parse.
81
+ #
82
+ # @return [Address]
83
+ # The parsed address.
84
+ #
85
+ # @api public
86
+ #
87
+ def self.import(address)
88
+ create(address: address)
89
+ end
90
+
91
+ #
92
+ # Converts the address into a string.
93
+ #
94
+ # @return [String]
95
+ # The address.
96
+ #
97
+ # @api public
98
+ #
99
+ def to_s
100
+ self.address.to_s
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/model'
22
+ require 'ronin/db/model/importable'
23
+
24
+ require 'active_record'
25
+
26
+ module Ronin
27
+ module DB
28
+ #
29
+ # Represents a vulnerability Advisory, with a Publisher, Number and
30
+ # URL.
31
+ #
32
+ class Advisory < ActiveRecord::Base
33
+
34
+ include Model
35
+ include Model::Importable
36
+
37
+ self.primary_key = :id
38
+
39
+ # @!attribute [rw] id
40
+ # Primary key of the advisory.
41
+ #
42
+ # @return [String]
43
+ attribute :id, :string
44
+
45
+ # @!attribute [rw] prefix
46
+ # The ID prefix (ex: `CVE` or `GHSA`).
47
+ #
48
+ # @return [String]
49
+ attribute :prefix, :string
50
+ validates :prefix, presence: true
51
+
52
+ # @!attribute [rw] year
53
+ # The year the advisory was published in.
54
+ #
55
+ # @return [Integer]
56
+ attribute :year, :integer
57
+ validates :year, allow_nil: true,
58
+ comparison: {
59
+ greater_than: 1990,
60
+ less_than_or_equal_to: Date.today.year
61
+ }
62
+
63
+ # @!attribute [rw] identifier
64
+ # The advisory identifier
65
+ #
66
+ # @return [String]
67
+ attribute :identifier, :string
68
+ validates :identifier, presence: true
69
+
70
+ #
71
+ # @api private
72
+ #
73
+ module ID
74
+ #
75
+ # Parses a security avdisory ID.
76
+ #
77
+ # @param [String] string
78
+ # The security advisory ID String to split.
79
+ #
80
+ # @return [Hash{Symbol => Object}]
81
+ # The parsed security advisory ID.
82
+ #
83
+ # @raise [ArgumentError]
84
+ # The ID does not appear to be a valid security ID.
85
+ #
86
+ def self.parse(string)
87
+ if (match = string.match(/\A([A-Z]+)-(\d{4})[:-]([0-9][0-9-]+)\z/))
88
+ {
89
+ id: match[0],
90
+ prefix: match[1],
91
+ year: match[2].to_i,
92
+ identifier: match[3]
93
+ }
94
+ elsif (match = string.match(/\AMS(\d{2})-(\d{3,})\z/))
95
+ {
96
+ id: match[0],
97
+ prefix: 'MS',
98
+ year: 2000 + match[1].to_i,
99
+ identifier: match[2]
100
+ }
101
+ elsif (match = string.match(/\A([A-Z]+)-(.+)\z/))
102
+ {
103
+ id: match[0],
104
+ prefix: match[1],
105
+ identifier: match[2]
106
+ }
107
+ else
108
+ raise(ArgumentError,"id does not appear to be a valid security advisory ID: #{string.inspect}")
109
+ end
110
+ end
111
+ end
112
+
113
+ #
114
+ # Looks up the advisory.
115
+ #
116
+ # @param [String] id
117
+ #
118
+ # @return [Advisory, nil]
119
+ #
120
+ def self.lookup(id)
121
+ find_by(id: id)
122
+ end
123
+
124
+ #
125
+ # Parses an Advisory ID String.
126
+ #
127
+ # @param [String] id
128
+ # The ID String for the advisory.
129
+ #
130
+ # @return [Advisory]
131
+ # The new advisory.
132
+ #
133
+ # @api public
134
+ #
135
+ def self.import(id)
136
+ create(**ID.parse(id))
137
+ end
138
+
139
+ #
140
+ # Generates a URL for the advisory.
141
+ #
142
+ # @return [String, nil]
143
+ # The URL for the advisory.
144
+ #
145
+ # @api public
146
+ #
147
+ def url
148
+ case prefix
149
+ when 'CVE' then "https://nvd.nist.gov/vuln/detail/#{id}"
150
+ when 'RHSA' then "https://access.redhat.com/errata/#{id}"
151
+ when 'GHSA' then "https://github.com/advisories/#{id}"
152
+ end
153
+ end
154
+
155
+ #
156
+ # Converts the advisory to a String.
157
+ #
158
+ # @return [String]
159
+ # The advisory ID string.
160
+ #
161
+ # @api public
162
+ #
163
+ def to_s
164
+ self.id
165
+ end
166
+
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/model'
22
+ require 'ronin/db/model/has_unique_name'
23
+
24
+ require 'active_record'
25
+
26
+ module Ronin
27
+ module DB
28
+ #
29
+ # Represents a Computer Architecture and predefines many other common
30
+ # architectures ({x86}, {x86_64}, {ppc}, {ppc64}, {mips}, {mips_le},
31
+ # {mips_be}, {arm}, {arm_le}, and {arm_be}).
32
+ #
33
+ class Arch < ActiveRecord::Base
34
+
35
+ include Model
36
+ include Model::HasUniqueName
37
+
38
+ # @!attribute [rw] id
39
+ # The primary key of the arch.
40
+ #
41
+ # @return [Integer]
42
+ attribute :id, :integer
43
+
44
+ # @!attribute [rw] endian
45
+ # Endianness of the architecture.
46
+ #
47
+ # @return [:little, :big]
48
+ enum :endian, {little: 'little', big: 'big'}
49
+ validates :endian, presence: true
50
+
51
+ # @!attribute [rw] word_size
52
+ # Address length of the architecture.
53
+ #
54
+ # @return [Integer]
55
+ attribute :word_size, :integer
56
+ validates :word_size, presence: true,
57
+ inclusion: {in: [4, 8]}
58
+
59
+ #
60
+ # The x86 Architecture
61
+ #
62
+ # @return [Arch]
63
+ #
64
+ def self.x86
65
+ find_or_create_by(name: 'x86')
66
+ end
67
+
68
+ #
69
+ # The i686 Architecture
70
+ #
71
+ # @return [Arch]
72
+ #
73
+ def self.i686
74
+ find_or_create_by(name: 'i686')
75
+ end
76
+
77
+ #
78
+ # The x86_64 Architecture
79
+ #
80
+ # @return [Arch]
81
+ #
82
+ def self.x86_64
83
+ find_or_create_by(name: 'x86-64')
84
+ end
85
+
86
+ #
87
+ # The 32-bit PowerPC Architecture
88
+ #
89
+ # @return [Arch]
90
+ #
91
+ def self.ppc
92
+ find_or_create_by(name: 'PPC')
93
+ end
94
+
95
+ #
96
+ # The 64-bit PowerPC Architecture
97
+ #
98
+ # @return [Arch]
99
+ #
100
+ def self.ppc64
101
+ find_or_create_by(name: 'PPC64')
102
+ end
103
+
104
+ #
105
+ # The MIPS Architecture
106
+ #
107
+ # @return [Arch]
108
+ #
109
+ def self.mips
110
+ find_or_create_by(name: 'MIPS')
111
+ end
112
+
113
+ #
114
+ # The MIPS (little endian) Architecture
115
+ #
116
+ # @return [Arch]
117
+ #
118
+ def self.mips_le
119
+ find_or_create_by(name: 'MIPS (Little-Endian)')
120
+ end
121
+
122
+ #
123
+ # The MIPS (big endian) Architecture
124
+ #
125
+ # @return [Arch]
126
+ #
127
+ def self.mips_be
128
+ find_or_create_by(name: 'MIPS (Big-Endian)')
129
+ end
130
+
131
+ #
132
+ # The ARM Architecture
133
+ #
134
+ # @return [Arch]
135
+ #
136
+ def self.arm
137
+ find_or_create_by(name: 'ARM')
138
+ end
139
+
140
+ #
141
+ # The ARM (little endian) Architecture
142
+ #
143
+ # @return [Arch]
144
+ #
145
+ def self.arm_le
146
+ find_or_create_by(name: 'ARM (Little-Endian)')
147
+ end
148
+
149
+ #
150
+ # The ARM (big endian) Architecture
151
+ #
152
+ # @return [Arch]
153
+ #
154
+ def self.arm_be
155
+ find_or_create_by(name: 'ARM (Big-Endian)')
156
+ end
157
+
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/model'
22
+
23
+ module Ronin
24
+ module DB
25
+ #
26
+ # Represents an ASN range.
27
+ #
28
+ class ASN < ActiveRecord::Base
29
+
30
+ include Model
31
+
32
+ # @!attribute [rw] id
33
+ # The primary key of the ASN range.
34
+ #
35
+ # @return [Integer]
36
+ attribute :id, :integer
37
+
38
+ # @!attribute [rw] version
39
+ # Whether the ASN range represents an IPv4 or IPv6 range.
40
+ #
41
+ # @return [Integer]
42
+ attribute :version, :integer
43
+ validates :version, presence: true,
44
+ inclusion: {in: [4, 6]}
45
+
46
+ # @!attribute [rw] range_start
47
+ # The starting IP address of the ASN range.
48
+ #
49
+ # @return [String]
50
+ attribute :range_start, :string
51
+ validates :range_start, presence: true
52
+
53
+ # @!attribute [rw] range_end
54
+ # The ending IP address of the ASN range.
55
+ #
56
+ # @return [String]
57
+ attribute :range_end, :string
58
+ validates :range_end, presence: true
59
+
60
+ # @!attribute [r] range_start_hton
61
+ # The starting IP address of the ASN range, but in network byte-order.
62
+ #
63
+ # @return [String]
64
+ attribute :range_start_hton, :binary
65
+
66
+ # @!attribute [r] range_end_hton
67
+ # The ending IP address of the ASN range, but in network byte-order.
68
+ #
69
+ # @return [String]
70
+ attribute :range_end_hton, :binary
71
+
72
+ before_save :set_hton
73
+
74
+ # @!attribute [rw] number
75
+ # The ASN number.
76
+ #
77
+ # @return [Integer]
78
+ attribute :number, :integer
79
+ validates :number, presence: true,
80
+ uniqueness: {scope: [:range_start, :range_end]}
81
+
82
+ # @!attribute [rw] country_code
83
+ # The country code of the ASN.
84
+ #
85
+ # @return [String]
86
+ attribute :country_code, :string
87
+
88
+ # @!attribute [rw] name
89
+ # The organization the ASN is currently assigned to.
90
+ #
91
+ # @return [String]
92
+ attribute :name, :string
93
+
94
+ #
95
+ # Searches for all IPv4 ASNs.
96
+ #
97
+ # @return [Array<ASN>]
98
+ # The IPv4 ASNs.
99
+ #
100
+ # @api public
101
+ #
102
+ def self.v4
103
+ where(version: 4)
104
+ end
105
+
106
+ #
107
+ # Searches for all IPv6 ASNs.
108
+ #
109
+ # @return [Array<ASNs>]
110
+ # The IPv6 ASNs.
111
+ #
112
+ # @api public
113
+ #
114
+ def self.v6
115
+ where(version: 6)
116
+ end
117
+
118
+ #
119
+ # Searches for all ASNs with the matching AS number.
120
+ #
121
+ # @param [Integer] number
122
+ # The AS number to search for.
123
+ #
124
+ # @return [Array<ASN>]
125
+ #
126
+ def self.with_number(number)
127
+ where(number: number)
128
+ end
129
+
130
+ #
131
+ # Searches for all ASNs with the matching country code.
132
+ #
133
+ # @param [String] country_code
134
+ # The two letter country code to search for.
135
+ #
136
+ # @return [Array<ASN>]
137
+ #
138
+ def self.with_country_code(country_code)
139
+ where(country_code: country_code)
140
+ end
141
+
142
+ #
143
+ # Searches for all ASNs with the matching name.
144
+ #
145
+ # @param [String] name
146
+ # The name to search for.
147
+ #
148
+ # @return [Array<ASN>]
149
+ #
150
+ def self.with_name(name)
151
+ where(name: name)
152
+ end
153
+
154
+ #
155
+ # Queries the ASN that contains the given IP address.
156
+ #
157
+ # @param [IPAddr, String] ip
158
+ #
159
+ # @return [ASN, nil]
160
+ #
161
+ def self.containing_ip(ip)
162
+ ip = IPAddr.new(ip) unless ip.kind_of?(IPAddr)
163
+ ip_hton = ip.hton
164
+
165
+ range_start_hton = self.arel_table[:range_start_hton]
166
+ range_end_hton = self.arel_table[:range_end_hton]
167
+
168
+ where(range_start_hton.lteq(ip_hton).and(range_end_hton.gteq(ip_hton))).first
169
+ end
170
+
171
+ #
172
+ # @return [IPAddr, nil]
173
+ #
174
+ def range_start_ipaddr
175
+ @range_start_ipaddr ||= if self.range_start
176
+ IPAddr.new(self.range_start)
177
+ end
178
+ end
179
+
180
+ #
181
+ # @return [IPAddr, nil]
182
+ #
183
+ def range_end_ipaddr
184
+ @range_end_ipaddr ||= if self.range_end
185
+ IPAddr.new(self.range_end)
186
+ end
187
+ end
188
+
189
+ #
190
+ # Queries all IP addresses within the ASN IP range.
191
+ #
192
+ # @return [Array<IPAddress>]
193
+ #
194
+ def ip_addresses
195
+ IPAddress.between(range_start,range_end)
196
+ end
197
+
198
+ private
199
+
200
+ #
201
+ # Sets the `range_start_hton` and `range_end_hton` attributes.
202
+ #
203
+ def set_hton
204
+ self.range_start_hton = range_start_ipaddr.hton
205
+ self.range_end_hton = range_end_ipaddr.hton
206
+ end
207
+
208
+ end
209
+ end
210
+ end
211
+
212
+ require 'ronin/db/ip_address'