net-ssh 2.7.0 → 7.3.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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.dockerignore +6 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +94 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +22 -0
- data/.rubocop_todo.yml +1081 -0
- data/CHANGES.txt +387 -0
- data/DEVELOPMENT.md +23 -0
- data/Dockerfile +29 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +13 -0
- data/Gemfile.noed25519 +12 -0
- data/Gemfile.norbnacl +12 -0
- data/ISSUE_TEMPLATE.md +30 -0
- data/Manifest +4 -5
- data/README.md +303 -0
- data/Rakefile +174 -40
- data/SECURITY.md +4 -0
- data/THANKS.txt +25 -0
- data/appveyor.yml +58 -0
- data/docker-compose.yml +25 -0
- data/lib/net/ssh/authentication/agent.rb +279 -18
- data/lib/net/ssh/authentication/certificate.rb +183 -0
- data/lib/net/ssh/authentication/constants.rb +17 -15
- data/lib/net/ssh/authentication/ed25519.rb +184 -0
- data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
- data/lib/net/ssh/authentication/key_manager.rb +125 -54
- data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
- data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
- data/lib/net/ssh/authentication/methods/none.rb +16 -19
- data/lib/net/ssh/authentication/methods/password.rb +56 -19
- data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
- data/lib/net/ssh/authentication/pageant.rb +483 -246
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +138 -120
- data/lib/net/ssh/buffer.rb +399 -300
- data/lib/net/ssh/buffered_io.rb +154 -150
- data/lib/net/ssh/config.rb +361 -166
- data/lib/net/ssh/connection/channel.rb +640 -596
- data/lib/net/ssh/connection/constants.rb +29 -29
- data/lib/net/ssh/connection/event_loop.rb +123 -0
- data/lib/net/ssh/connection/keepalive.rb +59 -0
- data/lib/net/ssh/connection/session.rb +628 -548
- data/lib/net/ssh/connection/term.rb +125 -123
- data/lib/net/ssh/errors.rb +101 -95
- data/lib/net/ssh/key_factory.rb +198 -100
- data/lib/net/ssh/known_hosts.rb +221 -98
- data/lib/net/ssh/loggable.rb +50 -49
- data/lib/net/ssh/packet.rb +83 -79
- data/lib/net/ssh/prompt.rb +50 -81
- data/lib/net/ssh/proxy/command.rb +108 -60
- data/lib/net/ssh/proxy/errors.rb +12 -10
- data/lib/net/ssh/proxy/http.rb +82 -78
- data/lib/net/ssh/proxy/https.rb +50 -0
- data/lib/net/ssh/proxy/jump.rb +54 -0
- data/lib/net/ssh/proxy/socks4.rb +5 -8
- data/lib/net/ssh/proxy/socks5.rb +18 -20
- data/lib/net/ssh/service/forward.rb +383 -255
- data/lib/net/ssh/test/channel.rb +145 -136
- data/lib/net/ssh/test/extensions.rb +131 -110
- data/lib/net/ssh/test/kex.rb +34 -32
- data/lib/net/ssh/test/local_packet.rb +46 -44
- data/lib/net/ssh/test/packet.rb +89 -70
- data/lib/net/ssh/test/remote_packet.rb +32 -30
- data/lib/net/ssh/test/script.rb +156 -142
- data/lib/net/ssh/test/socket.rb +49 -48
- data/lib/net/ssh/test.rb +82 -77
- data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
- data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
- data/lib/net/ssh/transport/algorithms.rb +472 -348
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/lib/net/ssh/transport/cipher_factory.rb +124 -100
- data/lib/net/ssh/transport/constants.rb +32 -24
- data/lib/net/ssh/transport/ctr.rb +42 -22
- data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac.rb +14 -12
- data/lib/net/ssh/transport/identity_cipher.rb +54 -44
- data/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/kex.rb +15 -12
- data/lib/net/ssh/transport/key_expander.rb +24 -20
- data/lib/net/ssh/transport/openssl.rb +161 -124
- data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/lib/net/ssh/transport/packet_stream.rb +246 -183
- data/lib/net/ssh/transport/server_version.rb +57 -51
- data/lib/net/ssh/transport/session.rb +307 -235
- data/lib/net/ssh/transport/state.rb +178 -176
- data/lib/net/ssh/verifiers/accept_new.rb +33 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
- data/lib/net/ssh/verifiers/always.rb +58 -0
- data/lib/net/ssh/verifiers/never.rb +19 -0
- data/lib/net/ssh/version.rb +57 -51
- data/lib/net/ssh.rb +140 -40
- data/net-ssh-public_cert.pem +21 -0
- data/net-ssh.gemspec +39 -184
- data/support/ssh_tunnel_bug.rb +5 -5
- data.tar.gz.sig +0 -0
- metadata +205 -99
- metadata.gz.sig +0 -0
- data/README.rdoc +0 -219
- data/Rudyfile +0 -96
- data/gem-public_cert.pem +0 -20
- data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
- data/lib/net/ssh/authentication/agent/socket.rb +0 -170
- data/lib/net/ssh/ruby_compat.rb +0 -51
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -54
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/setup.rb +0 -1585
- data/support/arcfour_check.rb +0 -20
- data/test/README.txt +0 -47
- data/test/authentication/methods/common.rb +0 -28
- data/test/authentication/methods/test_abstract.rb +0 -51
- data/test/authentication/methods/test_hostbased.rb +0 -114
- data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
- data/test/authentication/methods/test_none.rb +0 -41
- data/test/authentication/methods/test_password.rb +0 -52
- data/test/authentication/methods/test_publickey.rb +0 -148
- data/test/authentication/test_agent.rb +0 -205
- data/test/authentication/test_key_manager.rb +0 -218
- data/test/authentication/test_session.rb +0 -108
- data/test/common.rb +0 -108
- data/test/configs/eqsign +0 -3
- data/test/configs/exact_match +0 -8
- data/test/configs/host_plus +0 -10
- data/test/configs/multihost +0 -4
- data/test/configs/nohost +0 -19
- data/test/configs/numeric_host +0 -4
- data/test/configs/send_env +0 -2
- data/test/configs/substitutes +0 -8
- data/test/configs/wild_cards +0 -14
- data/test/connection/test_channel.rb +0 -467
- data/test/connection/test_session.rb +0 -526
- data/test/known_hosts/github +0 -1
- data/test/manual/test_forward.rb +0 -223
- data/test/start/test_options.rb +0 -36
- data/test/start/test_transport.rb +0 -28
- data/test/test_all.rb +0 -11
- data/test/test_buffer.rb +0 -433
- data/test/test_buffered_io.rb +0 -63
- data/test/test_config.rb +0 -151
- data/test/test_key_factory.rb +0 -173
- data/test/test_known_hosts.rb +0 -13
- data/test/transport/hmac/test_md5.rb +0 -41
- data/test/transport/hmac/test_md5_96.rb +0 -27
- data/test/transport/hmac/test_none.rb +0 -34
- data/test/transport/hmac/test_ripemd160.rb +0 -36
- data/test/transport/hmac/test_sha1.rb +0 -36
- data/test/transport/hmac/test_sha1_96.rb +0 -27
- data/test/transport/hmac/test_sha2_256.rb +0 -37
- data/test/transport/hmac/test_sha2_256_96.rb +0 -27
- data/test/transport/hmac/test_sha2_512.rb +0 -37
- data/test/transport/hmac/test_sha2_512_96.rb +0 -27
- data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
- data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
- data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
- data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
- data/test/transport/test_algorithms.rb +0 -330
- data/test/transport/test_cipher_factory.rb +0 -443
- data/test/transport/test_hmac.rb +0 -34
- data/test/transport/test_identity_cipher.rb +0 -40
- data/test/transport/test_packet_stream.rb +0 -1755
- data/test/transport/test_server_version.rb +0 -78
- data/test/transport/test_session.rb +0 -319
- data/test/transport/test_state.rb +0 -181
data/lib/net/ssh/test/channel.rb
CHANGED
@@ -1,138 +1,147 @@
|
|
1
|
-
module Net
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Test
|
4
|
+
# A mock channel, used for scripting actions in tests. It wraps a
|
5
|
+
# Net::SSH::Test::Script instance, and delegates to it for the most part.
|
6
|
+
# This class has little real functionality on its own, but rather acts as
|
7
|
+
# a convenience for scripting channel-related activity for later comparison
|
8
|
+
# in a unit test.
|
9
|
+
#
|
10
|
+
# story do |session|
|
11
|
+
# channel = session.opens_channel
|
12
|
+
# channel.sends_exec "ls"
|
13
|
+
# channel.gets_data "result of ls"
|
14
|
+
# channel.gets_extended_data "some error coming from ls"
|
15
|
+
# channel.gets_close
|
16
|
+
# channel.sends_close
|
17
|
+
# end
|
18
|
+
class Channel
|
19
|
+
# The Net::SSH::Test::Script instance employed by this mock channel.
|
20
|
+
attr_reader :script
|
21
|
+
|
22
|
+
# Sets the local-id of this channel object (the id assigned by the client).
|
23
|
+
attr_writer :local_id
|
24
|
+
|
25
|
+
# Sets the remote-id of this channel object (the id assigned by the mock-server).
|
26
|
+
attr_writer :remote_id
|
27
|
+
|
28
|
+
# Creates a new Test::Channel instance on top of the given +script+ (which
|
29
|
+
# must be a Net::SSH::Test::Script instance).
|
30
|
+
def initialize(script)
|
31
|
+
@script = script
|
32
|
+
@local_id = @remote_id = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the local (client-assigned) id for this channel, or a Proc object
|
36
|
+
# that will return the local-id later if the local id has not yet been set.
|
37
|
+
# (See Net::SSH::Test::Packet#instantiate!.)
|
38
|
+
def local_id
|
39
|
+
@local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the remote (server-assigned) id for this channel, or a Proc object
|
43
|
+
# that will return the remote-id later if the remote id has not yet been set.
|
44
|
+
# (See Net::SSH::Test::Packet#instantiate!.)
|
45
|
+
def remote_id
|
46
|
+
@remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Because adjacent calls to #gets_data will sometimes cause the data packets
|
50
|
+
# to be concatenated (causing expectations in tests to fail), you may
|
51
|
+
# need to separate those calls with calls to #inject_remote_delay! (which
|
52
|
+
# essentially just mimics receiving an empty data packet):
|
53
|
+
#
|
54
|
+
# channel.gets_data "abcdefg"
|
55
|
+
# channel.inject_remote_delay!
|
56
|
+
# channel.gets_data "hijklmn"
|
57
|
+
def inject_remote_delay!
|
58
|
+
gets_data("")
|
59
|
+
end
|
60
|
+
|
61
|
+
# Scripts the sending of an "exec" channel request packet to the mock
|
62
|
+
# server. If +reply+ is true, then the server is expected to reply to the
|
63
|
+
# request, otherwise no response to this request will be sent. If +success+
|
64
|
+
# is +true+, then the request will be successful, otherwise a failure will
|
65
|
+
# be scripted.
|
66
|
+
#
|
67
|
+
# channel.sends_exec "ls -l"
|
68
|
+
def sends_exec(command, reply = true, success = true)
|
69
|
+
script.sends_channel_request(self, "exec", reply, command, success)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Scripts the sending of a "subsystem" channel request packet to the mock
|
73
|
+
# server. See #sends_exec for a discussion of the meaning of the +reply+
|
74
|
+
# and +success+ arguments.
|
75
|
+
#
|
76
|
+
# channel.sends_subsystem "sftp"
|
77
|
+
def sends_subsystem(subsystem, reply = true, success = true)
|
78
|
+
script.sends_channel_request(self, "subsystem", reply, subsystem, success)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Scripts the sending of a data packet across the channel.
|
82
|
+
#
|
83
|
+
# channel.sends_data "foo"
|
84
|
+
def sends_data(data)
|
85
|
+
script.sends_channel_data(self, data)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Scripts the sending of an EOF packet across the channel.
|
89
|
+
#
|
90
|
+
# channel.sends_eof
|
91
|
+
def sends_eof
|
92
|
+
script.sends_channel_eof(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Scripts the sending of a "channel close" packet across the channel.
|
96
|
+
#
|
97
|
+
# channel.sends_close
|
98
|
+
def sends_close
|
99
|
+
script.sends_channel_close(self)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Scripts the sending of a "request pty" request packet across the channel.
|
103
|
+
#
|
104
|
+
# channel.sends_request_pty
|
105
|
+
def sends_request_pty
|
106
|
+
script.sends_channel_request_pty(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Scripts the reception of a channel data packet from the remote end.
|
110
|
+
#
|
111
|
+
# channel.gets_data "bar"
|
112
|
+
def gets_data(data)
|
113
|
+
script.gets_channel_data(self, data)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Scripts the reception of a channel extended data packet from the remote
|
117
|
+
# end.
|
118
|
+
#
|
119
|
+
# channel.gets_extended_data "whoops"
|
120
|
+
def gets_extended_data(data)
|
121
|
+
script.gets_channel_extended_data(self, data)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Scripts the reception of an "exit-status" channel request packet.
|
125
|
+
#
|
126
|
+
# channel.gets_exit_status(127)
|
127
|
+
def gets_exit_status(status = 0)
|
128
|
+
script.gets_channel_request(self, "exit-status", false, status)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Scripts the reception of an EOF packet from the remote end.
|
132
|
+
#
|
133
|
+
# channel.gets_eof
|
134
|
+
def gets_eof
|
135
|
+
script.gets_channel_eof(self)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Scripts the reception of a "channel close" packet from the remote end.
|
139
|
+
#
|
140
|
+
# channel.gets_close
|
141
|
+
def gets_close
|
142
|
+
script.gets_channel_close(self)
|
143
|
+
end
|
144
|
+
end
|
135
145
|
end
|
136
146
|
end
|
137
|
-
|
138
|
-
end; end; end
|
147
|
+
end
|
@@ -6,145 +6,166 @@ require 'net/ssh/connection/constants'
|
|
6
6
|
require 'net/ssh/transport/constants'
|
7
7
|
require 'net/ssh/transport/packet_stream'
|
8
8
|
|
9
|
-
module Net
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
module Net
|
10
|
+
module SSH
|
11
|
+
module Test
|
12
|
+
# A collection of modules used to extend/override the default behavior of
|
13
|
+
# Net::SSH internals for ease of testing. As a consumer of Net::SSH, you'll
|
14
|
+
# never need to use this directly--they're all used under the covers by
|
15
|
+
# the Net::SSH::Test system.
|
16
|
+
module Extensions
|
17
|
+
# An extension to Net::SSH::BufferedIo (assumes that the underlying IO
|
18
|
+
# is actually a StringIO). Facilitates unit testing.
|
19
|
+
module BufferedIo
|
20
|
+
# Returns +true+ if the position in the stream is less than the total
|
21
|
+
# length of the stream.
|
22
|
+
def select_for_read?
|
23
|
+
pos < size
|
24
|
+
end
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
# Set this to +true+ if you want the IO to pretend to be available for writing
|
27
|
+
attr_accessor :select_for_write
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
# Set this to +true+ if you want the IO to pretend to be in an error state
|
30
|
+
attr_accessor :select_for_error
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
alias select_for_write? select_for_write
|
33
|
+
alias select_for_error? select_for_error
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
# An extension to Net::SSH::Transport::PacketStream (assumes that the
|
37
|
+
# underlying IO is actually a StringIO). Facilitates unit testing.
|
38
|
+
module PacketStream
|
39
|
+
include BufferedIo # make sure we get the extensions here, too
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def self.included(base) # :nodoc:
|
42
|
+
base.send :alias_method, :real_available_for_read?, :available_for_read?
|
43
|
+
base.send :alias_method, :available_for_read?, :test_available_for_read?
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
base.send :alias_method, :real_enqueue_packet, :enqueue_packet
|
46
|
+
base.send :alias_method, :enqueue_packet, :test_enqueue_packet
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
base.send :alias_method, :real_poll_next_packet, :poll_next_packet
|
49
|
+
base.send :alias_method, :poll_next_packet, :test_poll_next_packet
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
# Called when another packet should be inspected from the current
|
53
|
+
# script. If the next packet is a remote packet, it pops it off the
|
54
|
+
# script and shoves it onto this IO object, making it available to
|
55
|
+
# be read.
|
56
|
+
def idle!
|
57
|
+
return false unless script.next(:first)
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
if script.next(:first).remote?
|
60
|
+
self.string << script.next.to_s
|
61
|
+
self.pos = pos
|
62
|
+
end
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
return true
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
idle!
|
72
|
-
false
|
73
|
-
end
|
67
|
+
# The testing version of Net::SSH::Transport::PacketStream#available_for_read?.
|
68
|
+
# Returns true if there is data pending to be read. Otherwise calls #idle!.
|
69
|
+
def test_available_for_read?
|
70
|
+
return true if select_for_read?
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
packet = Net::SSH::Buffer.new(payload.to_s)
|
79
|
-
script.process(packet)
|
80
|
-
end
|
72
|
+
idle!
|
73
|
+
false
|
74
|
+
end
|
81
75
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
Net::SSH::Packet.new(read_available(length))
|
89
|
-
end
|
90
|
-
end
|
76
|
+
# The testing version of Net::SSH::Transport::PacketStream#enqueued_packet.
|
77
|
+
# Simply calls Net::SSH::Test::Script#process on the packet.
|
78
|
+
def test_enqueue_packet(payload)
|
79
|
+
packet = Net::SSH::Buffer.new(payload.to_s)
|
80
|
+
script.process(packet)
|
81
|
+
end
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
base.send :alias_method, :send_data, :send_data_for_test
|
97
|
-
end
|
83
|
+
# The testing version of Net::SSH::Transport::PacketStream#poll_next_packet.
|
84
|
+
# Reads the next available packet from the IO object and returns it.
|
85
|
+
def test_poll_next_packet
|
86
|
+
return nil if available <= 0
|
98
87
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
send_data_for_real(data)
|
105
|
-
enqueue_pending_output
|
106
|
-
end
|
107
|
-
end
|
88
|
+
packet = Net::SSH::Buffer.new(read_available(4))
|
89
|
+
length = packet.read_long
|
90
|
+
Net::SSH::Packet.new(read_available(length))
|
91
|
+
end
|
92
|
+
end
|
108
93
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
94
|
+
# An extension to Net::SSH::Connection::Channel. Facilitates unit testing.
|
95
|
+
module Channel
|
96
|
+
def self.included(base) # :nodoc:
|
97
|
+
base.send :alias_method, :send_data_for_real, :send_data
|
98
|
+
base.send :alias_method, :send_data, :send_data_for_test
|
99
|
+
end
|
115
100
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
101
|
+
# The testing version of Net::SSH::Connection::Channel#send_data. Calls
|
102
|
+
# the original implementation, and then immediately enqueues the data for
|
103
|
+
# output so that scripted sends are properly interpreted as discrete
|
104
|
+
# (rather than concatenated) data packets.
|
105
|
+
def send_data_for_test(data)
|
106
|
+
send_data_for_real(data)
|
107
|
+
enqueue_pending_output
|
121
108
|
end
|
122
109
|
end
|
123
110
|
|
124
|
-
#
|
125
|
-
#
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
111
|
+
# An extension to the built-in ::IO class. Simply redefines IO.select
|
112
|
+
# so that it can be scripted in Net::SSH unit tests.
|
113
|
+
module IO
|
114
|
+
def self.included(base) # :nodoc:
|
115
|
+
base.extend(ClassMethods)
|
116
|
+
end
|
117
|
+
|
118
|
+
@extension_enabled = false
|
131
119
|
|
132
|
-
|
133
|
-
|
120
|
+
def self.with_test_extension(&block)
|
121
|
+
orig_value = @extension_enabled
|
122
|
+
@extension_enabled = true
|
123
|
+
begin
|
124
|
+
yield
|
125
|
+
ensure
|
126
|
+
@extension_enabled = orig_value
|
127
|
+
end
|
134
128
|
end
|
135
129
|
|
136
|
-
|
137
|
-
|
138
|
-
processed += 1 if reader.idle!
|
130
|
+
def self.extension_enabled?
|
131
|
+
@extension_enabled
|
139
132
|
end
|
140
133
|
|
141
|
-
|
134
|
+
module ClassMethods
|
135
|
+
def self.extended(obj) # :nodoc:
|
136
|
+
class << obj
|
137
|
+
alias_method :select_for_real, :select
|
138
|
+
alias_method :select, :select_for_test
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# The testing version of ::IO.select. Assumes that all readers,
|
143
|
+
# writers, and errors arrays are either nil, or contain only objects
|
144
|
+
# that mix in Net::SSH::Test::Extensions::BufferedIo.
|
145
|
+
def select_for_test(readers = nil, writers = nil, errors = nil, wait = nil)
|
146
|
+
return select_for_real(readers, writers, errors, wait) unless Net::SSH::Test::Extensions::IO.extension_enabled?
|
147
|
+
|
148
|
+
ready_readers = Array(readers).select { |r| r.select_for_read? }
|
149
|
+
ready_writers = Array(writers).select { |r| r.select_for_write? }
|
150
|
+
ready_errors = Array(errors).select { |r| r.select_for_error? }
|
151
|
+
|
152
|
+
return [ready_readers, ready_writers, ready_errors] if ready_readers.any? || ready_writers.any? || ready_errors.any?
|
153
|
+
|
154
|
+
processed = 0
|
155
|
+
Array(readers).each do |reader|
|
156
|
+
processed += 1 if reader.idle!
|
157
|
+
end
|
158
|
+
|
159
|
+
raise "no readers were ready for reading, and none had any incoming packets" if processed == 0 && wait != 0
|
160
|
+
|
161
|
+
[[], [], []]
|
162
|
+
end
|
163
|
+
end
|
142
164
|
end
|
143
165
|
end
|
144
166
|
end
|
145
167
|
end
|
146
|
-
|
147
|
-
end; end; end
|
168
|
+
end
|
148
169
|
|
149
170
|
Net::SSH::BufferedIo.send(:include, Net::SSH::Test::Extensions::BufferedIo)
|
150
171
|
Net::SSH::Transport::PacketStream.send(:include, Net::SSH::Test::Extensions::PacketStream)
|
data/lib/net/ssh/test/kex.rb
CHANGED
@@ -5,40 +5,42 @@ require 'net/ssh/transport/algorithms'
|
|
5
5
|
require 'net/ssh/transport/constants'
|
6
6
|
require 'net/ssh/transport/kex'
|
7
7
|
|
8
|
-
module Net
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
8
|
+
module Net
|
9
|
+
module SSH
|
10
|
+
module Test
|
11
|
+
# An implementation of a key-exchange strategy specifically for unit tests.
|
12
|
+
# (This strategy would never really work against a real SSH server--it makes
|
13
|
+
# too many assumptions about the server's response.)
|
14
|
+
#
|
15
|
+
# This registers itself with the transport key-exchange system as the
|
16
|
+
# "test" algorithm.
|
17
|
+
class Kex
|
18
|
+
include Net::SSH::Transport::Constants
|
19
|
+
|
20
|
+
# Creates a new instance of the testing key-exchange algorithm with the
|
21
|
+
# given arguments.
|
22
|
+
def initialize(algorithms, connection, data)
|
23
|
+
@connection = connection
|
24
|
+
end
|
25
|
+
|
26
|
+
# Exchange keys with the server. This returns a hash of constant values,
|
27
|
+
# and does not actually exchange keys.
|
28
|
+
def exchange_keys
|
29
|
+
result = Net::SSH::Buffer.from(:byte, NEWKEYS)
|
30
|
+
@connection.send_message(result)
|
31
|
+
|
32
|
+
buffer = @connection.next_message
|
33
|
+
raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
|
34
|
+
|
35
|
+
{ session_id: "abc-xyz",
|
36
|
+
server_key: OpenSSL::PKey::RSA.new(512),
|
37
|
+
shared_secret: OpenSSL::BN.new("1234567890", 10),
|
38
|
+
hashing_algorithm: OpenSSL::Digest::SHA1 }
|
39
|
+
end
|
40
|
+
end
|
38
41
|
end
|
39
42
|
end
|
40
|
-
|
41
|
-
end; end; end
|
43
|
+
end
|
42
44
|
|
43
45
|
Net::SSH::Transport::Algorithms::ALGORITHMS[:kex] << "test"
|
44
46
|
Net::SSH::Transport::Kex::MAP["test"] = Net::SSH::Test::Kex
|