rbl_mcafee 0.0.2 → 1.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fe5d6a370c1562c43a58901f5447ec61e5f5b04
4
- data.tar.gz: 52a905ddb5c3152984669ee13cf3a49d95aaa258
3
+ metadata.gz: 4e020eef8e74971b1837a2c58f2897ea9b8bab9a
4
+ data.tar.gz: 795633fa1241d021c7dcfe73116d97e3f7c57fa8
5
5
  SHA512:
6
- metadata.gz: 4aaaccad3566c5953089602333488cb755619f5a7e6af43b5117d6e9913656f8269341cbf4ab4905db2e9db52c6eb4840a31b9a090aa662fe7320df9c8e331c1
7
- data.tar.gz: e3f4737e92750d0326e340d86bace22c1c856ced8eb2526870f25ab7094209f93eb7c1477a27979a00e290b75ba570bd556d5c300b348fd4b8e2c9b8b72f74ad
6
+ metadata.gz: 7699ffe783f39a5a5c38a67dc2e5206bb3c6e73d601b2c05391b54514a4ab77911d4112a133bda0a20a5797744c7542e2cf8aaf9d924dd978d8147058e15bc22
7
+ data.tar.gz: 0f2050bcce6d2ee3e449bcf6bdbad74b7aa72b1d542a5c9441428f0184f87362be1fb7bb0327a31d57be9851a08c38b7dedacea2d1102c45e4cf7d0e82c4f8ed
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Solution to test if an IP address is listed in the McAfee RBL.
4
4
 
5
+ McAfee uses the Spamhaus Project (https://www.spamhaus.org/).
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -18,16 +20,19 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- To verify if an IP address is listed in the McAfee RBL:
23
+ To verify if an IP address is listed in one of the Spamhaus IP zones:
22
24
 
23
25
  ```ruby
24
- RblMcafee.blacklisted?('127.0.0.1')
26
+ zone = RblMcafee::Zone.new('127.0.0.1')
27
+ zone.pbl?
28
+ zone.sbl?
29
+ zone.xbl?
25
30
  ```
26
31
 
27
32
  Expected returned values are the following:
28
33
 
29
- * `true` when the IP address **is listed** in the McAfee RBL
30
- * `false` when the IP address **isn't listed** in the McAfee RBL
34
+ * `true` when the IP address **is listed** in the zone
35
+ * `false` when the IP address **isn't listed** in the zone
31
36
 
32
37
  When a **timeout** occurs, a `RblMcafee::Timeout` exception is raised.
33
38
 
@@ -1,27 +1,9 @@
1
1
  require "rbl_mcafee/version"
2
- require 'resolv'
3
2
 
4
3
  module RblMcafee
5
4
  # Indicates a timeout checking an IP address
6
5
  class Timeout < TimeoutError; end
7
6
 
8
- # @see https://kc.mcafee.com/corporate/index?page=content&id=KB53783
9
- # If the reply is in the format 127.0.0.XXX, the host is listed in the McAfee
10
- # RBL
11
- MC_AFEE_RBL_LISTED_REGEX = /^127\.0\.0\.\d{1,3}$/
12
-
13
- def self.blacklisted?(ip)
14
- if !ip.match(Resolv::IPv6::Regex) && !ip.match(Resolv::IPv4::Regex)
15
- raise ArgumentError, 'Invalid IP'
16
- end
17
-
18
- reversed_ip = ip.split('.').reverse.join('.')
19
- resolved_ip = Resolv::getaddress("#{reversed_ip}.cidr.bl.mcafee.com")
20
- return !!resolved_ip.match(MC_AFEE_RBL_LISTED_REGEX)
21
-
22
- rescue Resolv::ResolvError
23
- false
24
- rescue Resolv::ResolvTimeout
25
- raise RblMcafee::Timeout
26
- end
7
+ # Indicates a failure to resolve an IP address
8
+ class Error < StandardError; end;
27
9
  end
@@ -0,0 +1,23 @@
1
+ module RblMcafee
2
+ class Ip
3
+ attr_reader :ip
4
+
5
+ def initialize(ip)
6
+ @ip = ip
7
+ end
8
+
9
+ def valid?
10
+ ipv4? || ipv6?
11
+ end
12
+
13
+ private
14
+
15
+ def ipv4?
16
+ !!ip.match(Resolv::IPv4::Regex)
17
+ end
18
+
19
+ def ipv6?
20
+ !!ip.match(Resolv::IPv6::Regex)
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module RblMcafee
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,81 @@
1
+ require "rbl_mcafee/version"
2
+ require "rbl_mcafee/ip"
3
+ require 'resolv'
4
+
5
+ module RblMcafee
6
+ class Zone
7
+ PBL = :pbl
8
+ SBL = :sbl
9
+ XBL = :xbl
10
+
11
+ attr_reader :ip
12
+
13
+ def initialize(ip)
14
+ raise ArgumentError, 'Invalid IP' unless RblMcafee::Ip.new(ip).valid?
15
+
16
+ @ip = ip
17
+ end
18
+
19
+ def pbl?
20
+ zone == PBL
21
+ end
22
+
23
+ def sbl?
24
+ zone == SBL
25
+ end
26
+
27
+ def xbl?
28
+ zone == XBL
29
+ end
30
+
31
+
32
+ private
33
+
34
+ def zone
35
+ return @zone if defined? @zone
36
+
37
+ @zone = extract_zone(resolved_ip)
38
+ end
39
+
40
+ # Lookup the IP address on "cidr.bl.mcafee.com"
41
+ def resolved_ip
42
+ return @resolved_ip if defined? @resolved_ip
43
+
44
+ reversed_ip = ip.split('.').reverse.join('.')
45
+ @resolved_ip = Resolv::getaddress("#{reversed_ip}.cidr.bl.mcafee.com")
46
+
47
+ rescue Resolv::ResolvError
48
+ @resolved_ip = nil
49
+ rescue Resolv::ResolvTimeout
50
+ raise RblMcafee::Timeout
51
+ end
52
+
53
+
54
+ # @see https://kc.mcafee.com/corporate/index?page=content&id=KB53783
55
+ # If the reply is in the format 127.0.0.XXX, the host is listed in the
56
+ # McAfee RBL (@see below)
57
+ MC_AFEE_RBL_LISTED_REGEX = /^127\.0\.0\.\d{1,3}$/
58
+
59
+ # @see https://www.spamhaus.org/faq/section/DNSBL%20Usage#202
60
+ #
61
+ # DNSBL | Returns | Contains
62
+ # ------+---------------+---------------------------------------------------
63
+ # SBL | 127.0.0.2-3 | Static UBE sources, verified spam services
64
+ # | | (hosting or support) and ROKSO spammers
65
+ # XBL | 127.0.0.4-7 | Illegal 3rd party exploits, including proxies,
66
+ # \ | worms and trojan exploits
67
+ # PBL | 127.0.0.10-11 | IP ranges which should not be delivering
68
+ # | | unauthenticated SMTP email.
69
+ def extract_zone(resolved_ip)
70
+ return nil if resolved_ip.nil?
71
+ return nil unless resolved_ip.match(MC_AFEE_RBL_LISTED_REGEX)
72
+
73
+ case resolved_ip.split('.').last.to_i
74
+ when 2..3 then SBL
75
+ when 4..7 then XBL
76
+ when 10..11 then PBL
77
+ else nil
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ require 'rbl_mcafee/ip'
2
+
3
+ describe RblMcafee::Ip do
4
+ subject { RblMcafee::Ip.new(ip_address) }
5
+
6
+ context 'with an IPv4 address' do
7
+ let(:ip_address) { '1.160.10.240' }
8
+
9
+ it 'detects the IP as IPv4' do
10
+ expect(subject.send(:ipv4?)).to be true
11
+ end
12
+
13
+ it 'does not detect the IP as IPv6' do
14
+ expect(subject.send(:ipv6?)).to be false
15
+ end
16
+
17
+ it 'detects the IP as valid' do
18
+ expect(subject.valid?).to be true
19
+ end
20
+ end
21
+
22
+ context 'with an IPv6 address' do
23
+ let(:ip_address) { '3ffe:1900:4545:3:200:f8ff:fe21:67cf' }
24
+
25
+ it 'does not detect the IP as IPv4' do
26
+ expect(subject.send(:ipv4?)).to be false
27
+ end
28
+
29
+ it 'detects the IP as IPv6' do
30
+ expect(subject.send(:ipv6?)).to be true
31
+ end
32
+
33
+ it 'detects the IP as valid' do
34
+ expect(subject.valid?).to be true
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,120 @@
1
+ require 'rbl_mcafee'
2
+ require 'rbl_mcafee/zone'
3
+
4
+ describe RblMcafee::Zone do
5
+ subject { RblMcafee::Zone.new('127.0.0.1') }
6
+
7
+ # Extract zone
8
+ # ----------------------------------------------------------------------------
9
+ it 'extracts the zones correctly' do
10
+ expect(subject.send(:extract_zone, nil)).to be(nil)
11
+ expect(subject.send(:extract_zone,'127.0.0.1')).to be(nil)
12
+ expect(subject.send(:extract_zone,'127.0.0.2')).to be(RblMcafee::Zone::SBL)
13
+ expect(subject.send(:extract_zone,'127.0.0.3')).to be(RblMcafee::Zone::SBL)
14
+ expect(subject.send(:extract_zone,'127.0.0.4')).to be(RblMcafee::Zone::XBL)
15
+ expect(subject.send(:extract_zone,'127.0.0.5')).to be(RblMcafee::Zone::XBL)
16
+ expect(subject.send(:extract_zone,'127.0.0.6')).to be(RblMcafee::Zone::XBL)
17
+ expect(subject.send(:extract_zone,'127.0.0.7')).to be(RblMcafee::Zone::XBL)
18
+ expect(subject.send(:extract_zone,'127.0.0.8')).to be(nil)
19
+ expect(subject.send(:extract_zone,'127.0.0.9')).to be(nil)
20
+ expect(subject.send(:extract_zone,'127.0.0.10')).to be(RblMcafee::Zone::PBL)
21
+ expect(subject.send(:extract_zone,'127.0.0.11')).to be(RblMcafee::Zone::PBL)
22
+ expect(subject.send(:extract_zone,'127.0.0.12')).to be(nil)
23
+ end
24
+
25
+ # PBL zone
26
+ # ----------------------------------------------------------------------------
27
+ context 'with an IP address listed in the PBL zone' do
28
+ before(:each) { Resolv.stub(:getaddress) { '127.0.0.10' } }
29
+
30
+ it 'is not detected as belonging to the SBL zone' do
31
+ expect(subject.sbl?).to be false
32
+ end
33
+
34
+ it 'is not detected as belonging to the XBL zone' do
35
+ expect(subject.xbl?).to be false
36
+ end
37
+
38
+ it 'is detected as belonging to the PBL zone' do
39
+ expect(subject.pbl?).to be true
40
+ end
41
+ end
42
+
43
+ # SBL zone
44
+ # ----------------------------------------------------------------------------
45
+ context 'with an IP address listed in the SBL zone' do
46
+ before(:each) { Resolv.stub(:getaddress) { '127.0.0.3' } }
47
+
48
+ it 'is detected as belonging to the SBL zone' do
49
+ expect(subject.sbl?).to be true
50
+ end
51
+
52
+ it 'is not detected as belonging to the XBL zone' do
53
+ expect(subject.xbl?).to be false
54
+ end
55
+
56
+ it 'is not detected as belonging to the PBL zone' do
57
+ expect(subject.pbl?).to be false
58
+ end
59
+ end
60
+
61
+ # XBL zone
62
+ # ----------------------------------------------------------------------------
63
+ context 'with an IP address listed in the XBL zone' do
64
+ before(:each) { Resolv.stub(:getaddress) { '127.0.0.4' } }
65
+
66
+ it 'is not detected as belonging to the SBL zone' do
67
+ expect(subject.sbl?).to be false
68
+ end
69
+
70
+ it 'is detected as belonging to the XBL zone' do
71
+ expect(subject.xbl?).to be true
72
+ end
73
+
74
+ it 'is not detected as belonging to the PBL zone' do
75
+ expect(subject.pbl?).to be false
76
+ end
77
+ end
78
+
79
+ # Without zone
80
+ # ----------------------------------------------------------------------------
81
+ context 'with an IP address not listed in any zone' do
82
+ before(:each) { Resolv.stub(:getaddress) { raise Resolv::ResolvError } }
83
+
84
+ it 'is not detected as belonging to the SBL zone' do
85
+ expect(subject.sbl?).to be false
86
+ end
87
+
88
+ it 'is not detected as belonging to the XBL zone' do
89
+ expect(subject.xbl?).to be false
90
+ end
91
+
92
+ it 'is not detected as belonging to the PBL zone' do
93
+ expect(subject.pbl?).to be false
94
+ end
95
+ end
96
+
97
+ # Exceptions
98
+ # ----------------------------------------------------------------------------
99
+ it 'raises an ArgumentError for invalid IP addresses' do
100
+ RblMcafee::Ip.any_instance.stub(:valid?) { false }
101
+
102
+ expect{subject}.to raise_error(ArgumentError)
103
+ end
104
+
105
+ it 'raises a RblMcafee::Timeout when a timeout error is raised by Resolv' do
106
+ Resolv.stub(:getaddress) { raise Resolv::ResolvTimeout }
107
+
108
+ expect{subject.sbl?}.to raise_error(RblMcafee::Timeout)
109
+ expect{subject.xbl?}.to raise_error(RblMcafee::Timeout)
110
+ expect{subject.pbl?}.to raise_error(RblMcafee::Timeout)
111
+ end
112
+
113
+ it 'raises unknown exceptions raised by Resolv' do
114
+ Resolv.stub(:getaddress) { raise 'oops' }
115
+
116
+ expect{subject.sbl?}.to raise_error('oops')
117
+ expect{subject.xbl?}.to raise_error('oops')
118
+ expect{subject.pbl?}.to raise_error('oops')
119
+ end
120
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbl_mcafee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Romain Salles
@@ -67,9 +67,12 @@ files:
67
67
  - README.md
68
68
  - Rakefile
69
69
  - lib/rbl_mcafee.rb
70
+ - lib/rbl_mcafee/ip.rb
70
71
  - lib/rbl_mcafee/version.rb
72
+ - lib/rbl_mcafee/zone.rb
71
73
  - rbl_mcafee.gemspec
72
- - spec/rbl_mcafee_spec.rb
74
+ - spec/rbl_mcafee/ip_spec.rb
75
+ - spec/rbl_mcafee/zone_spec.rb
73
76
  homepage: https://github.com/romainsalles/rbl_mcafee
74
77
  licenses:
75
78
  - MIT
@@ -95,4 +98,5 @@ signing_key:
95
98
  specification_version: 4
96
99
  summary: Solution to test if an IP address is listed in the McAfee RBL
97
100
  test_files:
98
- - spec/rbl_mcafee_spec.rb
101
+ - spec/rbl_mcafee/ip_spec.rb
102
+ - spec/rbl_mcafee/zone_spec.rb
@@ -1,54 +0,0 @@
1
- require 'rbl_mcafee'
2
-
3
- describe RblMcafee do
4
- subject { RblMcafee.blacklisted?(ip_address) }
5
- let(:ip_address) { '127.0.0.1' }
6
-
7
- context 'with a non listed IP address' do
8
- it 'returns false' do
9
- Resolv.stub(:getaddress) { raise Resolv::ResolvError.new('whatever') }
10
-
11
- expect(subject).to be false
12
- end
13
- end
14
-
15
- context 'with a listed IP address' do
16
- it 'returns true' do
17
- Resolv.stub(:getaddress) { '127.0.0.11' }
18
-
19
- expect(subject).to be true
20
- end
21
- end
22
-
23
- context 'when a timeout error is raised by Resolv' do
24
- it 'raises a RblMcafee::Timeout error' do
25
- Resolv.stub(:getaddress) { raise Resolv::ResolvTimeout }
26
-
27
- expect{subject}.to raise_error(RblMcafee::Timeout)
28
- end
29
- end
30
-
31
- context 'when an unknown exception is raised by Resolv' do
32
- it 'is re-raised by .blacklisted?' do
33
- Resolv.stub(:getaddress) { raise 'oops' }
34
-
35
- expect{subject}.to raise_error('oops')
36
- end
37
- end
38
-
39
- context 'when an invalid IP address is passed as argument' do
40
- let(:ip_address) { '001.8.9.10' }
41
-
42
- it 'raises an ArgumentError' do
43
- expect{subject}.to raise_error(ArgumentError)
44
- end
45
- end
46
-
47
- context 'when a valid website address is passed as argument' do
48
- let(:ip_address) { 'www.mcafee.com' }
49
-
50
- it 'raises an ArgumentError' do
51
- expect{subject}.to raise_error(ArgumentError)
52
- end
53
- end
54
- end