1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
# -*- coding: binary -*-
require 'spec_helper'
require 'packetfu/protos/eth'
require 'packetfu/protos/ip'
require 'packetfu/protos/ipv6'
require 'packetfu/protos/tcp'
require 'packetfu/protos/icmp'
require 'packetfu/capture'
require 'packetfu/config'
require 'packetfu/pcap'
require 'packetfu/utils'
require 'tempfile'
include PacketFu
describe Capture do
if Process.uid != 0
warn "Not running as root, PacketFu::Capture capabilities that require root will be skipped"
end
context "when creating an object from scratch" do
before :each do
@capture = PacketFu::Capture.new
end
xit "should have sane defaults" do
expect(@capture.array).to be_kind_of(Array)
expect(@capture.stream).to be_kind_of(Array)
expect(@capture.iface).to be_kind_of(String)
expect(@capture.snaplen).to eql(65535)
expect(@capture.promisc).to eql(false)
expect(@capture.timeout).to eql(1)
# Requires root/sudo to get this...
if Process.uid == 0
expect(@capture.filter).to eql(nil)
else
expect{@capture.filter}.to raise_error(RuntimeError)
end
end
xit "should allow creating a capture object with non-std attributes" do
# Can only run this if we're root
if Process.uid == 0
options = {
:iface => PacketFu::Utils::default_int,
:snaplen => 0xfffe,
:promisc => true,
:timeout => 5,
:filter => "not port 22",
}
@capture = PacketFu::Capture.new(options)
expect(@capture.array).to be_kind_of(Array)
expect(@capture.stream).to be_kind_of(PCAPRUB::Pcap)
expect(@capture.iface).to eql(options[:iface])
expect(@capture.snaplen).to eql(options[:snaplen])
expect(@capture.promisc).to eql(options[:promisc])
expect(@capture.timeout).to eql(options[:timeout])
expect(@capture.filter).to eql(options[:filter])
expect(@capture.bpf).to eql(options[:filter])
end
end
end
context "when capturing traffic on the wire" do
# Can only run this if we're root
if Process.uid == 0
xit "should capture an ICMP echo request from the wire" do
daddr = PacketFu::Utils.rand_routable_daddr.to_s
def do_capture_test(daddr)
begin
Timeout::timeout(3) {
cap = PacketFu::Capture.new(:iface => PacketFu::Utils::default_int, :start => true)
cap.stream.each do |p|
pkt = PacketFu::Packet.parse p
next unless pkt.is_icmp?
if pkt.ip_daddr == daddr and pkt.icmp_type == 8
return true
end
end
}
rescue Timeout::Error
return false
end
end
capture_thread = Thread.new { expect(do_capture_test(daddr)).to eql(true) }
%x{ping -c 1 #{daddr}}
capture_thread.join
end
xit "should capture only capture ICMP echo requests we ask for from the wire" do
daddr = PacketFu::Utils.rand_routable_daddr.to_s
daddr2 = PacketFu::Utils.rand_routable_daddr.to_s
def do_bpf_capture_test(daddr, daddr2)
count = 0
valid_icmp = false
invalid_icmp = false
begin
Timeout::timeout(3) {
cap = PacketFu::Capture.new(:iface => PacketFu::Utils::default_int, :start => true, :filter => "icmp and dst host #{daddr}")
cap.stream.each do |p|
pkt = PacketFu::Packet.parse p
next unless pkt.is_icmp?
count += 1
if pkt.ip_daddr == daddr and pkt.icmp_type == 8
valid_icmp = true
elsif pkt.ip_daddr == daddr2 and pkt.icmp_type == 8
invalid_icmp = true
end
end
}
rescue Timeout::Error
### do nothing, we need to wait for the timeout anyways
end
if count == 1 && valid_icmp == true && invalid_icmp == false
return true
else
return false
end
end
capture_thread = Thread.new { expect(do_bpf_capture_test(daddr,daddr2)).to eql(true) }
%x{ping -c 1 #{daddr}}
%x{ping -c 1 #{daddr2}}
capture_thread.join
end
end
end
end
|