net-ssh 5.2.0 → 6.0.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -4
- data/.rubocop_todo.yml +392 -379
- data/.travis.yml +16 -17
- data/CHANGES.txt +11 -0
- data/Manifest +0 -1
- data/README.md +286 -0
- data/Rakefile +1 -2
- data/appveyor.yml +4 -2
- data/lib/net/ssh.rb +7 -2
- data/lib/net/ssh/authentication/certificate.rb +10 -1
- data/lib/net/ssh/authentication/ed25519.rb +2 -1
- data/lib/net/ssh/authentication/ed25519_loader.rb +1 -1
- data/lib/net/ssh/authentication/key_manager.rb +34 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +3 -1
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +0 -1
- data/lib/net/ssh/authentication/session.rb +9 -6
- data/lib/net/ssh/buffer.rb +1 -10
- data/lib/net/ssh/buffered_io.rb +0 -1
- data/lib/net/ssh/config.rb +51 -32
- data/lib/net/ssh/connection/channel.rb +17 -5
- data/lib/net/ssh/connection/event_loop.rb +0 -1
- data/lib/net/ssh/connection/session.rb +7 -4
- data/lib/net/ssh/key_factory.rb +6 -8
- data/lib/net/ssh/known_hosts.rb +27 -29
- data/lib/net/ssh/loggable.rb +2 -2
- data/lib/net/ssh/proxy/command.rb +0 -1
- data/lib/net/ssh/proxy/socks5.rb +0 -1
- data/lib/net/ssh/service/forward.rb +2 -1
- data/lib/net/ssh/test.rb +3 -2
- data/lib/net/ssh/transport/algorithms.rb +67 -42
- data/lib/net/ssh/transport/cipher_factory.rb +11 -27
- data/lib/net/ssh/transport/constants.rb +10 -6
- data/lib/net/ssh/transport/ctr.rb +1 -7
- data/lib/net/ssh/transport/hmac.rb +15 -13
- data/lib/net/ssh/transport/hmac/abstract.rb +16 -0
- 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/kex.rb +14 -11
- data/lib/net/ssh/transport/kex/abstract.rb +123 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +1 -15
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +9 -118
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -6
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +18 -79
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
- data/lib/net/ssh/transport/openssl.rb +104 -107
- data/lib/net/ssh/transport/packet_stream.rb +44 -11
- data/lib/net/ssh/transport/state.rb +1 -1
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh-public_cert.pem +8 -8
- data/net-ssh.gemspec +9 -7
- metadata +46 -29
- metadata.gz.sig +2 -3
- data/Gemfile.noed25519.lock +0 -41
- data/README.rdoc +0 -194
- data/lib/net/ssh/ruby_compat.rb +0 -13
- data/support/arcfour_check.rb +0 -20
@@ -26,7 +26,7 @@ module Net
|
|
26
26
|
CipherFactory = Net::SSH::Transport::CipherFactory
|
27
27
|
|
28
28
|
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
29
|
-
MEND = "-----END OPENSSH PRIVATE KEY
|
29
|
+
MEND = "-----END OPENSSH PRIVATE KEY-----"
|
30
30
|
MAGIC = "openssh-key-v1"
|
31
31
|
|
32
32
|
class DecryptError < ArgumentError
|
@@ -41,6 +41,7 @@ module Net
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.read(datafull, password)
|
44
|
+
datafull = datafull.strip
|
44
45
|
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
|
45
46
|
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
|
46
47
|
datab64 = datafull[MBEGIN.size...-MEND.size]
|
@@ -30,6 +30,9 @@ module Net
|
|
30
30
|
# The list of user key data that will be examined
|
31
31
|
attr_reader :key_data
|
32
32
|
|
33
|
+
# The list of user key certificate files that will be examined
|
34
|
+
attr_reader :keycert_files
|
35
|
+
|
33
36
|
# The map of loaded identities
|
34
37
|
attr_reader :known_identities
|
35
38
|
|
@@ -43,6 +46,7 @@ module Net
|
|
43
46
|
self.logger = logger
|
44
47
|
@key_files = []
|
45
48
|
@key_data = []
|
49
|
+
@keycert_files = []
|
46
50
|
@use_agent = options[:use_agent] != false
|
47
51
|
@known_identities = {}
|
48
52
|
@agent = nil
|
@@ -66,6 +70,12 @@ module Net
|
|
66
70
|
self
|
67
71
|
end
|
68
72
|
|
73
|
+
# Add the given keycert_file to the list of keycert files that will be used.
|
74
|
+
def add_keycert(keycert_file)
|
75
|
+
keycert_files.push(File.expand_path(keycert_file)).uniq!
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
69
79
|
# Add the given key_file to the list of keys that will be used.
|
70
80
|
def add_key_data(key_data_)
|
71
81
|
key_data.push(key_data_).uniq!
|
@@ -108,7 +118,7 @@ module Net
|
|
108
118
|
user_identities.delete(corresponding_user_identity) if corresponding_user_identity
|
109
119
|
|
110
120
|
if !options[:keys_only] || corresponding_user_identity
|
111
|
-
known_identities[key] = { from: :agent }
|
121
|
+
known_identities[key] = { from: :agent, identity: key }
|
112
122
|
yield key
|
113
123
|
end
|
114
124
|
end
|
@@ -122,6 +132,21 @@ module Net
|
|
122
132
|
yield key
|
123
133
|
end
|
124
134
|
|
135
|
+
known_identity_blobs = known_identities.keys.map(&:to_blob)
|
136
|
+
keycert_files.each do |keycert_file|
|
137
|
+
keycert = KeyFactory.load_public_key(keycert_file)
|
138
|
+
next if known_identity_blobs.include?(keycert.to_blob)
|
139
|
+
|
140
|
+
(_, corresponding_identity) = known_identities.detect { |public_key, _|
|
141
|
+
public_key.to_pem == keycert.to_pem
|
142
|
+
}
|
143
|
+
|
144
|
+
if corresponding_identity
|
145
|
+
known_identities[keycert] = corresponding_identity
|
146
|
+
yield keycert
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
125
150
|
self
|
126
151
|
end
|
127
152
|
|
@@ -139,7 +164,7 @@ module Net
|
|
139
164
|
|
140
165
|
if info[:key].nil? && info[:from] == :file
|
141
166
|
begin
|
142
|
-
info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive])
|
167
|
+
info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive], options[:password_prompt])
|
143
168
|
rescue OpenSSL::OpenSSLError, Exception => e
|
144
169
|
raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})"
|
145
170
|
end
|
@@ -152,7 +177,7 @@ module Net
|
|
152
177
|
|
153
178
|
if info[:from] == :agent
|
154
179
|
raise KeyManagerError, "the agent is no longer available" unless agent
|
155
|
-
return agent.sign(identity, data.to_s)
|
180
|
+
return agent.sign(info[:identity], data.to_s)
|
156
181
|
end
|
157
182
|
|
158
183
|
raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})"
|
@@ -229,11 +254,15 @@ module Net
|
|
229
254
|
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
230
255
|
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
231
256
|
when :privkey_file
|
232
|
-
private_key = KeyFactory.load_private_key(
|
257
|
+
private_key = KeyFactory.load_private_key(
|
258
|
+
identity[:privkey_file], options[:passphrase], ask_passphrase, options[:password_prompt]
|
259
|
+
)
|
233
260
|
key = private_key.send(:public_key)
|
234
261
|
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
235
262
|
when :data
|
236
|
-
private_key = KeyFactory.load_data_private_key(
|
263
|
+
private_key = KeyFactory.load_data_private_key(
|
264
|
+
identity[:data], options[:passphrase], ask_passphrase, "<key in memory>", options[:password_prompt]
|
265
|
+
)
|
237
266
|
key = private_key.send(:public_key)
|
238
267
|
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
239
268
|
else
|
@@ -40,7 +40,9 @@ module Net
|
|
40
40
|
instruction = message.read_string
|
41
41
|
debug { "keyboard-interactive info request" }
|
42
42
|
|
43
|
-
|
43
|
+
if password.nil? && interactive? && prompter.nil?
|
44
|
+
prompter = prompt.start(type: 'keyboard-interactive', name: name, instruction: instruction)
|
45
|
+
end
|
44
46
|
|
45
47
|
_ = message.read_string # lang_tag
|
46
48
|
responses = []
|
@@ -63,6 +63,7 @@ module Net
|
|
63
63
|
|
64
64
|
key_manager = KeyManager.new(logger, options)
|
65
65
|
keys.each { |key| key_manager.add(key) } unless keys.empty?
|
66
|
+
keycerts.each { |keycert| key_manager.add_keycert(keycert) } unless keycerts.empty?
|
66
67
|
key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty?
|
67
68
|
default_keys.each { |key| key_manager.add(key) } unless options.key?(:keys) || options.key?(:key_data)
|
68
69
|
|
@@ -136,12 +137,8 @@ module Net
|
|
136
137
|
# Returns an array of paths to the key files usually defined
|
137
138
|
# by system default.
|
138
139
|
def default_keys
|
139
|
-
|
140
|
-
|
141
|
-
~/.ssh2/id_ed25519 ~/.ssh2/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_ecdsa]
|
142
|
-
else
|
143
|
-
%w[~/.ssh/id_dsa ~/.ssh/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_rsa]
|
144
|
-
end
|
140
|
+
%w[~/.ssh/id_ed25519 ~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa
|
141
|
+
~/.ssh2/id_ed25519 ~/.ssh2/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_ecdsa]
|
145
142
|
end
|
146
143
|
|
147
144
|
# Returns an array of paths to the key files that should be used when
|
@@ -150,6 +147,12 @@ module Net
|
|
150
147
|
Array(options[:keys])
|
151
148
|
end
|
152
149
|
|
150
|
+
# Returns an array of paths to the keycert files that should be used when
|
151
|
+
# attempting any key-based authentication mechanism.
|
152
|
+
def keycerts
|
153
|
+
Array(options[:keycerts])
|
154
|
+
end
|
155
|
+
|
153
156
|
# Returns an array of the key data that should be used when
|
154
157
|
# attempting any key-based authentication mechanism.
|
155
158
|
def key_data
|
data/lib/net/ssh/buffer.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'net/ssh/ruby_compat'
|
2
1
|
require 'net/ssh/transport/openssl'
|
3
2
|
|
4
3
|
require 'net/ssh/authentication/certificate'
|
@@ -323,15 +322,7 @@ module Net
|
|
323
322
|
Net::SSH::Authentication::ED25519Loader.raiseUnlessLoaded("unsupported key type `#{type}'")
|
324
323
|
key = Net::SSH::Authentication::ED25519::PubKey.read_keyblob(self)
|
325
324
|
when /^ecdsa\-sha2\-(\w*)$/
|
326
|
-
|
327
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
328
|
-
else
|
329
|
-
begin
|
330
|
-
key = OpenSSL::PKey::EC.read_keyblob($1, self)
|
331
|
-
rescue OpenSSL::PKey::ECError
|
332
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
333
|
-
end
|
334
|
-
end
|
325
|
+
key = OpenSSL::PKey::EC.read_keyblob($1, self)
|
335
326
|
else
|
336
327
|
raise NotImplementedError, "unsupported key type `#{type}'"
|
337
328
|
end
|
data/lib/net/ssh/buffered_io.rb
CHANGED
data/lib/net/ssh/config.rb
CHANGED
@@ -11,6 +11,7 @@ module Net
|
|
11
11
|
#
|
12
12
|
# * ChallengeResponseAuthentication => maps to the :auth_methods option challenge-response (then coleasced into keyboard-interactive)
|
13
13
|
# * KbdInteractiveAuthentication => maps to the :auth_methods keyboard-interactive
|
14
|
+
# * CertificateFile => maps to the :keycerts option
|
14
15
|
# * Ciphers => maps to the :encryption option
|
15
16
|
# * Compression => :compression
|
16
17
|
# * CompressionLevel => :compression_level
|
@@ -33,6 +34,7 @@ module Net
|
|
33
34
|
# * ProxyJump => maps to the :proxy option
|
34
35
|
# * PubKeyAuthentication => maps to the :auth_methods option
|
35
36
|
# * RekeyLimit => :rekey_limit
|
37
|
+
# * StrictHostKeyChecking => :strict_host_key_checking
|
36
38
|
# * User => :user
|
37
39
|
# * UserKnownHostsFile => :user_known_hosts_file
|
38
40
|
# * NumberOfPasswordPrompts => :number_of_password_prompts
|
@@ -128,7 +130,7 @@ module Net
|
|
128
130
|
block_seen = true
|
129
131
|
elsif !block_seen
|
130
132
|
case key
|
131
|
-
when 'identityfile'
|
133
|
+
when 'identityfile', 'certificatefile'
|
132
134
|
(globals[key] ||= []) << value
|
133
135
|
when 'include'
|
134
136
|
included_file_paths(base_dir, value).each do |file_path|
|
@@ -139,7 +141,7 @@ module Net
|
|
139
141
|
end
|
140
142
|
elsif block_matched
|
141
143
|
case key
|
142
|
-
when 'identityfile'
|
144
|
+
when 'identityfile', 'certificatefile'
|
143
145
|
(settings[key] ||= []) << value
|
144
146
|
when 'include'
|
145
147
|
included_file_paths(base_dir, value).each do |file_path|
|
@@ -149,11 +151,18 @@ module Net
|
|
149
151
|
settings[key] = value unless settings.key?(key)
|
150
152
|
end
|
151
153
|
end
|
154
|
+
|
155
|
+
# ProxyCommand and ProxyJump override each other so they need to be tracked togeather
|
156
|
+
%w[proxyjump proxycommand].each do |proxy_key|
|
157
|
+
if (proxy_value = settings.delete(proxy_key))
|
158
|
+
settings['proxy'] ||= [proxy_key, proxy_value]
|
159
|
+
end
|
160
|
+
end
|
152
161
|
end
|
153
162
|
|
154
163
|
globals.merge(settings) do |key, oldval, newval|
|
155
164
|
case key
|
156
|
-
when 'identityfile'
|
165
|
+
when 'identityfile', 'certificatefile'
|
157
166
|
oldval + newval
|
158
167
|
else
|
159
168
|
newval
|
@@ -188,24 +197,26 @@ module Net
|
|
188
197
|
|
189
198
|
private
|
190
199
|
|
200
|
+
TRANSLATE_CONFIG_KEY_RENAME_MAP = {
|
201
|
+
bindaddress: :bind_address,
|
202
|
+
compression: :compression,
|
203
|
+
compressionlevel: :compression_level,
|
204
|
+
certificatefile: :keycerts,
|
205
|
+
connecttimeout: :timeout,
|
206
|
+
forwardagent: :forward_agent,
|
207
|
+
identitiesonly: :keys_only,
|
208
|
+
identityagent: :identity_agent,
|
209
|
+
globalknownhostsfile: :global_known_hosts_file,
|
210
|
+
hostkeyalias: :host_key_alias,
|
211
|
+
identityfile: :keys,
|
212
|
+
fingerprinthash: :fingerprint_hash,
|
213
|
+
port: :port,
|
214
|
+
stricthostkeychecking: :strict_host_key_checking,
|
215
|
+
user: :user,
|
216
|
+
userknownhostsfile: :user_known_hosts_file,
|
217
|
+
checkhostip: :check_host_ip
|
218
|
+
}.freeze
|
191
219
|
def translate_config_key(hash, key, value, settings)
|
192
|
-
rename = {
|
193
|
-
bindaddress: :bind_address,
|
194
|
-
compression: :compression,
|
195
|
-
compressionlevel: :compression_level,
|
196
|
-
connecttimeout: :timeout,
|
197
|
-
forwardagent: :forward_agent,
|
198
|
-
identitiesonly: :keys_only,
|
199
|
-
identityagent: :identity_agent,
|
200
|
-
globalknownhostsfile: :global_known_hosts_file,
|
201
|
-
hostkeyalias: :host_key_alias,
|
202
|
-
identityfile: :keys,
|
203
|
-
fingerprinthash: :fingerprint_hash,
|
204
|
-
port: :port,
|
205
|
-
user: :user,
|
206
|
-
userknownhostsfile: :user_known_hosts_file,
|
207
|
-
checkhostip: :check_host_ip
|
208
|
-
}
|
209
220
|
case key
|
210
221
|
when :ciphers
|
211
222
|
hash[:encryption] = value.split(/,/)
|
@@ -250,15 +261,9 @@ module Net
|
|
250
261
|
end
|
251
262
|
when :preferredauthentications
|
252
263
|
hash[:auth_methods] = value.split(/,/) # TODO we should place to preferred_auth_methods rather than auth_methods
|
253
|
-
when :
|
254
|
-
if
|
255
|
-
|
256
|
-
hash[:proxy] = Net::SSH::Proxy::Command.new(value)
|
257
|
-
end
|
258
|
-
when :proxyjump
|
259
|
-
if value
|
260
|
-
require 'net/ssh/proxy/jump'
|
261
|
-
hash[:proxy] = Net::SSH::Proxy::Jump.new(value)
|
264
|
+
when :proxy
|
265
|
+
if (proxy = setup_proxy(*value))
|
266
|
+
hash[:proxy] = proxy
|
262
267
|
end
|
263
268
|
when :pubkeyauthentication
|
264
269
|
if value
|
@@ -271,10 +276,25 @@ module Net
|
|
271
276
|
when :sendenv
|
272
277
|
multi_send_env = value.to_s.split(/\s+/)
|
273
278
|
hash[:send_env] = multi_send_env.map { |e| Regexp.new pattern2regex(e).source, false }
|
279
|
+
when :setenv
|
280
|
+
hash[:set_env] = Shellwords.split(value.to_s).map { |e| e.split '=', 2 }.to_h
|
274
281
|
when :numberofpasswordprompts
|
275
282
|
hash[:number_of_password_prompts] = value.to_i
|
276
|
-
when *
|
277
|
-
hash[
|
283
|
+
when *TRANSLATE_CONFIG_KEY_RENAME_MAP.keys
|
284
|
+
hash[TRANSLATE_CONFIG_KEY_RENAME_MAP[key]] = value
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def setup_proxy(type, value)
|
289
|
+
case type
|
290
|
+
when 'proxycommand'
|
291
|
+
if value !~ /^none$/
|
292
|
+
require 'net/ssh/proxy/command'
|
293
|
+
Net::SSH::Proxy::Command.new(value)
|
294
|
+
end
|
295
|
+
when 'proxyjump'
|
296
|
+
require 'net/ssh/proxy/jump'
|
297
|
+
Net::SSH::Proxy::Jump.new(value)
|
278
298
|
end
|
279
299
|
end
|
280
300
|
|
@@ -369,6 +389,5 @@ module Net
|
|
369
389
|
end
|
370
390
|
end
|
371
391
|
end
|
372
|
-
|
373
392
|
end
|
374
393
|
end
|
@@ -2,8 +2,8 @@ require 'net/ssh/loggable'
|
|
2
2
|
require 'net/ssh/connection/constants'
|
3
3
|
require 'net/ssh/connection/term'
|
4
4
|
|
5
|
-
module Net
|
6
|
-
module SSH
|
5
|
+
module Net
|
6
|
+
module SSH
|
7
7
|
module Connection
|
8
8
|
|
9
9
|
# The channel abstraction. Multiple "channels" can be multiplexed onto a
|
@@ -530,6 +530,7 @@ module Net
|
|
530
530
|
@remote_maximum_packet_size = max_packet
|
531
531
|
connection.forward.agent(self) if connection.options[:forward_agent] && type == "session"
|
532
532
|
forward_local_env(connection.options[:send_env]) if connection.options[:send_env]
|
533
|
+
set_remote_env(connection.options[:set_env]) if connection.options[:set_env]
|
533
534
|
@on_confirm_open.call(self) if @on_confirm_open
|
534
535
|
end
|
535
536
|
|
@@ -648,10 +649,14 @@ module Net
|
|
648
649
|
def update_local_window_size(size)
|
649
650
|
@local_window_size -= size
|
650
651
|
if local_window_size < local_maximum_window_size / 2
|
651
|
-
connection.send_message(
|
652
|
-
:long, remote_id, :long, LOCAL_WINDOW_SIZE_INCREMENT)
|
652
|
+
connection.send_message(
|
653
|
+
Buffer.from(:byte, CHANNEL_WINDOW_ADJUST, :long, remote_id, :long, LOCAL_WINDOW_SIZE_INCREMENT)
|
654
|
+
)
|
653
655
|
@local_window_size += LOCAL_WINDOW_SIZE_INCREMENT
|
654
|
-
|
656
|
+
|
657
|
+
if @local_maximum_window_size < @local_window_size || @local_maximum_window_size < GOOD_LOCAL_MAXIUMUM_WINDOW_SIZE
|
658
|
+
@local_maximum_window_size += LOCAL_WINDOW_SIZE_INCREMENT
|
659
|
+
end
|
655
660
|
end
|
656
661
|
end
|
657
662
|
|
@@ -673,6 +678,13 @@ module Net
|
|
673
678
|
end
|
674
679
|
end
|
675
680
|
end
|
681
|
+
|
682
|
+
# Set a +Hash+ of environment variables in the remote process' environment.
|
683
|
+
#
|
684
|
+
# channel.set_remote_env foo: 'bar', baz: 'whale'
|
685
|
+
def set_remote_env(env)
|
686
|
+
env.each { |key, value| self.env(key, value) }
|
687
|
+
end
|
676
688
|
end
|
677
689
|
|
678
690
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'net/ssh/loggable'
|
2
|
-
require 'net/ssh/ruby_compat'
|
3
2
|
require 'net/ssh/connection/channel'
|
4
3
|
require 'net/ssh/connection/constants'
|
5
4
|
require 'net/ssh/service/forward'
|
@@ -580,8 +579,10 @@ module Net
|
|
580
579
|
info { "global request received: #{packet[:request_type]} #{packet[:want_reply]}" }
|
581
580
|
callback = @on_global_request[packet[:request_type]]
|
582
581
|
result = callback ? callback.call(packet[:request_data], packet[:want_reply]) : false
|
583
|
-
|
584
|
-
|
582
|
+
|
583
|
+
if result != :sent && result != true && result != false
|
584
|
+
raise "expected global request handler for `#{packet[:request_type]}' to return true, false, or :sent, but got #{result.inspect}"
|
585
|
+
end
|
585
586
|
|
586
587
|
if packet[:want_reply] && result != :sent
|
587
588
|
msg = Buffer.from(:byte, result ? REQUEST_SUCCESS : REQUEST_FAILURE)
|
@@ -624,7 +625,9 @@ module Net
|
|
624
625
|
failure = [err.code, err.reason]
|
625
626
|
else
|
626
627
|
channels[local_id] = channel
|
627
|
-
msg = Buffer.from(:byte, CHANNEL_OPEN_CONFIRMATION, :long, channel.remote_id, :long,
|
628
|
+
msg = Buffer.from(:byte, CHANNEL_OPEN_CONFIRMATION, :long, channel.remote_id, :long,
|
629
|
+
channel.local_id, :long, channel.local_maximum_window_size, :long,
|
630
|
+
channel.local_maximum_packet_size)
|
628
631
|
end
|
629
632
|
else
|
630
633
|
failure = [3, "unknown channel type #{channel.type}"]
|
data/lib/net/ssh/key_factory.rb
CHANGED
@@ -18,14 +18,12 @@ module Net
|
|
18
18
|
class KeyFactory
|
19
19
|
# Specifies the mapping of SSH names to OpenSSL key classes.
|
20
20
|
MAP = {
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
'dh' => OpenSSL::PKey::DH,
|
22
|
+
'rsa' => OpenSSL::PKey::RSA,
|
23
|
+
'dsa' => OpenSSL::PKey::DSA,
|
24
|
+
'ecdsa' => OpenSSL::PKey::EC
|
24
25
|
}
|
25
|
-
if defined?
|
26
|
-
MAP["ecdsa"] = OpenSSL::PKey::EC
|
27
|
-
MAP["ed25519"] = Net::SSH::Authentication::ED25519::PrivKey if defined? Net::SSH::Authentication::ED25519
|
28
|
-
end
|
26
|
+
MAP["ed25519"] = Net::SSH::Authentication::ED25519::PrivKey if defined? Net::SSH::Authentication::ED25519
|
29
27
|
|
30
28
|
class <<self
|
31
29
|
# Fetch an OpenSSL key instance by its SSH name. It will be a new,
|
@@ -207,7 +205,7 @@ module Net
|
|
207
205
|
return OpenSSLDSAKeyType
|
208
206
|
elsif data.match(/-----BEGIN RSA PRIVATE KEY-----/)
|
209
207
|
return OpenSSLRSAKeyType
|
210
|
-
elsif data.match(/-----BEGIN EC PRIVATE KEY-----/)
|
208
|
+
elsif data.match(/-----BEGIN EC PRIVATE KEY-----/)
|
211
209
|
return OpenSSLECKeyType
|
212
210
|
elsif data.match(/-----BEGIN (.+) PRIVATE KEY-----/)
|
213
211
|
raise OpenSSL::PKey::PKeyError, "not a supported key type '#{$1}'"
|