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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e14e949eb49846743dae609d76bb3ff8e7e26332
4
- data.tar.gz: b373032655d4f986f1695d231eafc1d7f3a7fffd
3
+ metadata.gz: f322b0b79581a7d7b24a917b79ddabc8563b5a5c
4
+ data.tar.gz: a9e3a2c9cfa281f1b91a335bda58f4b6dcc568fd
5
5
  SHA512:
6
- metadata.gz: 073c77cec7e4420dec75779906809319fb65f8163a4b99cfd3fbafaa1f1fce1e209ac96cb8ac22c82c182835f1ff7609625492108612f2158c1ba26fffd828a1
7
- data.tar.gz: 293eb2965ccb35840c5bc29abc8c5be3ae78ab55461ce7ca42cc21045ed3ef02bcf44356e2bb33ef115e479ef1c11e269e88cd8d6f260a79b6e75273fe869175
6
+ metadata.gz: fcd0f1c4c2a6833e75509523cf19195cbb2320860f5f20800ce780f785d52093ae24331b27ac3dcfd49d62de341048ed611078f15449f3052830cf7c1630e309
7
+ data.tar.gz: 3b3fa8989372dbbe9a84fdfdbc22dde5b9ea69fcb206b9e859aa83f6a46b729b117dfe024c49a1fe969a2fedc2dbacbc190d2b5764603efe6780c10f15b31f58
@@ -1,3 +1 @@
1
- *�6+3T�t~
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
@@ -3,3 +3,6 @@ inherit_from: .rubocop_todo.yml
3
3
  AllCops:
4
4
  Exclude:
5
5
  - 'tryout/**/*'
6
+
7
+ Style/DoubleNegation:
8
+ Enabled: false
@@ -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 processin in ssh config [Aleksandrs Ļedovskis, #642]
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
 
@@ -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 ArgumentError, "Decrypt failed on private key" if (check1 != check2)
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
@@ -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
- key_read, error_classes = classify_key(data, filename)
53
+ key_type = classify_key(data, filename)
54
54
 
55
- encrypted_key = data.match(/ENCRYPTED/)
55
+ encrypted_key = nil
56
56
  tries = 0
57
57
 
58
58
  prompter = nil
59
59
  result =
60
60
  begin
61
- key_read[data, passphrase || 'invalid']
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 ->(key_data, passphrase) { Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader.read(key_data, passphrase) }, [ArgumentError]
203
+ return OpenSSHPrivateKeyType
115
204
  elsif OpenSSL::PKey.respond_to?(:read)
116
- return ->(key_data, passphrase) { OpenSSL::PKey.read(key_data, passphrase) }, [ArgumentError, OpenSSL::PKey::PKeyError]
205
+ return OpenSSLPKeyType
117
206
  elsif data.match(/-----BEGIN DSA PRIVATE KEY-----/)
118
- return ->(key_data, passphrase) { OpenSSL::PKey::DSA.new(key_data, passphrase) }, [OpenSSL::PKey::DSAError]
207
+ return OpenSSLDSAKeyType
119
208
  elsif data.match(/-----BEGIN RSA PRIVATE KEY-----/)
120
- return ->(key_data, passphrase) { OpenSSL::PKey::RSA.new(key_data, passphrase) }, [OpenSSL::PKey::RSAError]
209
+ return OpenSSLRSAKeyType
121
210
  elsif data.match(/-----BEGIN EC PRIVATE KEY-----/) && defined?(OpenSSL::PKey::EC)
122
- return ->(key_data, passphrase) { OpenSSL::PKey::EC.new(key_data, passphrase) }, [OpenSSL::PKey::ECError]
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
@@ -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 = entries.all? { |entry| hostlist.include?(entry) } ||
138
- known_host_hash?(hostlist, entries)
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)
@@ -279,7 +279,7 @@ module Net
279
279
  # method.
280
280
  class CompatibleVerifier
281
281
  def initialize(verifier)
282
- @verifier
282
+ @verifier = verifier
283
283
  end
284
284
 
285
285
  def verify(arguments)
@@ -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 = 1
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 = nil
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.1.0
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: 2018-12-28 00:00:00.000000000 Z
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: '0'
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