net-ssh 3.2.0 → 7.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +93 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +13 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +237 -7
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +27 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +298 -0
  22. data/Rakefile +125 -74
  23. data/SECURITY.md +4 -0
  24. data/appveyor.yml +58 -0
  25. data/docker-compose.yml +23 -0
  26. data/lib/net/ssh/authentication/agent.rb +279 -18
  27. data/lib/net/ssh/authentication/certificate.rb +183 -0
  28. data/lib/net/ssh/authentication/constants.rb +17 -15
  29. data/lib/net/ssh/authentication/ed25519.rb +186 -0
  30. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  31. data/lib/net/ssh/authentication/key_manager.rb +86 -39
  32. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  33. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  34. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +13 -13
  35. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  36. data/lib/net/ssh/authentication/methods/password.rb +27 -17
  37. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  38. data/lib/net/ssh/authentication/pageant.rb +471 -367
  39. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  40. data/lib/net/ssh/authentication/session.rb +131 -121
  41. data/lib/net/ssh/buffer.rb +399 -300
  42. data/lib/net/ssh/buffered_io.rb +154 -150
  43. data/lib/net/ssh/config.rb +308 -185
  44. data/lib/net/ssh/connection/channel.rb +635 -613
  45. data/lib/net/ssh/connection/constants.rb +29 -29
  46. data/lib/net/ssh/connection/event_loop.rb +123 -0
  47. data/lib/net/ssh/connection/keepalive.rb +55 -51
  48. data/lib/net/ssh/connection/session.rb +620 -551
  49. data/lib/net/ssh/connection/term.rb +125 -123
  50. data/lib/net/ssh/errors.rb +101 -99
  51. data/lib/net/ssh/key_factory.rb +197 -105
  52. data/lib/net/ssh/known_hosts.rb +214 -127
  53. data/lib/net/ssh/loggable.rb +50 -49
  54. data/lib/net/ssh/packet.rb +83 -79
  55. data/lib/net/ssh/prompt.rb +50 -81
  56. data/lib/net/ssh/proxy/command.rb +105 -90
  57. data/lib/net/ssh/proxy/errors.rb +12 -10
  58. data/lib/net/ssh/proxy/http.rb +82 -79
  59. data/lib/net/ssh/proxy/https.rb +50 -0
  60. data/lib/net/ssh/proxy/jump.rb +54 -0
  61. data/lib/net/ssh/proxy/socks4.rb +2 -6
  62. data/lib/net/ssh/proxy/socks5.rb +14 -17
  63. data/lib/net/ssh/service/forward.rb +370 -317
  64. data/lib/net/ssh/test/channel.rb +145 -136
  65. data/lib/net/ssh/test/extensions.rb +131 -110
  66. data/lib/net/ssh/test/kex.rb +34 -32
  67. data/lib/net/ssh/test/local_packet.rb +46 -44
  68. data/lib/net/ssh/test/packet.rb +89 -70
  69. data/lib/net/ssh/test/remote_packet.rb +32 -30
  70. data/lib/net/ssh/test/script.rb +156 -142
  71. data/lib/net/ssh/test/socket.rb +49 -48
  72. data/lib/net/ssh/test.rb +82 -77
  73. data/lib/net/ssh/transport/algorithms.rb +462 -359
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  75. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  76. data/lib/net/ssh/transport/cipher_factory.rb +122 -99
  77. data/lib/net/ssh/transport/constants.rb +32 -24
  78. data/lib/net/ssh/transport/ctr.rb +42 -22
  79. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  87. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  88. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  89. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  90. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  91. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  92. data/lib/net/ssh/transport/hmac.rb +14 -12
  93. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  94. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  95. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  96. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  97. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  98. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  99. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  100. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  101. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  103. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  104. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  105. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  106. data/lib/net/ssh/transport/kex.rb +15 -12
  107. data/lib/net/ssh/transport/key_expander.rb +24 -20
  108. data/lib/net/ssh/transport/openssl.rb +161 -124
  109. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  110. data/lib/net/ssh/transport/packet_stream.rb +246 -185
  111. data/lib/net/ssh/transport/server_version.rb +55 -56
  112. data/lib/net/ssh/transport/session.rb +306 -255
  113. data/lib/net/ssh/transport/state.rb +178 -176
  114. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  115. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  116. data/lib/net/ssh/verifiers/always.rb +58 -0
  117. data/lib/net/ssh/verifiers/never.rb +19 -0
  118. data/lib/net/ssh/version.rb +55 -53
  119. data/lib/net/ssh.rb +111 -47
  120. data/net-ssh-public_cert.pem +18 -18
  121. data/net-ssh.gemspec +38 -205
  122. data/support/ssh_tunnel_bug.rb +5 -5
  123. data.tar.gz.sig +0 -0
  124. metadata +173 -118
  125. metadata.gz.sig +0 -0
  126. data/.travis.yml +0 -18
  127. data/README.rdoc +0 -182
  128. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  129. data/lib/net/ssh/authentication/agent/socket.rb +0 -178
  130. data/lib/net/ssh/ruby_compat.rb +0 -46
  131. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  132. data/lib/net/ssh/verifiers/null.rb +0 -12
  133. data/lib/net/ssh/verifiers/secure.rb +0 -52
  134. data/lib/net/ssh/verifiers/strict.rb +0 -24
  135. data/setup.rb +0 -1585
  136. data/support/arcfour_check.rb +0 -20
  137. data/test/README.txt +0 -18
  138. data/test/authentication/methods/common.rb +0 -28
  139. data/test/authentication/methods/test_abstract.rb +0 -51
  140. data/test/authentication/methods/test_hostbased.rb +0 -114
  141. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  142. data/test/authentication/methods/test_none.rb +0 -41
  143. data/test/authentication/methods/test_password.rb +0 -95
  144. data/test/authentication/methods/test_publickey.rb +0 -148
  145. data/test/authentication/test_agent.rb +0 -232
  146. data/test/authentication/test_key_manager.rb +0 -240
  147. data/test/authentication/test_session.rb +0 -107
  148. data/test/common.rb +0 -125
  149. data/test/configs/auth_off +0 -5
  150. data/test/configs/auth_on +0 -4
  151. data/test/configs/empty +0 -0
  152. data/test/configs/eqsign +0 -3
  153. data/test/configs/exact_match +0 -8
  154. data/test/configs/host_plus +0 -10
  155. data/test/configs/multihost +0 -4
  156. data/test/configs/negative_match +0 -6
  157. data/test/configs/nohost +0 -19
  158. data/test/configs/numeric_host +0 -4
  159. data/test/configs/proxy_remote_user +0 -2
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -487
  164. data/test/connection/test_session.rb +0 -564
  165. data/test/integration/README.txt +0 -17
  166. data/test/integration/Vagrantfile +0 -12
  167. data/test/integration/common.rb +0 -63
  168. data/test/integration/playbook.yml +0 -56
  169. data/test/integration/test_forward.rb +0 -637
  170. data/test/integration/test_id_rsa_keys.rb +0 -96
  171. data/test/integration/test_proxy.rb +0 -93
  172. data/test/known_hosts/github +0 -1
  173. data/test/known_hosts/github_hash +0 -1
  174. data/test/manual/test_pageant.rb +0 -37
  175. data/test/start/test_connection.rb +0 -53
  176. data/test/start/test_options.rb +0 -57
  177. data/test/start/test_transport.rb +0 -28
  178. data/test/start/test_user_nil.rb +0 -27
  179. data/test/test_all.rb +0 -12
  180. data/test/test_buffer.rb +0 -433
  181. data/test/test_buffered_io.rb +0 -63
  182. data/test/test_config.rb +0 -268
  183. data/test/test_key_factory.rb +0 -191
  184. data/test/test_known_hosts.rb +0 -66
  185. data/test/transport/hmac/test_md5.rb +0 -41
  186. data/test/transport/hmac/test_md5_96.rb +0 -27
  187. data/test/transport/hmac/test_none.rb +0 -34
  188. data/test/transport/hmac/test_ripemd160.rb +0 -36
  189. data/test/transport/hmac/test_sha1.rb +0 -36
  190. data/test/transport/hmac/test_sha1_96.rb +0 -27
  191. data/test/transport/hmac/test_sha2_256.rb +0 -37
  192. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  193. data/test/transport/hmac/test_sha2_512.rb +0 -37
  194. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  195. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  196. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  197. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  198. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  199. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  200. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  201. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  202. data/test/transport/test_algorithms.rb +0 -328
  203. data/test/transport/test_cipher_factory.rb +0 -443
  204. data/test/transport/test_hmac.rb +0 -34
  205. data/test/transport/test_identity_cipher.rb +0 -40
  206. data/test/transport/test_packet_stream.rb +0 -1762
  207. data/test/transport/test_server_version.rb +0 -74
  208. data/test/transport/test_session.rb +0 -331
  209. data/test/transport/test_state.rb +0 -181
  210. data/test/verifiers/test_secure.rb +0 -40
@@ -5,25 +5,24 @@ module Net
5
5
  module SSH
6
6
  module Authentication
7
7
  module Methods
8
-
9
8
  # Implements the "keyboard-interactive" SSH authentication method.
10
9
  class KeyboardInteractive < Abstract
11
- include Prompt
12
-
13
10
  USERAUTH_INFO_REQUEST = 60
14
11
  USERAUTH_INFO_RESPONSE = 61
15
12
 
16
13
  # Attempt to authenticate the given user for the given service.
17
- def authenticate(next_service, username, password=nil)
14
+ def authenticate(next_service, username, password = nil)
18
15
  debug { "trying keyboard-interactive" }
19
16
  send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
20
17
 
18
+ prompter = nil
21
19
  loop do
22
20
  message = session.next_message
23
21
 
24
22
  case message.type
25
23
  when USERAUTH_SUCCESS
26
24
  debug { "keyboard-interactive succeeded" }
25
+ prompter.success if prompter
27
26
  return true
28
27
  when USERAUTH_FAILURE
29
28
  debug { "keyboard-interactive failed" }
@@ -31,26 +30,27 @@ module Net
31
30
  raise Net::SSH::Authentication::DisallowedMethod unless
32
31
  message[:authentications].split(/,/).include? 'keyboard-interactive'
33
32
 
34
- return false
33
+ return false unless interactive?
34
+
35
+ password = nil
36
+ debug { "retrying keyboard-interactive" }
37
+ send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
35
38
  when USERAUTH_INFO_REQUEST
36
39
  name = message.read_string
37
40
  instruction = message.read_string
38
41
  debug { "keyboard-interactive info request" }
39
42
 
40
- unless password
41
- if interactive?
42
- puts(name) unless name.empty?
43
- puts(instruction) unless instruction.empty?
44
- end
43
+ if password.nil? && interactive? && prompter.nil?
44
+ prompter = prompt.start(type: 'keyboard-interactive', name: name, instruction: instruction)
45
45
  end
46
46
 
47
47
  _ = message.read_string # lang_tag
48
- responses =[]
49
-
48
+ responses = []
49
+
50
50
  message.read_long.times do
51
51
  text = message.read_string
52
52
  echo = message.read_bool
53
- password_to_send = password || (interactive? ? prompt(text, echo) : nil)
53
+ password_to_send = password || (prompter && prompter.ask(text, echo))
54
54
  responses << password_to_send
55
55
  end
56
56
 
@@ -5,32 +5,29 @@ module Net
5
5
  module SSH
6
6
  module Authentication
7
7
  module Methods
8
-
9
8
  # Implements the "none" SSH authentication method.
10
9
  class None < Abstract
11
10
  # Attempt to authenticate as "none"
12
- def authenticate(next_service, user="", password="")
13
- send_message(userauth_request(user, next_service, "none"))
11
+ def authenticate(next_service, user = "", password = "")
12
+ send_message(userauth_request(user, next_service, "none"))
14
13
  message = session.next_message
15
-
14
+
16
15
  case message.type
17
- when USERAUTH_SUCCESS
18
- debug { "none succeeded" }
19
- return true
20
- when USERAUTH_FAILURE
21
- debug { "none failed" }
22
-
23
- raise Net::SSH::Authentication::DisallowedMethod unless
24
- message[:authentications].split(/,/).include? 'none'
25
-
26
- return false
27
- else
28
- raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
29
- end
30
-
16
+ when USERAUTH_SUCCESS
17
+ debug { "none succeeded" }
18
+ return true
19
+ when USERAUTH_FAILURE
20
+ debug { "none failed" }
21
+
22
+ raise Net::SSH::Authentication::DisallowedMethod unless
23
+ message[:authentications].split(/,/).include? 'none'
24
+
25
+ return false
26
+ else
27
+ raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
28
+ end
31
29
  end
32
30
  end
33
-
34
31
  end
35
32
  end
36
33
  end
@@ -6,16 +6,14 @@ module Net
6
6
  module SSH
7
7
  module Authentication
8
8
  module Methods
9
-
10
9
  # Implements the "password" SSH authentication method.
11
10
  class Password < Abstract
12
- include Prompt
13
-
14
11
  # Attempt to authenticate the given user for the given service. If
15
12
  # the password parameter is nil, this will ask for password
16
- def authenticate(next_service, username, password=nil)
13
+ def authenticate(next_service, username, password = nil)
14
+ clear_prompter!
17
15
  retries = 0
18
- max_retries = get_max_retries
16
+ max_retries = get_max_retries
19
17
  return false if !password && max_retries == 0
20
18
 
21
19
  begin
@@ -30,21 +28,23 @@ module Net
30
28
 
31
29
  raise Net::SSH::Authentication::DisallowedMethod unless
32
30
  message[:authentications].split(/,/).include? 'password'
31
+
33
32
  password = nil
34
33
  end
35
34
  end until (message.type != USERAUTH_FAILURE || retries >= max_retries)
36
35
 
37
36
  case message.type
38
- when USERAUTH_SUCCESS
39
- debug { "password succeeded" }
40
- return true
41
- when USERAUTH_FAILURE
42
- return false
43
- when USERAUTH_PASSWD_CHANGEREQ
44
- debug { "password change request received, failing" }
45
- return false
46
- else
47
- raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
37
+ when USERAUTH_SUCCESS
38
+ debug { "password succeeded" }
39
+ @prompter.success if @prompter
40
+ return true
41
+ when USERAUTH_FAILURE
42
+ return false
43
+ when USERAUTH_PASSWD_CHANGEREQ
44
+ debug { "password change request received, failing" }
45
+ return false
46
+ else
47
+ raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
48
48
  end
49
49
  end
50
50
 
@@ -52,9 +52,20 @@ module Net
52
52
 
53
53
  NUMBER_OF_PASSWORD_PROMPTS = 3
54
54
 
55
+ def clear_prompter!
56
+ @prompt_info = nil
57
+ @prompter = nil
58
+ end
59
+
55
60
  def ask_password(username)
61
+ host = session.transport.host
62
+ prompt_info = { type: 'password', user: username, host: host }
63
+ if @prompt_info != prompt_info
64
+ @prompt_info = prompt_info
65
+ @prompter = prompt.start(prompt_info)
66
+ end
56
67
  echo = false
57
- prompt("#{username}@#{session.transport.host}'s password:", echo)
68
+ @prompter.ask("#{username}@#{host}'s password:", echo)
58
69
  end
59
70
 
60
71
  def get_max_retries
@@ -63,7 +74,6 @@ module Net
63
74
  options[:non_interactive] ? 0 : result
64
75
  end
65
76
  end
66
-
67
77
  end
68
78
  end
69
79
  end
@@ -6,14 +6,13 @@ module Net
6
6
  module SSH
7
7
  module Authentication
8
8
  module Methods
9
-
10
9
  # Implements the "publickey" SSH authentication method.
11
10
  class Publickey < Abstract
12
11
  # Attempts to perform public-key authentication for the given
13
12
  # username, trying each identity known to the key manager. If any of
14
13
  # them succeed, returns +true+, otherwise returns +false+. This
15
14
  # requires the presence of a key manager.
16
- def authenticate(next_service, username, password=nil)
15
+ def authenticate(next_service, username, password = nil)
17
16
  return false unless key_manager
18
17
 
19
18
  key_manager.each_identity do |identity|
@@ -25,71 +24,113 @@ module Net
25
24
 
26
25
  private
27
26
 
28
- # Builds a packet that contains the request formatted for sending
29
- # a public-key request to the server.
30
- def build_request(pub_key, username, next_service, has_sig)
31
- blob = Net::SSH::Buffer.new
32
- blob.write_key pub_key
27
+ # Builds a packet that contains the request formatted for sending
28
+ # a public-key request to the server.
29
+ def build_request(pub_key, username, next_service, alg, has_sig)
30
+ blob = Net::SSH::Buffer.new
31
+ blob.write_key pub_key
33
32
 
34
- userauth_request(username, next_service, "publickey", has_sig,
35
- pub_key.ssh_type, blob.to_s)
36
- end
33
+ userauth_request(username, next_service, "publickey", has_sig,
34
+ alg, blob.to_s)
35
+ end
37
36
 
38
- # Builds and sends a request formatted for a public-key
39
- # authentication request.
40
- def send_request(pub_key, username, next_service, signature=nil)
41
- msg = build_request(pub_key, username, next_service, !signature.nil?)
42
- msg.write_string(signature) if signature
43
- send_message(msg)
44
- end
37
+ # Builds and sends a request formatted for a public-key
38
+ # authentication request.
39
+ def send_request(pub_key, username, next_service, alg, signature = nil)
40
+ msg = build_request(pub_key, username, next_service, alg,
41
+ !signature.nil?)
42
+ msg.write_string(signature) if signature
43
+ send_message(msg)
44
+ end
45
+
46
+ def authenticate_with_alg(identity, next_service, username, alg, sig_alg = nil)
47
+ debug { "trying publickey (#{identity.fingerprint})" }
48
+ send_request(identity, username, next_service, alg)
45
49
 
46
- # Attempts to perform public-key authentication for the given
47
- # username, with the given identity (public key). Returns +true+ if
48
- # successful, or +false+ otherwise.
49
- def authenticate_with(identity, next_service, username)
50
- debug { "trying publickey (#{identity.fingerprint})" }
51
- send_request(identity, username, next_service)
50
+ message = session.next_message
52
51
 
52
+ case message.type
53
+ when USERAUTH_PK_OK
54
+ buffer = build_request(identity, username, next_service, alg,
55
+ true)
56
+ sig_data = Net::SSH::Buffer.new
57
+ sig_data.write_string(session_id)
58
+ sig_data.append(buffer.to_s)
59
+
60
+ sig_blob = key_manager.sign(identity, sig_data, sig_alg)
61
+
62
+ send_request(identity, username, next_service, alg, sig_blob.to_s)
53
63
  message = session.next_message
54
64
 
55
65
  case message.type
56
- when USERAUTH_PK_OK
57
- buffer = build_request(identity, username, next_service, true)
58
- sig_data = Net::SSH::Buffer.new
59
- sig_data.write_string(session_id)
60
- sig_data.append(buffer.to_s)
61
-
62
- sig_blob = key_manager.sign(identity, sig_data)
63
-
64
- send_request(identity, username, next_service, sig_blob.to_s)
65
- message = session.next_message
66
-
67
- case message.type
68
- when USERAUTH_SUCCESS
69
- debug { "publickey succeeded (#{identity.fingerprint})" }
70
- return true
71
- when USERAUTH_FAILURE
72
- debug { "publickey failed (#{identity.fingerprint})" }
73
-
74
- raise Net::SSH::Authentication::DisallowedMethod unless
75
- message[:authentications].split(/,/).include? 'publickey'
76
-
77
- return false
78
- else
79
- raise Net::SSH::Exception,
80
- "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
81
- end
66
+ when USERAUTH_SUCCESS
67
+ debug { "publickey succeeded (#{identity.fingerprint})" }
68
+ return true
69
+ when USERAUTH_FAILURE
70
+ debug { "publickey failed (#{identity.fingerprint})" }
71
+
72
+ raise Net::SSH::Authentication::DisallowedMethod unless
73
+ message[:authentications].split(/,/).include? 'publickey'
74
+
75
+ return false
76
+ else
77
+ raise Net::SSH::Exception,
78
+ "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
79
+ end
82
80
 
83
- when USERAUTH_FAILURE
84
- return false
81
+ when USERAUTH_FAILURE
82
+ return false
83
+ when USERAUTH_SUCCESS
84
+ return true
85
85
 
86
- else
87
- raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
88
- end
86
+ else
87
+ raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
89
88
  end
89
+ end
90
90
 
91
+ # Attempts to perform public-key authentication for the given
92
+ # username, with the given identity (public key). Returns +true+ if
93
+ # successful, or +false+ otherwise.
94
+ def authenticate_with(identity, next_service, username)
95
+ type = identity.ssh_type
96
+ if type == "ssh-rsa"
97
+ pubkey_algorithms.each do |pk_alg|
98
+ case pk_alg
99
+ when "rsa-sha2-512", "rsa-sha2-256", "ssh-rsa"
100
+ if authenticate_with_alg(identity, next_service, username, pk_alg, pk_alg)
101
+ # success
102
+ return true
103
+ end
104
+ end
105
+ end
106
+ elsif type == "ssh-rsa-cert-v01@openssh.com"
107
+ pubkey_algorithms.each do |pk_alg|
108
+ case pk_alg
109
+ when "rsa-sha2-512-cert-v01@openssh.com"
110
+ if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-512")
111
+ # success
112
+ return true
113
+ end
114
+ when "rsa-sha2-256-cert-v01@openssh.com"
115
+ if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-256")
116
+ # success
117
+ return true
118
+ end
119
+ when "ssh-rsa-cert-v01@openssh.com"
120
+ if authenticate_with_alg(identity, next_service, username, pk_alg)
121
+ # success
122
+ return true
123
+ end
124
+ end
125
+ end
126
+ elsif authenticate_with_alg(identity, next_service, username, type)
127
+ # success
128
+ return true
129
+ end
130
+ # failure
131
+ return false
132
+ end
91
133
  end
92
-
93
134
  end
94
135
  end
95
136
  end