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,51 @@
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
+ $:.unshift "../lib"
18
+
19
+ require 'net/ssh'
20
+
21
+ # This assumes three things:
22
+ #
23
+ # 1) That you have an SSH server running on your local machine,
24
+ # 2) That the USER environment variable is set to your user name, and
25
+ # 3) That you have public and private keys conigured so that you can log into
26
+ # your machine via SSH without being prompted for a password.
27
+ #
28
+ # If #2 or #3 are not true, you can add your user-name and password as the
29
+ # second and third parameters (respectively) to Net::SSH.start.
30
+
31
+ Net::SSH.start( 'localhost' ) do |session|
32
+ session.forward.local( 12345, 'www.yahoo.com', 80 )
33
+ session.forward.local( 12346, 'www.google.com', 80 )
34
+
35
+ trap("SIGINT") do
36
+ puts "direct channels open : #{session.forward.open_direct_channel_count}"
37
+ puts "direct channels opened: #{session.forward.direct_channel_count}"
38
+ puts "active local forwards : #{session.forward.active_locals.length} " +
39
+ "(#{session.forward.active_locals.inspect})"
40
+ session.close
41
+ end
42
+
43
+ begin
44
+ puts "forwarding ports..."
45
+ session.loop { true }
46
+ rescue Exception => e
47
+ unless e.message =~ /connection closed by remote host/
48
+ raise
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,91 @@
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
+ $:.unshift "../lib"
18
+ require 'net/ssh'
19
+
20
+ # This assumes three things:
21
+ #
22
+ # 1) That you have an SSH server running on your local machine,
23
+ # 2) That the USER environment variable is set to your user name, and
24
+ # 3) That you have public and private keys conigured so that you can log into
25
+ # your machine via SSH without being prompted for a password.
26
+ #
27
+ # If #2 or #3 are not true, you can add your user-name and password as the
28
+ # second and third parameters (respectively) to Net::SSH.start.
29
+
30
+ Net::SSH.start( 'localhost' ) do |session|
31
+
32
+ # ===========================================================================
33
+
34
+ session.process.open( "bc" ) do |bc|
35
+ dialog = [ "5+5", "7*12", "sqrt(2.000000)" ]
36
+
37
+ bc.on_success do |p|
38
+ puts "process started successfully. starting interactive session."
39
+ puts "requesting result of #{dialog.first}"
40
+ p.puts dialog.shift
41
+ end
42
+
43
+ bc.on_failure do |p, status|
44
+ puts "process failed to start (#{status})"
45
+ end
46
+
47
+ bc.on_stdout do |p,data|
48
+ puts "--> #{data}"
49
+ unless dialog.empty?
50
+ puts "requesting result of #{dialog.first}"
51
+ p.puts dialog.shift
52
+ else
53
+ p.close_input
54
+ end
55
+ end
56
+
57
+ bc.on_stderr do |p,data|
58
+ puts "got stuff from stderr: #{data}"
59
+ end
60
+
61
+ bc.on_exit do |p, status|
62
+ puts "process finished with exit status: #{status}"
63
+ end
64
+ end
65
+
66
+ puts "done!"
67
+
68
+ # ===========================================================================
69
+
70
+ puts "now, trying 'bc' with popen3..."
71
+
72
+ input, output, error = session.process.popen3( "bc" )
73
+ input.puts "5+5"
74
+ puts "5+5=#{output.read}"
75
+ input.puts "10*2"
76
+ puts "10*2=#{output.read}"
77
+ input.puts "quit"
78
+
79
+ # ===========================================================================
80
+
81
+ puts "trying 'cat' with popen3"
82
+ session.process.popen3( "cat" ) do |input,output,error|
83
+ input.puts "hello"
84
+ puts output.read
85
+ input.puts "world"
86
+ puts output.read
87
+ end
88
+
89
+ puts "done!"
90
+
91
+ end
@@ -0,0 +1,45 @@
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
+ $:.unshift "../lib"
18
+
19
+ require 'net/ssh'
20
+
21
+ # This assumes four things:
22
+ #
23
+ # 1) That you have an SSH server running on your local machine,
24
+ # 2) That the USER environment variable is set to your user name, and
25
+ # 3) That you have public and private keys conigured so that you can log into
26
+ # your machine via SSH without being prompted for a password.
27
+ # 4) That you have a web server running on your local machine on port 80.
28
+ #
29
+ # If #2 or #3 are not true, you can add your user-name and password as the
30
+ # second and third parameters (respectively) to Net::SSH.start.
31
+
32
+ Net::SSH.start( 'localhost' ) do |session|
33
+ session.forward.remote_to( 80, "localhost", 12345 )
34
+
35
+ trap("SIGINT") { session.close }
36
+
37
+ begin
38
+ puts "forwarding remote port via localhost..."
39
+ session.loop { true }
40
+ rescue Exception => e
41
+ unless e.message =~ /connection closed by remote host/
42
+ raise
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,80 @@
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
+ $:.unshift "../lib"
18
+
19
+ require 'net/ssh'
20
+
21
+ # This assumes three things:
22
+ #
23
+ # 1) That you have an SSH server running on your local machine,
24
+ # 2) That the USER environment variable is set to your user name, and
25
+ # 3) That you have public and private keys conigured so that you can log into
26
+ # your machine via SSH without being prompted for a password.
27
+ #
28
+ # If #2 or #3 are not true, you can add your user-name and password as the
29
+ # second and third parameters (respectively) to Net::SSH.start.
30
+
31
+ class RemoteForwardListener
32
+ def error( msg )
33
+ raise "[#{self.class}] An error occurred: #{msg}"
34
+ end
35
+
36
+ def setup( remote_port )
37
+ puts "[#{self.class}] forwarding enabled from remote port #{remote_port}"
38
+ end
39
+
40
+ def on_open( channel, c_addr, c_port, o_addr, o_port )
41
+ puts "[#{self.class}] channel opened from remote server:"
42
+ puts " - connected address: #{c_addr}:#{c_port}"
43
+ puts " - originator address: #{o_addr}:#{o_port}"
44
+ end
45
+
46
+ def on_receive( channel, data )
47
+ puts "data recevied from remote machine: #{data.inspect}"
48
+ msg = "It worked! You just connected over a remote forwarded SSH " +
49
+ "connection!\n\n" +
50
+ "------\n" +
51
+ data
52
+ channel.send_data "HTTP/1.0 200 OK\r\n" +
53
+ "Content-Type: text/plain\r\n" +
54
+ "Content-Length: #{msg.length}\r\n" +
55
+ "\r\n" +
56
+ msg
57
+ end
58
+
59
+ def on_close( channel )
60
+ puts "remote channel closed"
61
+ end
62
+
63
+ def on_eof( channel )
64
+ puts "remote end of channel promised not to send any more data"
65
+ end
66
+ end
67
+
68
+ Net::SSH.start( 'localhost' ) do |session|
69
+ session.forward.remote( RemoteForwardListener.new, 12345 )
70
+
71
+ trap("SIGINT") { session.close }
72
+
73
+ begin
74
+ session.loop { true }
75
+ rescue Exception => e
76
+ unless e.message =~ /connection closed by remote host/
77
+ raise
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,49 @@
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
+ $:.unshift "../lib"
18
+ require 'net/ssh'
19
+
20
+ # This assumes three things:
21
+ #
22
+ # 1) That you have an SSH server running on your local machine,
23
+ # 2) That the USER environment variable is set to your user name, and
24
+ # 3) That you have public and private keys conigured so that you can log into
25
+ # your machine via SSH without being prompted for a password.
26
+ #
27
+ # If #2 or #3 are not true, you can add your user-name and password as the
28
+ # second and third parameters (respectively) to Net::SSH.start.
29
+
30
+ Net::SSH.start( 'localhost' ) do |session|
31
+
32
+ # Note: two things here,
33
+ #
34
+ # 1) open_channel does not immediately invoke the associated block. It only
35
+ # calls the block after the server has confirmed that the channel is valid.
36
+ # 2) channel.exec does not block--it just sends the request to the server and
37
+ # returns.
38
+ #
39
+ # For these two reasons, you MUST call session.loop, so that packets get
40
+ # processed and dispatched to the appropriate channel for handling.
41
+
42
+ session.open_channel do |channel|
43
+ channel.on_data { |chan,data| puts "--> #{data.inspect}" }
44
+ channel.on_extended_data { |chan,type,data| print data }
45
+ channel.exec "tail -f /tmp/mylog"
46
+ end
47
+
48
+ session.loop
49
+ end
data/lib/net/ssh.rb ADDED
@@ -0,0 +1,52 @@
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/session'
18
+
19
+ #--
20
+ # Documentation Roadmap:
21
+ #
22
+ # 1. Start with net/ssh/session.rb (Net::SSH::Session). This creates a new
23
+ # Needle registry and registers all the services.
24
+ #
25
+ # 2. Look at net/ssh/transport/services.rb to see how the transport services
26
+ # are defined, and what classes implement each of them.
27
+ #
28
+ # 3. Look at net/ssh/transport/session.rb (Net::SSH::Transport::Session). This
29
+ # implements the driver for the transport layer.
30
+ #
31
+ # 4. Look at net/ssh/userauth/services.rb to see how the services for the
32
+ # user authentication layer are defined, and implemented.
33
+ #
34
+ # 5. Look at net/ssh/connection/services.rb to see how the services for the
35
+ # connection layer are defined and implemented.
36
+ #
37
+ # 6. Look at net/ssh/service/services.rb to see how the auxiliary services
38
+ # (process and forward) are defined.
39
+ #++
40
+
41
+ module Net
42
+ module SSH
43
+
44
+ # A convenience method for starting a new SSH session. See
45
+ # Net::SSH::Session.
46
+ def start( *args, &block )
47
+ Net::SSH::Session.new( *args, &block )
48
+ end
49
+ module_function :start
50
+
51
+ end
52
+ end
@@ -0,0 +1,411 @@
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/connection/constants'
18
+
19
+ module Net
20
+ module SSH
21
+ module Connection
22
+
23
+ class Channel
24
+ include Constants
25
+
26
+ #--
27
+ # ====================================================================
28
+ # ATTRIBUTES
29
+ # ====================================================================
30
+ #++
31
+
32
+ # The channel's local id (assigned by the connection)
33
+ attr_reader :local_id
34
+
35
+ # The channel's remote id (assigned by the remote server)
36
+ attr_reader :remote_id
37
+
38
+ # The connection driver instance that owns this channel
39
+ attr_reader :connection
40
+
41
+ # The type of this channel
42
+ attr_reader :type
43
+
44
+ # The maximum packet size that may be sent over this channel
45
+ attr_reader :maximum_packet_size
46
+
47
+ # The maximum data window size for this channel
48
+ attr_reader :window_size
49
+
50
+ #--
51
+ # ====================================================================
52
+ # FACTORY METHODS
53
+ # ====================================================================
54
+ #++
55
+
56
+ # Requests that a new channel be opened on the remote host.
57
+ # This will return immediately, but the +on_confirm_open+ callback
58
+ # will be invoked when the remote host confirms that the channel has
59
+ # been successfully opened.
60
+ def self.open( connection, log, buffers, type, data=nil )
61
+ channel = new( connection, log, buffers, type )
62
+
63
+ msg = buffers.writer
64
+
65
+ msg.write_byte CHANNEL_OPEN
66
+ msg.write_string type
67
+ msg.write_long channel.local_id
68
+ msg.write_long 0x7FFFFFFF, 0x7FFFFFFF
69
+ msg.write data.to_s if data
70
+
71
+ connection.send_message msg
72
+
73
+ channel
74
+ end
75
+
76
+ # Creates a new channel object with the given internal
77
+ # information. The channel is assumed to already be
78
+ # connected to a remote host.
79
+ def self.create( connection, log, buffers, type, remote_id,
80
+ window_size, packet_size )
81
+ # begin
82
+ channel = new( connection, log, buffers, type )
83
+ channel.do_confirm_open remote_id, window_size, packet_size
84
+ channel
85
+ end
86
+
87
+ private_class_method :new
88
+
89
+ #--
90
+ # ====================================================================
91
+ # CONSTRUCTOR
92
+ # ====================================================================
93
+ #++
94
+
95
+ # Create a new channel object on the given connection, and of the given
96
+ # type.
97
+ def initialize( connection, log, buffers, type )
98
+ @connection = connection
99
+ @log = log
100
+ @buffers = buffers
101
+ @type = type
102
+ @local_id = @connection.allocate_channel_id
103
+ end
104
+
105
+ #--
106
+ # ====================================================================
107
+ # CALLBACK HOOKS
108
+ # ====================================================================
109
+ #++
110
+
111
+ # Set the callback to use when the channel has been confirmed
112
+ # to be open.
113
+ def on_confirm_open( &block )
114
+ @on_confirm_open = block
115
+ end
116
+
117
+ # Set the callback to use when the channel could not be opened
118
+ # for some reason.
119
+ def on_confirm_failed( &block )
120
+ @on_confirm_failed = block
121
+ end
122
+
123
+ # Set the callback to be invoked when the server requests
124
+ # that the window size be adjusted.
125
+ def on_window_adjust( &block )
126
+ @on_window_adjust = block
127
+ end
128
+
129
+ # Set the callback to be invoked when the server sends a
130
+ # data packet over the channel.
131
+ def on_data( &block )
132
+ @on_data = block
133
+ end
134
+
135
+ # Set the callback to be invoked when the server sends an
136
+ # extended data packet over the channel.
137
+ def on_extended_data( &block )
138
+ @on_extended_data = block
139
+ end
140
+
141
+ # Set the callback to be invoked when the server sends an EOF
142
+ # packet.
143
+ def on_eof( &block )
144
+ @on_eof = block
145
+ end
146
+
147
+ # Set the callback to be invoked when the server sends a
148
+ # request packet.
149
+ def on_request( &block )
150
+ @on_request = block
151
+ end
152
+
153
+ # Set the callback to invoked when the server sends
154
+ # confirmation of a successful operation.
155
+ def on_success( &block )
156
+ @on_success = block
157
+ end
158
+
159
+ # Set the callback to invoked when the server sends
160
+ # notification of a failed operation.
161
+ def on_failure( &block )
162
+ @on_failure = block
163
+ end
164
+
165
+ # Set the callback to be invoked when the channel is closed.
166
+ def on_close( &block )
167
+ @on_close = block
168
+ end
169
+
170
+ #--
171
+ # ====================================================================
172
+ # CHANNEL STATE ACCESSORS
173
+ # ====================================================================
174
+ #++
175
+
176
+ def valid?
177
+ not @local_id.nil?
178
+ end
179
+
180
+ # Retrieved a named property of the channel.
181
+ def property( name )
182
+ ( @properties ||= Hash.new )[ name ]
183
+ end
184
+
185
+ # Set a named property on the channel.
186
+ def set_property( name, value )
187
+ ( @properties ||= Hash.new )[ name ] = value
188
+ end
189
+
190
+ alias :[] :property
191
+ alias :[]= :set_property
192
+
193
+ #--
194
+ # ====================================================================
195
+ # CHANNEL AFFECTORS
196
+ # ====================================================================
197
+ #++
198
+
199
+ # Closes the channel.
200
+ def close( client_initiated=true )
201
+ unless defined?(@already_closed) && @already_closed
202
+ msg = @buffers.writer
203
+ msg.write_byte CHANNEL_CLOSE
204
+ msg.write_long @remote_id
205
+ @connection.send_message msg
206
+ @already_closed = true
207
+ end
208
+
209
+ unless client_initiated
210
+ @connection.remove_channel( self )
211
+ callback :close, self
212
+ end
213
+
214
+ self
215
+ end
216
+
217
+ # Send an EOF across the channel. No data should be sent from the client
218
+ # to the server over this channel after this, although packets may still
219
+ # be received from the server.
220
+ def send_eof
221
+ msg = @buffers.writer
222
+ msg.write_byte CHANNEL_EOF
223
+ msg.write_long @remote_id
224
+ @connection.send_message msg
225
+ self
226
+ end
227
+
228
+ # Send the given signal to process on the other side of the channel. The
229
+ # parameter should be one of the Channel::SIGxxx constants.
230
+ def send_signal( sig, want_reply=false )
231
+ send_request_string "signal", sig, want_reply
232
+ self
233
+ end
234
+
235
+ # Send a channel request with the given name. It will have one data
236
+ # item, which will be interpreted as a string.
237
+ def send_request_string( request_name, data, want_reply=false )
238
+ msg = @buffers.writer
239
+ msg.write_string data.to_s
240
+ send_request request_name, msg, want_reply
241
+ end
242
+
243
+ # Send a generic channel request with the given name. The data item will
244
+ # be written directly into the request (after converting it to a string,
245
+ # as necessary).
246
+ def send_request( request_name, data, want_reply=false )
247
+ msg = @buffers.writer
248
+ msg.write_byte CHANNEL_REQUEST
249
+ msg.write_long @remote_id
250
+ msg.write_string request_name
251
+ msg.write_bool want_reply
252
+ msg.write data.to_s
253
+ @connection.send_message msg
254
+ self
255
+ end
256
+
257
+ # Send a data packet to the server, over the channel.
258
+ def send_data( data )
259
+ msg = @buffers.writer
260
+ msg.write_byte CHANNEL_DATA
261
+ msg.write_long @remote_id
262
+ msg.write_string data.to_s
263
+ @connection.send_message msg
264
+ end
265
+
266
+ # Send an extended data packet to the server, over the channel.
267
+ # Extended data always has a numeric type associated with it. The
268
+ # only predefined type is 1, whic corresponds to +stderr+ data.
269
+ def send_extended_data( type, data )
270
+ msg = @buffers.writer
271
+ msg.write_byte CHANNEL_EXTENDED_DATA
272
+ msg.write_long @remote_id
273
+ msg.write_long type
274
+ msg.write_string data.to_s
275
+ @connection.send_message msg
276
+ end
277
+
278
+ VALID_PTY_OPTIONS = { :term=>"xterm",
279
+ :chars_wide=>80,
280
+ :chars_high=>24,
281
+ :pixels_wide=>640,
282
+ :pixels_high=>480,
283
+ :modes=>{},
284
+ :want_reply=>false }
285
+
286
+ # Request that a pty be opened for this channel. Valid options are
287
+ # :term, :chars_wide, :chars_high, :pixels_wide, :pixels_high, :modes,
288
+ # and :want_reply. :modes is a Hash, where the keys are constants from
289
+ # Net::SSH::Service::Term, and values are integers describing the
290
+ # corresponding key.
291
+ def request_pty( opts = {} )
292
+ invalid_opts = opts.keys - VALID_PTY_OPTIONS.keys
293
+ unless invalid_opts.empty?
294
+ raise ArgumentError,
295
+ "invalid option(s) to request_pty: #{invalid_opts.inspect}"
296
+ end
297
+
298
+ VALID_PTY_OPTIONS.keys.each do |opt|
299
+ opts[ opt ] ||= VALID_PTY_OPTIONS[ opt ]
300
+ end
301
+
302
+ msg = @buffers.writer
303
+ msg.write_string opts[ :term ]
304
+ msg.write_long opts[ :chars_wide ]
305
+ msg.write_long opts[ :chars_high ]
306
+ msg.write_long opts[ :pixels_wide ]
307
+ msg.write_long opts[ :pixels_high ]
308
+
309
+ modes = @buffers.writer
310
+ opts[ :modes ].each do |mode, data|
311
+ modes.write_byte mode
312
+ modes.write_long data
313
+ end
314
+ modes.write_byte Term::TTY_OP_END
315
+
316
+ msg.write_string modes.to_s
317
+
318
+ send_request "pty-req", msg, opts[:want_reply]
319
+ end
320
+
321
+ # Execute the given remote command over the channel. This should be
322
+ # invoked in the "on_confirm" callback of a channel. This method will
323
+ # return immediately.
324
+ def exec( command, want_reply=false )
325
+ send_request_string "exec", command, want_reply
326
+ end
327
+
328
+ # Request the given subsystem. This method will return immediately.
329
+ def subsystem( subsystem, want_reply=true )
330
+ send_request_string "subsystem", subsystem, want_reply
331
+ end
332
+
333
+ #--
334
+ # ====================================================================
335
+ # CHANNEL EVENTS
336
+ # ====================================================================
337
+ #++
338
+
339
+ # A convenience method for defining new event callbacks.
340
+ def self.event( event, *parameters )
341
+ define_method "do_#{event}" do |*args|
342
+ callback event, self, *args
343
+ self
344
+ end
345
+ end
346
+
347
+ # Invoked when the server confirms the opening of a channel.
348
+ def do_confirm_open( remote_id, window_size, packet_size )
349
+ @remote_id = remote_id
350
+ @window_size = window_size
351
+ @maximum_packet_size = packet_size
352
+ callback :confirm_open, self
353
+ end
354
+
355
+ # Invoked when the server failed to confirm the opening of a channel.
356
+ def do_confirm_failed( reason_code, description, language )
357
+ @local_id = nil
358
+ @connection = nil
359
+ callback :confirm_failed, self, reason_code, description, language
360
+ end
361
+
362
+ # Invoked when the server asks to adjust the window size. This in turn
363
+ # calls the "on_window_adjust" callback.
364
+ def do_window_adjust( bytes_to_add )
365
+ @window_size += bytes_to_add
366
+ callback :window_adjust, self, bytes_to_add
367
+ end
368
+
369
+ # Invoked when the server sends a data packet. This in turn calls the
370
+ # "on_data" callback.
371
+ event :data, :data
372
+
373
+ # Invoked when the server sends an extended data packet. This in turn
374
+ # calls the "on_extended_data" callback.
375
+ event :extended_data, :type, :data
376
+
377
+ # Invoked when the server sends an EOF packet. This in turn calls the
378
+ # "on_eof" callback.
379
+ event :eof
380
+
381
+ # Invoked when the server sends a request packet. This in turn calls
382
+ # the "on_request" callback.
383
+ event :request, :want_reply, :data
384
+
385
+ # Invoked when the server sends confirmation of a successful operation.
386
+ # This in turn invokes the "on_success" callback, if set.
387
+ event :success
388
+
389
+ # Invoked when the server sends notification of a failed operation.
390
+ # This in turn invokes the "on_failure" callback, if set.
391
+ event :failure
392
+
393
+ #--
394
+ # ====================================================================
395
+ # PRIVATE UTILITIES
396
+ # ====================================================================
397
+ #++
398
+
399
+ # A convenience utility method for invoking a named callback with a
400
+ # set of arguments.
401
+ def callback( which, *args )
402
+ block = instance_variable_get( "@on_#{which.to_s}" )
403
+ block.call( *args ) if block
404
+ end
405
+ private :callback
406
+
407
+ end
408
+
409
+ end
410
+ end
411
+ end