nmunch 0.1.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.
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nmunch/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Michael Henriksen"]
6
+ gem.email = ["michenriksen87@gmail.com"]
7
+ gem.description = %q{Nmunch is a passive network discovery tool that finds live network nodes by analyzing ARP and broadcast packets.}
8
+ gem.summary = %q{OM NOM NOM NOM}
9
+ gem.homepage = "https://github.com/michenriksen/nmunch"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nmunch"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Nmunch::VERSION
17
+ gem.add_development_dependency('rspec')
18
+ gem.add_development_dependency('rake', '>= 0.9.2')
19
+ gem.add_dependency('methadone', '~> 1.2.3')
20
+ gem.add_dependency('pcap', '~> 0.7.7')
21
+ gem.add_dependency('paint')
22
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Arp do
4
+ let(:arp_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(ARP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(false)
8
+ packet
9
+ end
10
+
11
+ subject { Nmunch::Dissectors::Arp.new(arp_pcap_packet) }
12
+
13
+ describe '#ip_address' do
14
+ it 'returns correct IP address' do
15
+ subject.ip_address.should == '192.168.0.125'
16
+ end
17
+ end
18
+
19
+ describe '#mac_address' do
20
+ it 'returns correct MAC address' do
21
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Base do
4
+ let(:arp_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(ARP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(false)
8
+ packet
9
+ end
10
+
11
+ let(:ip_pcap_packet) do
12
+ packet = stub(Pcap::Packet)
13
+ packet.stub(:raw_data).and_return(IP_PACKET_DATA)
14
+ packet.stub(:ip?).and_return(true)
15
+ packet
16
+ end
17
+
18
+ subject { Nmunch::Dissectors::Base.new(arp_pcap_packet) }
19
+
20
+ describe '#pcap_packet' do
21
+ it 'returns pcap packet given in initializer' do
22
+ subject.pcap_packet.should == arp_pcap_packet
23
+ end
24
+ end
25
+
26
+ describe '#raw_data' do
27
+ it 'returns an array of bytes represented in HEX' do
28
+ subject.raw_data.should == ARP_PACKET_DATA.unpack('H*').first.scan(/.{2}/)
29
+ end
30
+ end
31
+
32
+ describe '.factory' do
33
+ context 'when given ARP packet' do
34
+ it 'returns an ARP dissector' do
35
+ Nmunch::Dissectors::Base.factory(arp_pcap_packet).should be_a(Nmunch::Dissectors::Arp)
36
+ end
37
+ end
38
+
39
+ context 'when given an IP packet' do
40
+ it 'returns an IP dissector' do
41
+ Nmunch::Dissectors::Base.factory(ip_pcap_packet).should be_a(Nmunch::Dissectors::Ip)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Dissectors::Ip do
4
+ let(:ip_pcap_packet) do
5
+ packet = stub(Pcap::Packet)
6
+ packet.stub(:raw_data).and_return(IP_PACKET_DATA)
7
+ packet.stub(:ip?).and_return(true)
8
+ packet
9
+ end
10
+
11
+ subject { Nmunch::Dissectors::Ip.new(ip_pcap_packet) }
12
+
13
+ describe '#ip_address' do
14
+ it 'returns correct IP address' do
15
+ ip_pcap_packet.should_receive(:ip_src).and_return('192.168.0.125')
16
+ subject.ip_address.should == '192.168.0.125'
17
+ end
18
+ end
19
+
20
+ describe '#mac_address' do
21
+ it 'returns correct MAC address' do
22
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::MacOuiLookup do
4
+ context 'when given an Apple mac address' do
5
+ it 'returns Apple' do
6
+ Nmunch::MacOuiLookup.instance.lookup('58:b0:35:31:33:73').should == 'Apple'
7
+ end
8
+ end
9
+
10
+ context 'when given a Cisco mac address' do
11
+ it 'returns Cisco Systems' do
12
+ Nmunch::MacOuiLookup.instance.lookup('00:01:63:42:42:42').should == 'Cisco Systems'
13
+ end
14
+ end
15
+
16
+ context 'when given a mac address with an unknown prefix' do
17
+ it 'returns Unknown' do
18
+ Nmunch::MacOuiLookup.instance.lookup('de:ad:be:ef:de:ad').should == 'Unknown'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Node do
4
+ subject { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
5
+
6
+ describe '#ip_address' do
7
+ it 'returns correct IP address' do
8
+ subject.ip_address.should == '192.168.0.1'
9
+ end
10
+ end
11
+
12
+ describe '#mac_address' do
13
+ it 'returns correct MAC address' do
14
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
15
+ end
16
+ end
17
+
18
+ describe '#meta_address?' do
19
+ context 'when IP is not a meta address' do
20
+ it 'returns false' do
21
+ subject.should_not be_meta_address
22
+ end
23
+ end
24
+
25
+ context 'when IP is a meta address' do
26
+ it 'returns true' do
27
+ subject.stub(:ip_address).and_return('0.0.0.0')
28
+ subject.should be_meta_address
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '.create_from_dissector' do
34
+ let(:dissector) do
35
+ dissector = stub
36
+ dissector.stub(:ip_address).and_return('192.168.0.1')
37
+ dissector.stub(:mac_address).and_return('de:ad:be:ef:de:ad')
38
+ dissector
39
+ end
40
+ subject { Nmunch::Node.create_from_dissector(dissector) }
41
+
42
+ it 'returns a node' do
43
+ subject.should be_a(Nmunch::Node)
44
+ end
45
+
46
+ it 'has correct IP address' do
47
+ subject.ip_address.should == '192.168.0.1'
48
+ end
49
+
50
+ it 'has correct MAC address' do
51
+ subject.mac_address.should == 'de:ad:be:ef:de:ad'
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ class TestSubscriber
4
+ def process(node); end
5
+ end
6
+
7
+ describe Nmunch::Report do
8
+ let(:node) { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
9
+ let(:options) { {interface: 'en1'} }
10
+ let(:subscriber) { TestSubscriber.new }
11
+ subject { Nmunch::Report.new(options) }
12
+
13
+ describe '#publish_node' do
14
+ before(:each) do
15
+ subject.register_subscriber(subscriber)
16
+ end
17
+
18
+ it 'delegates the node to the subscriber' do
19
+ subscriber.should_receive(:process).with(node)
20
+ subject.publish_node(node)
21
+ end
22
+
23
+ context 'when node has a meta address' do
24
+ it 'does not delegate node to subscribers' do
25
+ node.stub(:ip_address).and_return('0.0.0.0')
26
+ subscriber.should_not_receive(:process)
27
+ subject.publish_node(node)
28
+ end
29
+ end
30
+
31
+ context 'when node is already discovered' do
32
+ it 'does not delegate node to subscribers' do
33
+ subject.publish_node(node)
34
+ subscriber.should_not_receive(:process)
35
+ subject.publish_node(node)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Subscribers::Base do
4
+ let(:options) { {interface: 'en1'} }
5
+ subject { Nmunch::Subscribers::Base.new(options) }
6
+
7
+ describe '.initialize' do
8
+ it 'assigns options to instance variable' do
9
+ subject.options.should == options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch::Subscribers::Stdout do
4
+ let(:node) { Nmunch::Node.new(ip_address: '192.168.0.1', mac_address: 'de:ad:be:ef:de:ad') }
5
+ let(:options) { {interface: 'en1'} }
6
+ subject { Nmunch::Subscribers::Stdout.new(options) }
7
+
8
+ describe '#process' do
9
+ it 'prints node details to STDOUT' do
10
+ output = capture_stdout { subject.process(node) }
11
+ output.should include('192.168.0.1')
12
+ output.should include('de:ad:be:ef:de:ad')
13
+ output.should include('Unknown')
14
+ end
15
+
16
+ context 'when --no-prefix-lookup option is set' do
17
+ it 'does not look up mac address prefix' do
18
+ options['no-prefix-lookup'] = true
19
+ output = capture_stdout { subject.process(node) }
20
+ output.should include('192.168.0.1')
21
+ output.should include('de:ad:be:ef:de:ad')
22
+ output.should_not include('Unknown')
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nmunch do
4
+ describe 'PCAP filter expression' do
5
+ it 'allows only ARP and broadcast packets' do
6
+ Nmunch::CAPTURE_FILTER.should == 'arp or broadcast'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ require 'bundler'
2
+ begin
3
+ Bundler.setup(:default, :development)
4
+ rescue Bundler::BundlerError => e
5
+ $stderr.puts e.message
6
+ $stderr.puts 'Run `bundle install` to install missing gems'
7
+ exit e.status_code
8
+ end
9
+
10
+ require 'pcap'
11
+ require 'ipaddr'
12
+ require 'paint'
13
+ require 'nmunch'
14
+
15
+ RSpec.configure do |config|
16
+ config.filter_run :focus => true
17
+ config.run_all_when_everything_filtered = true
18
+ end
19
+
20
+ def capture_stdout
21
+ original_stdout = $stdout
22
+ $stdout = fake = StringIO.new
23
+ begin
24
+ yield
25
+ ensure
26
+ $stdout = original_stdout
27
+ end
28
+ fake.string
29
+ end
30
+
31
+ ARP_PACKET_DATA = "\xff\xff\xff\xff\xff\xff\xde\xad\xbe\xef\xde\xad\x08\x06\x00\x01" +
32
+ "\x08\x00\x06\x04\x00\x01\xde\xad\xbe\xef\xde\xad\xc0\xa8\x00\x7d" +
33
+ "\x00\x00\x00\x00\x00\x00\xc0\xa8\x00\x42"
34
+
35
+ IP_PACKET_DATA = "\x7b\x22\x68\x6f\x73\x74\xde\xad\xbe\xef\xde\xad\x20\x32\x36\x37" +
36
+ "\x35\x37\x32\x31\x31\x30\x2c\x20\x22\x76\x65\x72\x73\x69\x6f\x6e" +
37
+ "\x22\x3a\x20\x5b\x31\x2c\x20\x38\x5d\x2c\x20\x22\x64\x69\x73\x70" +
38
+ "\x6c\x61\x79\x6e\x61\x6d\x65\x22\x3a\x20\x22\x32\x36\x37\x35\x37" +
39
+ "\x32\x31\x31\x30\x22\x2c\x20\x22\x70\x6f\x72\x74\x22\x3a\x20\x31" +
40
+ "\x37\x35\x30\x30\x2c\x20\x22\x6e\x61\x6d\x65\x73\x70\x61\x63\x65" +
41
+ "\x73\x22\x3a\x20\x5b\x31\x34\x33\x30\x30\x33\x33\x37\x36\x2c\x20" +
42
+ "\x31\x31\x35\x36\x33\x34\x38\x35\x38\x2c\x20\x31\x31\x38\x39\x30" +
43
+ "\x36\x37\x30\x31\x5d\x7d"
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nmunch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Henriksen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.2
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: methadone
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.3
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.2.3
62
+ - !ruby/object:Gem::Dependency
63
+ name: pcap
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.7.7
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.7.7
78
+ - !ruby/object:Gem::Dependency
79
+ name: paint
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Nmunch is a passive network discovery tool that finds live network nodes
95
+ by analyzing ARP and broadcast packets.
96
+ email:
97
+ - michenriksen87@gmail.com
98
+ executables:
99
+ - nmunch
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - .gitignore
104
+ - Gemfile
105
+ - Gemfile.lock
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - bin/nmunch
110
+ - lib/nmunch.rb
111
+ - lib/nmunch/dissectors/arp.rb
112
+ - lib/nmunch/dissectors/base.rb
113
+ - lib/nmunch/dissectors/ip.rb
114
+ - lib/nmunch/mac_oui_lookup.rb
115
+ - lib/nmunch/node.rb
116
+ - lib/nmunch/report.rb
117
+ - lib/nmunch/subscribers/base.rb
118
+ - lib/nmunch/subscribers/stdout.rb
119
+ - lib/nmunch/version.rb
120
+ - mac-prefixes.txt
121
+ - nmunch.gemspec
122
+ - spec/lib/nmunch/dissectors/arp_spec.rb
123
+ - spec/lib/nmunch/dissectors/base_spec.rb
124
+ - spec/lib/nmunch/dissectors/ip_spec.rb
125
+ - spec/lib/nmunch/mac_oui_lookup_spec.rb
126
+ - spec/lib/nmunch/node_spec.rb
127
+ - spec/lib/nmunch/report_spec.rb
128
+ - spec/lib/nmunch/subscribers/base_spec.rb
129
+ - spec/lib/nmunch/subscribers/stdout_spec.rb
130
+ - spec/lib/nmunch_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: https://github.com/michenriksen/nmunch
133
+ licenses: []
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: OM NOM NOM NOM
156
+ test_files:
157
+ - spec/lib/nmunch/dissectors/arp_spec.rb
158
+ - spec/lib/nmunch/dissectors/base_spec.rb
159
+ - spec/lib/nmunch/dissectors/ip_spec.rb
160
+ - spec/lib/nmunch/mac_oui_lookup_spec.rb
161
+ - spec/lib/nmunch/node_spec.rb
162
+ - spec/lib/nmunch/report_spec.rb
163
+ - spec/lib/nmunch/subscribers/base_spec.rb
164
+ - spec/lib/nmunch/subscribers/stdout_spec.rb
165
+ - spec/lib/nmunch_spec.rb
166
+ - spec/spec_helper.rb