net-ssh 1.1.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|