ronin-support 0.2.0 → 0.3.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.
Files changed (62) hide show
  1. data/.gitignore +11 -0
  2. data/ChangeLog.md +42 -1
  3. data/README.md +4 -1
  4. data/gemspec.yml +2 -1
  5. data/lib/ronin/extensions.rb +2 -0
  6. data/lib/ronin/extensions/enumerable.rb +54 -0
  7. data/lib/ronin/extensions/file.rb +70 -2
  8. data/lib/ronin/extensions/ip_addr.rb +45 -45
  9. data/lib/ronin/extensions/regexp.rb +45 -0
  10. data/lib/ronin/extensions/resolv.rb +80 -0
  11. data/lib/ronin/extensions/string.rb +35 -32
  12. data/lib/ronin/formatting/extensions/binary/integer.rb +12 -5
  13. data/lib/ronin/formatting/extensions/binary/string.rb +44 -16
  14. data/lib/ronin/formatting/extensions/html/integer.rb +51 -31
  15. data/lib/ronin/formatting/extensions/html/string.rb +50 -31
  16. data/lib/ronin/formatting/extensions/http/integer.rb +10 -2
  17. data/lib/ronin/formatting/extensions/sql.rb +20 -0
  18. data/lib/ronin/formatting/extensions/sql/string.rb +98 -0
  19. data/lib/ronin/formatting/extensions/text/array.rb +11 -9
  20. data/lib/ronin/formatting/extensions/text/string.rb +213 -29
  21. data/lib/ronin/formatting/sql.rb +20 -0
  22. data/lib/ronin/network/extensions/http.rb +1 -0
  23. data/lib/ronin/network/extensions/http/net.rb +2 -2
  24. data/lib/ronin/network/extensions/http/uri/http.rb +226 -0
  25. data/lib/ronin/network/extensions/imap/net.rb +1 -1
  26. data/lib/ronin/network/extensions/ssl/net.rb +7 -1
  27. data/lib/ronin/network/http/proxy.rb +20 -21
  28. data/lib/ronin/network/mixins.rb +27 -0
  29. data/lib/ronin/network/mixins/esmtp.rb +165 -0
  30. data/lib/ronin/network/mixins/http.rb +723 -0
  31. data/lib/ronin/network/mixins/imap.rb +151 -0
  32. data/lib/ronin/network/mixins/pop3.rb +141 -0
  33. data/lib/ronin/network/mixins/smtp.rb +159 -0
  34. data/lib/ronin/network/mixins/tcp.rb +331 -0
  35. data/lib/ronin/network/mixins/telnet.rb +199 -0
  36. data/lib/ronin/network/mixins/udp.rb +227 -0
  37. data/lib/ronin/network/ssl.rb +17 -11
  38. data/lib/ronin/path.rb +3 -3
  39. data/lib/ronin/spec/ui/output.rb +28 -0
  40. data/lib/ronin/support.rb +3 -0
  41. data/lib/ronin/support/version.rb +1 -1
  42. data/lib/ronin/ui/output.rb +21 -0
  43. data/lib/ronin/ui/output/helpers.rb +248 -0
  44. data/lib/ronin/ui/output/output.rb +146 -0
  45. data/lib/ronin/ui/output/terminal.rb +21 -0
  46. data/lib/ronin/ui/output/terminal/color.rb +118 -0
  47. data/lib/ronin/ui/output/terminal/raw.rb +103 -0
  48. data/lib/ronin/ui/shell.rb +219 -0
  49. data/ronin-support.gemspec +1 -1
  50. data/spec/extensions/enumerable_spec.rb +24 -0
  51. data/spec/extensions/file_spec.rb +39 -0
  52. data/spec/extensions/ip_addr_spec.rb +6 -0
  53. data/spec/extensions/resolv_spec.rb +18 -0
  54. data/spec/formatting/html/integer_spec.rb +2 -2
  55. data/spec/formatting/html/string_spec.rb +1 -1
  56. data/spec/formatting/sql/string_spec.rb +55 -0
  57. data/spec/formatting/text/string_spec.rb +110 -0
  58. data/spec/network/ssl_spec.rb +10 -4
  59. data/spec/ui/classes/test_shell.rb +22 -0
  60. data/spec/ui/output_spec.rb +32 -0
  61. data/spec/ui/shell_spec.rb +79 -0
  62. metadata +132 -90
@@ -99,7 +99,7 @@ Gem::Specification.new do |gemspec|
99
99
  end
100
100
 
101
101
  if gemspec.respond_to?(:required_rubygems_version=)
102
- gemspec.required_rubygems_version = metadata['required_ruby_version']
102
+ gemspec.required_rubygems_version = metadata['required_rubygems_version']
103
103
  end
104
104
 
105
105
  parse_versions = lambda { |versions|
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'ronin/extensions/enumerable'
3
+
4
+ describe Enumerable do
5
+ describe "#map_hash" do
6
+ it "should map elements to a Hash" do
7
+ [1, 2, 3].map_hash { |i| i ** 2 }.should == {
8
+ 1 => 1,
9
+ 2 => 4,
10
+ 3 => 9
11
+ }
12
+ end
13
+
14
+ it "should not map the same element twice" do
15
+ [1, 2, 2].map_hash { |i| rand }.keys.should =~ [1, 2]
16
+ end
17
+
18
+ it "should set the default_proc of the Hash" do
19
+ hash = [].map_hash { |i| i ** 2 }
20
+
21
+ hash[3].should == 9
22
+ end
23
+ end
24
+ end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
  require 'ronin/extensions/file'
3
3
 
4
+ require 'tempfile'
5
+
4
6
  describe File do
5
7
  subject { File }
6
8
 
@@ -8,6 +10,43 @@ describe File do
8
10
  subject.should respond_to(:escape_path)
9
11
  end
10
12
 
13
+ describe "each_line" do
14
+ let(:lines) { %w[one two three] }
15
+
16
+ before(:all) do
17
+ @file = Tempfile.new('ronin-support')
18
+ @file.puts(*lines)
19
+ @file.close
20
+ end
21
+
22
+ it "should enumerate over each line in the file" do
23
+ File.each_line(@file.path).to_a.should == lines
24
+ end
25
+ end
26
+
27
+ describe "each_row" do
28
+ let(:rows) do
29
+ [
30
+ %w[one two three],
31
+ %w[four five six]
32
+ ]
33
+ end
34
+
35
+ let(:separator) { '|' }
36
+ let(:newline) { "\r\n" }
37
+ let(:lines) { rows.map { |row| row.join(separator) }.join(newline) }
38
+
39
+ before(:all) do
40
+ @file = Tempfile.new('ronin-support')
41
+ @file.write(lines)
42
+ @file.close
43
+ end
44
+
45
+ it "should enumerate over each row from each line" do
46
+ File.each_row(@file.path,separator).to_a.should == rows
47
+ end
48
+ end
49
+
11
50
  describe "escape_path" do
12
51
  it "should remove null-bytes" do
13
52
  File.escape_path("hello\0world\0").should == "helloworld"
@@ -160,10 +160,16 @@ describe IPAddr do
160
160
  let(:bad_ip) { IPAddr.new('0.0.0.0') }
161
161
 
162
162
  describe "#lookup" do
163
+ let(:nameserver) { '4.2.2.1' }
164
+
163
165
  it "should lookup the host-name for an IP" do
164
166
  ip.lookup.should include('localhost')
165
167
  end
166
168
 
169
+ it "may lookup host-names via other nameservers" do
170
+ ip.lookup(nameserver).should be_empty
171
+ end
172
+
167
173
  it "should return an empty Array for unknown IP addresses" do
168
174
  bad_ip.lookup.should be_empty
169
175
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'ronin/extensions/resolv'
3
+
4
+ describe Resolv do
5
+ describe "resolver" do
6
+ let(:nameserver) { '4.2.2.1' }
7
+
8
+ subject { Resolv }
9
+
10
+ it "should create a new Resolv::DNS object if a nameserver is given" do
11
+ subject.resolver(nameserver).should be_kind_of(Resolv::DNS)
12
+ end
13
+
14
+ it "should return the default resolver otherwise" do
15
+ subject.resolver.should == Resolv
16
+ end
17
+ end
18
+ end
@@ -53,14 +53,14 @@ describe Integer do
53
53
  end
54
54
 
55
55
  describe "#format_js" do
56
- let(:js_escaped) { "%26" }
56
+ let(:js_escaped) { '\x26' }
57
57
 
58
58
  it "should JavaScript format ascii bytes" do
59
59
  subject.format_js.should == js_escaped
60
60
  end
61
61
 
62
62
  it "should JavaScript format unicode bytes" do
63
- 0xd556.format_js.should == "%uD556"
63
+ 0xd556.format_js.should == '\uD556'
64
64
  end
65
65
  end
66
66
  end
@@ -94,7 +94,7 @@ describe String do
94
94
  end
95
95
 
96
96
  describe "#format_js" do
97
- let(:js_formatted) { "%6F%6E%65%20%26%20%74%77%6F" }
97
+ let(:js_formatted) { '\x6F\x6E\x65\x20\x26\x20\x74\x77\x6F' }
98
98
 
99
99
  it "should JavaScript escape all characters" do
100
100
  subject.format_js.should == js_formatted
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'ronin/formatting/extensions/sql/string'
3
+
4
+ describe String do
5
+ before(:all) do
6
+ @string = '/etc/passwd'
7
+ @sql_encoded = '0x2f6574632f706173737764'
8
+ @string_with_quotes = %{"O'Brian"}
9
+ end
10
+
11
+ it "should provide the #sql_escape method" do
12
+ @string.should respond_to(:sql_escape)
13
+ end
14
+
15
+ it "should provide the #sql_encode method" do
16
+ @string.should respond_to(:sql_encode)
17
+ end
18
+
19
+ it "should provide the #sql_decode method" do
20
+ @string.should respond_to(:sql_decode)
21
+ end
22
+
23
+ describe "SQL escaping" do
24
+ it "should be able to single-quote escape" do
25
+ @string_with_quotes.sql_escape(:single).should == %{'"O''Brian"'}
26
+ end
27
+
28
+ it "should be able to double-quote escape" do
29
+ @string_with_quotes.sql_escape(:double).should == %{"""O'Brian"""}
30
+ end
31
+ end
32
+
33
+ describe "SQL-hex encoding" do
34
+ it "should be able to be SQL-hex encoded" do
35
+ @string.sql_encode.should == @sql_encoded
36
+ end
37
+
38
+ it "should return an empty String if empty" do
39
+ ''.sql_encode.should == ''
40
+ end
41
+ end
42
+
43
+ describe "SQL-hex decoding" do
44
+ it "should be able to be SQL-hex decoded" do
45
+ encoded = @string.sql_encode
46
+
47
+ encoded.should == @sql_encoded
48
+ encoded.sql_decode.should == @string
49
+ end
50
+
51
+ it "should be able to decode SQL comma-escaping" do
52
+ "'Conan O''Brian'".sql_decode.should == "Conan O'Brian"
53
+ end
54
+ end
55
+ end
@@ -4,6 +4,10 @@ require 'ronin/formatting/text'
4
4
  describe String do
5
5
  subject { "hello" }
6
6
 
7
+ it "should provide String.generate" do
8
+ described_class.should respond_to(:generate)
9
+ end
10
+
7
11
  it "should provide String#format_chars" do
8
12
  should respond_to(:format_chars)
9
13
  end
@@ -24,6 +28,112 @@ describe String do
24
28
  should respond_to(:insert_after)
25
29
  end
26
30
 
31
+ describe "generate" do
32
+ subject { described_class }
33
+
34
+ it "should generate Strings from CharSets" do
35
+ strings = subject.generate(:lowercase_hexadecimal, :numeric).to_a
36
+
37
+ strings.grep(/^[0-9a-f][0-9]$/).should == strings
38
+ end
39
+
40
+ it "should generate Strings from lengths of CharSets" do
41
+ strings = subject.generate([:numeric, 2]).to_a
42
+
43
+ strings.grep(/^[0-9]{2}$/).should == strings
44
+ end
45
+
46
+ it "should generate Strings from varying lengths of CharSets" do
47
+ strings = subject.generate([:numeric, 1..2]).to_a
48
+
49
+ strings.grep(/^[0-9]{1,2}$/).should == strings
50
+ end
51
+
52
+ it "should generate Strings from custom CharSets" do
53
+ strings = subject.generate([%w[a b c], 2]).to_a
54
+
55
+ strings.grep(/^[abc]{2}$/).should == strings
56
+ end
57
+
58
+ it "should generate Strings containing known Strings" do
59
+ strings = subject.generate('foo', [%w[a b c], 2]).to_a
60
+
61
+ strings.grep(/^foo[abc]{2}$/).should == strings
62
+ end
63
+
64
+ it "should raise a TypeError for non String, Symbol, Enumerable CharSets" do
65
+ lambda {
66
+ subject.generate([Object.new, 2]).to_a
67
+ }.should raise_error(TypeError)
68
+ end
69
+
70
+ it "should raise an ArgumentError for unknown CharSets" do
71
+ lambda {
72
+ subject.generate([:foo_bar, 2]).to_a
73
+ }.should raise_error(ArgumentError)
74
+ end
75
+
76
+ it "should raise a TypeError for non Integer,Array,Range lengths" do
77
+ lambda {
78
+ subject.generate([:numeric, 'foo']).to_a
79
+ }.should raise_error(TypeError)
80
+ end
81
+ end
82
+
83
+ describe "#fuzz" do
84
+ subject { 'GET /one/two/three' }
85
+
86
+ it "should match Regexps" do
87
+ fuzzed = subject.fuzz(/GET/ => ['get']).to_a
88
+
89
+ fuzzed.should == ['get /one/two/three']
90
+ end
91
+
92
+ it "should match Strings" do
93
+ fuzzed = subject.fuzz('GET' => ['get']).to_a
94
+
95
+ fuzzed.should == ['get /one/two/three']
96
+ end
97
+
98
+ it "should match Integers" do
99
+ fuzzed = subject.fuzz(0x20 => ["\t"]).to_a
100
+
101
+ fuzzed.should == ["GET\t/one/two/three"]
102
+ end
103
+
104
+ it "should substitute using Procs" do
105
+ fuzzed = subject.fuzz('GET' => [lambda { |s| s.downcase }]).to_a
106
+
107
+ fuzzed.should == ['get /one/two/three']
108
+ end
109
+
110
+ it "should substitute using Integers" do
111
+ fuzzed = subject.fuzz(' ' => [0x09]).to_a
112
+
113
+ fuzzed.should == ["GET\t/one/two/three"]
114
+ end
115
+
116
+ it "should incrementally replace each occurrence" do
117
+ fuzzed = subject.fuzz('/' => ["\n\r"]).to_a
118
+
119
+ fuzzed.should == [
120
+ "GET \n\rone/two/three",
121
+ "GET /one\n\rtwo/three",
122
+ "GET /one/two\n\rthree"
123
+ ]
124
+ end
125
+
126
+ it "should replace each occurrence with each substitution" do
127
+ fuzzed = subject.fuzz('GET' => ["\n\rGET", "G\n\rET", "GET\n\r"]).to_a
128
+
129
+ fuzzed.should == [
130
+ "\n\rGET /one/two/three",
131
+ "G\n\rET /one/two/three",
132
+ "GET\n\r /one/two/three"
133
+ ]
134
+ end
135
+ end
136
+
27
137
  describe "#format_bytes" do
28
138
  it "should format each byte in the String" do
29
139
  subject.format_bytes { |b|
@@ -2,13 +2,19 @@ require 'spec_helper'
2
2
  require 'ronin/network/ssl'
3
3
 
4
4
  describe Network::SSL do
5
- describe 'verify' do
6
- it "should map verify mode names to numeric values" do
7
- subject.verify(:peer).should == OpenSSL::SSL::VERIFY_PEER
5
+ describe 'VERIFY' do
6
+ subject { Network::SSL::VERIFY }
7
+
8
+ it "should map verify mode names to OpenSSL VERIFY_* constants" do
9
+ subject[:peer].should == OpenSSL::SSL::VERIFY_PEER
8
10
  end
9
11
 
10
12
  it "should default to VERIFY_NONE if no verify mode name is given" do
11
- subject.verify.should == OpenSSL::SSL::VERIFY_NONE
13
+ subject[nil].should == OpenSSL::SSL::VERIFY_NONE
14
+ end
15
+
16
+ it "should raise an exception for unknown verify modes" do
17
+ lambda { subject[:foo_bar] }.should raise_error
12
18
  end
13
19
  end
14
20
  end
@@ -0,0 +1,22 @@
1
+ require 'ronin/ui/shell'
2
+
3
+ class TestShell < Ronin::UI::Shell
4
+
5
+ def a_public_method
6
+ end
7
+
8
+ protected
9
+
10
+ def command1
11
+ :command1
12
+ end
13
+
14
+ def command_with_arg(arg)
15
+ arg
16
+ end
17
+
18
+ def command_with_args(*args)
19
+ args
20
+ end
21
+
22
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'ronin/ui/output'
3
+
4
+ describe UI::Output do
5
+ it "should be quiet by default" do
6
+ should be_quiet
7
+ end
8
+
9
+ it "may become verbose" do
10
+ subject.verbose!
11
+
12
+ should be_verbose
13
+ should_not be_quiet
14
+ should_not be_silent
15
+ end
16
+
17
+ it "may become quiet" do
18
+ subject.quiet!
19
+
20
+ should be_quiet
21
+ should_not be_silent
22
+ should_not be_verbose
23
+ end
24
+
25
+ it "may become silent" do
26
+ subject.silent!
27
+
28
+ should be_silent
29
+ should_not be_quiet
30
+ should_not be_verbose
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'ronin/ui/shell'
3
+
4
+ require 'ui/classes/test_shell'
5
+
6
+ describe UI::Shell do
7
+ context "with handler callback" do
8
+ let(:line) { 'one two three' }
9
+
10
+ it "should call the input handler with the shell and input line" do
11
+ lines = []
12
+ shell = described_class.new { |shell,input| lines << input }
13
+
14
+ shell.call(line)
15
+
16
+ lines.should == [line]
17
+ end
18
+ end
19
+
20
+ context "with commands" do
21
+ subject { TestShell.new }
22
+
23
+ describe "#commands" do
24
+ it "should include builtin methods" do
25
+ subject.commands.should include(:help, :exit)
26
+ end
27
+
28
+ it "should include protected methods" do
29
+ subject.commands.should include(:command1, :command_with_arg, :command_with_args)
30
+ end
31
+
32
+ it "should not include public methods" do
33
+ subject.commands.should_not include(:a_public_method)
34
+ end
35
+ end
36
+
37
+ describe "#call" do
38
+ it "should ignore empty lines" do
39
+ subject.call('').should == false
40
+ end
41
+
42
+ it "should ignore white-space lines" do
43
+ subject.call(" \t ").should == false
44
+ end
45
+
46
+ it "should not allow calling the handler method" do
47
+ subject.call('handler').should == false
48
+ end
49
+
50
+ it "should not allow calling unknown commands" do
51
+ subject.call('an_unknown_command').should == false
52
+ end
53
+
54
+ it "should not allow calling unknown commands" do
55
+ subject.call('an_unknown_command').should == false
56
+ end
57
+
58
+ it "should not allow calling public methods" do
59
+ subject.call('a_public_method').should == false
60
+ end
61
+
62
+ it "should allow calling protected methods" do
63
+ subject.call('command1').should == :command1
64
+ end
65
+
66
+ it "should raise an exception when passing invalid number of arguments" do
67
+ lambda {
68
+ subject.call('command_with_arg too many args')
69
+ }.should raise_error(ArgumentError)
70
+ end
71
+
72
+ it "should splat the command arguments to the command method" do
73
+ subject.call('command_with_args one two three').should == [
74
+ 'one', 'two', 'three'
75
+ ]
76
+ end
77
+ end
78
+ end
79
+ end