net-ssh 5.1.0 → 5.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -3
- data.tar.gz.sig +0 -0
- data/.rubocop.yml +3 -0
- data/CHANGES.txt +8 -1
- data/lib/net/ssh.rb +5 -1
- data/lib/net/ssh/authentication/ed25519.rb +12 -1
- data/lib/net/ssh/key_factory.rb +98 -9
- data/lib/net/ssh/known_hosts.rb +21 -6
- data/lib/net/ssh/transport/session.rb +1 -1
- data/lib/net/ssh/version.rb +2 -2
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f322b0b79581a7d7b24a917b79ddabc8563b5a5c
|
4
|
+
data.tar.gz: a9e3a2c9cfa281f1b91a335bda58f4b6dcc568fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcd0f1c4c2a6833e75509523cf19195cbb2320860f5f20800ce780f785d52093ae24331b27ac3dcfd49d62de341048ed611078f15449f3052830cf7c1630e309
|
7
|
+
data.tar.gz: 3b3fa8989372dbbe9a84fdfdbc22dde5b9ea69fcb206b9e859aa83f6a46b729b117dfe024c49a1fe969a2fedc2dbacbc190d2b5764603efe6780c10f15b31f58
|
checksums.yaml.gz.sig
CHANGED
@@ -1,3 +1 @@
|
|
1
|
-
|
2
|
-
��k�)��Ȗ0��cq�?�J�k��d�_�@����&%y]ȋt�������V��Z���SdQ%n�4"U�8�ȯ5�ud�9���wO�'"7�
|
3
|
-
=�BH6¾!n�'Pi���վQB3�U�� �l�M�L~�-���m���M4��J�~��-�X�π͋�P��e7��s@��#�`>Wٌ���M���G�@$Ke�P�N\kn8x^��\
|
1
|
+
4�QQ�t���UPSG*�˩�rMd�"\B���b2�b�n����!�8����)�a,�(k��2$��.cKKS���U@T�~g�� &�0v)��Z�%���/H-�z�˺�{�v�1j�~�_*M/f��J�feѬ*p������M]��&��|ϕO�yA'F��ha�Z������CZe�^�t���X�,eJ%&u_zwn- ;tx�H��,�N�HYs���iL���J�~�1�� 6��\���� A
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.rubocop.yml
CHANGED
data/CHANGES.txt
CHANGED
@@ -1,8 +1,15 @@
|
|
1
|
+
=== 5.2.0.rc1
|
2
|
+
|
3
|
+
* Interpret * and ? in know_hosts file [Romain Tartière, #660]
|
4
|
+
* New :check_host_ip so ip checking can be disabled in known hosts [Romain Tartière, #656]
|
5
|
+
|
6
|
+
=== 5.1.0
|
7
|
+
|
1
8
|
=== 5.1.0.rc1
|
2
9
|
|
3
10
|
* Support new OpenSSH private key format for rsa - bcrypt for rsa (ed25519 already supported) [#646]
|
4
11
|
* Support IdentityAgent is ssh config [Frank Groeneveld, #645]
|
5
|
-
* Improve Match
|
12
|
+
* Improve Match processing in ssh config [Aleksandrs Ļedovskis, #642]
|
6
13
|
* Ignore signature verification when verify_host_key is never [Piotr Kliczewski, #641]
|
7
14
|
* Alg preference was changed to prefer stronger encryptions [Tray, #637]
|
8
15
|
|
data/lib/net/ssh.rb
CHANGED
@@ -73,7 +73,7 @@ module Net
|
|
73
73
|
max_win_size send_env use_agent number_of_password_prompts
|
74
74
|
append_all_supported_algorithms non_interactive password_prompt
|
75
75
|
agent_socket_factory minimum_dh_bits verify_host_key
|
76
|
-
fingerprint_hash
|
76
|
+
fingerprint_hash check_host_ip
|
77
77
|
]
|
78
78
|
|
79
79
|
# The standard means of starting a new SSH connection. When used with a
|
@@ -108,6 +108,8 @@ module Net
|
|
108
108
|
# * :bind_address => the IP address on the connecting machine to use in
|
109
109
|
# establishing connection. (:bind_address is discarded if :proxy
|
110
110
|
# is set.)
|
111
|
+
# * :check_host_ip => Also ckeck IP address when connecting to remote host.
|
112
|
+
# Defaults to +true+.
|
111
113
|
# * :compression => the compression algorithm to use, or +true+ to use
|
112
114
|
# whatever is supported.
|
113
115
|
# * :compression_level => the compression level to use when sending data
|
@@ -290,6 +292,8 @@ module Net
|
|
290
292
|
%i[password passphrase].each do |key|
|
291
293
|
options.delete(key) if options.key?(key) && options[key].nil?
|
292
294
|
end
|
295
|
+
|
296
|
+
options[:check_host_ip] = true unless options.key?(:check_host_ip)
|
293
297
|
end
|
294
298
|
|
295
299
|
def self._sanitize_options(options)
|
@@ -29,6 +29,17 @@ module Net
|
|
29
29
|
MEND = "-----END OPENSSH PRIVATE KEY-----\n"
|
30
30
|
MAGIC = "openssh-key-v1"
|
31
31
|
|
32
|
+
class DecryptError < ArgumentError
|
33
|
+
def initialize(message, encrypted_key: false)
|
34
|
+
super(message)
|
35
|
+
@encrypted_key = encrypted_key
|
36
|
+
end
|
37
|
+
|
38
|
+
def encrypted_key?
|
39
|
+
return @encrypted_key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
32
43
|
def self.read(datafull, password)
|
33
44
|
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
|
34
45
|
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
|
@@ -74,7 +85,7 @@ module Net
|
|
74
85
|
check1 = decoded.read_long
|
75
86
|
check2 = decoded.read_long
|
76
87
|
|
77
|
-
raise
|
88
|
+
raise DecryptError.new("Decrypt failed on private key", encrypted_key: kdfname == 'bcrypt') if (check1 != check2)
|
78
89
|
|
79
90
|
type_name = decoded.read_string
|
80
91
|
case type_name
|
data/lib/net/ssh/key_factory.rb
CHANGED
@@ -50,16 +50,17 @@ module Net
|
|
50
50
|
# encrypted (requiring a passphrase to use), the user will be
|
51
51
|
# prompted to enter their password unless passphrase works.
|
52
52
|
def load_data_private_key(data, passphrase=nil, ask_passphrase=true, filename="", prompt=Prompt.default)
|
53
|
-
|
53
|
+
key_type = classify_key(data, filename)
|
54
54
|
|
55
|
-
encrypted_key =
|
55
|
+
encrypted_key = nil
|
56
56
|
tries = 0
|
57
57
|
|
58
58
|
prompter = nil
|
59
59
|
result =
|
60
60
|
begin
|
61
|
-
|
62
|
-
rescue *error_classes
|
61
|
+
key_type.read(data, passphrase || 'invalid')
|
62
|
+
rescue *key_type.error_classes => e
|
63
|
+
encrypted_key = !!key_type.encrypted_key?(data, e) if encrypted_key.nil?
|
63
64
|
if encrypted_key && ask_passphrase
|
64
65
|
tries += 1
|
65
66
|
if tries <= 3
|
@@ -106,20 +107,108 @@ module Net
|
|
106
107
|
|
107
108
|
private
|
108
109
|
|
110
|
+
# rubocop:disable Style/Documentation, Lint/DuplicateMethods
|
111
|
+
class KeyType
|
112
|
+
def self.read(key_data, passphrase)
|
113
|
+
raise Exception, "TODO subclasses should implement read"
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.error_classes
|
117
|
+
raise Exception, "TODO subclasses should implement read"
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.encrypted_key?(data, error)
|
121
|
+
raise Exception, "TODO subclasses should implement is_encrypted_key"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class OpenSSHPrivateKeyType < KeyType
|
126
|
+
def self.read(key_data, passphrase)
|
127
|
+
Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader.read(key_data, passphrase)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.error_classes
|
131
|
+
[Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError]
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.encrypted_key?(key_data, decode_error)
|
135
|
+
decode_error.is_a?(Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader::DecryptError) && decode_error.encrypted_key?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class OpenSSLKeyTypeBase < KeyType
|
140
|
+
def self.open_ssl_class
|
141
|
+
raise Exception, "TODO: subclasses should implement"
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.read(key_data, passphrase)
|
145
|
+
open_ssl_class.new(key_data, passphrase)
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.encrypted_key?(key_data, error)
|
149
|
+
key_data.match(/ENCRYPTED/)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class OpenSSLPKeyType < OpenSSLKeyTypeBase
|
154
|
+
def self.read(key_data, passphrase)
|
155
|
+
open_ssl_class.read(key_data, passphrase)
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.open_ssl_class
|
159
|
+
OpenSSL::PKey
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.error_classes
|
163
|
+
[ArgumentError, OpenSSL::PKey::PKeyError]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class OpenSSLDSAKeyType < OpenSSLKeyTypeBase
|
168
|
+
def self.open_ssl_class
|
169
|
+
OpenSSL::PKey::DSA
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.error_classes
|
173
|
+
[OpenSSL::PKey::DSAError]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class OpenSSLRSAKeyType < OpenSSLKeyTypeBase
|
178
|
+
def self.open_ssl_class
|
179
|
+
OpenSSL::PKey::RSA
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.error_classes
|
183
|
+
[OpenSSL::PKey::RSAError]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class OpenSSLECKeyType < OpenSSLKeyTypeBase
|
188
|
+
def self.open_ssl_class
|
189
|
+
OpenSSL::PKey::EC
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.error_classes
|
193
|
+
[OpenSSL::PKey::ECError]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
# rubocop:enable Style/Documentation, Lint/DuplicateMethods
|
197
|
+
|
109
198
|
# Determine whether the file describes an RSA or DSA key, and return how load it
|
110
199
|
# appropriately.
|
111
200
|
def classify_key(data, filename)
|
112
201
|
if data.match(/-----BEGIN OPENSSH PRIVATE KEY-----/)
|
113
202
|
Net::SSH::Authentication::ED25519Loader.raiseUnlessLoaded("OpenSSH keys only supported if ED25519 is available")
|
114
|
-
return
|
203
|
+
return OpenSSHPrivateKeyType
|
115
204
|
elsif OpenSSL::PKey.respond_to?(:read)
|
116
|
-
return
|
205
|
+
return OpenSSLPKeyType
|
117
206
|
elsif data.match(/-----BEGIN DSA PRIVATE KEY-----/)
|
118
|
-
return
|
207
|
+
return OpenSSLDSAKeyType
|
119
208
|
elsif data.match(/-----BEGIN RSA PRIVATE KEY-----/)
|
120
|
-
return
|
209
|
+
return OpenSSLRSAKeyType
|
121
210
|
elsif data.match(/-----BEGIN EC PRIVATE KEY-----/) && defined?(OpenSSL::PKey::EC)
|
122
|
-
return
|
211
|
+
return OpenSSLECKeyType
|
123
212
|
elsif data.match(/-----BEGIN (.+) PRIVATE KEY-----/)
|
124
213
|
raise OpenSSL::PKey::PKeyError, "not a supported key type '#{$1}'"
|
125
214
|
else
|
data/lib/net/ssh/known_hosts.rb
CHANGED
@@ -53,13 +53,13 @@ module Net
|
|
53
53
|
# Searches all known host files (see KnownHosts.hostfiles) for all keys
|
54
54
|
# of the given host. Returns an enumerable of keys found.
|
55
55
|
def search_for(host, options={})
|
56
|
-
HostKeys.new(search_in(hostfiles(options), host), host, self, options)
|
56
|
+
HostKeys.new(search_in(hostfiles(options), host, options), host, self, options)
|
57
57
|
end
|
58
58
|
|
59
59
|
# Search for all known keys for the given host, in every file given in
|
60
60
|
# the +files+ array. Returns the list of keys.
|
61
|
-
def search_in(files, host)
|
62
|
-
files.flat_map { |file| KnownHosts.new(file).keys_for(host) }
|
61
|
+
def search_in(files, host, options = {})
|
62
|
+
files.flat_map { |file| KnownHosts.new(file).keys_for(host, options) }
|
63
63
|
end
|
64
64
|
|
65
65
|
# Looks in the given +options+ hash for the :user_known_hosts_file and
|
@@ -119,11 +119,13 @@ module Net
|
|
119
119
|
# "[net.ssh.test]:5555"
|
120
120
|
# "[1,2,3,4]:5555"
|
121
121
|
# "[net.ssh.test]:5555,[1.2.3.4]:5555
|
122
|
-
def keys_for(host)
|
122
|
+
def keys_for(host, options = {})
|
123
123
|
keys = []
|
124
124
|
return keys unless File.readable?(source)
|
125
125
|
|
126
126
|
entries = host.split(/,/)
|
127
|
+
host_name = entries[0]
|
128
|
+
host_ip = entries[1]
|
127
129
|
|
128
130
|
File.open(source) do |file|
|
129
131
|
scanner = StringScanner.new("")
|
@@ -134,8 +136,10 @@ module Net
|
|
134
136
|
next if scanner.match?(/$|#/)
|
135
137
|
|
136
138
|
hostlist = scanner.scan(/\S+/).split(/,/)
|
137
|
-
found =
|
138
|
-
|
139
|
+
found = hostlist.any? { |pattern| match(host_name, pattern) } || known_host_hash?(hostlist, entries)
|
140
|
+
next unless found
|
141
|
+
|
142
|
+
found = hostlist.include?(host_ip) if options[:check_host_ip] && entries.size > 1 && hostlist.size > 1
|
139
143
|
next unless found
|
140
144
|
|
141
145
|
scanner.skip(/\s*/)
|
@@ -152,6 +156,17 @@ module Net
|
|
152
156
|
keys
|
153
157
|
end
|
154
158
|
|
159
|
+
def match(host, pattern)
|
160
|
+
# see man 8 sshd for pattern details
|
161
|
+
pattern_regexp = pattern.split('*').map do |x|
|
162
|
+
x.split('?').map do |y|
|
163
|
+
Regexp.escape(y)
|
164
|
+
end.join('.')
|
165
|
+
end.join('[^.]*')
|
166
|
+
|
167
|
+
host =~ Regexp.new("\\A#{pattern_regexp}\\z")
|
168
|
+
end
|
169
|
+
|
155
170
|
# Indicates whether one of the entries matches an hostname that has been
|
156
171
|
# stored as a HMAC-SHA1 hash in the known hosts.
|
157
172
|
def known_host_hash?(hostlist, entries)
|
data/lib/net/ssh/version.rb
CHANGED
@@ -49,14 +49,14 @@ module Net
|
|
49
49
|
MAJOR = 5
|
50
50
|
|
51
51
|
# The minor component of this version of the Net::SSH library
|
52
|
-
MINOR =
|
52
|
+
MINOR = 2
|
53
53
|
|
54
54
|
# The tiny component of this version of the Net::SSH library
|
55
55
|
TINY = 0
|
56
56
|
|
57
57
|
# The prerelease component of this version of the Net::SSH library
|
58
58
|
# nil allowed
|
59
|
-
PRE =
|
59
|
+
PRE = "rc1"
|
60
60
|
|
61
61
|
# The current version of the Net::SSH library as a Version instance
|
62
62
|
CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamis Buck
|
@@ -32,7 +32,7 @@ cert_chain:
|
|
32
32
|
ZFwoIuXKeDmTTpryd/vI7sdLXDuV6MbWOLGh6gXn9RDDXG1EqEXW0bjovATBMpdH
|
33
33
|
9OGohJvAFzcvhDTWPwT6w3PG5B80pqb9j1hEAg==
|
34
34
|
-----END CERTIFICATE-----
|
35
|
-
date:
|
35
|
+
date: 2019-03-02 00:00:00.000000000 Z
|
36
36
|
dependencies:
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: bcrypt_pbkdf
|
@@ -262,9 +262,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
262
262
|
version: 2.2.6
|
263
263
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
264
264
|
requirements:
|
265
|
-
- - "
|
265
|
+
- - ">"
|
266
266
|
- !ruby/object:Gem::Version
|
267
|
-
version:
|
267
|
+
version: 1.3.1
|
268
268
|
requirements: []
|
269
269
|
rubyforge_project:
|
270
270
|
rubygems_version: 2.6.8
|
metadata.gz.sig
CHANGED
Binary file
|