net-ssh 4.1.0 → 6.1.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.
Files changed (111) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +5 -0
  5. data/.rubocop.yml +8 -2
  6. data/.rubocop_todo.yml +405 -552
  7. data/.travis.yml +23 -22
  8. data/CHANGES.txt +112 -1
  9. data/Gemfile +1 -7
  10. data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
  11. data/Manifest +4 -5
  12. data/README.md +287 -0
  13. data/Rakefile +40 -29
  14. data/appveyor.yml +12 -6
  15. data/lib/net/ssh.rb +68 -32
  16. data/lib/net/ssh/authentication/agent.rb +234 -222
  17. data/lib/net/ssh/authentication/certificate.rb +175 -164
  18. data/lib/net/ssh/authentication/constants.rb +17 -14
  19. data/lib/net/ssh/authentication/ed25519.rb +162 -141
  20. data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
  21. data/lib/net/ssh/authentication/key_manager.rb +40 -9
  22. data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
  23. data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
  24. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  25. data/lib/net/ssh/authentication/methods/none.rb +10 -10
  26. data/lib/net/ssh/authentication/methods/password.rb +13 -13
  27. data/lib/net/ssh/authentication/methods/publickey.rb +56 -55
  28. data/lib/net/ssh/authentication/pageant.rb +468 -465
  29. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  30. data/lib/net/ssh/authentication/session.rb +130 -122
  31. data/lib/net/ssh/buffer.rb +345 -312
  32. data/lib/net/ssh/buffered_io.rb +163 -163
  33. data/lib/net/ssh/config.rb +316 -238
  34. data/lib/net/ssh/connection/channel.rb +670 -650
  35. data/lib/net/ssh/connection/constants.rb +30 -26
  36. data/lib/net/ssh/connection/event_loop.rb +108 -105
  37. data/lib/net/ssh/connection/keepalive.rb +54 -50
  38. data/lib/net/ssh/connection/session.rb +682 -671
  39. data/lib/net/ssh/connection/term.rb +180 -176
  40. data/lib/net/ssh/errors.rb +101 -99
  41. data/lib/net/ssh/key_factory.rb +195 -108
  42. data/lib/net/ssh/known_hosts.rb +161 -152
  43. data/lib/net/ssh/loggable.rb +57 -55
  44. data/lib/net/ssh/packet.rb +82 -78
  45. data/lib/net/ssh/prompt.rb +55 -53
  46. data/lib/net/ssh/proxy/command.rb +104 -89
  47. data/lib/net/ssh/proxy/errors.rb +12 -8
  48. data/lib/net/ssh/proxy/http.rb +93 -91
  49. data/lib/net/ssh/proxy/https.rb +42 -39
  50. data/lib/net/ssh/proxy/jump.rb +50 -47
  51. data/lib/net/ssh/proxy/socks4.rb +0 -2
  52. data/lib/net/ssh/proxy/socks5.rb +11 -12
  53. data/lib/net/ssh/service/forward.rb +370 -317
  54. data/lib/net/ssh/test.rb +83 -77
  55. data/lib/net/ssh/test/channel.rb +146 -142
  56. data/lib/net/ssh/test/extensions.rb +150 -146
  57. data/lib/net/ssh/test/kex.rb +35 -31
  58. data/lib/net/ssh/test/local_packet.rb +48 -44
  59. data/lib/net/ssh/test/packet.rb +87 -84
  60. data/lib/net/ssh/test/remote_packet.rb +35 -31
  61. data/lib/net/ssh/test/script.rb +173 -171
  62. data/lib/net/ssh/test/socket.rb +59 -55
  63. data/lib/net/ssh/transport/algorithms.rb +430 -364
  64. data/lib/net/ssh/transport/cipher_factory.rb +95 -91
  65. data/lib/net/ssh/transport/constants.rb +33 -25
  66. data/lib/net/ssh/transport/ctr.rb +33 -11
  67. data/lib/net/ssh/transport/hmac.rb +15 -13
  68. data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
  69. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  70. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  71. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  72. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  73. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  74. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  75. data/lib/net/ssh/transport/identity_cipher.rb +55 -51
  76. data/lib/net/ssh/transport/kex.rb +14 -13
  77. data/lib/net/ssh/transport/kex/abstract.rb +123 -0
  78. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  79. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
  80. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  81. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  82. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
  83. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
  84. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  85. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  86. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  87. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  88. data/lib/net/ssh/transport/key_expander.rb +29 -25
  89. data/lib/net/ssh/transport/openssl.rb +116 -116
  90. data/lib/net/ssh/transport/packet_stream.rb +223 -190
  91. data/lib/net/ssh/transport/server_version.rb +64 -66
  92. data/lib/net/ssh/transport/session.rb +306 -257
  93. data/lib/net/ssh/transport/state.rb +198 -196
  94. data/lib/net/ssh/verifiers/accept_new.rb +35 -0
  95. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
  96. data/lib/net/ssh/verifiers/always.rb +56 -0
  97. data/lib/net/ssh/verifiers/never.rb +21 -0
  98. data/lib/net/ssh/version.rb +55 -53
  99. data/net-ssh-public_cert.pem +18 -19
  100. data/net-ssh.gemspec +12 -11
  101. data/support/ssh_tunnel_bug.rb +2 -2
  102. metadata +86 -75
  103. metadata.gz.sig +0 -0
  104. data/Gemfile.norbnacl.lock +0 -41
  105. data/README.rdoc +0 -169
  106. data/lib/net/ssh/ruby_compat.rb +0 -24
  107. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  108. data/lib/net/ssh/verifiers/null.rb +0 -12
  109. data/lib/net/ssh/verifiers/secure.rb +0 -52
  110. data/lib/net/ssh/verifiers/strict.rb +0 -24
  111. data/support/arcfour_check.rb +0 -20
@@ -2,77 +2,75 @@ require 'net/ssh/errors'
2
2
  require 'net/ssh/loggable'
3
3
  require 'net/ssh/version'
4
4
 
5
- module Net; module SSH; module Transport
5
+ module Net
6
+ module SSH
7
+ module Transport
6
8
 
7
- # Negotiates the SSH protocol version and trades information about server
8
- # and client. This is never used directly--it is always called by the
9
- # transport layer as part of the initialization process of the transport
10
- # layer.
11
- #
12
- # Note that this class also encapsulates the negotiated version, and acts as
13
- # the authoritative reference for any queries regarding the version in effect.
14
- class ServerVersion
15
- include Loggable
16
-
17
- # The SSH version string as reported by Net::SSH
18
- PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
19
-
20
- # Any header text sent by the server prior to sending the version.
21
- attr_reader :header
22
-
23
- # The version string reported by the server.
24
- attr_reader :version
25
-
26
- # Instantiates a new ServerVersion and immediately (and synchronously)
27
- # negotiates the SSH protocol in effect, using the given socket.
28
- def initialize(socket, logger, timeout = nil)
29
- @header = ""
30
- @version = nil
31
- @logger = logger
32
- negotiate!(socket, timeout)
33
- end
34
-
35
- private
36
-
37
- # Negotiates the SSH protocol to use, via the given socket. If the server
38
- # reports an incompatible SSH version (e.g., SSH1), this will raise an
39
- # exception.
40
- def negotiate!(socket, timeout)
41
- info { "negotiating protocol version" }
42
-
43
- debug { "local is `#{PROTO_VERSION}'" }
44
- socket.write "#{PROTO_VERSION}\r\n"
45
- socket.flush
46
-
47
- if timeout && !IO.select([socket], nil, nil, timeout)
48
- raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating"
9
+ # Negotiates the SSH protocol version and trades information about server
10
+ # and client. This is never used directly--it is always called by the
11
+ # transport layer as part of the initialization process of the transport
12
+ # layer.
13
+ #
14
+ # Note that this class also encapsulates the negotiated version, and acts as
15
+ # the authoritative reference for any queries regarding the version in effect.
16
+ class ServerVersion
17
+ include Loggable
18
+
19
+ # The SSH version string as reported by Net::SSH
20
+ PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
21
+
22
+ # Any header text sent by the server prior to sending the version.
23
+ attr_reader :header
24
+
25
+ # The version string reported by the server.
26
+ attr_reader :version
27
+
28
+ # Instantiates a new ServerVersion and immediately (and synchronously)
29
+ # negotiates the SSH protocol in effect, using the given socket.
30
+ def initialize(socket, logger, timeout = nil)
31
+ @header = ""
32
+ @version = nil
33
+ @logger = logger
34
+ negotiate!(socket, timeout)
49
35
  end
50
- loop do
51
- @version = ""
36
+
37
+ private
38
+
39
+ # Negotiates the SSH protocol to use, via the given socket. If the server
40
+ # reports an incompatible SSH version (e.g., SSH1), this will raise an
41
+ # exception.
42
+ def negotiate!(socket, timeout)
43
+ info { "negotiating protocol version" }
44
+
45
+ debug { "local is `#{PROTO_VERSION}'" }
46
+ socket.write "#{PROTO_VERSION}\r\n"
47
+ socket.flush
48
+
49
+ raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating" if timeout && !IO.select([socket], nil, nil, timeout)
52
50
  loop do
53
- begin
54
- b = socket.readpartial(1)
55
- raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil?
56
- rescue EOFError
57
- raise Net::SSH::Disconnect, "connection closed by remote host"
51
+ @version = ""
52
+ loop do
53
+ begin
54
+ b = socket.readpartial(1)
55
+ raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil?
56
+ rescue EOFError
57
+ raise Net::SSH::Disconnect, "connection closed by remote host"
58
+ end
59
+ @version << b
60
+ break if b == "\n"
58
61
  end
59
- @version << b
60
- break if b == "\n"
62
+ break if @version.match(/^SSH-/)
63
+ @header << @version
61
64
  end
62
- break if @version.match(/^SSH-/)
63
- @header << @version
64
- end
65
-
66
- @version.chomp!
67
- debug { "remote is `#{@version}'" }
68
-
69
- unless @version.match(/^SSH-(1\.99|2\.0)-/)
70
- raise Net::SSH::Exception, "incompatible SSH version `#{@version}'"
71
- end
72
-
73
- if timeout && !IO.select(nil, [socket], nil, timeout)
74
- raise Net::SSH::ConnectionTimeout, "timeout during client version negotiating"
65
+
66
+ @version.chomp!
67
+ debug { "remote is `#{@version}'" }
68
+
69
+ raise Net::SSH::Exception, "incompatible SSH version `#{@version}'" unless @version.match(/^SSH-(1\.99|2\.0)-/)
70
+
71
+ raise Net::SSH::ConnectionTimeout, "timeout during client version negotiating" if timeout && !IO.select(nil, [socket], nil, timeout)
75
72
  end
76
73
  end
74
+ end
77
75
  end
78
- end; end; end
76
+ end
@@ -7,297 +7,346 @@ require 'net/ssh/transport/algorithms'
7
7
  require 'net/ssh/transport/constants'
8
8
  require 'net/ssh/transport/packet_stream'
9
9
  require 'net/ssh/transport/server_version'
10
- require 'net/ssh/verifiers/null'
11
- require 'net/ssh/verifiers/secure'
12
- require 'net/ssh/verifiers/strict'
13
- require 'net/ssh/verifiers/lenient'
14
-
15
- module Net; module SSH; module Transport
16
-
17
- # The transport layer represents the lowest level of the SSH protocol, and
18
- # implements basic message exchanging and protocol initialization. It will
19
- # never be instantiated directly (unless you really know what you're about),
20
- # but will instead be created for you automatically when you create a new
21
- # SSH session via Net::SSH.start.
22
- class Session
23
- include Constants, Loggable
24
-
25
- # The standard port for the SSH protocol.
26
- DEFAULT_PORT = 22
27
-
28
- # The host to connect to, as given to the constructor.
29
- attr_reader :host
30
-
31
- # The port number to connect to, as given in the options to the constructor.
32
- # If no port number was given, this will default to DEFAULT_PORT.
33
- attr_reader :port
34
-
35
- # The underlying socket object being used to communicate with the remote
36
- # host.
37
- attr_reader :socket
38
-
39
- # The ServerVersion instance that encapsulates the negotiated protocol
40
- # version.
41
- attr_reader :server_version
42
-
43
- # The Algorithms instance used to perform key exchanges.
44
- attr_reader :algorithms
45
-
46
- # The host-key verifier object used to verify host keys, to ensure that
47
- # the connection is not being spoofed.
48
- attr_reader :host_key_verifier
49
-
50
- # The hash of options that were given to the object at initialization.
51
- attr_reader :options
52
-
53
- # Instantiates a new transport layer abstraction. This will block until
54
- # the initial key exchange completes, leaving you with a ready-to-use
55
- # transport session.
56
- def initialize(host, options={})
57
- self.logger = options[:logger]
58
-
59
- @host = host
60
- @port = options[:port] || DEFAULT_PORT
61
- @bind_address = options[:bind_address] || nil
62
- @options = options
63
-
64
- debug { "establishing connection to #{@host}:#{@port}" }
65
-
66
- @socket =
67
- if (factory = options[:proxy])
68
- factory.open(@host, @port, options)
69
- else
70
- Socket.tcp(@host, @port, @bind_address, nil,
71
- connect_timeout: options[:timeout])
10
+ require 'net/ssh/verifiers/accept_new_or_local_tunnel'
11
+ require 'net/ssh/verifiers/accept_new'
12
+ require 'net/ssh/verifiers/always'
13
+ require 'net/ssh/verifiers/never'
14
+
15
+ module Net
16
+ module SSH
17
+ module Transport
18
+
19
+ # The transport layer represents the lowest level of the SSH protocol, and
20
+ # implements basic message exchanging and protocol initialization. It will
21
+ # never be instantiated directly (unless you really know what you're about),
22
+ # but will instead be created for you automatically when you create a new
23
+ # SSH session via Net::SSH.start.
24
+ class Session
25
+ include Loggable
26
+ include Constants
27
+
28
+ # The standard port for the SSH protocol.
29
+ DEFAULT_PORT = 22
30
+
31
+ # The host to connect to, as given to the constructor.
32
+ attr_reader :host
33
+
34
+ # The port number to connect to, as given in the options to the constructor.
35
+ # If no port number was given, this will default to DEFAULT_PORT.
36
+ attr_reader :port
37
+
38
+ # The underlying socket object being used to communicate with the remote
39
+ # host.
40
+ attr_reader :socket
41
+
42
+ # The ServerVersion instance that encapsulates the negotiated protocol
43
+ # version.
44
+ attr_reader :server_version
45
+
46
+ # The Algorithms instance used to perform key exchanges.
47
+ attr_reader :algorithms
48
+
49
+ # The host-key verifier object used to verify host keys, to ensure that
50
+ # the connection is not being spoofed.
51
+ attr_reader :host_key_verifier
52
+
53
+ # The hash of options that were given to the object at initialization.
54
+ attr_reader :options
55
+
56
+ # Instantiates a new transport layer abstraction. This will block until
57
+ # the initial key exchange completes, leaving you with a ready-to-use
58
+ # transport session.
59
+ def initialize(host, options={})
60
+ self.logger = options[:logger]
61
+
62
+ @host = host
63
+ @port = options[:port] || DEFAULT_PORT
64
+ @bind_address = options[:bind_address] || nil
65
+ @options = options
66
+
67
+ @socket =
68
+ if (factory = options[:proxy])
69
+ debug { "establishing connection to #{@host}:#{@port} through proxy" }
70
+ factory.open(@host, @port, options)
71
+ else
72
+ debug { "establishing connection to #{@host}:#{@port}" }
73
+ Socket.tcp(@host, @port, @bind_address, nil,
74
+ connect_timeout: options[:timeout])
75
+ end
76
+
77
+ @socket.extend(PacketStream)
78
+ @socket.logger = @logger
79
+
80
+ debug { "connection established" }
81
+
82
+ @queue = []
83
+
84
+ @host_key_verifier = select_host_key_verifier(options[:verify_host_key])
85
+
86
+ @server_version = ServerVersion.new(socket, logger, options[:timeout])
87
+
88
+ @algorithms = Algorithms.new(self, options)
89
+ @algorithms.start
90
+ wait { algorithms.initialized? }
91
+ rescue Errno::ETIMEDOUT
92
+ raise Net::SSH::ConnectionTimeout
72
93
  end
73
94
 
74
- @socket.extend(PacketStream)
75
- @socket.logger = @logger
76
-
77
- debug { "connection established" }
78
-
79
- @queue = []
80
-
81
- @host_key_verifier = select_host_key_verifier(options[:paranoid])
82
-
83
-
84
- @server_version = ServerVersion.new(socket, logger, options[:timeout])
85
-
86
- @algorithms = Algorithms.new(self, options)
87
- @algorithms.start
88
- wait { algorithms.initialized? }
89
- rescue Errno::ETIMEDOUT
90
- raise Net::SSH::ConnectionTimeout
91
- end
95
+ def host_keys
96
+ @host_keys ||= begin
97
+ known_hosts = options.fetch(:known_hosts, KnownHosts)
98
+ known_hosts.search_for(options[:host_key_alias] || host_as_string, options)
99
+ end
100
+ end
92
101
 
93
- def host_keys
94
- @host_keys ||= begin
95
- known_hosts = options.fetch(:known_hosts, KnownHosts)
96
- known_hosts.search_for(options[:host_key_alias] || host_as_string, options)
97
- end
98
- end
102
+ # Returns the host (and possibly IP address) in a format compatible with
103
+ # SSH known-host files.
104
+ def host_as_string
105
+ @host_as_string ||= begin
106
+ string = "#{host}"
107
+ string = "[#{string}]:#{port}" if port != DEFAULT_PORT
99
108
 
100
- # Returns the host (and possibly IP address) in a format compatible with
101
- # SSH known-host files.
102
- def host_as_string
103
- @host_as_string ||= begin
104
- string = "#{host}"
105
- string = "[#{string}]:#{port}" if port != DEFAULT_PORT
109
+ peer_ip = socket.peer_ip
106
110
 
107
- peer_ip = socket.peer_ip
111
+ if peer_ip != Net::SSH::Transport::PacketStream::PROXY_COMMAND_HOST_IP &&
112
+ peer_ip != host
113
+ string2 = peer_ip
114
+ string2 = "[#{string2}]:#{port}" if port != DEFAULT_PORT
115
+ string << "," << string2
116
+ end
108
117
 
109
- if peer_ip != Net::SSH::Transport::PacketStream::PROXY_COMMAND_HOST_IP &&
110
- peer_ip != host
111
- string2 = peer_ip
112
- string2 = "[#{string2}]:#{port}" if port != DEFAULT_PORT
113
- string << "," << string2
118
+ string
119
+ end
114
120
  end
115
121
 
116
- string
117
- end
118
- end
119
-
120
- # Returns true if the underlying socket has been closed.
121
- def closed?
122
- socket.closed?
123
- end
124
-
125
- # Cleans up (see PacketStream#cleanup) and closes the underlying socket.
126
- def close
127
- socket.cleanup
128
- socket.close
129
- end
122
+ # Returns true if the underlying socket has been closed.
123
+ def closed?
124
+ socket.closed?
125
+ end
130
126
 
131
- # Performs a "hard" shutdown of the connection. In general, this should
132
- # never be done, but it might be necessary (in a rescue clause, for instance,
133
- # when the connection needs to close but you don't know the status of the
134
- # underlying protocol's state).
135
- def shutdown!
136
- error { "forcing connection closed" }
137
- socket.close
138
- end
127
+ # Cleans up (see PacketStream#cleanup) and closes the underlying socket.
128
+ def close
129
+ socket.cleanup
130
+ socket.close
131
+ end
139
132
 
140
- # Returns a new service_request packet for the given service name, ready
141
- # for sending to the server.
142
- def service_request(service)
143
- Net::SSH::Buffer.from(:byte, SERVICE_REQUEST, :string, service)
144
- end
133
+ # Performs a "hard" shutdown of the connection. In general, this should
134
+ # never be done, but it might be necessary (in a rescue clause, for instance,
135
+ # when the connection needs to close but you don't know the status of the
136
+ # underlying protocol's state).
137
+ def shutdown!
138
+ error { "forcing connection closed" }
139
+ socket.close
140
+ end
145
141
 
146
- # Requests a rekey operation, and blocks until the operation completes.
147
- # If a rekey is already pending, this returns immediately, having no
148
- # effect.
149
- def rekey!
150
- if !algorithms.pending?
151
- algorithms.rekey!
152
- wait { algorithms.initialized? }
153
- end
154
- end
142
+ # Returns a new service_request packet for the given service name, ready
143
+ # for sending to the server.
144
+ def service_request(service)
145
+ Net::SSH::Buffer.from(:byte, SERVICE_REQUEST, :string, service)
146
+ end
155
147
 
156
- # Returns immediately if a rekey is already in process. Otherwise, if a
157
- # rekey is needed (as indicated by the socket, see PacketStream#if_needs_rekey?)
158
- # one is performed, causing this method to block until it completes.
159
- def rekey_as_needed
160
- return if algorithms.pending?
161
- socket.if_needs_rekey? { rekey! }
162
- end
148
+ # Requests a rekey operation, and blocks until the operation completes.
149
+ # If a rekey is already pending, this returns immediately, having no
150
+ # effect.
151
+ def rekey!
152
+ if !algorithms.pending?
153
+ algorithms.rekey!
154
+ wait { algorithms.initialized? }
155
+ end
156
+ end
163
157
 
164
- # Returns a hash of information about the peer (remote) side of the socket,
165
- # including :ip, :port, :host, and :canonized (see #host_as_string).
166
- def peer
167
- @peer ||= { ip: socket.peer_ip, port: @port.to_i, host: @host, canonized: host_as_string }
168
- end
158
+ # Returns immediately if a rekey is already in process. Otherwise, if a
159
+ # rekey is needed (as indicated by the socket, see PacketStream#if_needs_rekey?)
160
+ # one is performed, causing this method to block until it completes.
161
+ def rekey_as_needed
162
+ return if algorithms.pending?
163
+ socket.if_needs_rekey? { rekey! }
164
+ end
169
165
 
170
- # Blocks until a new packet is available to be read, and returns that
171
- # packet. See #poll_message.
172
- def next_message
173
- poll_message(:block)
174
- end
166
+ # Returns a hash of information about the peer (remote) side of the socket,
167
+ # including :ip, :port, :host, and :canonized (see #host_as_string).
168
+ def peer
169
+ @peer ||= { ip: socket.peer_ip, port: @port.to_i, host: @host, canonized: host_as_string }
170
+ end
175
171
 
176
- # Tries to read the next packet from the socket. If mode is :nonblock (the
177
- # default), this will not block and will return nil if there are no packets
178
- # waiting to be read. Otherwise, this will block until a packet is
179
- # available. Note that some packet types (DISCONNECT, IGNORE, UNIMPLEMENTED,
180
- # DEBUG, and KEXINIT) are handled silently by this method, and will never
181
- # be returned.
182
- #
183
- # If a key-exchange is in process and a disallowed packet type is
184
- # received, it will be enqueued and otherwise ignored. When a key-exchange
185
- # is not in process, and consume_queue is true, packets will be first
186
- # read from the queue before the socket is queried.
187
- def poll_message(mode=:nonblock, consume_queue=true)
188
- loop do
189
- if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
190
- return @queue.shift
172
+ # Blocks until a new packet is available to be read, and returns that
173
+ # packet. See #poll_message.
174
+ def next_message
175
+ poll_message(:block)
191
176
  end
192
177
 
193
- packet = socket.next_packet(mode)
194
- return nil if packet.nil?
178
+ # Tries to read the next packet from the socket. If mode is :nonblock (the
179
+ # default), this will not block and will return nil if there are no packets
180
+ # waiting to be read. Otherwise, this will block until a packet is
181
+ # available. Note that some packet types (DISCONNECT, IGNORE, UNIMPLEMENTED,
182
+ # DEBUG, and KEXINIT) are handled silently by this method, and will never
183
+ # be returned.
184
+ #
185
+ # If a key-exchange is in process and a disallowed packet type is
186
+ # received, it will be enqueued and otherwise ignored. When a key-exchange
187
+ # is not in process, and consume_queue is true, packets will be first
188
+ # read from the queue before the socket is queried.
189
+ def poll_message(mode=:nonblock, consume_queue=true)
190
+ loop do
191
+ return @queue.shift if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
192
+
193
+ packet = socket.next_packet(mode, options[:timeout])
194
+ return nil if packet.nil?
195
+
196
+ case packet.type
197
+ when DISCONNECT
198
+ raise Net::SSH::Disconnect, "disconnected: #{packet[:description]} (#{packet[:reason_code]})"
199
+
200
+ when IGNORE
201
+ debug { "IGNORE packet received: #{packet[:data].inspect}" }
202
+
203
+ when UNIMPLEMENTED
204
+ lwarn { "UNIMPLEMENTED: #{packet[:number]}" }
205
+
206
+ when DEBUG
207
+ send(packet[:always_display] ? :fatal : :debug) { packet[:message] }
208
+
209
+ when KEXINIT
210
+ algorithms.accept_kexinit(packet)
211
+
212
+ else
213
+ return packet if algorithms.allow?(packet)
214
+ push(packet)
215
+ end
216
+ end
217
+ end
195
218
 
196
- case packet.type
197
- when DISCONNECT
198
- raise Net::SSH::Disconnect, "disconnected: #{packet[:description]} (#{packet[:reason_code]})"
219
+ # Waits (blocks) until the given block returns true. If no block is given,
220
+ # this just waits long enough to see if there are any pending packets. Any
221
+ # packets read are enqueued (see #push).
222
+ def wait
223
+ loop do
224
+ break if block_given? && yield
225
+ message = poll_message(:nonblock, false)
226
+ push(message) if message
227
+ break if !block_given?
228
+ end
229
+ end
199
230
 
200
- when IGNORE
201
- debug { "IGNORE packet received: #{packet[:data].inspect}" }
231
+ # Adds the given packet to the packet queue. If the queue is non-empty,
232
+ # #poll_message will return packets from the queue in the order they
233
+ # were received.
234
+ def push(packet)
235
+ @queue.push(packet)
236
+ end
202
237
 
203
- when UNIMPLEMENTED
204
- lwarn { "UNIMPLEMENTED: #{packet[:number]}" }
238
+ # Sends the given message via the packet stream, blocking until the
239
+ # entire message has been sent.
240
+ def send_message(message)
241
+ socket.send_packet(message)
242
+ end
205
243
 
206
- when DEBUG
207
- send(packet[:always_display] ? :fatal : :debug) { packet[:message] }
244
+ # Enqueues the given message, such that it will be sent at the earliest
245
+ # opportunity. This does not block, but returns immediately.
246
+ def enqueue_message(message)
247
+ socket.enqueue_packet(message)
248
+ end
208
249
 
209
- when KEXINIT
210
- algorithms.accept_kexinit(packet)
250
+ # Configure's the packet stream's client state with the given set of
251
+ # options. This is typically used to define the cipher, compression, and
252
+ # hmac algorithms to use when sending packets to the server.
253
+ def configure_client(options={})
254
+ socket.client.set(options)
255
+ end
211
256
 
212
- else
213
- return packet if algorithms.allow?(packet)
214
- push(packet)
257
+ # Configure's the packet stream's server state with the given set of
258
+ # options. This is typically used to define the cipher, compression, and
259
+ # hmac algorithms to use when reading packets from the server.
260
+ def configure_server(options={})
261
+ socket.server.set(options)
215
262
  end
216
- end
217
- end
218
263
 
219
- # Waits (blocks) until the given block returns true. If no block is given,
220
- # this just waits long enough to see if there are any pending packets. Any
221
- # packets read are enqueued (see #push).
222
- def wait
223
- loop do
224
- break if block_given? && yield
225
- message = poll_message(:nonblock, false)
226
- push(message) if message
227
- break if !block_given?
228
- end
229
- end
264
+ # Sets a new hint for the packet stream, which the packet stream may use
265
+ # to change its behavior. (See PacketStream#hints).
266
+ def hint(which, value=true)
267
+ socket.hints[which] = value
268
+ end
230
269
 
231
- # Adds the given packet to the packet queue. If the queue is non-empty,
232
- # #poll_message will return packets from the queue in the order they
233
- # were received.
234
- def push(packet)
235
- @queue.push(packet)
236
- end
270
+ public
237
271
 
238
- # Sends the given message via the packet stream, blocking until the
239
- # entire message has been sent.
240
- def send_message(message)
241
- socket.send_packet(message)
242
- end
272
+ # this method is primarily for use in tests
273
+ attr_reader :queue #:nodoc:
243
274
 
244
- # Enqueues the given message, such that it will be sent at the earliest
245
- # opportunity. This does not block, but returns immediately.
246
- def enqueue_message(message)
247
- socket.enqueue_packet(message)
248
- end
275
+ private
249
276
 
250
- # Configure's the packet stream's client state with the given set of
251
- # options. This is typically used to define the cipher, compression, and
252
- # hmac algorithms to use when sending packets to the server.
253
- def configure_client(options={})
254
- socket.client.set(options)
255
- end
277
+ # Compatibility verifier which allows users to keep using
278
+ # custom verifier code without adding new :verify_signature
279
+ # method.
280
+ class CompatibleVerifier
281
+ def initialize(verifier)
282
+ @verifier = verifier
283
+ end
256
284
 
257
- # Configure's the packet stream's server state with the given set of
258
- # options. This is typically used to define the cipher, compression, and
259
- # hmac algorithms to use when reading packets from the server.
260
- def configure_server(options={})
261
- socket.server.set(options)
262
- end
285
+ def verify(arguments)
286
+ @verifier.verify(arguments)
287
+ end
263
288
 
264
- # Sets a new hint for the packet stream, which the packet stream may use
265
- # to change its behavior. (See PacketStream#hints).
266
- def hint(which, value=true)
267
- socket.hints[which] = value
268
- end
289
+ def verify_signature(&block)
290
+ yield
291
+ end
292
+ end
269
293
 
270
- public
271
-
272
- # this method is primarily for use in tests
273
- attr_reader :queue #:nodoc:
274
-
275
- private
276
-
277
- # Instantiates a new host-key verification class, based on the value of
278
- # the parameter. When true or nil, the default Lenient verifier is
279
- # returned. If it is false, the Null verifier is returned, and if it is
280
- # :very, the Strict verifier is returned. If it is :secure, the even more
281
- # strict Secure verifier is returned. If the argument happens to respond
282
- # to :verify, it is returned directly. Otherwise, an exception
283
- # is raised.
284
- def select_host_key_verifier(paranoid)
285
- case paranoid
286
- when true, nil then
287
- Net::SSH::Verifiers::Lenient.new
288
- when false then
289
- Net::SSH::Verifiers::Null.new
290
- when :very then
291
- Net::SSH::Verifiers::Strict.new
292
- when :secure then
293
- Net::SSH::Verifiers::Secure.new
294
- else
295
- if paranoid.respond_to?(:verify)
296
- paranoid
294
+ # Instantiates a new host-key verification class, based on the value of
295
+ # the parameter.
296
+ #
297
+ # Usually, the argument is a symbol like `:never` which corresponds to
298
+ # a verifier, like `::Net::SSH::Verifiers::Never`.
299
+ #
300
+ # - :never (very insecure)
301
+ # - :accept_new_or_local_tunnel (insecure)
302
+ # - :accept_new (insecure)
303
+ # - :always (secure)
304
+ #
305
+ # If the argument happens to respond to :verify and :verify_signature,
306
+ # it is returned directly. Otherwise, an exception is raised.
307
+ #
308
+ # Values false, true, and :very were deprecated in
309
+ # [#595](https://github.com/net-ssh/net-ssh/pull/595)
310
+ def select_host_key_verifier(verifier)
311
+ case verifier
312
+ when false
313
+ Kernel.warn('verify_host_key: false is deprecated, use :never')
314
+ Net::SSH::Verifiers::Never.new
315
+ when :never then
316
+ Net::SSH::Verifiers::Never.new
317
+ when true
318
+ Kernel.warn('verify_host_key: true is deprecated, use :accept_new_or_local_tunnel')
319
+ Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
320
+ when :accept_new_or_local_tunnel, nil then
321
+ Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
322
+ when :very
323
+ Kernel.warn('verify_host_key: :very is deprecated, use :accept_new')
324
+ Net::SSH::Verifiers::AcceptNew.new
325
+ when :accept_new then
326
+ Net::SSH::Verifiers::AcceptNew.new
327
+ when :secure then
328
+ Kernel.warn('verify_host_key: :secure is deprecated, use :always')
329
+ Net::SSH::Verifiers::Always.new
330
+ when :always then
331
+ Net::SSH::Verifiers::Always.new
297
332
  else
298
- raise ArgumentError, "argument to :paranoid is not valid: #{paranoid.inspect}"
333
+ if verifier.respond_to?(:verify)
334
+ if verifier.respond_to?(:verify_signature)
335
+ verifier
336
+ else
337
+ Kernel.warn("Warning: verifier without :verify_signature is deprecated")
338
+ CompatibleVerifier.new(verifier)
339
+ end
340
+ else
341
+ raise(
342
+ ArgumentError,
343
+ "Invalid argument to :verify_host_key (or deprecated " \
344
+ ":paranoid): #{verifier.inspect}"
345
+ )
346
+ end
299
347
  end
300
348
  end
301
349
  end
350
+ end
302
351
  end
303
- end; end; end
352
+ end