sockit 0.0.4 → 1.0.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.
data/lib/sockit.rb CHANGED
@@ -18,348 +18,78 @@
18
18
  #
19
19
  ################################################################################
20
20
 
21
- require "socket"
22
- require "resolv"
21
+ require 'socket'
22
+ require 'resolv'
23
+ require 'ostruct'
23
24
 
24
- require "sockit/version"
25
+ require 'sockit/version'
26
+
27
+ require 'sockit/v4/connection'
28
+ require 'sockit/v4/support'
29
+
30
+ require 'sockit/v5/authentication'
31
+ require 'sockit/v5/connection'
32
+ require 'sockit/v5/support'
33
+
34
+ require 'sockit/connection'
35
+ require 'sockit/support'
25
36
 
26
37
  class SockitError < RuntimeError; end
27
38
 
28
39
  module Sockit
29
40
  DEFAULT_CONFIG = {
30
41
  :version => 5,
31
- :ignore => ["127.0.0.1"],
32
- :debug => false
42
+ :ignore => %w( 127.0.0.1 ),
43
+ :debug => false
33
44
  }
34
45
 
35
46
  COLORS = {
36
- :reset => "\e[0m\e[37m",
37
- :red => "\e[1m\e[31m",
38
- :green => "\e[1m\e[32m",
39
- :yellow => "\e[1m\e[33m"
47
+ :reset => "\e[0m\e[37m",
48
+ :red => "\e[1m\e[31m",
49
+ :green => "\e[1m\e[32m",
50
+ :yellow => "\e[1m\e[33m",
51
+ :blue => "\e[1m\e[34m"
40
52
  }
41
53
 
42
- class << self
43
-
44
- def debug(color, message)
45
- timestamp = Time.now.utc
46
- puts("%s%s.%06d %s%s" % [COLORS[color], timestamp.strftime("%Y-%m-%d|%H:%M:%S"), timestamp.usec, message, COLORS[:reset]])
47
- end
48
-
49
- def dump(action, data)
50
- bytes = Array.new
51
- chars = Array.new
52
- for x in 0..(data.length - 1) do
53
- bytes << ("%03d" % data[x].ord)
54
- chars << ("%03s" % (data[x] =~ /^\w+$/ ? data[x].chr : "..."))
55
- end
56
- debug(:red, "#{action.to_s.upcase}: #{bytes.join(" ")}#{COLORS[:reset]}")
57
- debug(:red, "#{action.to_s.upcase}: #{chars.join(" ")}#{COLORS[:reset]}")
58
- end
59
-
60
- # 0x00 = request granted
61
- # 0x01 = general failure
62
- # 0x02 = connection not allowed by ruleset
63
- # 0x03 = network unreachable
64
- # 0x04 = host unreachable
65
- # 0x05 = connection refused by destination host
66
- # 0x06 = TTL expired
67
- # 0x07 = command not supported / protocol error
68
- # 0x08 = address type not supported
69
- def status_message(status_code)
70
- case status_code
71
- when 0x00 then
72
- "Request granted (Code: 0x%02X)" % status_code
73
- when 0x01 then
74
- "General failure (Code: 0x%02X)" % status_code
75
- when 0x02 then
76
- "Connection not allowed by ruleset (Code: 0x%02X)" % status_code
77
- when 0x03 then
78
- "Network unreachable (Code: 0x%02X)" % status_code
79
- when 0x04 then
80
- "Host unreachable (Code: 0x%02X)" % status_code
81
- when 0x05 then
82
- "Connection refused by destination host (Code: 0x%02X)" % status_code
83
- when 0x06 then
84
- "TTL expired (Code: 0x%02X)" % status_code
85
- when 0x07 then
86
- "Command not supported / Protocol error (Code: 0x%02X)" % status_code
87
- when 0x08 then
88
- "Address type not supported (Code: 0x%02X)" % status_code
89
- else
90
- "Unknown (Code: 0x%02X)" % status_code
91
- end
92
- end
93
-
94
- # The authentication methods supported are numbered as follows:
95
- # 0x00: No authentication
96
- # 0x01: GSSAPI[10]
97
- # 0x02: Username/Password[11]
98
- # 0x03-0x7F: methods assigned by IANA[12]
99
- # 0x80-0xFE: methods reserved for private use
100
- def authentication_method(auth_method)
101
- case auth_method
102
- when 0x00 then
103
- "No authentication (Code: 0x%02X)" % auth_method
104
- when 0x01 then
105
- "GSSAPI authentication (Code: 0x%02X)" % auth_method
106
- when 0x02 then
107
- "Username/Password authentication (Code: 0x%02X)" % auth_method
108
- when 0x03..0x7F then
109
- "Method assigned by IANA (Code: 0x%02X)" % auth_method
110
- when 0x80..0xFE then
111
- "Method reserved for private use (Code: 0x%02X)" % auth_method
112
- when 0xFF then
113
- "Unsupported (Code: 0x%02X)" % auth_method
114
- else
115
- "Unknown (Code: 0x%02X)" % auth_method
116
- end
117
- end
118
-
119
- # 0x00 = success
120
- # any other value = failure, connection must be closed
121
- def authentication_status(auth_status)
122
- case auth_status
123
- when 0x00 then
124
- "Authentication success (Code: 0x%02X)" % auth_status
125
- else
126
- "Authentication failure (Code: 0x%02X)" % auth_status
127
- end
128
- end
129
-
130
- end
131
- end
132
-
133
- class TCPSocket
134
-
135
- class << self
136
-
137
- def socks(&block)
138
- @@socks ||= OpenStruct.new(Sockit::DEFAULT_CONFIG)
139
- if block_given?
140
- yield(@@socks)
141
- else
142
- @@socks
143
- end
144
- end
145
-
146
- end
147
-
148
- def socks(&block)
149
- @@socks ||= OpenStruct.new(Sockit::DEFAULT_CONFIG)
54
+ def self.config(&block)
55
+ @@config ||= OpenStruct.new(Sockit::DEFAULT_CONFIG)
150
56
  if block_given?
151
- yield(@@socks)
152
- else
153
- @@socks
154
- end
155
- end
156
-
157
- alias :initialize_tcp :initialize
158
- def initialize(remote_host, remote_port, local_host=nil, local_port=nil)
159
- if (socks.host && socks.port && !socks.ignore.flatten.include?(remote_host))
160
- Sockit.debug(:yellow, "Connecting to SOCKS server #{socks.host}:#{socks.port}")
161
- initialize_tcp(socks.host, socks.port)
162
- (socks.version.to_i == 5) and socks_authenticate
163
- socks.host and socks_connect(remote_host, remote_port)
164
- Sockit.debug(:green, "Connected to #{remote_host}:#{remote_port} via SOCKS server #{socks.host}:#{socks.port}")
57
+ yield(@@config)
165
58
  else
166
- Sockit.debug(:yellow, "Directly connecting to #{remote_host}:#{remote_port}")
167
- initialize_tcp(remote_host, remote_port, local_host, local_port)
168
- Sockit.debug(:green, "Connected to #{remote_host}:#{remote_port}")
59
+ @@config
169
60
  end
170
61
  end
171
62
 
172
- def socks_authenticate
173
- # The authentication methods supported are numbered as follows:
174
- # 0x00: No authentication
175
- # 0x01: GSSAPI[10]
176
- # 0x02: Username/Password[11]
177
- # 0x03-0x7F: methods assigned by IANA[12]
178
- # 0x80-0xFE: methods reserved for private use
179
-
180
- # The initial greeting from the client is
181
- # field 1: SOCKS version number (must be 0x05 for this version)
182
- # field 2: number of authentication methods supported, 1 byte
183
- # field 3: authentication methods, variable length, 1 byte per method supported
184
- if (socks.username || socks.password)
185
- data = Array.new
186
- data << [socks.version, 0x02, 0x02, 0x00].pack("C*")
187
- data = data.flatten.join
188
-
189
- socks.debug and Sockit.debug(:yellow, "Requesting username/password authentication")
190
- socks.debug and Sockit.dump(:write, data)
191
- write(data)
192
- else
193
- data = Array.new
194
- data << [socks.version, 0x01, 0x00].pack("C*")
195
- data = data.flatten.join
196
-
197
- socks.debug and Sockit.debug(:yellow, "Requesting no authentication")
198
- socks.debug and Sockit.dump(:write, data)
199
- write(data)
200
- end
201
-
202
- # The server's choice is communicated:
203
- # field 1: SOCKS version, 1 byte (0x05 for this version)
204
- # field 2: chosen authentication method, 1 byte, or 0xFF if no acceptable methods were offered
205
- socks.debug and Sockit.debug(:yellow, "Waiting for SOCKS authentication reply")
206
- auth_reply = recv(2).unpack("C*")
207
- socks.debug and Sockit.dump(:read, auth_reply)
208
- server_socks_version = auth_reply[0]
209
- server_auth_method = auth_reply[1]
210
-
211
- if server_socks_version != socks.version
212
- raise SockitError, "SOCKS server does not support version #{socks.version}!"
213
- end
214
-
215
- if server_auth_method == 0xFF
216
- raise SockitError, Sockit.authentication_method(server_auth_method)
63
+ def config(&block)
64
+ @@config ||= OpenStruct.new(Sockit::DEFAULT_CONFIG)
65
+ if block_given?
66
+ yield(@@config)
217
67
  else
218
- socks.debug and Sockit.debug(:green, Sockit.authentication_method(server_auth_method))
219
- end
220
-
221
- # The subsequent authentication is method-dependent. Username and password authentication (method 0x02) is described in RFC 1929:
222
- case server_auth_method
223
- when 0x00 then
224
- # No authentication
225
- when 0x01 then
226
- # GSSAPI
227
- raise SockitError, "Authentication method GSSAPI not implemented"
228
- when 0x02 then
229
- # For username/password authentication the client's authentication request is
230
- # field 1: version number, 1 byte (must be 0x01)
231
- # field 2: username length, 1 byte
232
- # field 3: username
233
- # field 4: password length, 1 byte
234
- # field 5: password
235
- data = Array.new
236
- data << [0x01].pack("C*")
237
- data << [socks.username.length.to_i].pack("C*")
238
- data << socks.username
239
- data << [socks.password.length.to_i].pack("C*")
240
- data << socks.password
241
- data = data.flatten.join
242
-
243
- socks.debug and Sockit.debug(:yellow, "Sending username and password")
244
- socks.debug and Sockit.dump(:write, data)
245
- write(data)
246
-
247
- # Server response for username/password authentication:
248
- # field 1: version, 1 byte
249
- # field 2: status code, 1 byte.
250
- # 0x00 = success
251
- # any other value = failure, connection must be closed
252
- socks.debug and Sockit.debug(:yellow, "Waiting for SOCKS authentication reply")
253
- auth_reply = recv(2).unpack("C*")
254
- socks.debug and Sockit.dump(:read, auth_reply)
255
- version = auth_reply[0]
256
- status_code = auth_reply[1]
257
-
258
- if status_code == 0x00
259
- socks.debug and Sockit.debug(:green, Sockit.authentication_status(status_code))
260
- else
261
- raise SockitError, Sockit.authentication_status(status_code)
262
- end
68
+ @@config
263
69
  end
264
-
265
70
  end
266
71
 
267
- def socks_connect(remote_host, remote_port)
268
- # The client's connection request is
269
- # field 1: SOCKS version number, 1 byte (must be 0x05 for this version)
270
- # field 2: command code, 1 byte:
271
- # 0x01 = establish a TCP/IP stream connection
272
- # 0x02 = establish a TCP/IP port binding
273
- # 0x03 = associate a UDP port
274
- # field 3: reserved, must be 0x00
275
- # field 4: address type, 1 byte:
276
- # 0x01 = IPv4 address
277
- # 0x03 = Domain name
278
- # 0x04 = IPv6 address
279
- # field 5: destination address of
280
- # 4 bytes for IPv4 address
281
- # 1 byte of name length followed by the name for Domain name
282
- # 16 bytes for IPv6 address
283
- # field 6: port number in a network byte order, 2 bytes
284
- data = Array.new
285
- data << [ socks.version.to_i, 0x01, 0x00 ].pack("C*")
72
+ extend Sockit::V5::Authentication
73
+ extend Sockit::V5::Connection
74
+ extend Sockit::V5::Support
286
75
 
287
- # when doing proxy mode on SS5; we seemingly need to resolve all names first.
288
- if remote_host !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
289
- remote_host = Resolv::DNS.new.getaddress(remote_host).to_s
290
- end
76
+ extend Sockit::V4::Connection
77
+ extend Sockit::V4::Support
291
78
 
292
- if remote_host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
293
- data << [0x01].pack("C*")
294
- data << [$1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*")
295
- elsif remote_host =~ /^[:0-9a-f]+$/
296
- data << [0x04].pack("C*")
297
- data << [$1].pack("C*")
298
- else
299
- data << [0x03].pack("C*")
300
- data << [remote_host.length.to_i].pack("C*")
301
- data << remote_host
302
- end
303
- data << [remote_port].pack("n")
304
- data = data.flatten.join
305
-
306
- Sockit.debug(:yellow, "Requesting SOCKS connection to #{remote_host}:#{remote_port}")
307
- socks.debug and Sockit.dump(:write, data)
308
- write(data)
79
+ extend Sockit::Connection
80
+ extend Sockit::Support
81
+ end
309
82
 
310
- # Server response:
311
- # field 1: SOCKS protocol version, 1 byte (0x05 for this version)
312
- # field 2: status, 1 byte:
313
- # 0x00 = request granted
314
- # 0x01 = general failure
315
- # 0x02 = connection not allowed by ruleset
316
- # 0x03 = network unreachable
317
- # 0x04 = host unreachable
318
- # 0x05 = connection refused by destination host
319
- # 0x06 = TTL expired
320
- # 0x07 = command not supported / protocol error
321
- # 0x08 = address type not supported
322
- # field 3: reserved, must be 0x00
323
- # field 4: address type, 1 byte:
324
- # 0x01 = IPv4 address
325
- # 0x03 = Domain name
326
- # 0x04 = IPv6 address
327
- # field 5: destination address of
328
- # 4 bytes for IPv4 address
329
- # 1 byte of name length followed by the name for Domain name
330
- # 16 bytes for IPv6 address
331
- # field 6: network byte order port number, 2 bytes
332
- socks.debug and Sockit.debug(:yellow, "Waiting for SOCKS connection reply")
333
- packet = recv(4).unpack("C*")
334
- socks.debug and Sockit.dump(:read, packet)
335
- socks_version = packet[0]
336
- status_code = packet[1]
337
- reserved = packet[2]
338
- address_type = packet[3]
83
+ class TCPSocket
339
84
 
340
- if status_code == 0x00
341
- socks.debug and Sockit.debug(:green, Sockit.status_message(status_code))
85
+ alias :initialize_tcp :initialize
86
+ def initialize(remote_host, remote_port, local_host=nil, local_port=nil)
87
+ if Sockit.connect_via_socks?(remote_host)
88
+ initialize_tcp(Sockit.config.host, Sockit.config.port)
89
+ Sockit.perform_v5_authenticate(self) if Sockit.is_socks_v5?
90
+ Sockit.connect(self, remote_host, remote_port)
342
91
  else
343
- raise SockitError, Sockit.status_message(status_code)
344
- end
345
-
346
- address_length = case address_type
347
- when 0x01 then
348
- 4
349
- when 0x03 then
350
- data = recv(1).unpack("C*")
351
- socks.debug and Sockit.dump(:read, data)
352
- data[0]
353
- when 0x04 then
354
- 16
92
+ Sockit.direct_connect(self, remote_host, remote_port, local_host, local_port)
355
93
  end
356
- address = recv(address_length).unpack("C*")
357
- socks.debug and Sockit.dump(:read, address)
358
-
359
- port = recv(2).unpack("n")
360
- socks.debug and Sockit.dump(:read, port)
361
-
362
- socks.debug and Sockit.debug(:green, [address, port].inspect)
363
94
  end
364
-
365
95
  end
data/sockit.gemspec CHANGED
@@ -21,22 +21,32 @@
21
21
  # -*- encoding: utf-8 -*-
22
22
  require File.expand_path('../lib/sockit/version', __FILE__)
23
23
 
24
- Gem::Specification.new do |gem|
25
- gem.authors = ["Zachary Patten"]
26
- gem.email = ["zachary@jovelabs.com"]
27
- gem.description = %q{Transparent SOCKS 5 support for TCPSocket}
28
- gem.summary = %q{Transparent SOCKS 5 support for TCPSocket}
29
- gem.homepage = "https://github.com/zpatten/sockit"
24
+ Gem::Specification.new do |spec|
25
+ spec.name = "sockit"
26
+ spec.version = Sockit::VERSION
27
+ spec.authors = %(Zachary Patten)
28
+ spec.email = [ %(zachary AT jovelabs DOT com) ]
29
+ spec.description = %(Transparent SOCKS v4 and SOCKS v5 support for TCPSocket)
30
+ spec.summary = %(Transparent SOCKS v4 and SOCKS v5 support for TCPSocket)
31
+ spec.homepage = %(https://github.com/zpatten/sockit)
32
+ spec.license = "Apache 2.0"
30
33
 
31
- gem.files = `git ls-files`.split($\)
32
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
33
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
34
- gem.name = "sockit"
35
- gem.require_paths = ["lib"]
36
- gem.version = Sockit::VERSION
34
+ spec.files = `git ls-files`.split($/)
35
+ spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
36
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
37
+ spec.require_paths = ["lib"]
37
38
 
38
- gem.add_development_dependency("pry")
39
- gem.add_development_dependency("rspec")
40
- gem.add_development_dependency("yard")
41
- gem.add_development_dependency("redcarpet")
39
+ spec.required_ruby_version = '>= 2.0.0'
40
+
41
+ spec.add_development_dependency("pry")
42
+ spec.add_development_dependency("rake")
43
+ spec.add_development_dependency("rspec")
44
+ spec.add_development_dependency("yard")
45
+ spec.add_development_dependency("redcarpet")
46
+ spec.add_development_dependency("coveralls")
47
+ spec.add_development_dependency("yarjuf")
48
+ spec.add_development_dependency("simplecov-rcov")
49
+
50
+ spec.add_development_dependency("travis")
51
+ spec.add_development_dependency("websocket-native")
42
52
  end
@@ -0,0 +1,211 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary AT jovelabs DOT com>
4
+ # Copyright: Copyright (c) Zachary Patten
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ require "spec_helper"
22
+
23
+ describe Sockit do
24
+
25
+ subject { Sockit }
26
+
27
+ describe "class" do
28
+
29
+ it "should be Sockit" do
30
+ expect(subject).to be Sockit
31
+ end
32
+
33
+ it "should have a default config" do
34
+ expect(subject.config.debug).to eq false
35
+ expect(subject.config.username).to eq nil
36
+ expect(subject.config.password).to eq nil
37
+ expect(subject.config.host).to eq nil
38
+ expect(subject.config.port).to eq nil
39
+ end
40
+
41
+ it "should report as configured when it is" do
42
+ Sockit.config.version = 5
43
+ Sockit.config.host = "127.0.0.1"
44
+ Sockit.config.port = "1080"
45
+
46
+ expect(Sockit.is_configured?).to eq true
47
+ end
48
+
49
+ it "should not report as configured when it is not" do
50
+ Sockit.config.version = 5
51
+ Sockit.config.host = "127.0.0.1"
52
+ Sockit.config.port = ""
53
+
54
+ expect(Sockit.is_configured?).to eq false
55
+ end
56
+
57
+ it "should report as SOCKS v5 when configured as such" do
58
+ Sockit.config.version = 5
59
+ Sockit.config.host = "127.0.0.1"
60
+ Sockit.config.port = "1080"
61
+
62
+ expect(Sockit.is_socks_v5?).to eq true
63
+ end
64
+
65
+ it "should not report as SOCKS v5 when configured as such" do
66
+ Sockit.config.version = 5
67
+ Sockit.config.host = ""
68
+ Sockit.config.port = "1080"
69
+
70
+ expect(Sockit.is_socks_v5?).to eq false
71
+ end
72
+
73
+ it "should report as SOCKS v4 when configured as such" do
74
+ Sockit.config.version = 4
75
+ Sockit.config.host = "127.0.0.1"
76
+ Sockit.config.port = "1080"
77
+
78
+ expect(Sockit.is_socks_v4?).to eq true
79
+ end
80
+
81
+ it "should not report as SOCKS v4 when configured as such" do
82
+ Sockit.config.version = 4
83
+ Sockit.config.host = ""
84
+ Sockit.config.port = "1080"
85
+
86
+ expect(Sockit.is_socks_v4?).to eq false
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ describe TCPSocket do
94
+
95
+ describe "connections" do
96
+
97
+ describe "direct" do
98
+
99
+ it "should allow a direct connection to github" do
100
+ Sockit.config do |config|
101
+ config.version = nil
102
+ config.host = nil
103
+ config.port = nil
104
+ end
105
+
106
+ socket = TCPSocket.new('github.com', '22')
107
+ data = socket.gets
108
+ expect(data).to match(/SSH/)
109
+ end
110
+
111
+ end
112
+
113
+ describe "SOCKS v5" do
114
+
115
+ it "should allow a SOCKS v4 connection to github (no debug/no auth)" do
116
+ Sockit.config do |config|
117
+ config.debug = false
118
+ config.version = 4
119
+ config.host = "127.0.0.1"
120
+ config.port = "1080"
121
+ config.username = nil
122
+ config.password = nil
123
+ end
124
+
125
+ socket = TCPSocket.new('github.com', '22')
126
+ data = socket.gets
127
+ expect(data).to match(/SSH/)
128
+ end
129
+
130
+ it "should allow a SOCKS v5 connection to github (no debug/no auth)" do
131
+ Sockit.config do |config|
132
+ config.debug = false
133
+ config.version = 5
134
+ config.host = "127.0.0.1"
135
+ config.port = "1080"
136
+ config.username = nil
137
+ config.password = nil
138
+ end
139
+
140
+ socket = TCPSocket.new('github.com', '22')
141
+ data = socket.gets
142
+ expect(data).to match(/SSH/)
143
+ end
144
+
145
+ it "should allow a SOCKS v5 connection to github (debug/no auth)" do
146
+ $stdout = File.open('/dev/null', 'w')
147
+
148
+ Sockit.config do |config|
149
+ config.debug = true
150
+ config.version = 5
151
+ config.host = "127.0.0.1"
152
+ config.port = "1080"
153
+ config.username = nil
154
+ config.password = nil
155
+ end
156
+
157
+ socket = TCPSocket.new('github.com', '22')
158
+ data = socket.gets
159
+ expect(data).to match(/SSH/)
160
+ end
161
+
162
+ it "should allow a SOCKS v5 connection to github (no debug/auth)" do
163
+ Sockit.config do |config|
164
+ config.debug = false
165
+ config.version = 5
166
+ config.host = "127.0.0.1"
167
+ config.port = "1081"
168
+ config.username = "root"
169
+ config.password = "none"
170
+ end
171
+
172
+ socket = TCPSocket.new('github.com', '22')
173
+ data = socket.gets
174
+ expect(data).to match(/SSH/)
175
+ end
176
+
177
+ it "should allow a SOCKS v5 connection to github (debug/auth)" do
178
+ $stdout = File.open('/dev/null', 'w')
179
+
180
+ Sockit.config do |config|
181
+ config.debug = true
182
+ config.version = 5
183
+ config.host = "127.0.0.1"
184
+ config.port = "1081"
185
+ config.username = "root"
186
+ config.password = "none"
187
+ end
188
+
189
+ socket = TCPSocket.new('github.com', '22')
190
+ data = socket.gets
191
+ expect(data).to match(/SSH/)
192
+ end
193
+
194
+ it "should throw an exception if we use bad credentials (no debug/auth)" do
195
+ Sockit.config do |config|
196
+ config.debug = false
197
+ config.version = 5
198
+ config.host = "127.0.0.1"
199
+ config.port = "1081"
200
+ config.username = "root"
201
+ config.password = "blargh"
202
+ end
203
+
204
+ expect { TCPSocket.new('github.com', '22') }.to raise_exception(SockitError)
205
+ end
206
+
207
+ end
208
+
209
+ end
210
+
211
+ end
@@ -0,0 +1,43 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary AT jovelabs DOT com>
4
+ # Copyright: Copyright (c) Zachary Patten
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+ require 'simplecov'
21
+ require 'simplecov-rcov'
22
+ ################################################################################
23
+ require 'coveralls'
24
+ Coveralls.wear!
25
+ ################################################################################
26
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
27
+ [
28
+ SimpleCov::Formatter::HTMLFormatter,
29
+ SimpleCov::Formatter::RcovFormatter,
30
+ Coveralls::SimpleCov::Formatter
31
+ ]
32
+ )
33
+ SimpleCov.start
34
+ ################################################################################
35
+ require 'yarjuf'
36
+ ################################################################################
37
+
38
+ require 'tempfile'
39
+ require 'sockit'
40
+
41
+ ENV['LOG_LEVEL'] = "DEBUG"
42
+
43
+ ################################################################################