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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +39 -0
- data/Gemfile +27 -0
- data/README.md +143 -0
- data/Rakefile +72 -0
- data/db/migrate/0001_create_ronin_ip_address_mac_addresses_table.rb +43 -0
- data/db/migrate/0002_create_ronin_vulnerabilities_table.rb +61 -0
- data/db/migrate/0003_create_ronin_url_schemes_table.rb +32 -0
- data/db/migrate/0004_create_ronin_url_query_param_names_table.rb +32 -0
- data/db/migrate/0005_create_ronin_user_names_table.rb +33 -0
- data/db/migrate/0006_create_ronin_software_vendors_table.rb +32 -0
- data/db/migrate/0007_create_ronin_advisories_table.rb +42 -0
- data/db/migrate/0008_create_ronin_host_name_ip_addresses_table.rb +43 -0
- data/db/migrate/0009_create_ronin_host_names_table.rb +34 -0
- data/db/migrate/0010_create_ronin_arches_table.rb +37 -0
- data/db/migrate/0011_create_ronin_email_addresses_table.rb +44 -0
- data/db/migrate/0012_create_ronin_oses_table.rb +36 -0
- data/db/migrate/0013_create_ronin_organizations_table.rb +31 -0
- data/db/migrate/0014_create_ronin_ip_addresses_table.rb +35 -0
- data/db/migrate/0015_create_ronin_os_guesses_table.rb +40 -0
- data/db/migrate/0016_create_ronin_url_query_params_table.rb +42 -0
- data/db/migrate/0017_create_ronin_passwords_table.rb +32 -0
- data/db/migrate/0018_create_ronin_open_ports_table.rb +46 -0
- data/db/migrate/0019_create_ronin_urls_table.rb +50 -0
- data/db/migrate/0020_create_ronin_softwares_table.rb +39 -0
- data/db/migrate/0021_create_ronin_mac_addresses_table.rb +33 -0
- data/db/migrate/0022_create_ronin_countries_table.rb +34 -0
- data/db/migrate/0023_create_ronin_services_table.rb +32 -0
- data/db/migrate/0024_create_ronin_credentials_table.rb +44 -0
- data/db/migrate/0025_create_ronin_ports_table.rb +33 -0
- data/db/migrate/0026_create_ronin_asns_table.rb +44 -0
- data/db/migrate/0027_create_ronin_http_query_param_names_table.rb +32 -0
- data/db/migrate/0028_create_ronin_http_query_params_table.rb +42 -0
- data/db/migrate/0029_create_ronin_http_header_names_table.rb +31 -0
- data/db/migrate/0030_create_ronin_http_request_headers_table.rb +41 -0
- data/db/migrate/0031_create_ronin_http_response_headers_table.rb +41 -0
- data/db/migrate/0032_create_ronin_http_requests_table.rb +41 -0
- data/db/migrate/0033_create_ronin_http_responses_table.rb +36 -0
- data/db/migrate/0034_create_ronin_service_credentials_table.rb +41 -0
- data/db/migrate/0035_create_ronin_web_credentials_table.rb +41 -0
- data/gemspec.yml +28 -0
- data/lib/ronin/db/address.rb +105 -0
- data/lib/ronin/db/advisory.rb +169 -0
- data/lib/ronin/db/arch.rb +160 -0
- data/lib/ronin/db/asn.rb +212 -0
- data/lib/ronin/db/credential.rb +248 -0
- data/lib/ronin/db/email_address.rb +225 -0
- data/lib/ronin/db/host_name.rb +224 -0
- data/lib/ronin/db/host_name_ip_address.rb +65 -0
- data/lib/ronin/db/http_header_name.rb +75 -0
- data/lib/ronin/db/http_query_param.rb +79 -0
- data/lib/ronin/db/http_query_param_name.rb +76 -0
- data/lib/ronin/db/http_request.rb +120 -0
- data/lib/ronin/db/http_request_header.rb +78 -0
- data/lib/ronin/db/http_response.rb +91 -0
- data/lib/ronin/db/http_response_header.rb +78 -0
- data/lib/ronin/db/ip_address.rb +351 -0
- data/lib/ronin/db/ip_address_mac_address.rb +62 -0
- data/lib/ronin/db/mac_address.rb +91 -0
- data/lib/ronin/db/migrations.rb +137 -0
- data/lib/ronin/db/model/has_name.rb +102 -0
- data/lib/ronin/db/model/has_unique_name.rb +82 -0
- data/lib/ronin/db/model/importable.rb +85 -0
- data/lib/ronin/db/model/last_scanned_at.rb +48 -0
- data/lib/ronin/db/model.rb +37 -0
- data/lib/ronin/db/models.rb +108 -0
- data/lib/ronin/db/open_port.rb +148 -0
- data/lib/ronin/db/organization.rb +50 -0
- data/lib/ronin/db/os.rb +183 -0
- data/lib/ronin/db/os_guess.rb +67 -0
- data/lib/ronin/db/password.rb +167 -0
- data/lib/ronin/db/port.rb +123 -0
- data/lib/ronin/db/root.rb +28 -0
- data/lib/ronin/db/schema_migration.rb +34 -0
- data/lib/ronin/db/service.rb +48 -0
- data/lib/ronin/db/service_credential.rb +66 -0
- data/lib/ronin/db/software.rb +85 -0
- data/lib/ronin/db/software_vendor.rb +42 -0
- data/lib/ronin/db/url.rb +497 -0
- data/lib/ronin/db/url_query_param.rb +79 -0
- data/lib/ronin/db/url_query_param_name.rb +76 -0
- data/lib/ronin/db/url_scheme.rb +80 -0
- data/lib/ronin/db/user_name.rb +96 -0
- data/lib/ronin/db/vulnerability.rb +81 -0
- data/lib/ronin/db/web_credential.rb +69 -0
- data/ronin-db-activerecord.gemspec +61 -0
- data/spec/advisory_spec.rb +277 -0
- data/spec/arch_spec.rb +228 -0
- data/spec/asn_spec.rb +504 -0
- data/spec/credential_spec.rb +362 -0
- data/spec/email_address_spec.rb +372 -0
- data/spec/host_name_ip_address_spec.rb +8 -0
- data/spec/host_name_spec.rb +207 -0
- data/spec/http_header_name_spec.rb +25 -0
- data/spec/http_query_param_name_spec.rb +25 -0
- data/spec/http_query_param_spec.rb +104 -0
- data/spec/http_request_header_spec.rb +72 -0
- data/spec/http_request_spec.rb +168 -0
- data/spec/http_response_header_spec.rb +74 -0
- data/spec/http_response_spec.rb +103 -0
- data/spec/ip_address_mac_addresses_spec.rb +8 -0
- data/spec/ip_address_spec.rb +386 -0
- data/spec/mac_address_spec.rb +67 -0
- data/spec/migrations_spec.rb +122 -0
- data/spec/model/has_name_spec.rb +65 -0
- data/spec/model/has_unique_name_spec.rb +61 -0
- data/spec/model/importable_spec.rb +105 -0
- data/spec/models_spec.rb +60 -0
- data/spec/open_port_spec.rb +87 -0
- data/spec/organization_spec.rb +10 -0
- data/spec/os_guess_spec.rb +43 -0
- data/spec/os_spec.rb +114 -0
- data/spec/password_spec.rb +81 -0
- data/spec/port_spec.rb +102 -0
- data/spec/schema_migration_spec.rb +8 -0
- data/spec/service_credential_spec.rb +43 -0
- data/spec/service_spec.rb +39 -0
- data/spec/software_spec.rb +76 -0
- data/spec/software_vendor_spec.rb +33 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/url_query_param_name_spec.rb +25 -0
- data/spec/url_query_param_spec.rb +110 -0
- data/spec/url_scheme_spec.rb +39 -0
- data/spec/url_spec.rb +951 -0
- data/spec/user_name_spec.rb +54 -0
- data/spec/vulnerability_spec.rb +8 -0
- data/spec/web_credential_spec.rb +72 -0
- metadata +266 -0
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
require 'active_record'
|
|
24
|
+
|
|
25
|
+
module Ronin
|
|
26
|
+
module DB
|
|
27
|
+
#
|
|
28
|
+
# Represents Credentials used to access a TCP/UDP {Service}.
|
|
29
|
+
#
|
|
30
|
+
class ServiceCredential < ActiveRecord::Base
|
|
31
|
+
|
|
32
|
+
include Model
|
|
33
|
+
|
|
34
|
+
# @!attribute [rw] id
|
|
35
|
+
# Primary key of the service credential.
|
|
36
|
+
#
|
|
37
|
+
# @return [Integer]
|
|
38
|
+
attribute :id, :integer
|
|
39
|
+
|
|
40
|
+
# @!attribute [rw] credential
|
|
41
|
+
#
|
|
42
|
+
# @return [Credential]
|
|
43
|
+
belongs_to :credential
|
|
44
|
+
|
|
45
|
+
# @!attribute [rw] open_port
|
|
46
|
+
# The open port the credential belongs to.
|
|
47
|
+
#
|
|
48
|
+
# @return [OpenPort]
|
|
49
|
+
belongs_to :open_port
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Converts the service credential to a String.
|
|
53
|
+
#
|
|
54
|
+
# @return [String]
|
|
55
|
+
# The service credential string.
|
|
56
|
+
#
|
|
57
|
+
def to_s
|
|
58
|
+
"#{self.credential} (#{self.open_port})"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
require 'ronin/db/credential'
|
|
66
|
+
require 'ronin/db/open_port'
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
require 'active_record'
|
|
24
|
+
|
|
25
|
+
module Ronin
|
|
26
|
+
module DB
|
|
27
|
+
#
|
|
28
|
+
# Represents a Software product.
|
|
29
|
+
#
|
|
30
|
+
class Software < ActiveRecord::Base
|
|
31
|
+
|
|
32
|
+
include Model
|
|
33
|
+
|
|
34
|
+
# @!attribute [rw] id
|
|
35
|
+
# The primary key of the software.
|
|
36
|
+
#
|
|
37
|
+
# @return [Integer]
|
|
38
|
+
attribute :id, :integer
|
|
39
|
+
|
|
40
|
+
# @!attribute [rw] name
|
|
41
|
+
# The software's name.
|
|
42
|
+
#
|
|
43
|
+
# @return [String]
|
|
44
|
+
attribute :name, :string
|
|
45
|
+
validates :name, presence: true
|
|
46
|
+
|
|
47
|
+
# @!attribute [rw] version
|
|
48
|
+
# The software's Version.
|
|
49
|
+
#
|
|
50
|
+
# @return [String]
|
|
51
|
+
attribute :version, :string
|
|
52
|
+
validates :version, presence: true,
|
|
53
|
+
uniqueness: {scope: :name}
|
|
54
|
+
|
|
55
|
+
# @!attribute [rw] vendor
|
|
56
|
+
# The vendor of the software
|
|
57
|
+
#
|
|
58
|
+
# @return [SoftwareVendor, nil]
|
|
59
|
+
belongs_to :vendor, optional: true,
|
|
60
|
+
class_name: 'SoftwareVendor'
|
|
61
|
+
|
|
62
|
+
# @!attribute [rw] open_ports
|
|
63
|
+
# The open ports running the software
|
|
64
|
+
#
|
|
65
|
+
# @return [Array<OpenPort>]
|
|
66
|
+
has_many :open_ports
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Converts the software to a String.
|
|
70
|
+
#
|
|
71
|
+
# @return [String]
|
|
72
|
+
# The software vendor, name and version.
|
|
73
|
+
#
|
|
74
|
+
# @api public
|
|
75
|
+
#
|
|
76
|
+
def to_s
|
|
77
|
+
[self.vendor, self.name, self.version].compact.join(' ')
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
require 'ronin/db/software_vendor'
|
|
85
|
+
require 'ronin/db/open_port'
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
module Ronin
|
|
25
|
+
module DB
|
|
26
|
+
#
|
|
27
|
+
# Represents a {Software} vendor.
|
|
28
|
+
#
|
|
29
|
+
class SoftwareVendor < ActiveRecord::Base
|
|
30
|
+
|
|
31
|
+
include Model
|
|
32
|
+
include Model::HasUniqueName
|
|
33
|
+
|
|
34
|
+
# The primary-key of the vendor
|
|
35
|
+
attribute :id, :integer
|
|
36
|
+
|
|
37
|
+
# Products published by the vendor
|
|
38
|
+
has_many :software, class_name: 'Software'
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/ronin/db/url.rb
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
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
|
+
require 'uri/generic'
|
|
27
|
+
require 'uri/http'
|
|
28
|
+
require 'uri/https'
|
|
29
|
+
require 'uri/ftp'
|
|
30
|
+
require 'uri/query_params'
|
|
31
|
+
|
|
32
|
+
module Ronin
|
|
33
|
+
module DB
|
|
34
|
+
#
|
|
35
|
+
# Represents parsed URLs.
|
|
36
|
+
#
|
|
37
|
+
class URL < ActiveRecord::Base
|
|
38
|
+
|
|
39
|
+
include Model
|
|
40
|
+
include Model::Importable
|
|
41
|
+
include Model::LastScannedAt
|
|
42
|
+
|
|
43
|
+
# Mapping of URL Schemes and URI classes
|
|
44
|
+
SCHEMES = {
|
|
45
|
+
'https' => ::URI::HTTPS,
|
|
46
|
+
'http' => ::URI::HTTP,
|
|
47
|
+
'ftp' => ::URI::FTP
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# @!attribute [rw] id
|
|
51
|
+
# The primary key of the URL.
|
|
52
|
+
#
|
|
53
|
+
# @return [Integer]
|
|
54
|
+
attribute :id, :integer
|
|
55
|
+
|
|
56
|
+
# @!attribute [rw] scheme
|
|
57
|
+
# The scheme of the URL.
|
|
58
|
+
#
|
|
59
|
+
# @return [URLScheme]
|
|
60
|
+
belongs_to :scheme, required: true,
|
|
61
|
+
class_name: 'URLScheme'
|
|
62
|
+
|
|
63
|
+
# @!attribute [rw] host_name
|
|
64
|
+
# The host name of the URL
|
|
65
|
+
#
|
|
66
|
+
# @return [HostName]
|
|
67
|
+
belongs_to :host_name, required: true
|
|
68
|
+
|
|
69
|
+
# @!attribute [rw] port
|
|
70
|
+
# The port of the URL.
|
|
71
|
+
#
|
|
72
|
+
# @return [Port, nil]
|
|
73
|
+
belongs_to :port, optional: true,
|
|
74
|
+
class_name: 'Port'
|
|
75
|
+
|
|
76
|
+
# @!attribute [rw] path
|
|
77
|
+
# The path of the URL.
|
|
78
|
+
#
|
|
79
|
+
# @return [String]
|
|
80
|
+
attribute :path, :string
|
|
81
|
+
|
|
82
|
+
# @!attribute [rw] query
|
|
83
|
+
# The query string part of the URL.
|
|
84
|
+
#
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
attribute :query, :string
|
|
87
|
+
|
|
88
|
+
# @!attribute [rw] fragment
|
|
89
|
+
# The fragment of the URL.
|
|
90
|
+
#
|
|
91
|
+
# @return [String, nil]
|
|
92
|
+
attribute :fragment, :string
|
|
93
|
+
|
|
94
|
+
# @!attribute [r] created_at
|
|
95
|
+
# Defines the created_at timestamp
|
|
96
|
+
#
|
|
97
|
+
# @return [Time]
|
|
98
|
+
attribute :created_at, :time
|
|
99
|
+
|
|
100
|
+
# @!attribute [rw] query_params
|
|
101
|
+
# The query params of the URL.
|
|
102
|
+
#
|
|
103
|
+
# @return [Array<URLQueryParam>]
|
|
104
|
+
has_many :query_params, class_name: 'URLQueryParam',
|
|
105
|
+
dependent: :destroy
|
|
106
|
+
|
|
107
|
+
# @!attribute [rw] web_credentials
|
|
108
|
+
# Any credentials used with the URL.
|
|
109
|
+
#
|
|
110
|
+
# @return [Array<WebCredential>]
|
|
111
|
+
has_many :web_credentials, dependent: :destroy
|
|
112
|
+
|
|
113
|
+
# @!attribute [rw] credentials
|
|
114
|
+
# The credentials that will work with this URL.
|
|
115
|
+
#
|
|
116
|
+
# @return [Array<Credentials>]
|
|
117
|
+
has_many :credentials, through: :web_credentials
|
|
118
|
+
|
|
119
|
+
#
|
|
120
|
+
# Searches for all URLs using HTTP.
|
|
121
|
+
#
|
|
122
|
+
# @return [Array<URL>]
|
|
123
|
+
# The matching URLs.
|
|
124
|
+
#
|
|
125
|
+
# @api public
|
|
126
|
+
#
|
|
127
|
+
def self.http
|
|
128
|
+
joins(:scheme).where(scheme: {name: 'http'})
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
#
|
|
132
|
+
# Searches for all URLs using HTTPS.
|
|
133
|
+
#
|
|
134
|
+
# @return [Array<URL>]
|
|
135
|
+
# The matching URLs.
|
|
136
|
+
#
|
|
137
|
+
# @api public
|
|
138
|
+
#
|
|
139
|
+
def self.https
|
|
140
|
+
joins(:scheme).where(scheme: {name: 'https'})
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Searches for URLs with specific host name(s).
|
|
145
|
+
#
|
|
146
|
+
# @param [String, Array<String>] name
|
|
147
|
+
# The host name(s) to search for.
|
|
148
|
+
#
|
|
149
|
+
# @return [Array<URL>]
|
|
150
|
+
# The matching URLs.
|
|
151
|
+
#
|
|
152
|
+
# @api public
|
|
153
|
+
#
|
|
154
|
+
def self.with_host_name(name)
|
|
155
|
+
joins(:host_name).where(host_name: {name: name})
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
#
|
|
159
|
+
# Searches for URLs with the specific port number(s).
|
|
160
|
+
#
|
|
161
|
+
# @param [Integer, Array<Integer>] number
|
|
162
|
+
# The port number(s) to search for.
|
|
163
|
+
#
|
|
164
|
+
# @return [Array<URL>]
|
|
165
|
+
# The matching URLs.
|
|
166
|
+
#
|
|
167
|
+
# @api public
|
|
168
|
+
#
|
|
169
|
+
def self.with_port_number(number)
|
|
170
|
+
joins(:port).where(port: {number: number})
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
#
|
|
174
|
+
# Searches for all URLs with the exact path.
|
|
175
|
+
#
|
|
176
|
+
# @param [String] path
|
|
177
|
+
# The path to search for.
|
|
178
|
+
#
|
|
179
|
+
# @return [Array<URL>]
|
|
180
|
+
# The URL with the matching path.
|
|
181
|
+
#
|
|
182
|
+
# @api public
|
|
183
|
+
#
|
|
184
|
+
def self.with_path(path)
|
|
185
|
+
where(path: path)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
#
|
|
189
|
+
# Searches for all URLs with the exact fragment.
|
|
190
|
+
#
|
|
191
|
+
# @param [String] fragment
|
|
192
|
+
# The fragment to search for.
|
|
193
|
+
#
|
|
194
|
+
# @return [Array<URL>]
|
|
195
|
+
# The URL with the matching fragment.
|
|
196
|
+
#
|
|
197
|
+
# @api public
|
|
198
|
+
#
|
|
199
|
+
def self.with_fragment(fragment)
|
|
200
|
+
where(fragment: fragment)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
#
|
|
204
|
+
# Searches for all URLs sharing a common sub-directory.
|
|
205
|
+
#
|
|
206
|
+
# @param [String] root_dir
|
|
207
|
+
# The sub-directory to search for.
|
|
208
|
+
#
|
|
209
|
+
# @return [Array<URL>]
|
|
210
|
+
# The URL with the common sub-directory.
|
|
211
|
+
#
|
|
212
|
+
# @api public
|
|
213
|
+
#
|
|
214
|
+
def self.with_directory(root_dir)
|
|
215
|
+
path_column = self.arel_table[:path]
|
|
216
|
+
|
|
217
|
+
where(path: root_dir).or(where(path_column.matches("#{root_dir}/%")))
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
#
|
|
221
|
+
# Searches for all URLs sharing a common base name.
|
|
222
|
+
#
|
|
223
|
+
# @param [String] basename
|
|
224
|
+
# The base name to search for.
|
|
225
|
+
#
|
|
226
|
+
# @return [Array<URL>]
|
|
227
|
+
# The URL with the common base name.
|
|
228
|
+
#
|
|
229
|
+
# @api public
|
|
230
|
+
#
|
|
231
|
+
def self.with_basename(basename)
|
|
232
|
+
path_column = self.arel_table[:path]
|
|
233
|
+
|
|
234
|
+
where(path_column.matches("%/#{basename}"))
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
#
|
|
238
|
+
# Searches for all URLs with a common file-extension.
|
|
239
|
+
#
|
|
240
|
+
# @param [String] ext
|
|
241
|
+
# The file extension to search for.
|
|
242
|
+
#
|
|
243
|
+
# @return [Array<URL>]
|
|
244
|
+
# The URLs with the common file-extension.
|
|
245
|
+
#
|
|
246
|
+
# @api public
|
|
247
|
+
#
|
|
248
|
+
def self.with_file_ext(ext)
|
|
249
|
+
path_column = self.arel_table[:path]
|
|
250
|
+
|
|
251
|
+
where(path_column.matches("%.#{sanitize_sql_like(ext)}"))
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
#
|
|
255
|
+
# Searches for URLs with the given query param name and value.
|
|
256
|
+
#
|
|
257
|
+
# @param [String, Array<String>] name
|
|
258
|
+
# The query param name to search for.
|
|
259
|
+
#
|
|
260
|
+
# @param [String, Array<String>] value
|
|
261
|
+
# The query param value to search for.
|
|
262
|
+
#
|
|
263
|
+
# @return [Array<URL>]
|
|
264
|
+
# The URLs with the given query param.
|
|
265
|
+
#
|
|
266
|
+
# @api public
|
|
267
|
+
#
|
|
268
|
+
def self.with_query_param(name,value)
|
|
269
|
+
joins(query_params: :name).where(
|
|
270
|
+
query_params: {
|
|
271
|
+
ronin_url_query_param_names: {name: name},
|
|
272
|
+
value: value
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
#
|
|
278
|
+
# Search for all URLs with a given query param name.
|
|
279
|
+
#
|
|
280
|
+
# @param [Array<String>, String] name
|
|
281
|
+
# The query param name to search for.
|
|
282
|
+
#
|
|
283
|
+
# @return [Array<URL>]
|
|
284
|
+
# The URLs with the given query param name.
|
|
285
|
+
#
|
|
286
|
+
# @api public
|
|
287
|
+
#
|
|
288
|
+
def self.with_query_param_name(name)
|
|
289
|
+
joins(query_params: [:name]).where(
|
|
290
|
+
query_params: {
|
|
291
|
+
ronin_url_query_param_names: {name: name}
|
|
292
|
+
}
|
|
293
|
+
)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
#
|
|
297
|
+
# Search for all URLs with a given query param value.
|
|
298
|
+
#
|
|
299
|
+
# @param [Array<String>, String] value
|
|
300
|
+
# The query param value to search for.
|
|
301
|
+
#
|
|
302
|
+
# @return [Array<URL>]
|
|
303
|
+
# The URLs with the given query param value.
|
|
304
|
+
#
|
|
305
|
+
# @api public
|
|
306
|
+
#
|
|
307
|
+
def self.with_query_param_value(value)
|
|
308
|
+
joins(:query_params).where(query_params: {value: value})
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
#
|
|
312
|
+
# Searches for a URL.
|
|
313
|
+
#
|
|
314
|
+
# @param [URI::HTTP, String] url
|
|
315
|
+
# The URL to search for.
|
|
316
|
+
#
|
|
317
|
+
# @return [URL, nil]
|
|
318
|
+
# The matching URL.
|
|
319
|
+
#
|
|
320
|
+
# @api public
|
|
321
|
+
#
|
|
322
|
+
def self.lookup(url)
|
|
323
|
+
uri = URI(url)
|
|
324
|
+
|
|
325
|
+
# create the initial query
|
|
326
|
+
query = joins(:scheme, :host_name).where(
|
|
327
|
+
scheme: {name: uri.scheme},
|
|
328
|
+
host_name: {name: uri.host},
|
|
329
|
+
path: normalized_path(uri),
|
|
330
|
+
query: uri.query,
|
|
331
|
+
fragment: uri.fragment
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
if uri.port
|
|
335
|
+
# query the port
|
|
336
|
+
query = query.joins(:port).where(port: {number: uri.port})
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
return query.first
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
#
|
|
343
|
+
# Creates a new URL.
|
|
344
|
+
#
|
|
345
|
+
# @param [String, URI::HTTP] uri
|
|
346
|
+
# The URI to create the URL from.
|
|
347
|
+
#
|
|
348
|
+
# @return [URL]
|
|
349
|
+
# The new URL.
|
|
350
|
+
#
|
|
351
|
+
# @api public
|
|
352
|
+
#
|
|
353
|
+
def self.import(uri)
|
|
354
|
+
uri = URI(uri)
|
|
355
|
+
|
|
356
|
+
# find or create the URL scheme, host_name and port
|
|
357
|
+
scheme = URLScheme.find_or_create_by(name: uri.scheme)
|
|
358
|
+
host_name = HostName.find_or_create_by(name: uri.host)
|
|
359
|
+
port = if uri.port
|
|
360
|
+
Port.find_or_create_by(
|
|
361
|
+
protocol: :tcp,
|
|
362
|
+
number: uri.port
|
|
363
|
+
)
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
path = normalized_path(uri)
|
|
367
|
+
query = uri.query
|
|
368
|
+
fragment = uri.fragment
|
|
369
|
+
|
|
370
|
+
query_params = []
|
|
371
|
+
|
|
372
|
+
if uri.respond_to?(:query_params)
|
|
373
|
+
# find or create the URL query params
|
|
374
|
+
uri.query_params.each do |name,value|
|
|
375
|
+
query_params << URLQueryParam.new(
|
|
376
|
+
name: URLQueryParamName.find_or_create_by(name: name),
|
|
377
|
+
value: value
|
|
378
|
+
)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# find or create the URL
|
|
383
|
+
return find_or_create_by(
|
|
384
|
+
scheme: scheme,
|
|
385
|
+
host_name: host_name,
|
|
386
|
+
port: port,
|
|
387
|
+
path: path,
|
|
388
|
+
query: query,
|
|
389
|
+
fragment: fragment,
|
|
390
|
+
query_params: query_params
|
|
391
|
+
)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
#
|
|
395
|
+
# The host name of the URL.
|
|
396
|
+
#
|
|
397
|
+
# @return [String]
|
|
398
|
+
# The address of host name.
|
|
399
|
+
#
|
|
400
|
+
# @api public
|
|
401
|
+
#
|
|
402
|
+
def host
|
|
403
|
+
self.host_name.name
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
#
|
|
407
|
+
# The port number used by the URL.
|
|
408
|
+
#
|
|
409
|
+
# @return [Integer, nil]
|
|
410
|
+
# The port number.
|
|
411
|
+
#
|
|
412
|
+
# @api public
|
|
413
|
+
#
|
|
414
|
+
def port_number
|
|
415
|
+
self.port.number if self.port
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
#
|
|
419
|
+
# Builds a URI object from the URL.
|
|
420
|
+
#
|
|
421
|
+
# @return [URI::HTTP, URI::HTTPS]
|
|
422
|
+
# The URI object created from the URL attributes.
|
|
423
|
+
#
|
|
424
|
+
# @api public
|
|
425
|
+
#
|
|
426
|
+
def to_uri
|
|
427
|
+
# map the URL scheme to a URI class
|
|
428
|
+
url_class = SCHEMES.fetch(self.scheme.name,::URI::Generic)
|
|
429
|
+
|
|
430
|
+
scheme = if self.scheme
|
|
431
|
+
self.scheme.name
|
|
432
|
+
end
|
|
433
|
+
host = if self.host_name
|
|
434
|
+
self.host_name.name
|
|
435
|
+
end
|
|
436
|
+
port = if self.port
|
|
437
|
+
self.port.number
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# build the URI
|
|
441
|
+
return url_class.build(
|
|
442
|
+
scheme: scheme,
|
|
443
|
+
host: host,
|
|
444
|
+
port: port,
|
|
445
|
+
path: self.path,
|
|
446
|
+
query: self.query,
|
|
447
|
+
fragment: self.fragment
|
|
448
|
+
)
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
#
|
|
452
|
+
# Converts the URL to a String.
|
|
453
|
+
#
|
|
454
|
+
# @return [String]
|
|
455
|
+
# The string form of the URL.
|
|
456
|
+
#
|
|
457
|
+
# @api public
|
|
458
|
+
#
|
|
459
|
+
def to_s
|
|
460
|
+
self.to_uri.to_s
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
protected
|
|
464
|
+
|
|
465
|
+
#
|
|
466
|
+
# Normalizes the path of a URI.
|
|
467
|
+
#
|
|
468
|
+
# @param [URI] uri
|
|
469
|
+
# The URI containing the path.
|
|
470
|
+
#
|
|
471
|
+
# @return [String, nil]
|
|
472
|
+
# The normalized path.
|
|
473
|
+
#
|
|
474
|
+
# @api private
|
|
475
|
+
#
|
|
476
|
+
def self.normalized_path(uri)
|
|
477
|
+
case uri
|
|
478
|
+
when ::URI::HTTP
|
|
479
|
+
# map empty HTTP paths to '/'
|
|
480
|
+
unless uri.path.empty? then uri.path
|
|
481
|
+
else '/'
|
|
482
|
+
end
|
|
483
|
+
else
|
|
484
|
+
uri.path
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
require 'ronin/db/host_name'
|
|
493
|
+
require 'ronin/db/port'
|
|
494
|
+
require 'ronin/db/url_scheme'
|
|
495
|
+
require 'ronin/db/url_query_param_name'
|
|
496
|
+
require 'ronin/db/url_query_param'
|
|
497
|
+
require 'ronin/db/web_credential'
|