net-ssh 5.0.0.beta1 → 5.0.0.beta2

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