net-ssh 5.0.0.beta1 → 5.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.rubocop_todo.yml +98 -258
  5. data/CHANGES.txt +8 -0
  6. data/Gemfile +1 -3
  7. data/Rakefile +37 -39
  8. data/lib/net/ssh.rb +26 -25
  9. data/lib/net/ssh/authentication/agent.rb +228 -225
  10. data/lib/net/ssh/authentication/certificate.rb +166 -164
  11. data/lib/net/ssh/authentication/constants.rb +17 -14
  12. data/lib/net/ssh/authentication/ed25519.rb +107 -104
  13. data/lib/net/ssh/authentication/ed25519_loader.rb +32 -28
  14. data/lib/net/ssh/authentication/key_manager.rb +5 -3
  15. data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
  16. data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
  17. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -4
  18. data/lib/net/ssh/authentication/methods/none.rb +10 -10
  19. data/lib/net/ssh/authentication/methods/password.rb +13 -13
  20. data/lib/net/ssh/authentication/methods/publickey.rb +54 -55
  21. data/lib/net/ssh/authentication/pageant.rb +468 -465
  22. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +44 -0
  23. data/lib/net/ssh/authentication/session.rb +127 -123
  24. data/lib/net/ssh/buffer.rb +305 -303
  25. data/lib/net/ssh/buffered_io.rb +163 -162
  26. data/lib/net/ssh/config.rb +230 -227
  27. data/lib/net/ssh/connection/channel.rb +659 -654
  28. data/lib/net/ssh/connection/constants.rb +30 -26
  29. data/lib/net/ssh/connection/event_loop.rb +108 -104
  30. data/lib/net/ssh/connection/keepalive.rb +54 -50
  31. data/lib/net/ssh/connection/session.rb +677 -678
  32. data/lib/net/ssh/connection/term.rb +180 -176
  33. data/lib/net/ssh/errors.rb +101 -99
  34. data/lib/net/ssh/key_factory.rb +108 -108
  35. data/lib/net/ssh/known_hosts.rb +148 -154
  36. data/lib/net/ssh/loggable.rb +56 -54
  37. data/lib/net/ssh/packet.rb +82 -78
  38. data/lib/net/ssh/prompt.rb +55 -53
  39. data/lib/net/ssh/proxy/command.rb +103 -102
  40. data/lib/net/ssh/proxy/errors.rb +12 -8
  41. data/lib/net/ssh/proxy/http.rb +92 -91
  42. data/lib/net/ssh/proxy/https.rb +42 -39
  43. data/lib/net/ssh/proxy/jump.rb +50 -47
  44. data/lib/net/ssh/proxy/socks4.rb +0 -2
  45. data/lib/net/ssh/proxy/socks5.rb +11 -11
  46. data/lib/net/ssh/ruby_compat.rb +1 -0
  47. data/lib/net/ssh/service/forward.rb +364 -362
  48. data/lib/net/ssh/test.rb +85 -83
  49. data/lib/net/ssh/test/channel.rb +146 -142
  50. data/lib/net/ssh/test/extensions.rb +148 -146
  51. data/lib/net/ssh/test/kex.rb +35 -31
  52. data/lib/net/ssh/test/local_packet.rb +48 -44
  53. data/lib/net/ssh/test/packet.rb +87 -84
  54. data/lib/net/ssh/test/remote_packet.rb +35 -31
  55. data/lib/net/ssh/test/script.rb +173 -171
  56. data/lib/net/ssh/test/socket.rb +59 -55
  57. data/lib/net/ssh/transport/algorithms.rb +413 -412
  58. data/lib/net/ssh/transport/cipher_factory.rb +108 -105
  59. data/lib/net/ssh/transport/constants.rb +35 -31
  60. data/lib/net/ssh/transport/ctr.rb +1 -1
  61. data/lib/net/ssh/transport/hmac.rb +1 -1
  62. data/lib/net/ssh/transport/hmac/abstract.rb +67 -64
  63. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +1 -1
  64. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +1 -1
  65. data/lib/net/ssh/transport/identity_cipher.rb +55 -51
  66. data/lib/net/ssh/transport/kex.rb +2 -4
  67. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +47 -40
  68. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +201 -197
  69. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -56
  70. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +94 -87
  71. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +17 -10
  72. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +17 -10
  73. data/lib/net/ssh/transport/key_expander.rb +29 -25
  74. data/lib/net/ssh/transport/openssl.rb +17 -30
  75. data/lib/net/ssh/transport/packet_stream.rb +193 -192
  76. data/lib/net/ssh/transport/server_version.rb +64 -66
  77. data/lib/net/ssh/transport/session.rb +286 -284
  78. data/lib/net/ssh/transport/state.rb +198 -196
  79. data/lib/net/ssh/verifiers/lenient.rb +29 -25
  80. data/lib/net/ssh/verifiers/null.rb +13 -9
  81. data/lib/net/ssh/verifiers/secure.rb +45 -45
  82. data/lib/net/ssh/verifiers/strict.rb +20 -16
  83. data/lib/net/ssh/version.rb +55 -53
  84. data/net-ssh.gemspec +4 -4
  85. data/support/ssh_tunnel_bug.rb +2 -2
  86. metadata +25 -24
  87. metadata.gz.sig +0 -0
@@ -3,90 +3,92 @@ require 'net/ssh/connection/session'
3
3
  require 'net/ssh/test/kex'
4
4
  require 'net/ssh/test/socket'
5
5
 
6
- module Net; module SSH
6
+ module Net
7
+ module SSH
7
8
 
8
- # This module may be used in unit tests, for when you want to test that your
9
- # SSH state machines are really doing what you expect they are doing. You will
10
- # typically include this module in your unit test class, and then build a
11
- # "story" of expected sends and receives:
12
- #
13
- # require 'minitest/autorun'
14
- # require 'net/ssh/test'
15
- #
16
- # class MyTest < Minitest::Test
17
- # include Net::SSH::Test
18
- #
19
- # def test_exec_via_channel_works
20
- # story do |session|
21
- # channel = session.opens_channel
22
- # channel.sends_exec "ls"
23
- # channel.gets_data "result of ls"
24
- # channel.gets_close
25
- # channel.sends_close
26
- # end
27
- #
28
- # assert_scripted do
29
- # result = nil
30
- #
31
- # connection.open_channel do |ch|
32
- # ch.exec("ls") do |success|
33
- # ch.on_data { |c, data| result = data }
34
- # ch.on_close { |c| c.close }
35
- # end
36
- # end
37
- #
38
- # connection.loop
39
- # assert_equal "result of ls", result
40
- # end
41
- # end
42
- # end
43
- #
44
- # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options.
45
- #
46
- # Note that the Net::SSH::Test system is rather finicky yet, and can be kind
47
- # of frustrating to get working. Any suggestions for improvement will be
48
- # welcome!
49
- module Test
50
- # If a block is given, yields the script for the test socket (#socket).
51
- # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script.
52
- def story
53
- Net::SSH::Test::Extensions::IO.with_test_extension { yield socket.script if block_given? }
54
- return socket.script
9
+ # This module may be used in unit tests, for when you want to test that your
10
+ # SSH state machines are really doing what you expect they are doing. You will
11
+ # typically include this module in your unit test class, and then build a
12
+ # "story" of expected sends and receives:
13
+ #
14
+ # require 'minitest/autorun'
15
+ # require 'net/ssh/test'
16
+ #
17
+ # class MyTest < Minitest::Test
18
+ # include Net::SSH::Test
19
+ #
20
+ # def test_exec_via_channel_works
21
+ # story do |session|
22
+ # channel = session.opens_channel
23
+ # channel.sends_exec "ls"
24
+ # channel.gets_data "result of ls"
25
+ # channel.gets_close
26
+ # channel.sends_close
27
+ # end
28
+ #
29
+ # assert_scripted do
30
+ # result = nil
31
+ #
32
+ # connection.open_channel do |ch|
33
+ # ch.exec("ls") do |success|
34
+ # ch.on_data { |c, data| result = data }
35
+ # ch.on_close { |c| c.close }
36
+ # end
37
+ # end
38
+ #
39
+ # connection.loop
40
+ # assert_equal "result of ls", result
41
+ # end
42
+ # end
43
+ # end
44
+ #
45
+ # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options.
46
+ #
47
+ # Note that the Net::SSH::Test system is rather finicky yet, and can be kind
48
+ # of frustrating to get working. Any suggestions for improvement will be
49
+ # welcome!
50
+ module Test
51
+ # If a block is given, yields the script for the test socket (#socket).
52
+ # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script.
53
+ def story
54
+ Net::SSH::Test::Extensions::IO.with_test_extension { yield socket.script if block_given? }
55
+ return socket.script
56
+ end
57
+
58
+ # Returns the test socket instance to use for these tests (see
59
+ # Net::SSH::Test::Socket).
60
+ def socket(options={})
61
+ @socket ||= Net::SSH::Test::Socket.new
62
+ end
63
+
64
+ # Returns the connection session (Net::SSH::Connection::Session) for use
65
+ # in these tests. It is a fully functional SSH session, operating over
66
+ # a mock socket (#socket).
67
+ def connection(options={})
68
+ @connection ||= Net::SSH::Connection::Session.new(transport(options), options)
69
+ end
70
+
71
+ # Returns the transport session (Net::SSH::Transport::Session) for use
72
+ # in these tests. It is a fully functional SSH transport session, operating
73
+ # over a mock socket (#socket).
74
+ def transport(options={})
75
+ @transport ||= Net::SSH::Transport::Session.new(
76
+ options[:host] || "localhost",
77
+ options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key: false, proxy: socket(options))
78
+ )
79
+ end
80
+
81
+ # First asserts that a story has been described (see #story). Then yields,
82
+ # and then asserts that all items described in the script have been
83
+ # processed. Typically, this is called immediately after a story has
84
+ # been built, and the SSH commands being tested are then executed within
85
+ # the block passed to this assertion.
86
+ def assert_scripted
87
+ raise "there is no script to be processed" if socket.script.events.empty?
88
+ Net::SSH::Test::Extensions::IO.with_test_extension { yield }
89
+ assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still #{socket.script.events.length} pending"
90
+ end
55
91
  end
56
92
 
57
- # Returns the test socket instance to use for these tests (see
58
- # Net::SSH::Test::Socket).
59
- def socket(options={})
60
- @socket ||= Net::SSH::Test::Socket.new
61
- end
62
-
63
- # Returns the connection session (Net::SSH::Connection::Session) for use
64
- # in these tests. It is a fully functional SSH session, operating over
65
- # a mock socket (#socket).
66
- def connection(options={})
67
- @connection ||= Net::SSH::Connection::Session.new(transport(options), options)
68
- end
69
-
70
- # Returns the transport session (Net::SSH::Transport::Session) for use
71
- # in these tests. It is a fully functional SSH transport session, operating
72
- # over a mock socket (#socket).
73
- def transport(options={})
74
- @transport ||= Net::SSH::Transport::Session.new(
75
- options[:host] || "localhost",
76
- options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key: false, proxy: socket(options))
77
- )
78
- end
79
-
80
- # First asserts that a story has been described (see #story). Then yields,
81
- # and then asserts that all items described in the script have been
82
- # processed. Typically, this is called immediately after a story has
83
- # been built, and the SSH commands being tested are then executed within
84
- # the block passed to this assertion.
85
- def assert_scripted
86
- raise "there is no script to be processed" if socket.script.events.empty?
87
- Net::SSH::Test::Extensions::IO.with_test_extension { yield }
88
- assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still #{socket.script.events.length} pending"
89
- end
90
93
  end
91
-
92
- end; end
94
+ end
@@ -1,145 +1,149 @@
1
- module Net; module SSH; module Test
1
+ module Net
2
+ module SSH
3
+ module Test
4
+
5
+ # A mock channel, used for scripting actions in tests. It wraps a
6
+ # Net::SSH::Test::Script instance, and delegates to it for the most part.
7
+ # This class has little real functionality on its own, but rather acts as
8
+ # a convenience for scripting channel-related activity for later comparison
9
+ # in a unit test.
10
+ #
11
+ # story do |session|
12
+ # channel = session.opens_channel
13
+ # channel.sends_exec "ls"
14
+ # channel.gets_data "result of ls"
15
+ # channel.gets_extended_data "some error coming from ls"
16
+ # channel.gets_close
17
+ # channel.sends_close
18
+ # end
19
+ class Channel
20
+ # The Net::SSH::Test::Script instance employed by this mock channel.
21
+ attr_reader :script
22
+
23
+ # Sets the local-id of this channel object (the id assigned by the client).
24
+ attr_writer :local_id
25
+
26
+ # Sets the remote-id of this channel object (the id assigned by the mock-server).
27
+ attr_writer :remote_id
28
+
29
+ # Creates a new Test::Channel instance on top of the given +script+ (which
30
+ # must be a Net::SSH::Test::Script instance).
31
+ def initialize(script)
32
+ @script = script
33
+ @local_id = @remote_id = nil
34
+ end
35
+
36
+ # Returns the local (client-assigned) id for this channel, or a Proc object
37
+ # that will return the local-id later if the local id has not yet been set.
38
+ # (See Net::SSH::Test::Packet#instantiate!.)
39
+ def local_id
40
+ @local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
41
+ end
42
+
43
+ # Returns the remote (server-assigned) id for this channel, or a Proc object
44
+ # that will return the remote-id later if the remote id has not yet been set.
45
+ # (See Net::SSH::Test::Packet#instantiate!.)
46
+ def remote_id
47
+ @remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
48
+ end
49
+
50
+ # Because adjacent calls to #gets_data will sometimes cause the data packets
51
+ # to be concatenated (causing expectations in tests to fail), you may
52
+ # need to separate those calls with calls to #inject_remote_delay! (which
53
+ # essentially just mimics receiving an empty data packet):
54
+ #
55
+ # channel.gets_data "abcdefg"
56
+ # channel.inject_remote_delay!
57
+ # channel.gets_data "hijklmn"
58
+ def inject_remote_delay!
59
+ gets_data("")
60
+ end
61
+
62
+ # Scripts the sending of an "exec" channel request packet to the mock
63
+ # server. If +reply+ is true, then the server is expected to reply to the
64
+ # request, otherwise no response to this request will be sent. If +success+
65
+ # is +true+, then the request will be successful, otherwise a failure will
66
+ # be scripted.
67
+ #
68
+ # channel.sends_exec "ls -l"
69
+ def sends_exec(command, reply=true, success=true)
70
+ script.sends_channel_request(self, "exec", reply, command, success)
71
+ end
72
+
73
+ # Scripts the sending of a "subsystem" channel request packet to the mock
74
+ # server. See #sends_exec for a discussion of the meaning of the +reply+
75
+ # and +success+ arguments.
76
+ #
77
+ # channel.sends_subsystem "sftp"
78
+ def sends_subsystem(subsystem, reply=true, success=true)
79
+ script.sends_channel_request(self, "subsystem", reply, subsystem, success)
80
+ end
81
+
82
+ # Scripts the sending of a data packet across the channel.
83
+ #
84
+ # channel.sends_data "foo"
85
+ def sends_data(data)
86
+ script.sends_channel_data(self, data)
87
+ end
88
+
89
+ # Scripts the sending of an EOF packet across the channel.
90
+ #
91
+ # channel.sends_eof
92
+ def sends_eof
93
+ script.sends_channel_eof(self)
94
+ end
95
+
96
+ # Scripts the sending of a "channel close" packet across the channel.
97
+ #
98
+ # channel.sends_close
99
+ def sends_close
100
+ script.sends_channel_close(self)
101
+ end
102
+
103
+ # Scripts the sending of a "request pty" request packet across the channel.
104
+ #
105
+ # channel.sends_request_pty
106
+ def sends_request_pty
107
+ script.sends_channel_request_pty(self)
108
+ end
109
+
110
+ # Scripts the reception of a channel data packet from the remote end.
111
+ #
112
+ # channel.gets_data "bar"
113
+ def gets_data(data)
114
+ script.gets_channel_data(self, data)
115
+ end
116
+
117
+ # Scripts the reception of a channel extended data packet from the remote
118
+ # end.
119
+ #
120
+ # channel.gets_extended_data "whoops"
121
+ def gets_extended_data(data)
122
+ script.gets_channel_extended_data(self, data)
123
+ end
124
+
125
+ # Scripts the reception of an "exit-status" channel request packet.
126
+ #
127
+ # channel.gets_exit_status(127)
128
+ def gets_exit_status(status=0)
129
+ script.gets_channel_request(self, "exit-status", false, status)
130
+ end
131
+
132
+ # Scripts the reception of an EOF packet from the remote end.
133
+ #
134
+ # channel.gets_eof
135
+ def gets_eof
136
+ script.gets_channel_eof(self)
137
+ end
138
+
139
+ # Scripts the reception of a "channel close" packet from the remote end.
140
+ #
141
+ # channel.gets_close
142
+ def gets_close
143
+ script.gets_channel_close(self)
144
+ end
145
+ end
2
146
 
3
- # A mock channel, used for scripting actions in tests. It wraps a
4
- # Net::SSH::Test::Script instance, and delegates to it for the most part.
5
- # This class has little real functionality on its own, but rather acts as
6
- # a convenience for scripting channel-related activity for later comparison
7
- # in a unit test.
8
- #
9
- # story do |session|
10
- # channel = session.opens_channel
11
- # channel.sends_exec "ls"
12
- # channel.gets_data "result of ls"
13
- # channel.gets_extended_data "some error coming from ls"
14
- # channel.gets_close
15
- # channel.sends_close
16
- # end
17
- class Channel
18
- # The Net::SSH::Test::Script instance employed by this mock channel.
19
- attr_reader :script
20
-
21
- # Sets the local-id of this channel object (the id assigned by the client).
22
- attr_writer :local_id
23
-
24
- # Sets the remote-id of this channel object (the id assigned by the mock-server).
25
- attr_writer :remote_id
26
-
27
- # Creates a new Test::Channel instance on top of the given +script+ (which
28
- # must be a Net::SSH::Test::Script instance).
29
- def initialize(script)
30
- @script = script
31
- @local_id = @remote_id = nil
32
- end
33
-
34
- # Returns the local (client-assigned) id for this channel, or a Proc object
35
- # that will return the local-id later if the local id has not yet been set.
36
- # (See Net::SSH::Test::Packet#instantiate!.)
37
- def local_id
38
- @local_id || Proc.new { @local_id or raise "local-id has not been set yet!" }
39
- end
40
-
41
- # Returns the remote (server-assigned) id for this channel, or a Proc object
42
- # that will return the remote-id later if the remote id has not yet been set.
43
- # (See Net::SSH::Test::Packet#instantiate!.)
44
- def remote_id
45
- @remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" }
46
- end
47
-
48
- # Because adjacent calls to #gets_data will sometimes cause the data packets
49
- # to be concatenated (causing expectations in tests to fail), you may
50
- # need to separate those calls with calls to #inject_remote_delay! (which
51
- # essentially just mimics receiving an empty data packet):
52
- #
53
- # channel.gets_data "abcdefg"
54
- # channel.inject_remote_delay!
55
- # channel.gets_data "hijklmn"
56
- def inject_remote_delay!
57
- gets_data("")
58
- end
59
-
60
- # Scripts the sending of an "exec" channel request packet to the mock
61
- # server. If +reply+ is true, then the server is expected to reply to the
62
- # request, otherwise no response to this request will be sent. If +success+
63
- # is +true+, then the request will be successful, otherwise a failure will
64
- # be scripted.
65
- #
66
- # channel.sends_exec "ls -l"
67
- def sends_exec(command, reply=true, success=true)
68
- script.sends_channel_request(self, "exec", reply, command, success)
69
- end
70
-
71
- # Scripts the sending of a "subsystem" channel request packet to the mock
72
- # server. See #sends_exec for a discussion of the meaning of the +reply+
73
- # and +success+ arguments.
74
- #
75
- # channel.sends_subsystem "sftp"
76
- def sends_subsystem(subsystem, reply=true, success=true)
77
- script.sends_channel_request(self, "subsystem", reply, subsystem, success)
78
- end
79
-
80
- # Scripts the sending of a data packet across the channel.
81
- #
82
- # channel.sends_data "foo"
83
- def sends_data(data)
84
- script.sends_channel_data(self, data)
85
- end
86
-
87
- # Scripts the sending of an EOF packet across the channel.
88
- #
89
- # channel.sends_eof
90
- def sends_eof
91
- script.sends_channel_eof(self)
92
- end
93
-
94
- # Scripts the sending of a "channel close" packet across the channel.
95
- #
96
- # channel.sends_close
97
- def sends_close
98
- script.sends_channel_close(self)
99
- end
100
-
101
- # Scripts the sending of a "request pty" request packet across the channel.
102
- #
103
- # channel.sends_request_pty
104
- def sends_request_pty
105
- script.sends_channel_request_pty(self)
106
- end
107
-
108
- # Scripts the reception of a channel data packet from the remote end.
109
- #
110
- # channel.gets_data "bar"
111
- def gets_data(data)
112
- script.gets_channel_data(self, data)
113
- end
114
-
115
- # Scripts the reception of a channel extended data packet from the remote
116
- # end.
117
- #
118
- # channel.gets_extended_data "whoops"
119
- def gets_extended_data(data)
120
- script.gets_channel_extended_data(self, data)
121
- end
122
-
123
- # Scripts the reception of an "exit-status" channel request packet.
124
- #
125
- # channel.gets_exit_status(127)
126
- def gets_exit_status(status=0)
127
- script.gets_channel_request(self, "exit-status", false, status)
128
- end
129
-
130
- # Scripts the reception of an EOF packet from the remote end.
131
- #
132
- # channel.gets_eof
133
- def gets_eof
134
- script.gets_channel_eof(self)
135
- end
136
-
137
- # Scripts the reception of a "channel close" packet from the remote end.
138
- #
139
- # channel.gets_close
140
- def gets_close
141
- script.gets_channel_close(self)
142
147
  end
143
148
  end
144
-
145
- end; end; end
149
+ end