net-ssh 0.5.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 (179) hide show
  1. data/doc/LICENSE-BSD +27 -0
  2. data/doc/LICENSE-GPL +280 -0
  3. data/doc/LICENSE-RUBY +56 -0
  4. data/doc/README +13 -0
  5. data/doc/manual-html/chapter-1.html +333 -0
  6. data/doc/manual-html/chapter-2.html +455 -0
  7. data/doc/manual-html/chapter-3.html +413 -0
  8. data/doc/manual-html/chapter-4.html +353 -0
  9. data/doc/manual-html/chapter-5.html +393 -0
  10. data/doc/manual-html/chapter-6.html +296 -0
  11. data/doc/manual-html/index.html +217 -0
  12. data/doc/manual-html/manual.css +192 -0
  13. data/doc/manual/chapter.erb +18 -0
  14. data/doc/manual/example.erb +18 -0
  15. data/doc/manual/index.erb +29 -0
  16. data/doc/manual/manual.css +192 -0
  17. data/doc/manual/manual.rb +240 -0
  18. data/doc/manual/manual.yml +67 -0
  19. data/doc/manual/page.erb +87 -0
  20. data/doc/manual/parts/channels_callbacks.txt +32 -0
  21. data/doc/manual/parts/channels_loop.txt +14 -0
  22. data/doc/manual/parts/channels_open.txt +20 -0
  23. data/doc/manual/parts/channels_operations.txt +15 -0
  24. data/doc/manual/parts/channels_types.txt +3 -0
  25. data/doc/manual/parts/channels_what_are.txt +7 -0
  26. data/doc/manual/parts/exec_channels.txt +28 -0
  27. data/doc/manual/parts/exec_open.txt +51 -0
  28. data/doc/manual/parts/exec_popen3.txt +35 -0
  29. data/doc/manual/parts/forward_direct.txt +37 -0
  30. data/doc/manual/parts/forward_handlers.txt +16 -0
  31. data/doc/manual/parts/forward_intro.txt +18 -0
  32. data/doc/manual/parts/forward_local.txt +18 -0
  33. data/doc/manual/parts/forward_remote.txt +14 -0
  34. data/doc/manual/parts/intro_author.txt +1 -0
  35. data/doc/manual/parts/intro_getting.txt +39 -0
  36. data/doc/manual/parts/intro_license.txt +6 -0
  37. data/doc/manual/parts/intro_support.txt +7 -0
  38. data/doc/manual/parts/intro_what_is.txt +7 -0
  39. data/doc/manual/parts/intro_what_is_not.txt +3 -0
  40. data/doc/manual/parts/proxy_http.txt +52 -0
  41. data/doc/manual/parts/proxy_intro.txt +1 -0
  42. data/doc/manual/parts/proxy_socks.txt +23 -0
  43. data/doc/manual/parts/session_key.txt +66 -0
  44. data/doc/manual/parts/session_options.txt +42 -0
  45. data/doc/manual/parts/session_session.txt +14 -0
  46. data/doc/manual/parts/session_start.txt +49 -0
  47. data/doc/manual/tutorial.erb +30 -0
  48. data/examples/channel-demo.rb +81 -0
  49. data/examples/port-forward.rb +51 -0
  50. data/examples/process-demo.rb +91 -0
  51. data/examples/remote-net-port-forward.rb +45 -0
  52. data/examples/remote-port-forward.rb +80 -0
  53. data/examples/tail-demo.rb +49 -0
  54. data/lib/net/ssh.rb +52 -0
  55. data/lib/net/ssh/connection/channel.rb +411 -0
  56. data/lib/net/ssh/connection/constants.rb +47 -0
  57. data/lib/net/ssh/connection/driver.rb +343 -0
  58. data/lib/net/ssh/connection/services.rb +72 -0
  59. data/lib/net/ssh/connection/term.rb +90 -0
  60. data/lib/net/ssh/errors.rb +27 -0
  61. data/lib/net/ssh/proxy/errors.rb +34 -0
  62. data/lib/net/ssh/proxy/http.rb +126 -0
  63. data/lib/net/ssh/proxy/socks4.rb +83 -0
  64. data/lib/net/ssh/proxy/socks5.rb +160 -0
  65. data/lib/net/ssh/service/forward/driver.rb +319 -0
  66. data/lib/net/ssh/service/forward/local-network-handler.rb +74 -0
  67. data/lib/net/ssh/service/forward/remote-network-handler.rb +81 -0
  68. data/lib/net/ssh/service/forward/services.rb +76 -0
  69. data/lib/net/ssh/service/process/driver.rb +153 -0
  70. data/lib/net/ssh/service/process/open.rb +193 -0
  71. data/lib/net/ssh/service/process/popen3.rb +160 -0
  72. data/lib/net/ssh/service/process/services.rb +66 -0
  73. data/lib/net/ssh/service/services.rb +44 -0
  74. data/lib/net/ssh/session.rb +242 -0
  75. data/lib/net/ssh/transport/algorithm-negotiator.rb +267 -0
  76. data/lib/net/ssh/transport/compress/compressor.rb +53 -0
  77. data/lib/net/ssh/transport/compress/decompressor.rb +53 -0
  78. data/lib/net/ssh/transport/compress/none-compressor.rb +39 -0
  79. data/lib/net/ssh/transport/compress/none-decompressor.rb +39 -0
  80. data/lib/net/ssh/transport/compress/services.rb +68 -0
  81. data/lib/net/ssh/transport/compress/zlib-compressor.rb +60 -0
  82. data/lib/net/ssh/transport/compress/zlib-decompressor.rb +52 -0
  83. data/lib/net/ssh/transport/constants.rb +66 -0
  84. data/lib/net/ssh/transport/errors.rb +47 -0
  85. data/lib/net/ssh/transport/identity-cipher.rb +61 -0
  86. data/lib/net/ssh/transport/kex/dh-gex.rb +106 -0
  87. data/lib/net/ssh/transport/kex/dh.rb +231 -0
  88. data/lib/net/ssh/transport/kex/services.rb +60 -0
  89. data/lib/net/ssh/transport/ossl/buffer-factory.rb +52 -0
  90. data/lib/net/ssh/transport/ossl/buffer.rb +87 -0
  91. data/lib/net/ssh/transport/ossl/cipher-factory.rb +98 -0
  92. data/lib/net/ssh/transport/ossl/digest-factory.rb +51 -0
  93. data/lib/net/ssh/transport/ossl/hmac-factory.rb +71 -0
  94. data/lib/net/ssh/transport/ossl/hmac/hmac.rb +62 -0
  95. data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +44 -0
  96. data/lib/net/ssh/transport/ossl/hmac/md5.rb +46 -0
  97. data/lib/net/ssh/transport/ossl/hmac/none.rb +46 -0
  98. data/lib/net/ssh/transport/ossl/hmac/services.rb +68 -0
  99. data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +44 -0
  100. data/lib/net/ssh/transport/ossl/hmac/sha1.rb +45 -0
  101. data/lib/net/ssh/transport/ossl/key-factory.rb +113 -0
  102. data/lib/net/ssh/transport/ossl/services.rb +149 -0
  103. data/lib/net/ssh/transport/packet-stream.rb +210 -0
  104. data/lib/net/ssh/transport/services.rb +146 -0
  105. data/lib/net/ssh/transport/session.rb +296 -0
  106. data/lib/net/ssh/transport/version-negotiator.rb +73 -0
  107. data/lib/net/ssh/userauth/agent.rb +218 -0
  108. data/lib/net/ssh/userauth/constants.rb +35 -0
  109. data/lib/net/ssh/userauth/driver.rb +176 -0
  110. data/lib/net/ssh/userauth/methods/hostbased.rb +119 -0
  111. data/lib/net/ssh/userauth/methods/password.rb +70 -0
  112. data/lib/net/ssh/userauth/methods/publickey.rb +137 -0
  113. data/lib/net/ssh/userauth/methods/services.rb +63 -0
  114. data/lib/net/ssh/userauth/services.rb +126 -0
  115. data/lib/net/ssh/userauth/userkeys.rb +258 -0
  116. data/lib/net/ssh/util/buffer.rb +274 -0
  117. data/lib/net/ssh/util/openssl.rb +146 -0
  118. data/lib/net/ssh/util/prompter.rb +73 -0
  119. data/lib/net/ssh/version.rb +29 -0
  120. data/test/ALL-TESTS.rb +21 -0
  121. data/test/connection/tc_channel.rb +136 -0
  122. data/test/connection/tc_driver.rb +287 -0
  123. data/test/connection/tc_integration.rb +85 -0
  124. data/test/proxy/tc_http.rb +209 -0
  125. data/test/proxy/tc_socks4.rb +148 -0
  126. data/test/proxy/tc_socks5.rb +214 -0
  127. data/test/service/forward/tc_driver.rb +289 -0
  128. data/test/service/forward/tc_local_network_handler.rb +123 -0
  129. data/test/service/forward/tc_remote_network_handler.rb +108 -0
  130. data/test/service/process/tc_driver.rb +79 -0
  131. data/test/service/process/tc_integration.rb +117 -0
  132. data/test/service/process/tc_open.rb +179 -0
  133. data/test/service/process/tc_popen3.rb +164 -0
  134. data/test/tc_integration.rb +79 -0
  135. data/test/transport/compress/tc_none_compress.rb +41 -0
  136. data/test/transport/compress/tc_none_decompress.rb +45 -0
  137. data/test/transport/compress/tc_zlib_compress.rb +61 -0
  138. data/test/transport/compress/tc_zlib_decompress.rb +48 -0
  139. data/test/transport/kex/tc_dh.rb +304 -0
  140. data/test/transport/kex/tc_dh_gex.rb +70 -0
  141. data/test/transport/ossl/fixtures/dsa-encrypted +15 -0
  142. data/test/transport/ossl/fixtures/dsa-encrypted-bad +15 -0
  143. data/test/transport/ossl/fixtures/dsa-unencrypted +12 -0
  144. data/test/transport/ossl/fixtures/dsa-unencrypted-bad +12 -0
  145. data/test/transport/ossl/fixtures/dsa-unencrypted.pub +1 -0
  146. data/test/transport/ossl/fixtures/not-a-private-key +4 -0
  147. data/test/transport/ossl/fixtures/not-supported +2 -0
  148. data/test/transport/ossl/fixtures/rsa-encrypted +18 -0
  149. data/test/transport/ossl/fixtures/rsa-encrypted-bad +18 -0
  150. data/test/transport/ossl/fixtures/rsa-unencrypted +15 -0
  151. data/test/transport/ossl/fixtures/rsa-unencrypted-bad +15 -0
  152. data/test/transport/ossl/fixtures/rsa-unencrypted.pub +1 -0
  153. data/test/transport/ossl/hmac/tc_hmac.rb +58 -0
  154. data/test/transport/ossl/hmac/tc_md5.rb +50 -0
  155. data/test/transport/ossl/hmac/tc_md5_96.rb +50 -0
  156. data/test/transport/ossl/hmac/tc_none.rb +50 -0
  157. data/test/transport/ossl/hmac/tc_sha1.rb +50 -0
  158. data/test/transport/ossl/hmac/tc_sha1_96.rb +50 -0
  159. data/test/transport/ossl/tc_buffer.rb +97 -0
  160. data/test/transport/ossl/tc_buffer_factory.rb +67 -0
  161. data/test/transport/ossl/tc_cipher_factory.rb +84 -0
  162. data/test/transport/ossl/tc_digest_factory.rb +39 -0
  163. data/test/transport/ossl/tc_hmac_factory.rb +72 -0
  164. data/test/transport/ossl/tc_key_factory.rb +199 -0
  165. data/test/transport/tc_algorithm_negotiator.rb +169 -0
  166. data/test/transport/tc_identity_cipher.rb +52 -0
  167. data/test/transport/tc_integration.rb +110 -0
  168. data/test/transport/tc_packet_stream.rb +183 -0
  169. data/test/transport/tc_session.rb +283 -0
  170. data/test/transport/tc_version_negotiator.rb +86 -0
  171. data/test/userauth/methods/tc_hostbased.rb +136 -0
  172. data/test/userauth/methods/tc_password.rb +89 -0
  173. data/test/userauth/methods/tc_publickey.rb +167 -0
  174. data/test/userauth/tc_agent.rb +223 -0
  175. data/test/userauth/tc_driver.rb +190 -0
  176. data/test/userauth/tc_integration.rb +81 -0
  177. data/test/userauth/tc_userkeys.rb +265 -0
  178. data/test/util/tc_buffer.rb +217 -0
  179. metadata +256 -0
@@ -0,0 +1,319 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/ssh/errors'
18
+
19
+ module Net
20
+ module SSH
21
+ module Service
22
+ module Forward
23
+
24
+ # The Forward::Driver class manages ports that have been forwarded.
25
+ # It will open a socket on each local port and listen for local
26
+ # connections, forwarding those connections over an SSH channel to
27
+ # the other end.
28
+ class Driver
29
+
30
+ # The number of direct (local-to-remote) channels that have been
31
+ # opened.
32
+ attr_reader :direct_channel_count
33
+
34
+ # The number of direct (local-to-remote) channels that are currently
35
+ # open.
36
+ attr_reader :open_direct_channel_count
37
+
38
+ # Create a new Driver instance.
39
+ def initialize( connection, buffers, log, handlers )
40
+ @connection = connection
41
+ @buffers = buffers
42
+ @log = log
43
+ @handlers = handlers
44
+
45
+ @local_forwards = Hash.new
46
+ @remote_forwards = Hash.new
47
+ @direct_channel_count = 0
48
+ @open_direct_channel_count = 0
49
+
50
+ @connection.add_channel_open_handler(
51
+ "forwarded-tcpip", &method(:do_open_channel) )
52
+ end
53
+
54
+ # Open a direct "tcpip" channel to the remote machine, which will then
55
+ # forward the connection to the given remote-host and remote-port. The
56
+ # connection will appear to have come from the given port on the local
57
+ # machine.
58
+ #
59
+ # The handler object may respond to the following messages, in order
60
+ # to respond to requests over the channel:
61
+ #
62
+ # * on_receive( channel, data ): when data is received over the
63
+ # channel (from the remote machine), this method will be invoked.
64
+ # * on_eof( channel ): when the remote machine will no longer send
65
+ # data, this method will be invoked. The client may continue to send
66
+ # data over the channel, however.
67
+ # * on_close( channel ): when the channel has been closed and is no
68
+ # longer valid for passing data, this method will be invoked.
69
+ # * confirm( channel, local_port, remote_host, remote_port, *data ):
70
+ # when the channel has been opened and the remote machine has
71
+ # confirmed it, this method will be invoked. The +data+ parameters
72
+ # are the same parameters as were passed to the direct_channel
73
+ # method.
74
+ # * process( channel ): invoked after the channel is confirmed, to
75
+ # process the channel. It is invoked in a new Thread.
76
+ #
77
+ # Only the +process+ method is required--the others will only be
78
+ # invoked if the handler responds to them.
79
+ def direct_channel( local_port, remote_host, remote_port,
80
+ handler, *data )
81
+ # begin
82
+ writer = @buffers.writer
83
+ writer.write_string remote_host
84
+ writer.write_long remote_port.to_i
85
+ writer.write_string "127.0.0.1"
86
+ writer.write_long local_port.to_i
87
+
88
+ @direct_channel_count += 1
89
+ @open_direct_channel_count += 1
90
+
91
+ if @log.debug?
92
+ @log.debug "opening direct channel for " +
93
+ "#{local_port}:#{remote_host}:#{remote_port}"
94
+ end
95
+
96
+ c = @connection.open_channel( 'direct-tcpip', writer ) do |channel|
97
+ if @log.debug?
98
+ @log.debug "direct channel confirmed for " +
99
+ "#{local_port}:#{remote_host}:#{remote_port}"
100
+ end
101
+
102
+ if handler.respond_to?( :on_receive )
103
+ channel.on_data( &handler.method(:on_receive) )
104
+ end
105
+
106
+ if handler.respond_to?( :on_eof )
107
+ channel.on_eof( &handler.method(:on_eof) )
108
+ end
109
+
110
+ channel.on_close do |ch|
111
+ @open_direct_channel_count -= 1
112
+ handler.on_close( ch ) if handler.respond_to?( :on_close )
113
+ end
114
+
115
+ if handler.respond_to?( :confirm )
116
+ handler.confirm( channel, local_port, remote_host,
117
+ remote_port, *data )
118
+ end
119
+
120
+ if handler.respond_to?( :process )
121
+ Thread.new { handler.process( channel ) }
122
+ end
123
+ end
124
+
125
+ c.on_confirm_failed do |channel, code,desc,lang|
126
+ raise Net::SSH::Exception, "could not open direct channel for " +
127
+ "#{local_port}:#{remote_host}:#{remote_port} (#{code}, #{desc})"
128
+ end
129
+
130
+ nil
131
+ end
132
+
133
+ # Forward connections on the given local port, to the given remote
134
+ # host and remote port.
135
+ #
136
+ # This method will return immediately, forwarding the connections
137
+ # asynchronously.
138
+ def local( *args )
139
+ if args.length < 3 || args.length > 4
140
+ raise ArgumentError,
141
+ "expected 3 or 4 parameters, got #{args.length+1}"
142
+ end
143
+
144
+ bind_address = "127.0.0.1"
145
+ bind_address = args.shift if args.first.is_a? String
146
+
147
+ local_port = args.shift.to_i
148
+ remote_host = args.shift
149
+ remote_port = args.shift
150
+
151
+ Thread.new do
152
+ begin
153
+ key = [ local_port.to_i, bind_address ]
154
+
155
+ if @log.debug?
156
+ @log.debug "starting local forwarding server on " +
157
+ key.inspect
158
+ end
159
+
160
+ socket = TCPServer.new( bind_address, local_port )
161
+
162
+ @local_forwards[ key ] = { :thread => Thread.current,
163
+ :socket => socket }
164
+
165
+ if @log.debug?
166
+ @log.debug "listening for connections on #{key.inspect}"
167
+ end
168
+
169
+ while ( client = socket.accept )
170
+ @log.debug "#{key.inspect} received connection" if @log.debug?
171
+
172
+ direct_channel( local_port,
173
+ remote_host,
174
+ remote_port,
175
+ @handlers[:local].call( client ) )
176
+ end
177
+
178
+ rescue Exception => e
179
+ @log.error "error forwarding local connection: " +
180
+ "#{e.class} (#{e.message})\n " +
181
+ e.backtrace.join( "\n " )
182
+ end
183
+ end
184
+ end
185
+
186
+ # Initiate forwarding of the given remote port on the connected host.
187
+ # Forwarded packets will be passed to the given block as they are
188
+ # recieved. The remote-host represents the address that should be
189
+ # bound on the remote host, and defaults to '127.0.0.1'.
190
+ def remote( handler, remote_port, remote_host="127.0.0.1" )
191
+ if @remote_forwards[ remote_port ]
192
+ raise Net::SSH::Exception, "#{remote_port} is already forwarded"
193
+ end
194
+
195
+ writer = @buffers.writer
196
+ writer.write_string remote_host
197
+ writer.write_long remote_port.to_i
198
+
199
+ @connection.global_request( "tcpip-forward", writer
200
+ ) do |success, response|
201
+ if success
202
+ remote_port = response.read_long if remote_port == 0
203
+ @remote_forwards[ remote_port ] = { :port => remote_port,
204
+ :handler => handler }
205
+ handler.setup( remote_port ) if handler.respond_to?( :setup )
206
+ else
207
+ msg = "remote port #{remote_port} could not be forwarded " +
208
+ "to local host"
209
+ if handler.respond_to?( :error )
210
+ handler.error( msg )
211
+ else
212
+ raise Net::SSH::Exception, msg
213
+ end
214
+ end
215
+ end
216
+ end
217
+
218
+ # A convenience method for setting up a forwarded connection from the
219
+ # given port on the remote host, to the given host and port (local).
220
+ def remote_to( port, host, remote_port, remote_host="127.0.0.1" )
221
+ # begin
222
+ remote( @handlers[:remote].call( port, host ), remote_port,
223
+ remote_host )
224
+ end
225
+
226
+ # Return an array of the active forwarded local connections. Each
227
+ # element of the array is another array containing the local port, and
228
+ # the remote host and port of the connection.
229
+ def active_locals
230
+ @local_forwards.keys
231
+ end
232
+
233
+ # Return an array of the active forwarded remote connections. Each
234
+ # element of the array is an integer representing the port number of
235
+ # the remote host that is being forwarded to the local client.
236
+ def active_remotes
237
+ @remote_forwards.keys
238
+ end
239
+
240
+ # Cease forwarding connections from the given local port (and
241
+ # interface). The parameters must match those given to a prior call to
242
+ # #local. Existing forwarded connections are not affected by
243
+ # this call, but no more connections will be accepted on the local
244
+ # port.
245
+ def cancel_local( local_port, bind_address="127.0.0.1" )
246
+ key = [ local_port.to_i, bind_address ]
247
+
248
+ forward = @local_forwards[ key ]
249
+ @local_forwards.delete key
250
+
251
+ forward[ :socket ].shutdown
252
+ forward[ :thread ].terminate
253
+
254
+ true
255
+ end
256
+
257
+ # Cease forwarding connections from the given remote port. The
258
+ # +remote_host+ parameter must match the corresponding parameter that
259
+ # was passed to #remote. Existing forwarded connections are
260
+ # not affected by this call, but no more connections will be
261
+ # forwarded from the remote host to the local host via that port.
262
+ def cancel_remote( remote_port, remote_host="127.0.0.1" )
263
+ writer = @buffers.writer
264
+ writer.write_string remote_host
265
+ writer.write_long remote_port.to_i
266
+
267
+ @connection.global_request( "cancel-tcpip-forward", writer
268
+ ) do |success, response|
269
+ if success
270
+ @remote_forwards.delete remote_port
271
+ else
272
+ raise Net::SSH::Exception,
273
+ "could not cancel remote forward request on " +
274
+ "(#{remote_port},#{remote_host})"
275
+ end
276
+ end
277
+ end
278
+
279
+ # open a new channel as requested by the server
280
+ def do_open_channel( connection, channel, data )
281
+ connected_address = data.read_string
282
+ connected_port = data.read_long
283
+ originator_address = data.read_string
284
+ originator_port = data.read_long
285
+
286
+ forward_data = @remote_forwards[ connected_port ]
287
+ unless forward_data
288
+ raise Net::SSH::Exception,
289
+ "recieved invalid channel-open command for a port forward " +
290
+ "that was never requested"
291
+ end
292
+
293
+ handler = forward_data[:handler]
294
+
295
+ forward_data[:channel] = channel
296
+
297
+ if handler.respond_to?( :on_open )
298
+ handler.on_open( channel,
299
+ connected_address, connected_port,
300
+ originator_address, originator_port )
301
+ end
302
+
303
+ channel.on_data( &handler.method(:on_receive) )
304
+
305
+ if handler.respond_to?( :on_close )
306
+ channel.on_close( &handler.method(:on_close) )
307
+ end
308
+
309
+ if handler.respond_to?( :on_eof )
310
+ channel.on_eof( &handler.method(:on_eof) )
311
+ end
312
+ end
313
+
314
+ end
315
+
316
+ end # Forward
317
+ end # Service
318
+ end # SSH
319
+ end # Net
@@ -0,0 +1,74 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ module Net
18
+ module SSH
19
+ module Service
20
+ module Forward
21
+
22
+ # This is a utility class used internally by Forward::Driver. It
23
+ # manages the network server instance for each locally forwarded port,
24
+ # and is passed as the handler to Driver#direct_channel by
25
+ # Forward::Driver#forward_local. Other clients may desire to extend
26
+ # this class and pass the modified class to
27
+ # Forward::Driver#direct_channel for their own purposes, but in general
28
+ # this class will rarely be used outside of Forward::Driver.
29
+ class LocalNetworkHandler
30
+
31
+ # Create a new LocalNetworkHandler for the given client connection.
32
+ def initialize( log, block_size, client )
33
+ @log = log
34
+ @block_size = block_size
35
+ @client = client
36
+ end
37
+
38
+ # Invoked when data is recieved from the channel. This method just
39
+ # sends the data to the client connection.
40
+ def on_receive( channel, data )
41
+ @client.send data, 0
42
+ end
43
+
44
+ # Invoked when the remote end of the channel will no longer be
45
+ # sending data. It may still receive data, however.
46
+ def on_eof( channel )
47
+ channel[:eof] = true
48
+ end
49
+
50
+ # Called to process the channel in a loop. It will repeatedly read
51
+ # from the client and send the results across the channel.
52
+ def process( channel )
53
+ begin
54
+ loop do
55
+ break if channel[:eof]
56
+ data = @client.recv( @block_size )
57
+ break if data.nil? || data.length < 1
58
+ channel.send_data data
59
+ end
60
+
61
+ channel.close
62
+ rescue StandardError, Exception => e
63
+ @log.error "error processing connection: " +
64
+ "#{e.class} (#{e.message})\n " +
65
+ e.backtrace.join("\n ")
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end # Forward
72
+ end # Service
73
+ end # SSH
74
+ end # Net
@@ -0,0 +1,81 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'socket'
18
+
19
+ module Net
20
+ module SSH
21
+ module Service
22
+ module Forward
23
+
24
+ # A helper class for managing ports forwarded from a remote host to
25
+ # the local host.
26
+ class RemoteNetworkHandler
27
+
28
+ # Instantiate a new RemoteNetworkHandler instance that will forward
29
+ # data to the given local port and host address.
30
+ def initialize( log, block_size, local_port, local_host='127.0.0.1' )
31
+ @log = log
32
+ @block_size = block_size
33
+ @local_port = local_port
34
+ @local_host = local_host
35
+ end
36
+
37
+ # Opens a new socket to the local host and port given when the
38
+ # handler was created, and forwards data from the channel to that
39
+ # connection.
40
+ def on_open( channel, c_addr, c_port, o_addr, o_port )
41
+ @client = TCPSocket.new( @local_host, @local_port )
42
+
43
+ Thread.new do
44
+ begin
45
+ loop do
46
+ break if channel[:eof]
47
+ data = @client.recv( @block_size )
48
+ break if data.nil? or data.length < 1
49
+ channel.send_data data
50
+ end
51
+ rescue Exception => e
52
+ @log.error "error while forwarding remote port: " +
53
+ "#{e.class}: #{e.message}\n " +
54
+ e.backtrace.join( "\n " )
55
+ ensure
56
+ channel.close
57
+ end
58
+ end
59
+ end
60
+
61
+ # Invoked when the channel indicates that the end is near.
62
+ def on_eof( channel )
63
+ channel[:eof] = true
64
+ end
65
+
66
+ # Invoked when the channel is closed.
67
+ def on_close( channel )
68
+ @client.shutdown
69
+ end
70
+
71
+ # Invoked when data is received over the channel.
72
+ def on_receive( channel, data )
73
+ @client.send data, 0
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end