File: capture_spec.rb

package info (click to toggle)
ruby-packetfu 2.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,520 kB
  • sloc: ruby: 8,344; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 4,354 bytes parent folder | download
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