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.
Files changed (101) hide show
  1. data/History.txt +74 -0
  2. data/README.rdoc +149 -0
  3. data/Rakefile +47 -0
  4. data/bin/b64 +5 -0
  5. data/bin/bgrep +5 -0
  6. data/bin/blit +5 -0
  7. data/bin/c +5 -0
  8. data/bin/crc32 +5 -0
  9. data/bin/d64 +5 -0
  10. data/bin/dedump +5 -0
  11. data/bin/feed +5 -0
  12. data/bin/hexify +5 -0
  13. data/bin/len +5 -0
  14. data/bin/plugsrv +271 -0
  15. data/bin/rex +10 -0
  16. data/bin/rstrings +5 -0
  17. data/bin/slice +5 -0
  18. data/bin/telson +5 -0
  19. data/bin/unhexify +5 -0
  20. data/bin/urldec +5 -0
  21. data/bin/urlenc +5 -0
  22. data/bin/xor +5 -0
  23. data/cli_usage.rdoc +285 -0
  24. data/doctor-bag.jpg +0 -0
  25. data/lib/rbkb.rb +51 -0
  26. data/lib/rbkb/cli.rb +219 -0
  27. data/lib/rbkb/cli/b64.rb +35 -0
  28. data/lib/rbkb/cli/bgrep.rb +86 -0
  29. data/lib/rbkb/cli/blit.rb +89 -0
  30. data/lib/rbkb/cli/chars.rb +24 -0
  31. data/lib/rbkb/cli/crc32.rb +35 -0
  32. data/lib/rbkb/cli/d64.rb +28 -0
  33. data/lib/rbkb/cli/dedump.rb +52 -0
  34. data/lib/rbkb/cli/feed.rb +229 -0
  35. data/lib/rbkb/cli/hexify.rb +65 -0
  36. data/lib/rbkb/cli/len.rb +76 -0
  37. data/lib/rbkb/cli/rstrings.rb +108 -0
  38. data/lib/rbkb/cli/slice.rb +47 -0
  39. data/lib/rbkb/cli/telson.rb +87 -0
  40. data/lib/rbkb/cli/unhexify.rb +50 -0
  41. data/lib/rbkb/cli/urldec.rb +35 -0
  42. data/lib/rbkb/cli/urlenc.rb +35 -0
  43. data/lib/rbkb/cli/xor.rb +43 -0
  44. data/lib/rbkb/extends.rb +725 -0
  45. data/lib/rbkb/http.rb +21 -0
  46. data/lib/rbkb/http/base.rb +172 -0
  47. data/lib/rbkb/http/body.rb +214 -0
  48. data/lib/rbkb/http/common.rb +74 -0
  49. data/lib/rbkb/http/headers.rb +370 -0
  50. data/lib/rbkb/http/parameters.rb +104 -0
  51. data/lib/rbkb/http/request.rb +58 -0
  52. data/lib/rbkb/http/response.rb +86 -0
  53. data/lib/rbkb/plug.rb +9 -0
  54. data/lib/rbkb/plug/blit.rb +222 -0
  55. data/lib/rbkb/plug/cli.rb +83 -0
  56. data/lib/rbkb/plug/feed_import.rb +74 -0
  57. data/lib/rbkb/plug/peer.rb +67 -0
  58. data/lib/rbkb/plug/plug.rb +215 -0
  59. data/lib/rbkb/plug/proxy.rb +26 -0
  60. data/lib/rbkb/plug/unix_domain.rb +75 -0
  61. data/lib_usage.rdoc +176 -0
  62. data/rbkb.gemspec +38 -0
  63. data/spec/rbkb_spec.rb +7 -0
  64. data/spec/spec_helper.rb +16 -0
  65. data/tasks/ann.rake +80 -0
  66. data/tasks/bones.rake +20 -0
  67. data/tasks/gem.rake +201 -0
  68. data/tasks/git.rake +40 -0
  69. data/tasks/notes.rake +27 -0
  70. data/tasks/post_load.rake +34 -0
  71. data/tasks/rdoc.rake +51 -0
  72. data/tasks/rubyforge.rake +55 -0
  73. data/tasks/setup.rb +292 -0
  74. data/tasks/spec.rake +54 -0
  75. data/tasks/svn.rake +47 -0
  76. data/tasks/test.rake +40 -0
  77. data/test/test_cli_b64.rb +35 -0
  78. data/test/test_cli_bgrep.rb +137 -0
  79. data/test/test_cli_blit.rb +11 -0
  80. data/test/test_cli_chars.rb +21 -0
  81. data/test/test_cli_crc32.rb +108 -0
  82. data/test/test_cli_d64.rb +22 -0
  83. data/test/test_cli_dedump.rb +118 -0
  84. data/test/test_cli_feed.rb +11 -0
  85. data/test/test_cli_helper.rb +96 -0
  86. data/test/test_cli_hexify.rb +63 -0
  87. data/test/test_cli_len.rb +96 -0
  88. data/test/test_cli_rstrings.rb +15 -0
  89. data/test/test_cli_slice.rb +73 -0
  90. data/test/test_cli_telson.rb +11 -0
  91. data/test/test_cli_unhexify.rb +43 -0
  92. data/test/test_cli_urldec.rb +50 -0
  93. data/test/test_cli_urlenc.rb +44 -0
  94. data/test/test_cli_xor.rb +71 -0
  95. data/test/test_helper.rb +5 -0
  96. data/test/test_http.rb +27 -0
  97. data/test/test_http_helper.rb +60 -0
  98. data/test/test_http_request.rb +136 -0
  99. data/test/test_http_response.rb +222 -0
  100. data/test/test_rbkb.rb +19 -0
  101. 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