net-ssh-clone 7.0.1

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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +6 -0
  3. data/.github/config/rubocop_linter_action.yml +4 -0
  4. data/.github/workflows/ci-with-docker.yml +44 -0
  5. data/.github/workflows/ci.yml +87 -0
  6. data/.github/workflows/rubocop.yml +13 -0
  7. data/.gitignore +13 -0
  8. data/.rubocop.yml +22 -0
  9. data/.rubocop_todo.yml +1081 -0
  10. data/CHANGES.txt +698 -0
  11. data/Dockerfile +27 -0
  12. data/Dockerfile.openssl3 +17 -0
  13. data/Gemfile +13 -0
  14. data/Gemfile.noed25519 +12 -0
  15. data/ISSUE_TEMPLATE.md +30 -0
  16. data/LICENSE.txt +19 -0
  17. data/Manifest +132 -0
  18. data/README.md +293 -0
  19. data/Rakefile +109 -0
  20. data/THANKS.txt +110 -0
  21. data/appveyor.yml +58 -0
  22. data/docker-compose.yml +23 -0
  23. data/lib/net/ssh/authentication/agent.rb +284 -0
  24. data/lib/net/ssh/authentication/certificate.rb +183 -0
  25. data/lib/net/ssh/authentication/constants.rb +20 -0
  26. data/lib/net/ssh/authentication/ed25519.rb +185 -0
  27. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  28. data/lib/net/ssh/authentication/key_manager.rb +310 -0
  29. data/lib/net/ssh/authentication/methods/abstract.rb +79 -0
  30. data/lib/net/ssh/authentication/methods/hostbased.rb +72 -0
  31. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +77 -0
  32. data/lib/net/ssh/authentication/methods/none.rb +34 -0
  33. data/lib/net/ssh/authentication/methods/password.rb +80 -0
  34. data/lib/net/ssh/authentication/methods/publickey.rb +137 -0
  35. data/lib/net/ssh/authentication/pageant.rb +497 -0
  36. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  37. data/lib/net/ssh/authentication/session.rb +165 -0
  38. data/lib/net/ssh/buffer.rb +449 -0
  39. data/lib/net/ssh/buffered_io.rb +202 -0
  40. data/lib/net/ssh/config.rb +406 -0
  41. data/lib/net/ssh/connection/channel.rb +694 -0
  42. data/lib/net/ssh/connection/constants.rb +33 -0
  43. data/lib/net/ssh/connection/event_loop.rb +123 -0
  44. data/lib/net/ssh/connection/keepalive.rb +59 -0
  45. data/lib/net/ssh/connection/session.rb +712 -0
  46. data/lib/net/ssh/connection/term.rb +180 -0
  47. data/lib/net/ssh/errors.rb +106 -0
  48. data/lib/net/ssh/key_factory.rb +218 -0
  49. data/lib/net/ssh/known_hosts.rb +265 -0
  50. data/lib/net/ssh/loggable.rb +62 -0
  51. data/lib/net/ssh/packet.rb +106 -0
  52. data/lib/net/ssh/prompt.rb +62 -0
  53. data/lib/net/ssh/proxy/command.rb +123 -0
  54. data/lib/net/ssh/proxy/errors.rb +16 -0
  55. data/lib/net/ssh/proxy/http.rb +98 -0
  56. data/lib/net/ssh/proxy/https.rb +50 -0
  57. data/lib/net/ssh/proxy/jump.rb +54 -0
  58. data/lib/net/ssh/proxy/socks4.rb +67 -0
  59. data/lib/net/ssh/proxy/socks5.rb +140 -0
  60. data/lib/net/ssh/service/forward.rb +426 -0
  61. data/lib/net/ssh/test/channel.rb +147 -0
  62. data/lib/net/ssh/test/extensions.rb +173 -0
  63. data/lib/net/ssh/test/kex.rb +46 -0
  64. data/lib/net/ssh/test/local_packet.rb +53 -0
  65. data/lib/net/ssh/test/packet.rb +101 -0
  66. data/lib/net/ssh/test/remote_packet.rb +40 -0
  67. data/lib/net/ssh/test/script.rb +180 -0
  68. data/lib/net/ssh/test/socket.rb +65 -0
  69. data/lib/net/ssh/test.rb +94 -0
  70. data/lib/net/ssh/transport/algorithms.rb +502 -0
  71. data/lib/net/ssh/transport/cipher_factory.rb +103 -0
  72. data/lib/net/ssh/transport/constants.rb +40 -0
  73. data/lib/net/ssh/transport/ctr.rb +115 -0
  74. data/lib/net/ssh/transport/hmac/abstract.rb +97 -0
  75. data/lib/net/ssh/transport/hmac/md5.rb +10 -0
  76. data/lib/net/ssh/transport/hmac/md5_96.rb +9 -0
  77. data/lib/net/ssh/transport/hmac/none.rb +13 -0
  78. data/lib/net/ssh/transport/hmac/ripemd160.rb +11 -0
  79. data/lib/net/ssh/transport/hmac/sha1.rb +11 -0
  80. data/lib/net/ssh/transport/hmac/sha1_96.rb +9 -0
  81. data/lib/net/ssh/transport/hmac/sha2_256.rb +11 -0
  82. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +9 -0
  83. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  84. data/lib/net/ssh/transport/hmac/sha2_512.rb +11 -0
  85. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +9 -0
  86. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  87. data/lib/net/ssh/transport/hmac.rb +47 -0
  88. data/lib/net/ssh/transport/identity_cipher.rb +57 -0
  89. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  90. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  91. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  92. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +37 -0
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  95. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +122 -0
  96. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +72 -0
  97. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +11 -0
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +39 -0
  99. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +21 -0
  100. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +21 -0
  101. data/lib/net/ssh/transport/kex.rb +31 -0
  102. data/lib/net/ssh/transport/key_expander.rb +30 -0
  103. data/lib/net/ssh/transport/openssl.rb +274 -0
  104. data/lib/net/ssh/transport/packet_stream.rb +280 -0
  105. data/lib/net/ssh/transport/server_version.rb +77 -0
  106. data/lib/net/ssh/transport/session.rb +354 -0
  107. data/lib/net/ssh/transport/state.rb +208 -0
  108. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  109. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  110. data/lib/net/ssh/verifiers/always.rb +58 -0
  111. data/lib/net/ssh/verifiers/never.rb +19 -0
  112. data/lib/net/ssh/version.rb +68 -0
  113. data/lib/net/ssh.rb +330 -0
  114. data/net-ssh-public_cert.pem +20 -0
  115. data/net-ssh.gemspec +44 -0
  116. data/support/ssh_tunnel_bug.rb +65 -0
  117. metadata +277 -0
@@ -0,0 +1,77 @@
1
+ require 'net/ssh/prompt'
2
+ require 'net/ssh/authentication/methods/abstract'
3
+
4
+ module Net
5
+ module SSH
6
+ module Authentication
7
+ module Methods
8
+ # Implements the "keyboard-interactive" SSH authentication method.
9
+ class KeyboardInteractive < Abstract
10
+ USERAUTH_INFO_REQUEST = 60
11
+ USERAUTH_INFO_RESPONSE = 61
12
+
13
+ # Attempt to authenticate the given user for the given service.
14
+ def authenticate(next_service, username, password = nil)
15
+ debug { "trying keyboard-interactive" }
16
+ send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
17
+
18
+ prompter = nil
19
+ loop do
20
+ message = session.next_message
21
+
22
+ case message.type
23
+ when USERAUTH_SUCCESS
24
+ debug { "keyboard-interactive succeeded" }
25
+ prompter.success if prompter
26
+ return true
27
+ when USERAUTH_FAILURE
28
+ debug { "keyboard-interactive failed" }
29
+
30
+ raise Net::SSH::Authentication::DisallowedMethod unless
31
+ message[:authentications].split(/,/).include? 'keyboard-interactive'
32
+
33
+ return false unless interactive?
34
+
35
+ password = nil
36
+ debug { "retrying keyboard-interactive" }
37
+ send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
38
+ when USERAUTH_INFO_REQUEST
39
+ name = message.read_string
40
+ instruction = message.read_string
41
+ debug { "keyboard-interactive info request" }
42
+
43
+ if password.nil? && interactive? && prompter.nil?
44
+ prompter = prompt.start(type: 'keyboard-interactive', name: name, instruction: instruction)
45
+ end
46
+
47
+ _ = message.read_string # lang_tag
48
+ responses = []
49
+
50
+ message.read_long.times do
51
+ text = message.read_string
52
+ echo = message.read_bool
53
+ password_to_send = password || (prompter && prompter.ask(text, echo))
54
+ responses << password_to_send
55
+ end
56
+
57
+ # if the password failed the first time around, don't try
58
+ # and use it on subsequent requests.
59
+ password = nil
60
+
61
+ msg = Buffer.from(:byte, USERAUTH_INFO_RESPONSE, :long, responses.length, :string, responses)
62
+ send_message(msg)
63
+ else
64
+ raise Net::SSH::Exception, "unexpected reply in keyboard interactive: #{message.type} (#{message.inspect})"
65
+ end
66
+ end
67
+ end
68
+
69
+ def interactive?
70
+ options = session.transport.options || {}
71
+ !options[:non_interactive]
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,34 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/authentication/methods/abstract'
3
+
4
+ module Net
5
+ module SSH
6
+ module Authentication
7
+ module Methods
8
+ # Implements the "none" SSH authentication method.
9
+ class None < Abstract
10
+ # Attempt to authenticate as "none"
11
+ def authenticate(next_service, user = "", password = "")
12
+ send_message(userauth_request(user, next_service, "none"))
13
+ message = session.next_message
14
+
15
+ case message.type
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
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,80 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/prompt'
3
+ require 'net/ssh/authentication/methods/abstract'
4
+
5
+ module Net
6
+ module SSH
7
+ module Authentication
8
+ module Methods
9
+ # Implements the "password" SSH authentication method.
10
+ class Password < Abstract
11
+ # Attempt to authenticate the given user for the given service. If
12
+ # the password parameter is nil, this will ask for password
13
+ def authenticate(next_service, username, password = nil)
14
+ clear_prompter!
15
+ retries = 0
16
+ max_retries = get_max_retries
17
+ return false if !password && max_retries == 0
18
+
19
+ begin
20
+ password_to_send = password || ask_password(username)
21
+
22
+ send_message(userauth_request(username, next_service, "password", false, password_to_send))
23
+ message = session.next_message
24
+ retries += 1
25
+
26
+ if message.type == USERAUTH_FAILURE
27
+ debug { "password failed" }
28
+
29
+ raise Net::SSH::Authentication::DisallowedMethod unless
30
+ message[:authentications].split(/,/).include? 'password'
31
+
32
+ password = nil
33
+ end
34
+ end until (message.type != USERAUTH_FAILURE || retries >= max_retries)
35
+
36
+ case message.type
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
+ end
49
+ end
50
+
51
+ private
52
+
53
+ NUMBER_OF_PASSWORD_PROMPTS = 3
54
+
55
+ def clear_prompter!
56
+ @prompt_info = nil
57
+ @prompter = nil
58
+ end
59
+
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
67
+ echo = false
68
+ @prompter.ask("#{username}@#{host}'s password:", echo)
69
+ end
70
+
71
+ def get_max_retries
72
+ options = session.transport.options || {}
73
+ result = options[:number_of_password_prompts] || NUMBER_OF_PASSWORD_PROMPTS
74
+ options[:non_interactive] ? 0 : result
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,137 @@
1
+ require 'net/ssh/buffer'
2
+ require 'net/ssh/errors'
3
+ require 'net/ssh/authentication/methods/abstract'
4
+
5
+ module Net
6
+ module SSH
7
+ module Authentication
8
+ module Methods
9
+ # Implements the "publickey" SSH authentication method.
10
+ class Publickey < Abstract
11
+ # Attempts to perform public-key authentication for the given
12
+ # username, trying each identity known to the key manager. If any of
13
+ # them succeed, returns +true+, otherwise returns +false+. This
14
+ # requires the presence of a key manager.
15
+ def authenticate(next_service, username, password = nil)
16
+ return false unless key_manager
17
+
18
+ key_manager.each_identity do |identity|
19
+ return true if authenticate_with(identity, next_service, username)
20
+ end
21
+
22
+ return false
23
+ end
24
+
25
+ private
26
+
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
32
+
33
+ userauth_request(username, next_service, "publickey", has_sig,
34
+ alg, blob.to_s)
35
+ end
36
+
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)
49
+
50
+ message = session.next_message
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)
63
+ message = session.next_message
64
+
65
+ case message.type
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
80
+
81
+ when USERAUTH_FAILURE
82
+ return false
83
+ when USERAUTH_SUCCESS
84
+ return true
85
+
86
+ else
87
+ raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
88
+ end
89
+ end
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
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end