net-ssh 1.1.4 → 2.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/CHANGELOG.rdoc +37 -0
- data/Manifest +101 -0
- data/README.rdoc +110 -0
- data/Rakefile +26 -0
- data/{THANKS → THANKS.rdoc} +2 -5
- data/lib/net/ssh.rb +189 -57
- data/lib/net/ssh/authentication/agent.rb +175 -0
- data/lib/net/ssh/authentication/constants.rb +18 -0
- data/lib/net/ssh/authentication/key_manager.rb +166 -0
- data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
- data/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
- data/lib/net/ssh/authentication/methods/password.rb +39 -0
- data/lib/net/ssh/authentication/methods/publickey.rb +92 -0
- data/lib/net/ssh/authentication/pageant.rb +176 -0
- data/lib/net/ssh/authentication/session.rb +116 -0
- data/lib/net/ssh/buffer.rb +339 -0
- data/lib/net/ssh/buffered_io.rb +149 -0
- data/lib/net/ssh/config.rb +173 -0
- data/lib/net/ssh/connection/channel.rb +575 -454
- data/lib/net/ssh/connection/constants.rb +31 -45
- data/lib/net/ssh/connection/session.rb +569 -0
- data/lib/net/ssh/connection/term.rb +176 -88
- data/lib/net/ssh/errors.rb +83 -61
- data/lib/net/ssh/key_factory.rb +85 -0
- data/lib/net/ssh/known_hosts.rb +129 -0
- data/lib/net/ssh/loggable.rb +61 -0
- data/lib/net/ssh/packet.rb +102 -0
- data/lib/net/ssh/prompt.rb +93 -0
- data/lib/net/ssh/proxy/errors.rb +8 -28
- data/lib/net/ssh/proxy/http.rb +75 -107
- data/lib/net/ssh/proxy/socks4.rb +35 -48
- data/lib/net/ssh/proxy/socks5.rb +76 -108
- data/lib/net/ssh/service/forward.rb +267 -0
- data/lib/net/ssh/test.rb +89 -0
- data/lib/net/ssh/test/channel.rb +129 -0
- data/lib/net/ssh/test/extensions.rb +152 -0
- data/lib/net/ssh/test/kex.rb +44 -0
- data/lib/net/ssh/test/local_packet.rb +51 -0
- data/lib/net/ssh/test/packet.rb +81 -0
- data/lib/net/ssh/test/remote_packet.rb +38 -0
- data/lib/net/ssh/test/script.rb +157 -0
- data/lib/net/ssh/test/socket.rb +59 -0
- data/lib/net/ssh/transport/algorithms.rb +384 -0
- data/lib/net/ssh/transport/cipher_factory.rb +72 -0
- data/lib/net/ssh/transport/constants.rb +22 -58
- data/lib/net/ssh/transport/hmac.rb +31 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +48 -0
- data/lib/net/ssh/transport/hmac/md5.rb +12 -0
- data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
- data/lib/net/ssh/transport/hmac/none.rb +15 -0
- data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
- data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
- data/lib/net/ssh/transport/identity_cipher.rb +40 -0
- data/lib/net/ssh/transport/kex.rb +13 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
- data/lib/net/ssh/{util → transport}/openssl.rb +22 -40
- data/lib/net/ssh/transport/packet_stream.rb +230 -0
- data/lib/net/ssh/transport/server_version.rb +61 -0
- data/lib/net/ssh/transport/session.rb +225 -303
- data/lib/net/ssh/transport/state.rb +170 -0
- data/lib/net/ssh/verifiers/lenient.rb +30 -0
- data/lib/net/ssh/verifiers/null.rb +12 -0
- data/lib/net/ssh/verifiers/strict.rb +53 -0
- data/lib/net/ssh/version.rb +57 -26
- data/net-ssh.gemspec +54 -0
- data/setup.rb +1585 -0
- data/test/authentication/methods/common.rb +28 -0
- data/test/authentication/methods/test_abstract.rb +51 -0
- data/test/authentication/methods/test_hostbased.rb +108 -0
- data/test/authentication/methods/test_keyboard_interactive.rb +98 -0
- data/test/authentication/methods/test_password.rb +50 -0
- data/test/authentication/methods/test_publickey.rb +123 -0
- data/test/authentication/test_agent.rb +205 -0
- data/test/authentication/test_key_manager.rb +100 -0
- data/test/authentication/test_session.rb +93 -0
- data/test/common.rb +106 -0
- data/test/configs/exact_match +8 -0
- data/test/configs/wild_cards +14 -0
- data/test/connection/test_channel.rb +452 -0
- data/test/connection/test_session.rb +483 -0
- data/test/test_all.rb +6 -0
- data/test/test_buffer.rb +336 -0
- data/test/test_buffered_io.rb +63 -0
- data/test/test_config.rb +78 -0
- data/test/test_key_factory.rb +67 -0
- data/test/transport/hmac/test_md5.rb +34 -0
- data/test/transport/hmac/test_md5_96.rb +25 -0
- data/test/transport/hmac/test_none.rb +34 -0
- data/test/transport/hmac/test_sha1.rb +34 -0
- data/test/transport/hmac/test_sha1_96.rb +25 -0
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
- data/test/transport/test_algorithms.rb +302 -0
- data/test/transport/test_cipher_factory.rb +163 -0
- data/test/transport/test_hmac.rb +34 -0
- data/test/transport/test_identity_cipher.rb +40 -0
- data/test/transport/test_packet_stream.rb +433 -0
- data/test/transport/test_server_version.rb +55 -0
- data/test/transport/test_session.rb +312 -0
- data/test/transport/test_state.rb +173 -0
- metadata +102 -253
- data/ChangeLog +0 -560
- data/LICENSE +0 -7
- data/NEWS +0 -152
- data/README +0 -14
- data/bin/rb-keygen +0 -210
- data/doc/LICENSE-BSD +0 -27
- data/doc/LICENSE-GPL +0 -280
- data/doc/LICENSE-RUBY +0 -56
- data/doc/manual-html/chapter-1.html +0 -388
- data/doc/manual-html/chapter-2.html +0 -552
- data/doc/manual-html/chapter-3.html +0 -470
- data/doc/manual-html/chapter-4.html +0 -413
- data/doc/manual-html/chapter-5.html +0 -525
- data/doc/manual-html/chapter-6.html +0 -456
- data/doc/manual-html/chapter-7.html +0 -343
- data/doc/manual-html/index.html +0 -235
- data/doc/manual-html/stylesheets/manual.css +0 -270
- data/doc/manual-html/stylesheets/ruby.css +0 -17
- data/doc/manual/chapter.erb +0 -38
- data/doc/manual/example.erb +0 -18
- data/doc/manual/index.erb +0 -29
- data/doc/manual/manual.rb +0 -311
- data/doc/manual/manual.yml +0 -73
- data/doc/manual/page.erb +0 -87
- data/doc/manual/parts/0000.txt +0 -5
- data/doc/manual/parts/0001.txt +0 -3
- data/doc/manual/parts/0002.txt +0 -40
- data/doc/manual/parts/0003.txt +0 -6
- data/doc/manual/parts/0004.txt +0 -7
- data/doc/manual/parts/0005.txt +0 -1
- data/doc/manual/parts/0006.txt +0 -49
- data/doc/manual/parts/0007.txt +0 -67
- data/doc/manual/parts/0008.txt +0 -43
- data/doc/manual/parts/0009.txt +0 -14
- data/doc/manual/parts/0010.txt +0 -7
- data/doc/manual/parts/0011.txt +0 -14
- data/doc/manual/parts/0012.txt +0 -3
- data/doc/manual/parts/0013.txt +0 -20
- data/doc/manual/parts/0014.txt +0 -32
- data/doc/manual/parts/0015.txt +0 -14
- data/doc/manual/parts/0016.txt +0 -28
- data/doc/manual/parts/0017.txt +0 -50
- data/doc/manual/parts/0018.txt +0 -35
- data/doc/manual/parts/0019.txt +0 -7
- data/doc/manual/parts/0020.txt +0 -72
- data/doc/manual/parts/0021.txt +0 -50
- data/doc/manual/parts/0022.txt +0 -42
- data/doc/manual/parts/0023.txt +0 -51
- data/doc/manual/parts/0024.txt +0 -18
- data/doc/manual/parts/0025.txt +0 -18
- data/doc/manual/parts/0026.txt +0 -15
- data/doc/manual/parts/0027.txt +0 -37
- data/doc/manual/parts/0028.txt +0 -16
- data/doc/manual/parts/0029.txt +0 -1
- data/doc/manual/parts/0030.txt +0 -52
- data/doc/manual/parts/0031.txt +0 -25
- data/doc/manual/stylesheets/manual.css +0 -270
- data/doc/manual/stylesheets/ruby.css +0 -17
- data/doc/manual/tutorial.erb +0 -30
- data/examples/auth-forward.rb +0 -41
- data/examples/channel-demo.rb +0 -81
- data/examples/port-forward.rb +0 -51
- data/examples/process-demo.rb +0 -91
- data/examples/remote-net-port-forward.rb +0 -45
- data/examples/remote-port-forward.rb +0 -80
- data/examples/shell-demo.rb +0 -46
- data/examples/ssh-client.rb +0 -67
- data/examples/sync-shell-demo.rb +0 -69
- data/examples/tail-demo.rb +0 -49
- data/lib/net/ssh/connection/driver.rb +0 -446
- data/lib/net/ssh/connection/services.rb +0 -72
- data/lib/net/ssh/host-key-verifier.rb +0 -52
- data/lib/net/ssh/known-hosts.rb +0 -96
- data/lib/net/ssh/lenient-host-key-verifier.rb +0 -25
- data/lib/net/ssh/null-host-key-verifier.rb +0 -14
- data/lib/net/ssh/service/agentforward/driver.rb +0 -78
- data/lib/net/ssh/service/agentforward/services.rb +0 -41
- data/lib/net/ssh/service/forward/driver.rb +0 -319
- data/lib/net/ssh/service/forward/local-network-handler.rb +0 -71
- data/lib/net/ssh/service/forward/remote-network-handler.rb +0 -83
- data/lib/net/ssh/service/forward/services.rb +0 -76
- data/lib/net/ssh/service/process/driver.rb +0 -153
- data/lib/net/ssh/service/process/open.rb +0 -193
- data/lib/net/ssh/service/process/popen3.rb +0 -178
- data/lib/net/ssh/service/process/services.rb +0 -66
- data/lib/net/ssh/service/services.rb +0 -60
- data/lib/net/ssh/service/shell/driver.rb +0 -86
- data/lib/net/ssh/service/shell/services.rb +0 -54
- data/lib/net/ssh/service/shell/shell.rb +0 -222
- data/lib/net/ssh/service/shell/sync.rb +0 -114
- data/lib/net/ssh/session.rb +0 -305
- data/lib/net/ssh/transport/algorithm-negotiator.rb +0 -275
- data/lib/net/ssh/transport/compress/compressor.rb +0 -53
- data/lib/net/ssh/transport/compress/decompressor.rb +0 -53
- data/lib/net/ssh/transport/compress/none-compressor.rb +0 -39
- data/lib/net/ssh/transport/compress/none-decompressor.rb +0 -39
- data/lib/net/ssh/transport/compress/services.rb +0 -68
- data/lib/net/ssh/transport/compress/zlib-compressor.rb +0 -60
- data/lib/net/ssh/transport/compress/zlib-decompressor.rb +0 -52
- data/lib/net/ssh/transport/errors.rb +0 -47
- data/lib/net/ssh/transport/identity-cipher.rb +0 -61
- data/lib/net/ssh/transport/kex/dh-gex.rb +0 -106
- data/lib/net/ssh/transport/kex/dh.rb +0 -249
- data/lib/net/ssh/transport/kex/services.rb +0 -62
- data/lib/net/ssh/transport/ossl/buffer-factory.rb +0 -52
- data/lib/net/ssh/transport/ossl/buffer.rb +0 -87
- data/lib/net/ssh/transport/ossl/cipher-factory.rb +0 -98
- data/lib/net/ssh/transport/ossl/digest-factory.rb +0 -51
- data/lib/net/ssh/transport/ossl/hmac-factory.rb +0 -71
- data/lib/net/ssh/transport/ossl/hmac/hmac.rb +0 -62
- data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +0 -44
- data/lib/net/ssh/transport/ossl/hmac/md5.rb +0 -46
- data/lib/net/ssh/transport/ossl/hmac/none.rb +0 -46
- data/lib/net/ssh/transport/ossl/hmac/services.rb +0 -68
- data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +0 -44
- data/lib/net/ssh/transport/ossl/hmac/sha1.rb +0 -45
- data/lib/net/ssh/transport/ossl/key-factory.rb +0 -116
- data/lib/net/ssh/transport/ossl/services.rb +0 -149
- data/lib/net/ssh/transport/packet-stream.rb +0 -236
- data/lib/net/ssh/transport/services.rb +0 -146
- data/lib/net/ssh/transport/version-negotiator.rb +0 -73
- data/lib/net/ssh/userauth/agent.rb +0 -222
- data/lib/net/ssh/userauth/constants.rb +0 -35
- data/lib/net/ssh/userauth/driver.rb +0 -183
- data/lib/net/ssh/userauth/methods/hostbased.rb +0 -119
- data/lib/net/ssh/userauth/methods/keyboard-interactive.rb +0 -104
- data/lib/net/ssh/userauth/methods/password.rb +0 -70
- data/lib/net/ssh/userauth/methods/publickey.rb +0 -137
- data/lib/net/ssh/userauth/methods/services.rb +0 -90
- data/lib/net/ssh/userauth/pageant.rb +0 -197
- data/lib/net/ssh/userauth/services.rb +0 -141
- data/lib/net/ssh/userauth/userkeys.rb +0 -258
- data/lib/net/ssh/util/buffer.rb +0 -274
- data/lib/net/ssh/util/prompter.rb +0 -73
- data/test/ALL-TESTS.rb +0 -18
- data/test/connection/tc_channel.rb +0 -136
- data/test/connection/tc_driver.rb +0 -287
- data/test/connection/tc_integration.rb +0 -87
- data/test/proxy/tc_http.rb +0 -209
- data/test/proxy/tc_socks4.rb +0 -148
- data/test/proxy/tc_socks5.rb +0 -214
- data/test/service/agentforward/tc_driver.rb +0 -138
- data/test/service/forward/tc_driver.rb +0 -289
- data/test/service/forward/tc_local_network_handler.rb +0 -123
- data/test/service/forward/tc_remote_network_handler.rb +0 -111
- data/test/service/process/tc_driver.rb +0 -79
- data/test/service/process/tc_integration.rb +0 -119
- data/test/service/process/tc_open.rb +0 -179
- data/test/service/process/tc_popen3.rb +0 -164
- data/test/tc_integration.rb +0 -80
- data/test/transport/compress/tc_none_compress.rb +0 -41
- data/test/transport/compress/tc_none_decompress.rb +0 -45
- data/test/transport/compress/tc_zlib_compress.rb +0 -61
- data/test/transport/compress/tc_zlib_decompress.rb +0 -48
- data/test/transport/kex/tc_dh.rb +0 -312
- data/test/transport/kex/tc_dh_gex.rb +0 -71
- data/test/transport/ossl/fixtures/dsa-encrypted +0 -15
- data/test/transport/ossl/fixtures/dsa-encrypted-bad +0 -15
- data/test/transport/ossl/fixtures/dsa-unencrypted +0 -12
- data/test/transport/ossl/fixtures/dsa-unencrypted-bad +0 -12
- data/test/transport/ossl/fixtures/dsa-unencrypted.pub +0 -1
- data/test/transport/ossl/fixtures/not-a-private-key +0 -4
- data/test/transport/ossl/fixtures/not-supported +0 -2
- data/test/transport/ossl/fixtures/rsa-encrypted +0 -18
- data/test/transport/ossl/fixtures/rsa-encrypted-bad +0 -18
- data/test/transport/ossl/fixtures/rsa-unencrypted +0 -15
- data/test/transport/ossl/fixtures/rsa-unencrypted-bad +0 -15
- data/test/transport/ossl/fixtures/rsa-unencrypted.pub +0 -1
- data/test/transport/ossl/hmac/tc_hmac.rb +0 -58
- data/test/transport/ossl/hmac/tc_md5.rb +0 -50
- data/test/transport/ossl/hmac/tc_md5_96.rb +0 -50
- data/test/transport/ossl/hmac/tc_none.rb +0 -50
- data/test/transport/ossl/hmac/tc_sha1.rb +0 -50
- data/test/transport/ossl/hmac/tc_sha1_96.rb +0 -50
- data/test/transport/ossl/tc_buffer.rb +0 -97
- data/test/transport/ossl/tc_buffer_factory.rb +0 -67
- data/test/transport/ossl/tc_cipher_factory.rb +0 -84
- data/test/transport/ossl/tc_digest_factory.rb +0 -39
- data/test/transport/ossl/tc_hmac_factory.rb +0 -72
- data/test/transport/ossl/tc_key_factory.rb +0 -199
- data/test/transport/tc_algorithm_negotiator.rb +0 -170
- data/test/transport/tc_identity_cipher.rb +0 -52
- data/test/transport/tc_integration.rb +0 -115
- data/test/transport/tc_packet_stream.rb +0 -184
- data/test/transport/tc_session.rb +0 -296
- data/test/transport/tc_version_negotiator.rb +0 -86
- data/test/userauth/methods/tc_hostbased.rb +0 -136
- data/test/userauth/methods/tc_password.rb +0 -89
- data/test/userauth/methods/tc_publickey.rb +0 -167
- data/test/userauth/tc_agent.rb +0 -223
- data/test/userauth/tc_driver.rb +0 -190
- data/test/userauth/tc_integration.rb +0 -97
- data/test/userauth/tc_userkeys.rb +0 -265
- data/test/util/tc_buffer.rb +0 -217
data/examples/sync-shell-demo.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# =============================================================================
|
3
|
-
# Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
|
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
|
-
Net::SSH.start( 'localhost' ) do |session|
|
21
|
-
|
22
|
-
shell = session.shell.sync
|
23
|
-
|
24
|
-
out = shell.pwd
|
25
|
-
p out.stdout
|
26
|
-
|
27
|
-
out = shell.cd "/"
|
28
|
-
|
29
|
-
out = shell.pwd
|
30
|
-
p out.stdout
|
31
|
-
|
32
|
-
out = shell.test "-e foo"
|
33
|
-
p out.status
|
34
|
-
|
35
|
-
out = shell.ls "-laZ"
|
36
|
-
p out.stderr
|
37
|
-
p out.status
|
38
|
-
|
39
|
-
out = shell.cd "/really/bogus/directory"
|
40
|
-
p out.stderr
|
41
|
-
p out.status
|
42
|
-
|
43
|
-
out = shell.send_command "/sbin/ifconfig"
|
44
|
-
p out.stdout
|
45
|
-
p out.status
|
46
|
-
|
47
|
-
out = shell.pwd
|
48
|
-
p out.stdout
|
49
|
-
|
50
|
-
out = shell.ruby "-v"
|
51
|
-
p out.stdout
|
52
|
-
|
53
|
-
out = shell.cd "/usr/lib"
|
54
|
-
|
55
|
-
out = shell.pwd
|
56
|
-
p out.stdout
|
57
|
-
|
58
|
-
out = shell.send_command( "bc", <<CMD )
|
59
|
-
5+5
|
60
|
-
10*2
|
61
|
-
scale=5
|
62
|
-
3/4
|
63
|
-
quit
|
64
|
-
CMD
|
65
|
-
p out.stdout
|
66
|
-
|
67
|
-
p shell.exit
|
68
|
-
|
69
|
-
end
|
data/examples/tail-demo.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# =============================================================================
|
3
|
-
# Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
|
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
|
@@ -1,446 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# =============================================================================
|
3
|
-
# Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
|
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 'thread'
|
18
|
-
require 'net/ssh/connection/constants'
|
19
|
-
require 'net/ssh/errors'
|
20
|
-
|
21
|
-
module Net
|
22
|
-
module SSH
|
23
|
-
module Connection
|
24
|
-
|
25
|
-
class Driver
|
26
|
-
include Constants
|
27
|
-
|
28
|
-
# A structure for representing global requests, as registered by the
|
29
|
-
# #global_request method.
|
30
|
-
Request = Struct.new( :type, :data, :callback )
|
31
|
-
|
32
|
-
# A structure for representing a data buffer that must be sent
|
33
|
-
# across a channel.
|
34
|
-
DataRequest = Struct.new( :channel, :data, :type )
|
35
|
-
|
36
|
-
#--
|
37
|
-
# ====================================================================
|
38
|
-
# CONSTRUCTOR
|
39
|
-
# ====================================================================
|
40
|
-
#++
|
41
|
-
|
42
|
-
# Create a new connection driver that communicates over the given
|
43
|
-
# transport session. +log+ is the logger instance to write log messages
|
44
|
-
# to, buffers is a buffer factory, and channels is a factory that can
|
45
|
-
# return new channel instances.
|
46
|
-
def initialize( session, log, buffers, factories )
|
47
|
-
@session = session
|
48
|
-
@log = log
|
49
|
-
@buffers = buffers
|
50
|
-
@factories = factories
|
51
|
-
|
52
|
-
@channel_id_mutex = Mutex.new
|
53
|
-
@next_channel_id = 0
|
54
|
-
|
55
|
-
@channel_map = Hash.new
|
56
|
-
@request_queue = Array.new
|
57
|
-
@channel_open_handlers = Hash.new
|
58
|
-
|
59
|
-
@data_requests = Array.new
|
60
|
-
@data_requests_mutex = Mutex.new
|
61
|
-
end
|
62
|
-
|
63
|
-
#--
|
64
|
-
# ====================================================================
|
65
|
-
# CHANNEL MANAGEMENT
|
66
|
-
# ====================================================================
|
67
|
-
#++
|
68
|
-
|
69
|
-
# Open and return a new channel. This returns immediately, before the
|
70
|
-
# server confirms that the channel was opened. When the server sends
|
71
|
-
# the confirmation, the +on_confirm+ callback will be invoked.
|
72
|
-
def open_channel( type, extra_data=nil, &on_confirm )
|
73
|
-
channel = @factories[:open].call( type, extra_data )
|
74
|
-
channel.on_confirm_open(&on_confirm)
|
75
|
-
@channel_map[ channel.local_id ] = channel
|
76
|
-
end
|
77
|
-
|
78
|
-
# Remove the given channel from the connection.
|
79
|
-
def remove_channel( channel )
|
80
|
-
@channel_map.delete channel.local_id
|
81
|
-
end
|
82
|
-
|
83
|
-
# Returns an array of active channels.
|
84
|
-
def channels
|
85
|
-
@channel_map.values
|
86
|
-
end
|
87
|
-
|
88
|
-
# Add a callback to be invoked when a channel-open request is recieved
|
89
|
-
# for a channel of the given type. The handler-id is returned.
|
90
|
-
def add_channel_open_handler( type, &block )
|
91
|
-
( @channel_open_handlers[ type ] ||= Array.new ).push block
|
92
|
-
@channel_open_handlers.length
|
93
|
-
end
|
94
|
-
|
95
|
-
# Remove a callback with the given id for channel-open requests of the
|
96
|
-
# given type.
|
97
|
-
def remove_channel_open_handler( type, id )
|
98
|
-
@channel_open_handlers[ type ][ id-1 ] = nil
|
99
|
-
end
|
100
|
-
|
101
|
-
# Return the next available channel id for this connection. This
|
102
|
-
# method is thread-safe.
|
103
|
-
def allocate_channel_id
|
104
|
-
@channel_id_mutex.synchronize do
|
105
|
-
@next_channel_id += 1
|
106
|
-
return @next_channel_id
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Register a data buffer (of an optional type) to be sent across the
|
111
|
-
# given channel at the next available opportunity.
|
112
|
-
#
|
113
|
-
# This is used internally by channels to hide the window size and
|
114
|
-
# maximum packet size from the client. Clients should not call this
|
115
|
-
# method directly.
|
116
|
-
def register_data_request( channel, data, type=nil )
|
117
|
-
@data_requests_mutex.synchronize do
|
118
|
-
@data_requests << DataRequest.new( channel, data, type )
|
119
|
-
end
|
120
|
-
|
121
|
-
# make sure the new data request has a chance to be sent to the
|
122
|
-
# server... Otherwise, it cannot be sent until the next time #process
|
123
|
-
# is invoked, which can be unexpected in synchronous situations.
|
124
|
-
process_data_requests
|
125
|
-
end
|
126
|
-
|
127
|
-
#--
|
128
|
-
# ====================================================================
|
129
|
-
# CONNECTION PROCESSING
|
130
|
-
# ====================================================================
|
131
|
-
#++
|
132
|
-
|
133
|
-
# Repeated call #process for as long as the given block returns
|
134
|
-
# +true+. If no block is given, then the loop continues until there
|
135
|
-
# are no more open channels on this connection.
|
136
|
-
def loop( &block )
|
137
|
-
block ||= proc do
|
138
|
-
channels = @channel_map.reject {|k,v| v.type == 'auth-agent@openssh.com' }
|
139
|
-
not channels.empty?
|
140
|
-
end
|
141
|
-
process while block.call
|
142
|
-
end
|
143
|
-
|
144
|
-
# Wait for and dispatch a single event. If +nonblock+ is false (the
|
145
|
-
# default) this will block until a message has been received. Otherwise,
|
146
|
-
# it will return immediately.
|
147
|
-
def process( nonblock=false )
|
148
|
-
process_data_requests
|
149
|
-
|
150
|
-
if !nonblock || reader_ready?
|
151
|
-
type, response = @session.wait_for_message
|
152
|
-
|
153
|
-
unless ( dispatcher = MESSAGES[ type ] )
|
154
|
-
raise Net::SSH::Exception,
|
155
|
-
"Unexpected response type '#{type}', (#{response.inspect})"
|
156
|
-
end
|
157
|
-
|
158
|
-
dispatcher[:method].bind( self ).call( response )
|
159
|
-
end
|
160
|
-
|
161
|
-
self
|
162
|
-
end
|
163
|
-
|
164
|
-
#--
|
165
|
-
# ====================================================================
|
166
|
-
# COMMUNICATION
|
167
|
-
# ====================================================================
|
168
|
-
#++
|
169
|
-
|
170
|
-
# Send a global request packet to the server. This returns immediately.
|
171
|
-
# The given block will be invoked when the server responds.
|
172
|
-
def global_request( type, data=nil, &block )
|
173
|
-
writer = @buffers.writer
|
174
|
-
writer.write_byte GLOBAL_REQUEST
|
175
|
-
writer.write_string type.to_s
|
176
|
-
writer.write_bool true
|
177
|
-
writer.write data.to_s if data
|
178
|
-
@session.send_message writer
|
179
|
-
|
180
|
-
@request_queue.push Request.new( type, data, block )
|
181
|
-
self
|
182
|
-
end
|
183
|
-
|
184
|
-
# Send a channel request packet to the server.
|
185
|
-
def channel_request( type )
|
186
|
-
writer = @buffers.writer
|
187
|
-
writer.write_byte CHANNEL_REQUEST
|
188
|
-
writer.write_long 0 # channel id
|
189
|
-
writer.write_string type
|
190
|
-
writer.write_byte 0 # want_confirm
|
191
|
-
|
192
|
-
@session.send_message writer
|
193
|
-
end
|
194
|
-
|
195
|
-
# A convenience method for sending messages.
|
196
|
-
def send_message( msg )
|
197
|
-
@session.send_message msg
|
198
|
-
self
|
199
|
-
end
|
200
|
-
|
201
|
-
# Delegates to the #reader_ready method of the transport session.
|
202
|
-
def reader_ready?
|
203
|
-
@session.reader_ready?
|
204
|
-
end
|
205
|
-
|
206
|
-
# Sends an innocuous packet to the server to test the connection. Can
|
207
|
-
# be used to defeat timeouts on long-running commands.
|
208
|
-
def ping!
|
209
|
-
@session.ping!
|
210
|
-
end
|
211
|
-
|
212
|
-
#--
|
213
|
-
# ====================================================================
|
214
|
-
# MESSAGE HANDLERS
|
215
|
-
# ====================================================================
|
216
|
-
#++
|
217
|
-
|
218
|
-
def do_global_request( response )
|
219
|
-
name = response.read_string
|
220
|
-
want_reply = response.read_bool
|
221
|
-
request_data = response.remainder_as_buffer
|
222
|
-
|
223
|
-
@log.debug "GLOBAL_REQUEST received (#{name})" if @log.debug?
|
224
|
-
|
225
|
-
if want_reply
|
226
|
-
writer = @buffers.writer
|
227
|
-
writer.write_byte REQUEST_SUCCESS
|
228
|
-
@session.send_message writer
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def do_request_success( response )
|
233
|
-
@log.debug "REQUEST_SUCCESS received" if @log.debug?
|
234
|
-
process_request response, true
|
235
|
-
end
|
236
|
-
|
237
|
-
def do_request_failure( response )
|
238
|
-
@log.debug "REQUEST_FAILURE received" if @log.debug?
|
239
|
-
process_request response, false
|
240
|
-
end
|
241
|
-
|
242
|
-
def do_channel_open( response )
|
243
|
-
ch_type = response.read_string
|
244
|
-
@log.debug "CHANNEL_OPEN recieved (#{ch_type})" if @log.debug?
|
245
|
-
handled = false
|
246
|
-
|
247
|
-
sender_channel = response.read_long
|
248
|
-
window_size = response.read_long
|
249
|
-
packet_size = response.read_long
|
250
|
-
|
251
|
-
channel = @factories[:create].call( ch_type, sender_channel,
|
252
|
-
window_size, packet_size )
|
253
|
-
|
254
|
-
( @channel_open_handlers[ ch_type ] || [] ).each do |handler|
|
255
|
-
next unless handler
|
256
|
-
handled = true
|
257
|
-
handler.call( self, channel, response )
|
258
|
-
end
|
259
|
-
|
260
|
-
unless handled
|
261
|
-
raise Net::SSH::Exception,
|
262
|
-
"cannot handle request to open a channel of type '#{ch_type}'"
|
263
|
-
end
|
264
|
-
|
265
|
-
@channel_map[channel.local_id] = channel
|
266
|
-
|
267
|
-
writer = @buffers.writer
|
268
|
-
writer.write_byte CHANNEL_OPEN_CONFIRMATION
|
269
|
-
writer.write_long channel.remote_id
|
270
|
-
writer.write_long channel.local_id
|
271
|
-
writer.write_long 0x7FFFFFFF
|
272
|
-
writer.write_long 0x7FFFFFFF
|
273
|
-
@session.send_message writer
|
274
|
-
end
|
275
|
-
|
276
|
-
def do_channel_open_failure( response )
|
277
|
-
local_id = response.read_long
|
278
|
-
reason_code = response.read_long
|
279
|
-
reason = response.read_string
|
280
|
-
language = response.read_string
|
281
|
-
|
282
|
-
@log.debug "CHANNEL_OPEN_FAILURE recieved (#{reason})" if @log.debug?
|
283
|
-
|
284
|
-
channel = @channel_map[ local_id ]
|
285
|
-
@channel_map.delete local_id
|
286
|
-
channel.do_confirm_failed reason_code, reason, language
|
287
|
-
end
|
288
|
-
|
289
|
-
def do_channel_open_confirmation( response )
|
290
|
-
local_id = response.read_long
|
291
|
-
remote_id = response.read_long
|
292
|
-
window_size = response.read_long
|
293
|
-
packet_size = response.read_long
|
294
|
-
|
295
|
-
if @log.debug?
|
296
|
-
@log.debug "CHANNEL_OPEN_CONFIRMATION recieved (#{local_id})"
|
297
|
-
end
|
298
|
-
|
299
|
-
channel = @channel_map[ local_id ]
|
300
|
-
channel.do_confirm_open remote_id, window_size, packet_size
|
301
|
-
end
|
302
|
-
|
303
|
-
def do_channel_window_adjust( response )
|
304
|
-
local_id = response.read_long
|
305
|
-
bytes_to_add = response.read_long
|
306
|
-
|
307
|
-
if @log.debug?
|
308
|
-
@log.debug "CHANNEL_WINDOW_ADJUST recieved " +
|
309
|
-
"(#{local_id}:#{bytes_to_add})"
|
310
|
-
end
|
311
|
-
|
312
|
-
@channel_map[ local_id ].do_window_adjust( bytes_to_add )
|
313
|
-
end
|
314
|
-
|
315
|
-
def do_channel_data( response )
|
316
|
-
local_id = response.read_long
|
317
|
-
data = response.read_string
|
318
|
-
|
319
|
-
if @log.debug?
|
320
|
-
@log.debug "CHANNEL_DATA recieved (#{local_id}:#{data.inspect})"
|
321
|
-
end
|
322
|
-
|
323
|
-
@channel_map[ local_id ].do_data data
|
324
|
-
end
|
325
|
-
|
326
|
-
def do_channel_extended_data( response )
|
327
|
-
local_id = response.read_long
|
328
|
-
data_type = response.read_long
|
329
|
-
data = response.read_string
|
330
|
-
|
331
|
-
if @log.debug?
|
332
|
-
@log.debug "CHANNEL_EXTENDED_DATA recieved " +
|
333
|
-
"(#{local_id}:#{data_type}:#{data.inspect})"
|
334
|
-
end
|
335
|
-
|
336
|
-
@channel_map[ local_id ].do_extended_data data_type, data
|
337
|
-
end
|
338
|
-
|
339
|
-
def do_channel_eof( response )
|
340
|
-
local_id = response.read_long
|
341
|
-
@log.debug "CHANNEL_EOF recieved (#{local_id})" if @log.debug?
|
342
|
-
@channel_map[ local_id ].do_eof
|
343
|
-
end
|
344
|
-
|
345
|
-
def do_channel_close( response )
|
346
|
-
local_id = response.read_long
|
347
|
-
@log.debug "CHANNEL_CLOSE recieved (#{local_id})" if @log.debug?
|
348
|
-
@channel_map[ local_id ].close false
|
349
|
-
end
|
350
|
-
|
351
|
-
def do_channel_request( response )
|
352
|
-
local_id = response.read_long
|
353
|
-
request = response.read_string
|
354
|
-
want_reply = response.read_bool
|
355
|
-
request_data = response.remainder_as_buffer
|
356
|
-
|
357
|
-
if @log.debug?
|
358
|
-
@log.debug "CHANNEL_REQUEST recieved (#{local_id}:#{request})"
|
359
|
-
end
|
360
|
-
|
361
|
-
@channel_map[ local_id ].do_request request, want_reply, request_data
|
362
|
-
end
|
363
|
-
|
364
|
-
def do_channel_success( response )
|
365
|
-
local_id = response.read_long
|
366
|
-
@log.debug "CHANNEL_SUCCESS recieved (#{local_id})" if @log.debug?
|
367
|
-
@channel_map[ local_id ].do_success
|
368
|
-
end
|
369
|
-
|
370
|
-
def do_channel_failure( response )
|
371
|
-
local_id = response.read_long
|
372
|
-
@log.debug "CHANNEL_FAILURE recieved (#{local_id})" if @log.debug?
|
373
|
-
@channel_map[ local_id ].do_failure
|
374
|
-
end
|
375
|
-
|
376
|
-
#--
|
377
|
-
# ====================================================================
|
378
|
-
# INTERNAL STATE MANAGEMENT
|
379
|
-
# ====================================================================
|
380
|
-
private
|
381
|
-
#++
|
382
|
-
|
383
|
-
# Process a response recived from a "global_request".
|
384
|
-
def process_request( response, success )
|
385
|
-
request = @request_queue.shift
|
386
|
-
request.callback.call( success, response ) if request.callback
|
387
|
-
end
|
388
|
-
|
389
|
-
# Process all pending data requests.
|
390
|
-
def process_data_requests
|
391
|
-
# guard against recursive calls
|
392
|
-
return if @processing_data_requests
|
393
|
-
|
394
|
-
# guard against simultaneous calls
|
395
|
-
@data_requests_mutex.synchronize do
|
396
|
-
begin
|
397
|
-
@processing_data_requests = true
|
398
|
-
@data_requests.map! do |req|
|
399
|
-
while req && req.channel.window_size > 0
|
400
|
-
remaining = if req.type
|
401
|
-
req.channel.send_extended_data_packet( req.type, req.data )
|
402
|
-
else
|
403
|
-
req.channel.send_data_packet( req.data )
|
404
|
-
end
|
405
|
-
if remaining
|
406
|
-
req.data = remaining
|
407
|
-
else
|
408
|
-
req = nil
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
req
|
413
|
-
end
|
414
|
-
@data_requests.compact!
|
415
|
-
ensure
|
416
|
-
@processing_data_requests = false
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
#--
|
422
|
-
# ====================================================================
|
423
|
-
# MESSAGE DISPATCHER SETUP
|
424
|
-
# ====================================================================
|
425
|
-
#++
|
426
|
-
|
427
|
-
MESSAGES = %w(
|
428
|
-
global_request
|
429
|
-
request_success request_failure channel_open channel_open_failure
|
430
|
-
channel_open_confirmation channel_window_adjust channel_data
|
431
|
-
channel_extended_data channel_eof channel_close channel_request
|
432
|
-
channel_success channel_failure
|
433
|
-
).inject({}) do |map, event|
|
434
|
-
constant = Constants.const_get event.upcase.to_sym
|
435
|
-
map[constant] = {
|
436
|
-
:name => event.to_sym,
|
437
|
-
:method => instance_method( "do_#{event}".to_sym )
|
438
|
-
}
|
439
|
-
map
|
440
|
-
end
|
441
|
-
|
442
|
-
end
|
443
|
-
|
444
|
-
end
|
445
|
-
end
|
446
|
-
end
|