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
@@ -1,72 +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
|
-
module Net
|
18
|
-
module SSH
|
19
|
-
module Connection
|
20
|
-
|
21
|
-
# Register the services that define the "connection" layer of the SSH
|
22
|
-
# protocol.
|
23
|
-
def register_services( container )
|
24
|
-
|
25
|
-
# The :connection namespace contains all of the services in the
|
26
|
-
# connection layer of the SSH protocol.
|
27
|
-
container.namespace_define :connection do |ns|
|
28
|
-
|
29
|
-
# The :channel namespace contains the channel-specific services.
|
30
|
-
ns.namespace_define :channel do |ch|
|
31
|
-
|
32
|
-
# The :open service provides a proc object that may be used to
|
33
|
-
# request that a new channel be opened.
|
34
|
-
ch.open do |c,p|
|
35
|
-
require 'net/ssh/connection/channel'
|
36
|
-
lambda do |type, data|
|
37
|
-
Channel.open( c[:driver],
|
38
|
-
c[:log_for, p],
|
39
|
-
c[:transport][:buffers],
|
40
|
-
type, data )
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# The :create service provides a proc object that may be used to
|
45
|
-
# create new channels, without sending a request to the server.
|
46
|
-
ch.create do |c,p|
|
47
|
-
require 'net/ssh/connection/channel'
|
48
|
-
lambda do |type,rid,wsize,psize|
|
49
|
-
Channel.create( c[:driver],
|
50
|
-
c[:log_for, p],
|
51
|
-
c[:transport][:buffers],
|
52
|
-
type, rid, wsize, psize )
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# The :driver service manages the connection layer.
|
58
|
-
ns.driver do |c,p|
|
59
|
-
require 'net/ssh/connection/driver'
|
60
|
-
Driver.new( c[:transport][:session],
|
61
|
-
c[:log_for, p],
|
62
|
-
c[:transport][:buffers],
|
63
|
-
:open => c[:channel][:open],
|
64
|
-
:create => c[:channel][:create] )
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
module_function :register_services
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'net/ssh/errors'
|
2
|
-
require 'net/ssh/known-hosts'
|
3
|
-
|
4
|
-
module Net
|
5
|
-
module SSH
|
6
|
-
|
7
|
-
class HostKeyVerifier
|
8
|
-
def verify(arguments)
|
9
|
-
host = canonize(arguments[:peer])
|
10
|
-
matches = Net::SSH::KnownHosts.search_for(host)
|
11
|
-
|
12
|
-
# we've never seen this host before, so just automatically add the key.
|
13
|
-
# not the most secure option (since the first hit might be the one that
|
14
|
-
# is hacked), but since almost nobody actually compares the key
|
15
|
-
# fingerprint, this is a reasonable compromise between usability and
|
16
|
-
# security.
|
17
|
-
if matches.empty?
|
18
|
-
Net::SSH::KnownHosts.add(host, arguments[:key])
|
19
|
-
return true
|
20
|
-
end
|
21
|
-
|
22
|
-
# If we found any matches, check to see that the key type and
|
23
|
-
# blob also match.
|
24
|
-
found = matches.any? do |key|
|
25
|
-
key.ssh_type == arguments[:key].ssh_type &&
|
26
|
-
key.to_blob == arguments[:key].to_blob
|
27
|
-
end
|
28
|
-
|
29
|
-
# If a match was found, return true. Otherwise, raise an exception
|
30
|
-
# indicating that the key was not recognized.
|
31
|
-
found || process_cache_miss(host, arguments)
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def process_cache_miss(host, args)
|
37
|
-
exception = HostKeyMismatch.new("fingerprint #{args[:fingerprint]} does not match for #{host.join(',')}")
|
38
|
-
exception.data = args
|
39
|
-
exception.callback = Proc.new { Net::SSH::KnownHosts.add(host, args[:key]) }
|
40
|
-
raise exception
|
41
|
-
end
|
42
|
-
|
43
|
-
def canonize(peer)
|
44
|
-
hosts = []
|
45
|
-
hosts << Net::SSH::KnownHosts.canonize(peer[:host], peer[:port])
|
46
|
-
hosts << Net::SSH::KnownHosts.canonize(peer[:ip], peer[:port])
|
47
|
-
hosts.compact
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
data/lib/net/ssh/known-hosts.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
require 'net/ssh/transport/ossl/buffer'
|
3
|
-
require 'net/ssh/util/openssl'
|
4
|
-
|
5
|
-
module Net; module SSH
|
6
|
-
class KnownHosts
|
7
|
-
class <<self
|
8
|
-
def canonize(location, port)
|
9
|
-
value = location
|
10
|
-
value = "[#{value}]:#{port}" if port && port != 22
|
11
|
-
value
|
12
|
-
end
|
13
|
-
|
14
|
-
def search_for(host)
|
15
|
-
search_in(hostfile_locations, host)
|
16
|
-
end
|
17
|
-
|
18
|
-
def add(host, key)
|
19
|
-
hostfile_locations.each do |file|
|
20
|
-
begin
|
21
|
-
KnownHosts.new(file).add(host, key)
|
22
|
-
return
|
23
|
-
rescue SystemCallError
|
24
|
-
# try the next hostfile
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def search_in(files, host)
|
30
|
-
files.map { |file| KnownHosts.new(file).keys_for(host) }.flatten
|
31
|
-
end
|
32
|
-
|
33
|
-
def hostfile_locations
|
34
|
-
@hostfile_locations ||= [
|
35
|
-
"#{home_directory}/.ssh/known_hosts",
|
36
|
-
"#{home_directory}/.ssh/known_hosts2",
|
37
|
-
"/etc/ssh/ssh_known_hosts",
|
38
|
-
"/etc/ssh/ssh_known_hosts2"
|
39
|
-
]
|
40
|
-
end
|
41
|
-
|
42
|
-
def home_directory
|
43
|
-
ENV['HOME'] ||
|
44
|
-
(ENV['HOMEPATH'] && "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}") ||
|
45
|
-
"/"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
attr_reader :source
|
51
|
-
|
52
|
-
def initialize(source)
|
53
|
-
@source = source
|
54
|
-
end
|
55
|
-
|
56
|
-
def keys_for(host)
|
57
|
-
keys = []
|
58
|
-
hosts = Array(host)
|
59
|
-
|
60
|
-
File.open(source) do |file|
|
61
|
-
scanner = StringScanner.new("")
|
62
|
-
file.each_line do |line|
|
63
|
-
scanner.string = line
|
64
|
-
|
65
|
-
scanner.skip(/\s*/)
|
66
|
-
next if scanner.match?(/$|#/)
|
67
|
-
|
68
|
-
hostlist = scanner.scan(/\S+/)
|
69
|
-
next if (hostlist.split(/,/) & hosts).empty?
|
70
|
-
|
71
|
-
scanner.skip(/\s*/)
|
72
|
-
type = scanner.scan(/\S+/)
|
73
|
-
scanner.skip(/\s*/)
|
74
|
-
blob = scanner.rest.unpack("m*").first
|
75
|
-
keys << Net::SSH::Transport::OSSL::Buffer.new(blob).read_key
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
keys
|
80
|
-
rescue SystemCallError
|
81
|
-
return []
|
82
|
-
end
|
83
|
-
|
84
|
-
def add(host, key)
|
85
|
-
dir = File.dirname(source)
|
86
|
-
Dir.mkdir(dir, 0700) if !File.exists?(dir)
|
87
|
-
|
88
|
-
File.open(source, "a") do |file|
|
89
|
-
buffer = Net::SSH::Transport::OSSL::Buffer.new
|
90
|
-
buffer.write_key(key)
|
91
|
-
blob = [buffer.to_s].pack("m*").gsub(/\s/, "")
|
92
|
-
file.puts "#{Array(host).join(',')} #{key.ssh_type} #{blob}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end; end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'net/ssh/host-key-verifier'
|
2
|
-
|
3
|
-
module Net
|
4
|
-
module SSH
|
5
|
-
|
6
|
-
class LenientHostKeyVerifier < HostKeyVerifier
|
7
|
-
def verify(arguments)
|
8
|
-
return true if tunnelled?(arguments)
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
# A connection is potentially being tunnelled if the port is not 22,
|
15
|
-
# and the ip refers to the localhost.
|
16
|
-
def tunnelled?(args)
|
17
|
-
return false if args[:peer][:port].to_i == 22
|
18
|
-
|
19
|
-
ip = args[:peer][:ip]
|
20
|
-
return ip == "127.0.0.1" || ip == "::1"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Net
|
2
|
-
module SSH
|
3
|
-
|
4
|
-
# The NullHostKeyVerifier simply allows every key it sees, without
|
5
|
-
# bothering to verify. This mimics the pre-1.1 behavior of Net::SSH, but
|
6
|
-
# is not very secure.
|
7
|
-
class NullHostKeyVerifier
|
8
|
-
def verify(arguments)
|
9
|
-
true
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# =============================================================================
|
3
|
-
# Copyright (c) 2007, Chris Andrews (chris@nodnol.org),
|
4
|
-
# Jamis Buck (jgb3@email.byu.edu)
|
5
|
-
# All rights reserved.
|
6
|
-
#
|
7
|
-
# This source file is distributed as part of the Net::SSH Secure Shell Client
|
8
|
-
# library for Ruby. This file (and the library as a whole) may be used only as
|
9
|
-
# allowed by either the BSD license, or the Ruby license (or, by association
|
10
|
-
# with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
|
11
|
-
# distribution for the texts of these licenses.
|
12
|
-
# -----------------------------------------------------------------------------
|
13
|
-
# net-ssh website : http://net-ssh.rubyforge.org
|
14
|
-
# project website: http://rubyforge.org/projects/net-ssh
|
15
|
-
# =============================================================================
|
16
|
-
#++
|
17
|
-
|
18
|
-
module Net
|
19
|
-
module SSH
|
20
|
-
module Service
|
21
|
-
module AgentForward
|
22
|
-
|
23
|
-
class Driver
|
24
|
-
|
25
|
-
def initialize( connection, buffers, log, agent )
|
26
|
-
@connection = connection
|
27
|
-
@buffers = buffers
|
28
|
-
@log = log
|
29
|
-
@agent = agent
|
30
|
-
@data = ''
|
31
|
-
|
32
|
-
@connection.add_channel_open_handler(
|
33
|
-
"auth-agent@openssh.com", &method(:do_open_channel) )
|
34
|
-
end
|
35
|
-
|
36
|
-
def request
|
37
|
-
@connection.channel_request( 'auth-agent-req@openssh.com' )
|
38
|
-
end
|
39
|
-
|
40
|
-
def do_open_channel( connection, channel, data )
|
41
|
-
channel.on_data(&method(:do_data))
|
42
|
-
end
|
43
|
-
|
44
|
-
# handle CHANNEL_DATA packets received on the agent-forward
|
45
|
-
# channel - pass complete received packets to the agent.
|
46
|
-
def do_data( channel, data )
|
47
|
-
@data = @data + data
|
48
|
-
reply = call_agent
|
49
|
-
if reply
|
50
|
-
channel.send_data reply
|
51
|
-
@data = ''
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Called if we have any data to forward to the
|
56
|
-
# agent. Examines the accumulated data to see if we have a
|
57
|
-
# complete packet, based on the length field (the first four
|
58
|
-
# bytes as a network long).
|
59
|
-
def call_agent
|
60
|
-
# if we have enough data to check the length of this packet
|
61
|
-
if @data.length >= 4
|
62
|
-
packet_length = @data[0..3].unpack('N').first
|
63
|
-
# send the complete packet to the agent and read the
|
64
|
-
# response
|
65
|
-
if @data.length == (4 + packet_length)
|
66
|
-
@agent.send_raw_packet @data
|
67
|
-
buffer = @agent.read_raw_packet
|
68
|
-
end
|
69
|
-
end
|
70
|
-
buffer
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
end # AgentForward
|
76
|
-
end # Service
|
77
|
-
end # SSH
|
78
|
-
end # Net
|
@@ -1,41 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# =============================================================================
|
3
|
-
# Copyright (c) 2007, Chris Andrews (chris@nodnol.org),
|
4
|
-
# Jamis Buck (jgb3@email.byu.edu)
|
5
|
-
# All rights reserved.
|
6
|
-
#
|
7
|
-
# This source file is distributed as part of the Net::SSH Secure Shell Client
|
8
|
-
# library for Ruby. This file (and the library as a whole) may be used only as
|
9
|
-
# allowed by either the BSD license, or the Ruby license (or, by association
|
10
|
-
# with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
|
11
|
-
# distribution for the texts of these licenses.
|
12
|
-
# -----------------------------------------------------------------------------
|
13
|
-
# net-ssh website : http://net-ssh.rubyforge.org
|
14
|
-
# project website: http://rubyforge.org/projects/net-ssh
|
15
|
-
# =============================================================================
|
16
|
-
#++
|
17
|
-
|
18
|
-
module Net
|
19
|
-
module SSH
|
20
|
-
module Service
|
21
|
-
module AgentForward
|
22
|
-
|
23
|
-
def register_services( container )
|
24
|
-
|
25
|
-
container.namespace_define :agentforward do |ns|
|
26
|
-
ns.driver :model => :singleton_deferred do |c,p|
|
27
|
-
require 'net/ssh/service/agentforward/driver'
|
28
|
-
Driver.new( c[:connection][:driver],
|
29
|
-
c[:transport][:buffers],
|
30
|
-
c[:log_for, p],
|
31
|
-
c[:userauth].agent)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
module_function :register_services
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,319 +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 '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
|
-
key = [ local_port.to_i, bind_address ]
|
152
|
-
|
153
|
-
if @log.debug?
|
154
|
-
@log.debug "starting local forwarding server on " +
|
155
|
-
key.inspect
|
156
|
-
end
|
157
|
-
|
158
|
-
socket = TCPServer.new( bind_address, local_port )
|
159
|
-
|
160
|
-
Thread.new do
|
161
|
-
begin
|
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
|