net-ssh 2.7.0 → 7.3.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.dockerignore +6 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +94 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +22 -0
- data/.rubocop_todo.yml +1081 -0
- data/CHANGES.txt +387 -0
- data/DEVELOPMENT.md +23 -0
- data/Dockerfile +29 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +13 -0
- data/Gemfile.noed25519 +12 -0
- data/Gemfile.norbnacl +12 -0
- data/ISSUE_TEMPLATE.md +30 -0
- data/Manifest +4 -5
- data/README.md +303 -0
- data/Rakefile +174 -40
- data/SECURITY.md +4 -0
- data/THANKS.txt +25 -0
- data/appveyor.yml +58 -0
- data/docker-compose.yml +25 -0
- data/lib/net/ssh/authentication/agent.rb +279 -18
- data/lib/net/ssh/authentication/certificate.rb +183 -0
- data/lib/net/ssh/authentication/constants.rb +17 -15
- data/lib/net/ssh/authentication/ed25519.rb +184 -0
- data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
- data/lib/net/ssh/authentication/key_manager.rb +125 -54
- data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
- data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
- data/lib/net/ssh/authentication/methods/none.rb +16 -19
- data/lib/net/ssh/authentication/methods/password.rb +56 -19
- data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
- data/lib/net/ssh/authentication/pageant.rb +483 -246
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +138 -120
- data/lib/net/ssh/buffer.rb +399 -300
- data/lib/net/ssh/buffered_io.rb +154 -150
- data/lib/net/ssh/config.rb +361 -166
- data/lib/net/ssh/connection/channel.rb +640 -596
- data/lib/net/ssh/connection/constants.rb +29 -29
- data/lib/net/ssh/connection/event_loop.rb +123 -0
- data/lib/net/ssh/connection/keepalive.rb +59 -0
- data/lib/net/ssh/connection/session.rb +628 -548
- data/lib/net/ssh/connection/term.rb +125 -123
- data/lib/net/ssh/errors.rb +101 -95
- data/lib/net/ssh/key_factory.rb +198 -100
- data/lib/net/ssh/known_hosts.rb +221 -98
- data/lib/net/ssh/loggable.rb +50 -49
- data/lib/net/ssh/packet.rb +83 -79
- data/lib/net/ssh/prompt.rb +50 -81
- data/lib/net/ssh/proxy/command.rb +108 -60
- data/lib/net/ssh/proxy/errors.rb +12 -10
- data/lib/net/ssh/proxy/http.rb +82 -78
- data/lib/net/ssh/proxy/https.rb +50 -0
- data/lib/net/ssh/proxy/jump.rb +54 -0
- data/lib/net/ssh/proxy/socks4.rb +5 -8
- data/lib/net/ssh/proxy/socks5.rb +18 -20
- data/lib/net/ssh/service/forward.rb +383 -255
- data/lib/net/ssh/test/channel.rb +145 -136
- data/lib/net/ssh/test/extensions.rb +131 -110
- data/lib/net/ssh/test/kex.rb +34 -32
- data/lib/net/ssh/test/local_packet.rb +46 -44
- data/lib/net/ssh/test/packet.rb +89 -70
- data/lib/net/ssh/test/remote_packet.rb +32 -30
- data/lib/net/ssh/test/script.rb +156 -142
- data/lib/net/ssh/test/socket.rb +49 -48
- data/lib/net/ssh/test.rb +82 -77
- data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
- data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
- data/lib/net/ssh/transport/algorithms.rb +472 -348
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/lib/net/ssh/transport/cipher_factory.rb +124 -100
- data/lib/net/ssh/transport/constants.rb +32 -24
- data/lib/net/ssh/transport/ctr.rb +42 -22
- data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- 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/hmac.rb +14 -12
- data/lib/net/ssh/transport/identity_cipher.rb +54 -44
- data/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/kex.rb +15 -12
- data/lib/net/ssh/transport/key_expander.rb +24 -20
- data/lib/net/ssh/transport/openssl.rb +161 -124
- data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/lib/net/ssh/transport/packet_stream.rb +246 -183
- data/lib/net/ssh/transport/server_version.rb +57 -51
- data/lib/net/ssh/transport/session.rb +307 -235
- data/lib/net/ssh/transport/state.rb +178 -176
- data/lib/net/ssh/verifiers/accept_new.rb +33 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
- data/lib/net/ssh/verifiers/always.rb +58 -0
- data/lib/net/ssh/verifiers/never.rb +19 -0
- data/lib/net/ssh/version.rb +57 -51
- data/lib/net/ssh.rb +140 -40
- data/net-ssh-public_cert.pem +21 -0
- data/net-ssh.gemspec +39 -184
- data/support/ssh_tunnel_bug.rb +5 -5
- data.tar.gz.sig +0 -0
- metadata +205 -99
- metadata.gz.sig +0 -0
- data/README.rdoc +0 -219
- data/Rudyfile +0 -96
- data/gem-public_cert.pem +0 -20
- data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
- data/lib/net/ssh/authentication/agent/socket.rb +0 -170
- data/lib/net/ssh/ruby_compat.rb +0 -51
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -54
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/setup.rb +0 -1585
- data/support/arcfour_check.rb +0 -20
- data/test/README.txt +0 -47
- data/test/authentication/methods/common.rb +0 -28
- data/test/authentication/methods/test_abstract.rb +0 -51
- data/test/authentication/methods/test_hostbased.rb +0 -114
- data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
- data/test/authentication/methods/test_none.rb +0 -41
- data/test/authentication/methods/test_password.rb +0 -52
- data/test/authentication/methods/test_publickey.rb +0 -148
- data/test/authentication/test_agent.rb +0 -205
- data/test/authentication/test_key_manager.rb +0 -218
- data/test/authentication/test_session.rb +0 -108
- data/test/common.rb +0 -108
- data/test/configs/eqsign +0 -3
- data/test/configs/exact_match +0 -8
- data/test/configs/host_plus +0 -10
- data/test/configs/multihost +0 -4
- data/test/configs/nohost +0 -19
- data/test/configs/numeric_host +0 -4
- data/test/configs/send_env +0 -2
- data/test/configs/substitutes +0 -8
- data/test/configs/wild_cards +0 -14
- data/test/connection/test_channel.rb +0 -467
- data/test/connection/test_session.rb +0 -526
- data/test/known_hosts/github +0 -1
- data/test/manual/test_forward.rb +0 -223
- data/test/start/test_options.rb +0 -36
- data/test/start/test_transport.rb +0 -28
- data/test/test_all.rb +0 -11
- data/test/test_buffer.rb +0 -433
- data/test/test_buffered_io.rb +0 -63
- data/test/test_config.rb +0 -151
- data/test/test_key_factory.rb +0 -173
- data/test/test_known_hosts.rb +0 -13
- data/test/transport/hmac/test_md5.rb +0 -41
- data/test/transport/hmac/test_md5_96.rb +0 -27
- data/test/transport/hmac/test_none.rb +0 -34
- data/test/transport/hmac/test_ripemd160.rb +0 -36
- data/test/transport/hmac/test_sha1.rb +0 -36
- data/test/transport/hmac/test_sha1_96.rb +0 -27
- data/test/transport/hmac/test_sha2_256.rb +0 -37
- data/test/transport/hmac/test_sha2_256_96.rb +0 -27
- data/test/transport/hmac/test_sha2_512.rb +0 -37
- data/test/transport/hmac/test_sha2_512_96.rb +0 -27
- data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
- data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
- data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
- data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
- data/test/transport/test_algorithms.rb +0 -330
- data/test/transport/test_cipher_factory.rb +0 -443
- data/test/transport/test_hmac.rb +0 -34
- data/test/transport/test_identity_cipher.rb +0 -40
- data/test/transport/test_packet_stream.rb +0 -1755
- data/test/transport/test_server_version.rb +0 -78
- data/test/transport/test_session.rb +0 -319
- data/test/transport/test_state.rb +0 -181
@@ -1,216 +1,122 @@
|
|
1
|
-
require 'net/ssh/
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
dh.p, dh.g = get_parameters
|
119
|
-
dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
|
120
|
-
|
121
|
-
dh.generate_key! until dh.valid?
|
122
|
-
|
123
|
-
dh
|
124
|
-
end
|
125
|
-
|
126
|
-
# Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
|
127
|
-
# resulting buffer.
|
128
|
-
#
|
129
|
-
# Parse the buffer from a KEXDH_REPLY message, returning a hash of
|
130
|
-
# the extracted values.
|
131
|
-
def send_kexinit #:nodoc:
|
132
|
-
init, reply = get_message_types
|
133
|
-
|
134
|
-
# send the KEXDH_INIT message
|
135
|
-
buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
|
136
|
-
connection.send_message(buffer)
|
137
|
-
|
138
|
-
# expect the KEXDH_REPLY message
|
139
|
-
buffer = connection.next_message
|
140
|
-
raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
|
141
|
-
|
142
|
-
result = Hash.new
|
143
|
-
|
144
|
-
result[:key_blob] = buffer.read_string
|
145
|
-
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
146
|
-
result[:server_dh_pubkey] = buffer.read_bignum
|
147
|
-
result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
|
148
|
-
|
149
|
-
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
150
|
-
sig_type = sig_buffer.read_string
|
151
|
-
if sig_type != algorithms.host_key
|
152
|
-
raise Net::SSH::Exception,
|
153
|
-
"host key algorithm mismatch for signature " +
|
154
|
-
"'#{sig_type}' != '#{algorithms.host_key}'"
|
1
|
+
require 'net/ssh/transport/kex/abstract'
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
7
|
+
# A key-exchange service implementing the "diffie-hellman-group1-sha1"
|
8
|
+
# key-exchange algorithm.
|
9
|
+
class DiffieHellmanGroup1SHA1 < Abstract
|
10
|
+
# The value of 'P', as a string, in hexadecimal
|
11
|
+
P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
|
12
|
+
"C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
|
13
|
+
"020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
|
14
|
+
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
|
15
|
+
"4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
|
16
|
+
"F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
|
17
|
+
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
|
18
|
+
"49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
|
19
|
+
|
20
|
+
# The radix in which P_s represents the value of P
|
21
|
+
P_r = 16
|
22
|
+
|
23
|
+
# The group constant
|
24
|
+
G = 2
|
25
|
+
|
26
|
+
def digester
|
27
|
+
OpenSSL::Digest::SHA1
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Returns the DH key parameters for the current connection. [p, q]
|
33
|
+
def get_parameters
|
34
|
+
[
|
35
|
+
OpenSSL::BN.new(self.class::P_s, self.class::P_r),
|
36
|
+
self.class::G
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the INIT/REPLY constants used by this algorithm.
|
41
|
+
def get_message_types
|
42
|
+
[KEXDH_INIT, KEXDH_REPLY]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Build the signature buffer to use when verifying a signature from
|
46
|
+
# the server.
|
47
|
+
def build_signature_buffer(result)
|
48
|
+
response = Net::SSH::Buffer.new
|
49
|
+
response.write_string data[:client_version_string],
|
50
|
+
data[:server_version_string],
|
51
|
+
data[:client_algorithm_packet],
|
52
|
+
data[:server_algorithm_packet],
|
53
|
+
result[:key_blob]
|
54
|
+
response.write_bignum dh.pub_key,
|
55
|
+
result[:server_dh_pubkey],
|
56
|
+
result[:shared_secret]
|
57
|
+
response
|
58
|
+
end
|
59
|
+
|
60
|
+
# Generate a DH key with a private key consisting of the given
|
61
|
+
# number of bytes.
|
62
|
+
def generate_key # :nodoc:
|
63
|
+
p, g = get_parameters
|
64
|
+
|
65
|
+
asn1 = OpenSSL::ASN1::Sequence(
|
66
|
+
[
|
67
|
+
OpenSSL::ASN1::Integer(p),
|
68
|
+
OpenSSL::ASN1::Integer(g)
|
69
|
+
]
|
70
|
+
)
|
71
|
+
|
72
|
+
dh_params = OpenSSL::PKey::DH.new(asn1.to_der)
|
73
|
+
# XXX No private key size check! In theory the latter call should work but fails on OpenSSL 3.0 as
|
74
|
+
# dh_paramgen_subprime_len is now reserved for DHX algorithm
|
75
|
+
# key = OpenSSL::PKey.generate_key(dh_params, "dh_paramgen_subprime_len" => data[:need_bytes]/8)
|
76
|
+
if OpenSSL::PKey.respond_to?(:generate_key)
|
77
|
+
OpenSSL::PKey.generate_key(dh_params)
|
78
|
+
else
|
79
|
+
dh_params.generate_key!
|
80
|
+
dh_params
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
|
85
|
+
# resulting buffer.
|
86
|
+
#
|
87
|
+
# Parse the buffer from a KEXDH_REPLY message, returning a hash of
|
88
|
+
# the extracted values.
|
89
|
+
def send_kexinit # :nodoc:
|
90
|
+
init, reply = get_message_types
|
91
|
+
|
92
|
+
# send the KEXDH_INIT message
|
93
|
+
buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
|
94
|
+
connection.send_message(buffer)
|
95
|
+
|
96
|
+
# expect the KEXDH_REPLY message
|
97
|
+
buffer = connection.next_message
|
98
|
+
raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
|
99
|
+
|
100
|
+
result = Hash.new
|
101
|
+
|
102
|
+
result[:key_blob] = buffer.read_string
|
103
|
+
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
104
|
+
result[:server_dh_pubkey] = buffer.read_bignum
|
105
|
+
result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
|
106
|
+
|
107
|
+
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
108
|
+
sig_type = sig_buffer.read_string
|
109
|
+
if sig_type != algorithms.host_key_format
|
110
|
+
raise Net::SSH::Exception,
|
111
|
+
"host key algorithm mismatch for signature " +
|
112
|
+
"'#{sig_type}' != '#{algorithms.host_key_format}'"
|
113
|
+
end
|
114
|
+
result[:server_sig] = sig_buffer.read_string
|
115
|
+
|
116
|
+
return result
|
117
|
+
end
|
155
118
|
end
|
156
|
-
result[:server_sig] = sig_buffer.read_string
|
157
|
-
|
158
|
-
return result
|
159
|
-
end
|
160
|
-
|
161
|
-
# Verify that the given key is of the expected type, and that it
|
162
|
-
# really is the key for the session's host. Raise Net::SSH::Exception
|
163
|
-
# if it is not.
|
164
|
-
def verify_server_key(key) #:nodoc:
|
165
|
-
if key.ssh_type != algorithms.host_key
|
166
|
-
raise Net::SSH::Exception,
|
167
|
-
"host key algorithm mismatch " +
|
168
|
-
"'#{key.ssh_type}' != '#{algorithms.host_key}'"
|
169
|
-
end
|
170
|
-
|
171
|
-
blob, fingerprint = generate_key_fingerprint(key)
|
172
|
-
|
173
|
-
unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection)
|
174
|
-
raise Net::SSH::Exception, "host key verification failed"
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def generate_key_fingerprint(key)
|
179
|
-
blob = Net::SSH::Buffer.from(:key, key).to_s
|
180
|
-
fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
|
181
|
-
|
182
|
-
[blob, fingerprint]
|
183
|
-
rescue ::Exception => e
|
184
|
-
[nil, "(could not generate fingerprint: #{e.message})"]
|
185
|
-
end
|
186
|
-
|
187
|
-
# Verify the signature that was received. Raise Net::SSH::Exception
|
188
|
-
# if the signature could not be verified. Otherwise, return the new
|
189
|
-
# session-id.
|
190
|
-
def verify_signature(result) #:nodoc:
|
191
|
-
response = build_signature_buffer(result)
|
192
|
-
|
193
|
-
hash = @digester.digest(response.to_s)
|
194
|
-
|
195
|
-
unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
|
196
|
-
raise Net::SSH::Exception, "could not verify server signature"
|
197
|
-
end
|
198
|
-
|
199
|
-
return hash
|
200
|
-
end
|
201
|
-
|
202
|
-
# Send the NEWKEYS message, and expect the NEWKEYS message in
|
203
|
-
# reply.
|
204
|
-
def confirm_newkeys #:nodoc:
|
205
|
-
# send own NEWKEYS message first (the wodSSHServer won't send first)
|
206
|
-
response = Net::SSH::Buffer.new
|
207
|
-
response.write_byte(NEWKEYS)
|
208
|
-
connection.send_message(response)
|
209
|
-
|
210
|
-
# wait for the server's NEWKEYS message
|
211
|
-
buffer = connection.next_message
|
212
|
-
raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
|
213
119
|
end
|
120
|
+
end
|
214
121
|
end
|
215
|
-
|
216
|
-
end; end; end; end
|
122
|
+
end
|
@@ -3,78 +3,70 @@ require 'net/ssh/transport/constants'
|
|
3
3
|
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
|
4
4
|
|
5
5
|
module Net::SSH::Transport::Kex
|
6
|
-
|
7
6
|
# A key-exchange service implementing the
|
8
7
|
# "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
|
9
8
|
class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
|
10
9
|
MINIMUM_BITS = 1024
|
11
10
|
MAXIMUM_BITS = 8192
|
12
11
|
|
13
|
-
KEXDH_GEX_GROUP = 31
|
14
|
-
KEXDH_GEX_INIT = 32
|
15
|
-
KEXDH_GEX_REPLY = 33
|
16
|
-
KEXDH_GEX_REQUEST = 34
|
17
|
-
|
18
12
|
private
|
19
13
|
|
20
|
-
|
21
|
-
|
14
|
+
# Compute the number of bits needed for the given number of bytes.
|
15
|
+
def compute_need_bits
|
16
|
+
# for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
|
17
|
+
need_bits = data[:need_bytes] * 8 * 2 + 1
|
22
18
|
|
23
|
-
|
24
|
-
need_bits = data[:need_bytes] * 8 * 2 + 1
|
19
|
+
data[:minimum_dh_bits] ||= MINIMUM_BITS
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
data[:need_bits ] = need_bits
|
33
|
-
data[:need_bytes] = need_bits / 8
|
21
|
+
if need_bits < data[:minimum_dh_bits]
|
22
|
+
need_bits = data[:minimum_dh_bits]
|
23
|
+
elsif need_bits > MAXIMUM_BITS
|
24
|
+
need_bits = MAXIMUM_BITS
|
34
25
|
end
|
35
26
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
27
|
+
data[:need_bits] = need_bits
|
28
|
+
data[:need_bytes] = need_bits / 8
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the DH key parameters for the given session.
|
32
|
+
def get_parameters
|
33
|
+
compute_need_bits
|
34
|
+
|
35
|
+
# request the DH key parameters for the given number of bits.
|
36
|
+
buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
|
37
|
+
:long, data[:need_bits], :long, MAXIMUM_BITS)
|
38
|
+
connection.send_message(buffer)
|
39
|
+
|
40
|
+
buffer = connection.next_message
|
41
|
+
raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}" unless buffer.type == KEXDH_GEX_GROUP
|
42
|
+
|
43
|
+
p = buffer.read_bignum
|
44
|
+
g = buffer.read_bignum
|
45
|
+
|
46
|
+
[p, g]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the INIT/REPLY constants used by this algorithm.
|
50
|
+
def get_message_types
|
51
|
+
[KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Build the signature buffer to use when verifying a signature from
|
55
|
+
# the server.
|
56
|
+
def build_signature_buffer(result)
|
57
|
+
response = Net::SSH::Buffer.new
|
58
|
+
response.write_string data[:client_version_string],
|
59
|
+
data[:server_version_string],
|
60
|
+
data[:client_algorithm_packet],
|
61
|
+
data[:server_algorithm_packet],
|
62
|
+
result[:key_blob]
|
63
|
+
response.write_long MINIMUM_BITS,
|
64
|
+
data[:need_bits],
|
65
|
+
MAXIMUM_BITS
|
66
|
+
response.write_bignum dh.p, dh.g, dh.pub_key,
|
67
|
+
result[:server_dh_pubkey],
|
68
|
+
result[:shared_secret]
|
69
|
+
response
|
70
|
+
end
|
78
71
|
end
|
79
|
-
|
80
72
|
end
|
@@ -1,15 +1,11 @@
|
|
1
1
|
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
|
2
2
|
|
3
3
|
module Net::SSH::Transport::Kex
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
super(*args)
|
10
|
-
|
11
|
-
@digester = OpenSSL::Digest::SHA256
|
12
|
-
end
|
4
|
+
# A key-exchange service implementing the
|
5
|
+
# "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
|
6
|
+
class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
|
7
|
+
def digester
|
8
|
+
OpenSSL::Digest::SHA256
|
13
9
|
end
|
14
10
|
end
|
15
11
|
end
|
@@ -1,93 +1,39 @@
|
|
1
|
-
require 'net/ssh/transport/
|
2
|
-
|
3
|
-
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def build_signature_buffer(result)
|
38
|
-
response = Net::SSH::Buffer.new
|
39
|
-
response.write_string data[:client_version_string],
|
40
|
-
data[:server_version_string],
|
41
|
-
data[:client_algorithm_packet],
|
42
|
-
data[:server_algorithm_packet],
|
43
|
-
result[:key_blob],
|
44
|
-
ecdh.public_key.to_bn.to_s(2),
|
45
|
-
result[:server_ecdh_pubkey]
|
46
|
-
response.write_bignum result[:shared_secret]
|
47
|
-
response
|
48
|
-
end
|
49
|
-
|
50
|
-
def generate_key #:nodoc:
|
51
|
-
OpenSSL::PKey::EC.new(curve_name).generate_key
|
52
|
-
end
|
53
|
-
|
54
|
-
def send_kexinit #:nodoc:
|
55
|
-
init, reply = get_message_types
|
56
|
-
|
57
|
-
# send the KEXECDH_INIT message
|
58
|
-
## byte SSH_MSG_KEX_ECDH_INIT
|
59
|
-
## string Q_C, client's ephemeral public key octet string
|
60
|
-
buffer = Net::SSH::Buffer.from(:byte, init, :string, ecdh.public_key.to_bn.to_s(2))
|
61
|
-
connection.send_message(buffer)
|
62
|
-
|
63
|
-
# expect the following KEXECDH_REPLY message
|
64
|
-
## byte SSH_MSG_KEX_ECDH_REPLY
|
65
|
-
## string K_S, server's public host key
|
66
|
-
## string Q_S, server's ephemeral public key octet string
|
67
|
-
## string the signature on the exchange hash
|
68
|
-
buffer = connection.next_message
|
69
|
-
raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
|
70
|
-
|
71
|
-
result = Hash.new
|
72
|
-
result[:key_blob] = buffer.read_string
|
73
|
-
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
74
|
-
result[:server_ecdh_pubkey] = buffer.read_string
|
75
|
-
|
76
|
-
# compute shared secret from server's public key and client's private key
|
77
|
-
pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
|
78
|
-
OpenSSL::BN.new(result[:server_ecdh_pubkey], 2))
|
79
|
-
result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
|
80
|
-
|
81
|
-
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
82
|
-
sig_type = sig_buffer.read_string
|
83
|
-
if sig_type != algorithms.host_key
|
84
|
-
raise Net::SSH::Exception,
|
85
|
-
"host key algorithm mismatch for signature " +
|
86
|
-
"'#{sig_type}' != '#{algorithms.host_key}'"
|
1
|
+
require 'net/ssh/transport/kex/abstract5656'
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
7
|
+
# A key-exchange service implementing the "ecdh-sha2-nistp256"
|
8
|
+
# key-exchange algorithm. (defined in RFC 5656)
|
9
|
+
class EcdhSHA2NistP256 < Abstract5656
|
10
|
+
def digester
|
11
|
+
OpenSSL::Digest::SHA256
|
12
|
+
end
|
13
|
+
|
14
|
+
def curve_name
|
15
|
+
OpenSSL::PKey::EC::CurveNameAlias['nistp256']
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_key # :nodoc:
|
21
|
+
OpenSSL::PKey::EC.generate(curve_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
# compute shared secret from server's public key and client's private key
|
25
|
+
def compute_shared_secret(server_ecdh_pubkey)
|
26
|
+
pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
|
27
|
+
OpenSSL::BN.new(server_ecdh_pubkey, 2))
|
28
|
+
OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
|
29
|
+
end
|
30
|
+
|
31
|
+
## string Q_C, client's ephemeral public key octet string
|
32
|
+
def ecdh_public_key_bytes
|
33
|
+
ecdh.public_key.to_bn.to_s(2)
|
34
|
+
end
|
35
|
+
end
|
87
36
|
end
|
88
|
-
result[:server_sig] = sig_buffer.read_string
|
89
|
-
|
90
|
-
return result
|
91
37
|
end
|
92
38
|
end
|
93
|
-
end
|
39
|
+
end
|
@@ -1,13 +1,21 @@
|
|
1
|
-
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
7
|
+
# A key-exchange service implementing the "ecdh-sha2-nistp256"
|
8
|
+
# key-exchange algorithm. (defined in RFC 5656)
|
9
|
+
class EcdhSHA2NistP384 < EcdhSHA2NistP256
|
10
|
+
def digester
|
11
|
+
OpenSSL::Digest::SHA384
|
12
|
+
end
|
13
|
+
|
14
|
+
def curve_name
|
15
|
+
OpenSSL::PKey::EC::CurveNameAlias['nistp384']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
11
19
|
end
|
12
20
|
end
|
13
|
-
end
|
21
|
+
end
|