rbkb 0.6.10
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.
- data/History.txt +74 -0
- data/README.rdoc +149 -0
- data/Rakefile +47 -0
- data/bin/b64 +5 -0
- data/bin/bgrep +5 -0
- data/bin/blit +5 -0
- data/bin/c +5 -0
- data/bin/crc32 +5 -0
- data/bin/d64 +5 -0
- data/bin/dedump +5 -0
- data/bin/feed +5 -0
- data/bin/hexify +5 -0
- data/bin/len +5 -0
- data/bin/plugsrv +271 -0
- data/bin/rex +10 -0
- data/bin/rstrings +5 -0
- data/bin/slice +5 -0
- data/bin/telson +5 -0
- data/bin/unhexify +5 -0
- data/bin/urldec +5 -0
- data/bin/urlenc +5 -0
- data/bin/xor +5 -0
- data/cli_usage.rdoc +285 -0
- data/doctor-bag.jpg +0 -0
- data/lib/rbkb.rb +51 -0
- data/lib/rbkb/cli.rb +219 -0
- data/lib/rbkb/cli/b64.rb +35 -0
- data/lib/rbkb/cli/bgrep.rb +86 -0
- data/lib/rbkb/cli/blit.rb +89 -0
- data/lib/rbkb/cli/chars.rb +24 -0
- data/lib/rbkb/cli/crc32.rb +35 -0
- data/lib/rbkb/cli/d64.rb +28 -0
- data/lib/rbkb/cli/dedump.rb +52 -0
- data/lib/rbkb/cli/feed.rb +229 -0
- data/lib/rbkb/cli/hexify.rb +65 -0
- data/lib/rbkb/cli/len.rb +76 -0
- data/lib/rbkb/cli/rstrings.rb +108 -0
- data/lib/rbkb/cli/slice.rb +47 -0
- data/lib/rbkb/cli/telson.rb +87 -0
- data/lib/rbkb/cli/unhexify.rb +50 -0
- data/lib/rbkb/cli/urldec.rb +35 -0
- data/lib/rbkb/cli/urlenc.rb +35 -0
- data/lib/rbkb/cli/xor.rb +43 -0
- data/lib/rbkb/extends.rb +725 -0
- data/lib/rbkb/http.rb +21 -0
- data/lib/rbkb/http/base.rb +172 -0
- data/lib/rbkb/http/body.rb +214 -0
- data/lib/rbkb/http/common.rb +74 -0
- data/lib/rbkb/http/headers.rb +370 -0
- data/lib/rbkb/http/parameters.rb +104 -0
- data/lib/rbkb/http/request.rb +58 -0
- data/lib/rbkb/http/response.rb +86 -0
- data/lib/rbkb/plug.rb +9 -0
- data/lib/rbkb/plug/blit.rb +222 -0
- data/lib/rbkb/plug/cli.rb +83 -0
- data/lib/rbkb/plug/feed_import.rb +74 -0
- data/lib/rbkb/plug/peer.rb +67 -0
- data/lib/rbkb/plug/plug.rb +215 -0
- data/lib/rbkb/plug/proxy.rb +26 -0
- data/lib/rbkb/plug/unix_domain.rb +75 -0
- data/lib_usage.rdoc +176 -0
- data/rbkb.gemspec +38 -0
- data/spec/rbkb_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/test_cli_b64.rb +35 -0
- data/test/test_cli_bgrep.rb +137 -0
- data/test/test_cli_blit.rb +11 -0
- data/test/test_cli_chars.rb +21 -0
- data/test/test_cli_crc32.rb +108 -0
- data/test/test_cli_d64.rb +22 -0
- data/test/test_cli_dedump.rb +118 -0
- data/test/test_cli_feed.rb +11 -0
- data/test/test_cli_helper.rb +96 -0
- data/test/test_cli_hexify.rb +63 -0
- data/test/test_cli_len.rb +96 -0
- data/test/test_cli_rstrings.rb +15 -0
- data/test/test_cli_slice.rb +73 -0
- data/test/test_cli_telson.rb +11 -0
- data/test/test_cli_unhexify.rb +43 -0
- data/test/test_cli_urldec.rb +50 -0
- data/test/test_cli_urlenc.rb +44 -0
- data/test/test_cli_xor.rb +71 -0
- data/test/test_helper.rb +5 -0
- data/test/test_http.rb +27 -0
- data/test/test_http_helper.rb +60 -0
- data/test/test_http_request.rb +136 -0
- data/test/test_http_response.rb +222 -0
- data/test/test_rbkb.rb +19 -0
- metadata +238 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
require 'rbkb'
|
7
|
+
|
8
|
+
module FeedImport
|
9
|
+
|
10
|
+
## TODO switch to pcaprub or some other up to date pcap lib. make it a dep.
|
11
|
+
begin
|
12
|
+
## This requires the 'ruby-pcap' library from:
|
13
|
+
## http://raa.ruby-lang.org/project/pcap/
|
14
|
+
## ... which is old and krufty...
|
15
|
+
$VERBOSE=nil
|
16
|
+
require 'pcaplet'
|
17
|
+
$VERBOSE=false
|
18
|
+
|
19
|
+
# Imports an array from pcap
|
20
|
+
def import_pcap(file, filter=nil)
|
21
|
+
ret = Array.new
|
22
|
+
pcap = Pcap::Capture.open_offline(file)
|
23
|
+
pcap.setfilter filter if filter
|
24
|
+
pcap.each_packet do |pkt|
|
25
|
+
if ( (pkt.udp? and dat=pkt.udp_data) or
|
26
|
+
(pkt.tcp? and dat=pkt.tcp_data and not dat.empty?)
|
27
|
+
)
|
28
|
+
ret << dat
|
29
|
+
end
|
30
|
+
end
|
31
|
+
return ret
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
def import_pcap(*args)
|
35
|
+
raise "you must install ruby-pcap to use this feature"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module_function :import_pcap
|
40
|
+
|
41
|
+
|
42
|
+
# Imports an array from yaml
|
43
|
+
def import_yaml(file)
|
44
|
+
unless ( ret = YAML.load_file(file) ).kind_of? Array
|
45
|
+
raise "#{file.inspect} did not provide an array"
|
46
|
+
end
|
47
|
+
return ret
|
48
|
+
end
|
49
|
+
module_function :import_yaml
|
50
|
+
|
51
|
+
|
52
|
+
# Imports from hexdumps separated by "%" and merged by ','
|
53
|
+
def import_dump(file)
|
54
|
+
ret = []
|
55
|
+
dat = File.read(file)
|
56
|
+
dat.strip.split(/^%$/).each do |msg|
|
57
|
+
ret << ""
|
58
|
+
msg.strip.split(/^,$/).each do |chunk|
|
59
|
+
ret[-1] << chunk.strip.dehexdump
|
60
|
+
end
|
61
|
+
end
|
62
|
+
return ret
|
63
|
+
end
|
64
|
+
module_function :import_dump
|
65
|
+
|
66
|
+
# Imports raw messages in files by a glob pattern (i.e. /tmp/foo/msgs.*)
|
67
|
+
# Manage filenames so that they're in the right order on import.
|
68
|
+
# See Dir.glob for valid globbing patterns.
|
69
|
+
def import_rawfiles(glob_pat)
|
70
|
+
Dir.glob(glob_pat).map { |f| File.read(f) }
|
71
|
+
end
|
72
|
+
module_function :import_rawfiles
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
module Plug
|
8
|
+
|
9
|
+
class Peer
|
10
|
+
attr_reader :addr, :transport, :name, :owner, :host, :port
|
11
|
+
attr_accessor :mute
|
12
|
+
|
13
|
+
def initialize(addr, owner)
|
14
|
+
@addr = addr
|
15
|
+
@owner = owner
|
16
|
+
@transport = @owner.transport
|
17
|
+
|
18
|
+
@port, @host = Socket.unpack_sockaddr_in(@addr)
|
19
|
+
@name = "PEER-#{@host}:#{@port}(#{@transport})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def say(dat, sender)
|
23
|
+
UI.dump(sender.name, self.name, dat)
|
24
|
+
|
25
|
+
if @transport == :UDP
|
26
|
+
@owner.send_datagram(dat, @host, @port)
|
27
|
+
else
|
28
|
+
@owner.send_data(dat)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def close
|
33
|
+
@owner.unbind unless @transport == :UDP
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class PeerList < Array
|
39
|
+
def initialize(owner, *args)
|
40
|
+
@owner = owner
|
41
|
+
@transport = @owner.transport
|
42
|
+
|
43
|
+
super(*args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_peer(addr)
|
47
|
+
self.find {|p| p.addr == addr }
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_peer(addr)
|
51
|
+
self << Peer.new(addr, @owner)
|
52
|
+
self.last
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_peer_manually(host, port)
|
56
|
+
addr = Socket.pack_sockaddr_in(port, host)
|
57
|
+
return (find_peer(addr) || add_peer(addr))
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete(addr)
|
61
|
+
if p=find_peer(addr)
|
62
|
+
p.close
|
63
|
+
super(p)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
|
5
|
+
require "rbkb/plug/peer.rb"
|
6
|
+
require 'stringio'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
|
10
|
+
module Plug
|
11
|
+
module UI
|
12
|
+
LOGCFG = {:out => STDERR, :dump => :hex}
|
13
|
+
|
14
|
+
def self.prompt(*msg); STDERR.puts msg ; STDIN.gets ; end
|
15
|
+
|
16
|
+
def self.log(*msg); LOGCFG[:out].puts msg ; end
|
17
|
+
|
18
|
+
def self.verbose(*msg); LOGCFG[:out].puts msg if LOGCFG[:verbose] ; end
|
19
|
+
|
20
|
+
def self.debug(*msg); LOGCFG[:out].puts msg if LOGCFG[:debug] ; end
|
21
|
+
|
22
|
+
def self.dump(from, to, dat)
|
23
|
+
if dump=LOGCFG[:dump]
|
24
|
+
LOGCFG[:out].puts "%% #{from} SAYS TO #{to} LEN=#{dat.size}" if LOGCFG[:verbose]
|
25
|
+
case dump
|
26
|
+
when :hex
|
27
|
+
dat.hexdump(:out => LOGCFG[:out])
|
28
|
+
when :raw
|
29
|
+
LOGCFG[:out].puts dat
|
30
|
+
else
|
31
|
+
LOGCFG[:out].puts dat
|
32
|
+
end
|
33
|
+
LOGCFG[:out].puts "%%" if LOGCFG[:verbose]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
module Base
|
40
|
+
attr_accessor :peers, :transport, :kind, :tls, :tls_opts, :no_stop_on_unbind
|
41
|
+
|
42
|
+
def initialize(transport, opts={})
|
43
|
+
# raise "Invalid transport #{transport.inspect}" unless (:UDP, :TCP).include?(transport)
|
44
|
+
@transport = transport
|
45
|
+
@peers = PeerList.new(self)
|
46
|
+
|
47
|
+
opts.each_pair do |k,v|
|
48
|
+
accessor = k.to_s + "="
|
49
|
+
if self.respond_to?(accessor)
|
50
|
+
self.send(accessor, v)
|
51
|
+
else
|
52
|
+
raise "Bad attribute: #{k}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def name
|
58
|
+
sn = get_sockname
|
59
|
+
addr = sn ? Socket.unpack_sockaddr_in(sn).reverse.join(":") : "PENDING"
|
60
|
+
"#{kind.to_s.upcase}-#{addr}(#{@transport})"
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# plug_peer creates a peering association for a given peer based on
|
65
|
+
# get_peername. The existing or newly created peer object is returned.
|
66
|
+
def plug_peer
|
67
|
+
paddr = get_peername
|
68
|
+
peer = (@peers.find_peer(paddr) || @peers.add_peer(paddr) )
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# plug_receive is used by receive_data to divert incoming messages.
|
73
|
+
# The "peer" is added if it is not already present. This instance
|
74
|
+
# will check whether # a peer is "muted" and will return the peer if not.
|
75
|
+
# This method can be overriden by child classes to implement additional
|
76
|
+
# checks. It receives "dat" so that such checks can optionally make
|
77
|
+
# forwarding decisions based on message data contents as well.
|
78
|
+
#
|
79
|
+
# Returns:
|
80
|
+
# - nil : indicates that the message should be stifled
|
81
|
+
# - A peer object : indicates that the message should be processed
|
82
|
+
# further
|
83
|
+
def plug_receive(dat)
|
84
|
+
peer = plug_peer
|
85
|
+
return peer unless peer.mute
|
86
|
+
end
|
87
|
+
|
88
|
+
# This instance of the say method is an abstract stub and just
|
89
|
+
# "dumps" the message. It should be overridden and optionally called
|
90
|
+
# with super() if you actually want to do anything useful when
|
91
|
+
# incoming messages are received.
|
92
|
+
def say(dat, sender)
|
93
|
+
UI.dump(sender.name, self.name, dat)
|
94
|
+
end
|
95
|
+
|
96
|
+
def post_init
|
97
|
+
UI.verbose "** #{name} Started"
|
98
|
+
if @kind==:server and peer=plug_peer
|
99
|
+
UI.log "** #{name} CONNECTED TO #{peer.name}"
|
100
|
+
if tls
|
101
|
+
start_tls(tls_opts || {})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def receive_data(dat)
|
107
|
+
if peer=plug_receive(dat)
|
108
|
+
say(dat, peer)
|
109
|
+
end
|
110
|
+
return peer
|
111
|
+
end
|
112
|
+
|
113
|
+
def connection_completed
|
114
|
+
peer = plug_peer
|
115
|
+
UI.log "** #{name} CONNECTED TO #{peer.name}"
|
116
|
+
if tls
|
117
|
+
start_tls(tls_opts || {})
|
118
|
+
end
|
119
|
+
return peer
|
120
|
+
end
|
121
|
+
|
122
|
+
def unbind
|
123
|
+
UI.log "** Connection " + ((@peers.empty?)? "refused." : "closed.")
|
124
|
+
unless @no_stop_on_unbind
|
125
|
+
UI.log "STOPPING!!"
|
126
|
+
EM.stop
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# An abstract module to implement custom servers for any protocol
|
133
|
+
# incoming messages are diverted to 'process(dat, sender)' which takes
|
134
|
+
# a block, the yields to which are messages to respond with
|
135
|
+
module UdpServer
|
136
|
+
include Base
|
137
|
+
|
138
|
+
def kind ; :server ; end
|
139
|
+
|
140
|
+
def say(dat, sender)
|
141
|
+
super(dat, sender)
|
142
|
+
|
143
|
+
if self.respond_to? :process
|
144
|
+
self.send(:process, dat, sender) { |rply| sender.say(rply, self) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
# Telson is just a receiver for blit
|
152
|
+
module Telson
|
153
|
+
include Base
|
154
|
+
def kind ; :telson ; end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
# Uses an array of static messages as a datasource for opaque protocol
|
159
|
+
# messages. Useful as a generic blit-able loop
|
160
|
+
module ArrayFeeder
|
161
|
+
include Base
|
162
|
+
attr_accessor :pos, :feed, :step, :close_at_end, :go_first,
|
163
|
+
:squelch_exhausted
|
164
|
+
|
165
|
+
def initialize(*args)
|
166
|
+
super(*args)
|
167
|
+
|
168
|
+
@pos ||= 0
|
169
|
+
@feed ||= []
|
170
|
+
|
171
|
+
raise "feed must be enumerable" unless Enumerable === @feed
|
172
|
+
end
|
173
|
+
|
174
|
+
def go
|
175
|
+
if @go_first
|
176
|
+
feed_data
|
177
|
+
@go_first = false
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def connection_completed
|
182
|
+
peer=super()
|
183
|
+
go if @go_first
|
184
|
+
return peer
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def say(dat, sender)
|
189
|
+
super(dat, sender)
|
190
|
+
if @step
|
191
|
+
EventMachine.defer(
|
192
|
+
proc { UI.prompt ">> Hit [enter] to continue at #{@pos}:" },
|
193
|
+
proc {|x| feed_data }
|
194
|
+
)
|
195
|
+
else
|
196
|
+
feed_data
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def feed_data(dst=plug_peer)
|
201
|
+
unless dat=@feed[@pos]
|
202
|
+
UI.log "** FEED EXHAUSTED" unless @squelch_exhausted
|
203
|
+
return nil
|
204
|
+
end
|
205
|
+
|
206
|
+
dst.say dat.to_s, self
|
207
|
+
|
208
|
+
if (@pos += 1) >= @feed.size and @close_at_end
|
209
|
+
close_connection_after_writing
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end # ArrayFeeder
|
214
|
+
end # Plug
|
215
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
|
5
|
+
module Plug
|
6
|
+
module Proxy
|
7
|
+
include Base
|
8
|
+
attr_accessor :target
|
9
|
+
|
10
|
+
def initialize(transport, target)
|
11
|
+
@transport = transport
|
12
|
+
@peers = ProxyPeerList.new(self)
|
13
|
+
@kind = :proxy
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class ProxyPeerList < PeerList
|
19
|
+
|
20
|
+
def add_peer(addr)
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_peer_manually(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright 2009 emonti at matasano.com
|
2
|
+
# See README.rdoc for license information
|
3
|
+
#
|
4
|
+
|
5
|
+
# Experimental!!!
|
6
|
+
|
7
|
+
require 'eventmachine'
|
8
|
+
require 'rbkb/plug'
|
9
|
+
require 'rbkb'
|
10
|
+
|
11
|
+
module Plug
|
12
|
+
class PeerStub
|
13
|
+
attr_reader :owner
|
14
|
+
|
15
|
+
def initialize(owner)
|
16
|
+
@owner = owner
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](junk)
|
20
|
+
@owner
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(junk)
|
24
|
+
[@owner]
|
25
|
+
end
|
26
|
+
|
27
|
+
def peers
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module UnixDomain
|
33
|
+
attr_accessor :mute, :peers
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@peers = PeerStub.new(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def name
|
40
|
+
"a domain socket"
|
41
|
+
end
|
42
|
+
|
43
|
+
def receive_data(dat)
|
44
|
+
puts "Got:", dat.hexdump
|
45
|
+
end
|
46
|
+
|
47
|
+
def say(dat, sender)
|
48
|
+
UI.dump(sender.name, self.name, dat)
|
49
|
+
send_data(dat)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
if $0 == __FILE__
|
56
|
+
Plug::UI::LOGCFG[:verbose] = true
|
57
|
+
|
58
|
+
b_addr = Plug::Blit::DEFAULT_IPADDR
|
59
|
+
b_port = Plug::Blit::DEFAULT_PORT
|
60
|
+
unless (sock=ARGV.shift and ARGV.shift.nil?)
|
61
|
+
STDERR.puts "usage: #{File.basename $0} unix_socket"
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
EventMachine.run {
|
67
|
+
s = EventMachine.connect_unix_domain(sock, Plug::UnixDomain)
|
68
|
+
Plug::UI::verbose("** UNIX-DOMAIN-#{sock.inspect} Started")
|
69
|
+
|
70
|
+
# connect a blit channel:
|
71
|
+
EventMachine.start_server(b_addr, b_port, Plug::Blit, :TCP, s)
|
72
|
+
Plug::UI::verbose("** BLITSRV-#{b_addr}:#{b_port}(TCP) Started")
|
73
|
+
}
|
74
|
+
|
75
|
+
end
|