harbr 0.2.10 → 2.8.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.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/exe/harbr +225 -150
- data/lib/examples/container.toml +13 -0
- data/lib/harbr/container.rb +14 -10
- data/lib/harbr/host.rb +21 -0
- data/lib/harbr/version.rb +1 -1
- data/lib/harbr.rb +21 -6
- data/vendor/bundle/ruby/3.2.0/cache/dddr-1.0.8.gem +0 -0
- data/vendor/bundle/ruby/3.2.0/cache/dddr-1.1.0.gem +0 -0
- data/vendor/bundle/ruby/3.2.0/cache/dddr-1.1.1.gem +0 -0
- data/vendor/bundle/ruby/3.2.0/cache/net-ssh-7.2.1.gem +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/.DS_Store +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/.rspec +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/.standard.yml +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/CHANGELOG.md +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/CODE_OF_CONDUCT.md +84 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/README.md +96 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/Rakefile +10 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/hero.png +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/lib/dddr/version.rb +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/lib/dddr.rb +205 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.0.8/sig/dddr.rbs +4 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/.DS_Store +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/.rspec +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/.standard.yml +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/CHANGELOG.md +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/CODE_OF_CONDUCT.md +84 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/README.md +96 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/Rakefile +10 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/hero.png +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/lib/dddr/version.rb +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/lib/dddr.rb +182 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.0/sig/dddr.rbs +4 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/.DS_Store +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/.rspec +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/.standard.yml +3 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/CHANGELOG.md +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/CODE_OF_CONDUCT.md +84 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/LICENSE.txt +21 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/README.md +96 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/Rakefile +10 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/hero.png +0 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/lib/dddr/version.rb +5 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/lib/dddr.rb +184 -0
- data/vendor/bundle/ruby/3.2.0/gems/dddr-1.1.1/sig/dddr.rbs +4 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.dockerignore +6 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.github/FUNDING.yml +1 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.github/config/rubocop_linter_action.yml +4 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.github/workflows/ci-with-docker.yml +44 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.github/workflows/ci.yml +94 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.github/workflows/rubocop.yml +16 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.gitignore +15 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.rubocop.yml +22 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/.rubocop_todo.yml +1081 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/CHANGES.txt +738 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/DEVELOPMENT.md +23 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Dockerfile +29 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Dockerfile.openssl3 +17 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Gemfile +13 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Gemfile.noed25519 +12 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Gemfile.norbnacl +12 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/ISSUE_TEMPLATE.md +30 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/LICENSE.txt +19 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Manifest +132 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/README.md +298 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/Rakefile +192 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/SECURITY.md +4 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/THANKS.txt +110 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/appveyor.yml +58 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/docker-compose.yml +25 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/agent.rb +284 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/certificate.rb +183 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/constants.rb +20 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/ed25519.rb +186 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/key_manager.rb +327 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/abstract.rb +79 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/hostbased.rb +72 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/keyboard_interactive.rb +77 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/none.rb +34 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/password.rb +80 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/publickey.rb +137 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/pageant.rb +497 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/session.rb +172 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/buffer.rb +449 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/buffered_io.rb +202 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/config.rb +406 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/channel.rb +694 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/constants.rb +33 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/event_loop.rb +123 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/keepalive.rb +59 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/session.rb +712 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/connection/term.rb +180 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/errors.rb +106 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/key_factory.rb +218 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/known_hosts.rb +265 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/loggable.rb +62 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/packet.rb +106 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/prompt.rb +62 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/command.rb +123 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/errors.rb +16 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/http.rb +98 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/https.rb +50 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/jump.rb +54 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/socks4.rb +67 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/proxy/socks5.rb +140 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/service/forward.rb +426 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/channel.rb +147 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/extensions.rb +173 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/kex.rb +46 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/local_packet.rb +53 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/packet.rb +101 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/remote_packet.rb +40 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/script.rb +180 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test/socket.rb +65 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/test.rb +94 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/algorithms.rb +524 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/cipher_factory.rb +128 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/constants.rb +40 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/ctr.rb +115 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/abstract.rb +97 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/md5.rb +10 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/md5_96.rb +9 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/none.rb +13 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/ripemd160.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha1.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha1_96.rb +9 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_256.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_256_96.rb +9 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_512.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_512_96.rb +9 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/hmac.rb +47 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/identity_cipher.rb +65 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +37 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +122 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +72 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +11 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +39 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +21 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +21 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex.rb +31 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/key_expander.rb +30 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/openssl.rb +274 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/packet_stream.rb +301 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/server_version.rb +77 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/session.rb +354 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/state.rb +208 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/verifiers/accept_new.rb +33 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/verifiers/always.rb +58 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/verifiers/never.rb +19 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/version.rb +68 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh.rb +338 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/net-ssh-public_cert.pem +20 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/net-ssh.gemspec +46 -0
- data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/support/ssh_tunnel_bug.rb +65 -0
- data/vendor/bundle/ruby/3.2.0/specifications/dddr-1.0.8.gemspec +27 -0
- data/vendor/bundle/ruby/3.2.0/specifications/dddr-1.1.0.gemspec +27 -0
- data/vendor/bundle/ruby/3.2.0/specifications/dddr-1.1.1.gemspec +27 -0
- data/vendor/bundle/ruby/3.2.0/specifications/net-ssh-7.2.1.gemspec +38 -0
- metadata +174 -9
- data/config/manifest.yml +0 -5
- data/lib/harbr/job.rb +0 -252
- data/lib/harbr/lxd/job.rb +0 -119
- data/lib/harbr/lxd/setup.rb +0 -45
data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
|
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 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
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
|
2
|
+
|
|
3
|
+
module Net
|
|
4
|
+
module SSH
|
|
5
|
+
module Transport
|
|
6
|
+
module Kex
|
|
7
|
+
# A key-exchange service implementing the "ecdh-sha2-nistp521"
|
|
8
|
+
# key-exchange algorithm. (defined in RFC 5656)
|
|
9
|
+
class EcdhSHA2NistP521 < EcdhSHA2NistP256
|
|
10
|
+
def digester
|
|
11
|
+
OpenSSL::Digest::SHA512
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def curve_name
|
|
15
|
+
OpenSSL::PKey::EC::CurveNameAlias['nistp521']
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
|
|
2
|
+
require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
|
|
3
|
+
require 'net/ssh/transport/kex/diffie_hellman_group14_sha256'
|
|
4
|
+
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
|
|
5
|
+
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
|
|
6
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
|
7
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
|
|
8
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
|
|
9
|
+
require 'net/ssh/transport/kex/curve25519_sha256_loader'
|
|
10
|
+
|
|
11
|
+
module Net::SSH::Transport
|
|
12
|
+
module Kex
|
|
13
|
+
# Maps the supported key-exchange algorithms as named by the SSH protocol
|
|
14
|
+
# to their corresponding implementors.
|
|
15
|
+
MAP = {
|
|
16
|
+
'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
|
|
17
|
+
'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
|
|
18
|
+
'diffie-hellman-group14-sha256' => DiffieHellmanGroup14SHA256,
|
|
19
|
+
'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
|
|
20
|
+
'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
|
|
21
|
+
'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
|
|
22
|
+
'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
|
|
23
|
+
'ecdh-sha2-nistp521' => EcdhSHA2NistP521
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
|
|
27
|
+
MAP['curve25519-sha256'] = Curve25519Sha256
|
|
28
|
+
MAP['curve25519-sha256@libssh.org'] = Curve25519Sha256
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Net
|
|
2
|
+
module SSH
|
|
3
|
+
module Transport
|
|
4
|
+
module KeyExpander
|
|
5
|
+
# Generate a key value in accordance with the SSH2 specification.
|
|
6
|
+
# (RFC4253 7.2. "Output from Key Exchange")
|
|
7
|
+
def self.expand_key(bytes, start, options = {})
|
|
8
|
+
if bytes == 0
|
|
9
|
+
return ""
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
k = start[0, bytes]
|
|
13
|
+
return k if k.length >= bytes
|
|
14
|
+
|
|
15
|
+
digester = options[:digester] or raise 'No digester supplied'
|
|
16
|
+
shared = options[:shared] or raise 'No shared secret supplied'
|
|
17
|
+
hash = options[:hash] or raise 'No hash supplied'
|
|
18
|
+
|
|
19
|
+
while k.length < bytes
|
|
20
|
+
step = digester.digest(shared + hash + k)
|
|
21
|
+
bytes_needed = bytes - k.length
|
|
22
|
+
k << step[0, bytes_needed]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
return k
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
require 'openssl'
|
|
2
|
+
require 'net/ssh/authentication/pub_key_fingerprint'
|
|
3
|
+
|
|
4
|
+
module OpenSSL
|
|
5
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
|
6
|
+
# have been added to it by the Net::SSH module for convenience in dealing with
|
|
7
|
+
# SSH functionality.
|
|
8
|
+
class BN
|
|
9
|
+
# Converts a BN object to a string. The format used is that which is
|
|
10
|
+
# required by the SSH2 protocol.
|
|
11
|
+
def to_ssh
|
|
12
|
+
if zero?
|
|
13
|
+
return [0].pack("N")
|
|
14
|
+
else
|
|
15
|
+
buf = to_s(2)
|
|
16
|
+
if buf.getbyte(0)[7] == 1
|
|
17
|
+
return [buf.length + 1, 0, buf].pack("NCA*")
|
|
18
|
+
else
|
|
19
|
+
return [buf.length, buf].pack("NA*")
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module PKey
|
|
26
|
+
class PKey
|
|
27
|
+
include Net::SSH::Authentication::PubKeyFingerprint
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
|
31
|
+
# have been added to it by the Net::SSH module for convenience in dealing
|
|
32
|
+
# with SSH functionality.
|
|
33
|
+
class DH
|
|
34
|
+
# Determines whether the pub_key for this key is valid. (This algorithm
|
|
35
|
+
# lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
|
|
36
|
+
def valid?
|
|
37
|
+
return false if pub_key.nil? || pub_key < 0
|
|
38
|
+
|
|
39
|
+
bits_set = 0
|
|
40
|
+
pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
|
|
41
|
+
return (bits_set > 1 && pub_key < p)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
|
46
|
+
# have been added to it by the Net::SSH module for convenience in dealing
|
|
47
|
+
# with SSH functionality.
|
|
48
|
+
class RSA
|
|
49
|
+
# Returns "ssh-rsa", which is the description of this key type used by the
|
|
50
|
+
# SSH2 protocol.
|
|
51
|
+
def ssh_type
|
|
52
|
+
"ssh-rsa"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
alias ssh_signature_type ssh_type
|
|
56
|
+
|
|
57
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
|
58
|
+
def to_blob
|
|
59
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Verifies the given signature matches the given data.
|
|
63
|
+
def ssh_do_verify(sig, data, options = {})
|
|
64
|
+
digester =
|
|
65
|
+
if options[:host_key] == "rsa-sha2-512"
|
|
66
|
+
OpenSSL::Digest::SHA512.new
|
|
67
|
+
elsif options[:host_key] == "rsa-sha2-256"
|
|
68
|
+
OpenSSL::Digest::SHA256.new
|
|
69
|
+
else
|
|
70
|
+
OpenSSL::Digest::SHA1.new
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
verify(digester, sig, data)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the signature for the given data.
|
|
77
|
+
def ssh_do_sign(data, sig_alg = nil)
|
|
78
|
+
digester =
|
|
79
|
+
if sig_alg == "rsa-sha2-512"
|
|
80
|
+
OpenSSL::Digest::SHA512.new
|
|
81
|
+
elsif sig_alg == "rsa-sha2-256"
|
|
82
|
+
OpenSSL::Digest::SHA256.new
|
|
83
|
+
else
|
|
84
|
+
OpenSSL::Digest::SHA1.new
|
|
85
|
+
end
|
|
86
|
+
sign(digester, data)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
|
91
|
+
# have been added to it by the Net::SSH module for convenience in dealing
|
|
92
|
+
# with SSH functionality.
|
|
93
|
+
class DSA
|
|
94
|
+
# Returns "ssh-dss", which is the description of this key type used by the
|
|
95
|
+
# SSH2 protocol.
|
|
96
|
+
def ssh_type
|
|
97
|
+
"ssh-dss"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
alias ssh_signature_type ssh_type
|
|
101
|
+
|
|
102
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
|
103
|
+
def to_blob
|
|
104
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
|
|
105
|
+
:bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Verifies the given signature matches the given data.
|
|
109
|
+
def ssh_do_verify(sig, data, options = {})
|
|
110
|
+
sig_r = sig[0, 20].unpack("H*")[0].to_i(16)
|
|
111
|
+
sig_s = sig[20, 20].unpack("H*")[0].to_i(16)
|
|
112
|
+
a1sig = OpenSSL::ASN1::Sequence([
|
|
113
|
+
OpenSSL::ASN1::Integer(sig_r),
|
|
114
|
+
OpenSSL::ASN1::Integer(sig_s)
|
|
115
|
+
])
|
|
116
|
+
return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Signs the given data.
|
|
120
|
+
def ssh_do_sign(data, sig_alg = nil)
|
|
121
|
+
sig = sign(OpenSSL::Digest::SHA1.new, data)
|
|
122
|
+
a1sig = OpenSSL::ASN1.decode(sig)
|
|
123
|
+
|
|
124
|
+
sig_r = a1sig.value[0].value.to_s(2)
|
|
125
|
+
sig_s = a1sig.value[1].value.to_s(2)
|
|
126
|
+
|
|
127
|
+
sig_size = params["q"].num_bits / 8
|
|
128
|
+
raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > sig_size || sig_s.length > sig_size
|
|
129
|
+
|
|
130
|
+
sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
|
|
131
|
+
sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
|
|
132
|
+
|
|
133
|
+
return sig_r + sig_s
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
|
138
|
+
# have been added to it by the Net::SSH module for convenience in dealing
|
|
139
|
+
# with SSH functionality.
|
|
140
|
+
class EC
|
|
141
|
+
CurveNameAlias = {
|
|
142
|
+
'nistp256' => 'prime256v1',
|
|
143
|
+
'nistp384' => 'secp384r1',
|
|
144
|
+
'nistp521' => 'secp521r1'
|
|
145
|
+
}.freeze
|
|
146
|
+
|
|
147
|
+
CurveNameAliasInv = {
|
|
148
|
+
'prime256v1' => 'nistp256',
|
|
149
|
+
'secp384r1' => 'nistp384',
|
|
150
|
+
'secp521r1' => 'nistp521'
|
|
151
|
+
}.freeze
|
|
152
|
+
|
|
153
|
+
def self.read_keyblob(curve_name_in_type, buffer)
|
|
154
|
+
curve_name_in_key = buffer.read_string
|
|
155
|
+
|
|
156
|
+
unless curve_name_in_type == curve_name_in_key
|
|
157
|
+
raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
public_key_oct = buffer.read_string
|
|
161
|
+
begin
|
|
162
|
+
curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
|
|
163
|
+
group = OpenSSL::PKey::EC::Group.new(curvename)
|
|
164
|
+
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
|
|
165
|
+
asn1 = OpenSSL::ASN1::Sequence(
|
|
166
|
+
[
|
|
167
|
+
OpenSSL::ASN1::Sequence(
|
|
168
|
+
[
|
|
169
|
+
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
|
|
170
|
+
OpenSSL::ASN1::ObjectId(curvename)
|
|
171
|
+
]
|
|
172
|
+
),
|
|
173
|
+
OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
|
|
174
|
+
]
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
key = OpenSSL::PKey::EC.new(asn1.to_der)
|
|
178
|
+
|
|
179
|
+
return key
|
|
180
|
+
rescue OpenSSL::PKey::ECError
|
|
181
|
+
raise NotImplementedError, "unsupported key type `#{type}'"
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Returns the description of this key type used by the
|
|
186
|
+
# SSH2 protocol, like "ecdsa-sha2-nistp256"
|
|
187
|
+
def ssh_type
|
|
188
|
+
"ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
alias ssh_signature_type ssh_type
|
|
192
|
+
|
|
193
|
+
def digester
|
|
194
|
+
if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
|
|
195
|
+
curve_size = Regexp.last_match(1).to_i
|
|
196
|
+
if curve_size <= 256
|
|
197
|
+
OpenSSL::Digest::SHA256.new
|
|
198
|
+
elsif curve_size <= 384
|
|
199
|
+
OpenSSL::Digest::SHA384.new
|
|
200
|
+
else
|
|
201
|
+
OpenSSL::Digest::SHA512.new
|
|
202
|
+
end
|
|
203
|
+
else
|
|
204
|
+
OpenSSL::Digest::SHA256.new
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
private :digester
|
|
208
|
+
|
|
209
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
|
210
|
+
def to_blob
|
|
211
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
|
|
212
|
+
:string, CurveNameAliasInv[group.curve_name],
|
|
213
|
+
:mstring, public_key.to_bn.to_s(2)).to_s
|
|
214
|
+
@blob
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Verifies the given signature matches the given data.
|
|
218
|
+
def ssh_do_verify(sig, data, options = {})
|
|
219
|
+
digest = digester.digest(data)
|
|
220
|
+
a1sig = nil
|
|
221
|
+
|
|
222
|
+
begin
|
|
223
|
+
sig_r_len = sig[0, 4].unpack('H*')[0].to_i(16)
|
|
224
|
+
sig_l_len = sig[4 + sig_r_len, 4].unpack('H*')[0].to_i(16)
|
|
225
|
+
|
|
226
|
+
sig_r = sig[4, sig_r_len].unpack('H*')[0]
|
|
227
|
+
sig_s = sig[4 + sig_r_len + 4, sig_l_len].unpack('H*')[0]
|
|
228
|
+
|
|
229
|
+
a1sig = OpenSSL::ASN1::Sequence([
|
|
230
|
+
OpenSSL::ASN1::Integer(sig_r.to_i(16)),
|
|
231
|
+
OpenSSL::ASN1::Integer(sig_s.to_i(16))
|
|
232
|
+
])
|
|
233
|
+
rescue StandardError
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
if a1sig.nil?
|
|
237
|
+
return false
|
|
238
|
+
else
|
|
239
|
+
dsa_verify_asn1(digest, a1sig.to_der)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Returns the signature for the given data.
|
|
244
|
+
def ssh_do_sign(data, sig_alg = nil)
|
|
245
|
+
digest = digester.digest(data)
|
|
246
|
+
sig = dsa_sign_asn1(digest)
|
|
247
|
+
a1sig = OpenSSL::ASN1.decode(sig)
|
|
248
|
+
|
|
249
|
+
sig_r = a1sig.value[0].value
|
|
250
|
+
sig_s = a1sig.value[1].value
|
|
251
|
+
|
|
252
|
+
Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
class Point
|
|
256
|
+
# Returns the description of this key type used by the
|
|
257
|
+
# SSH2 protocol, like "ecdsa-sha2-nistp256"
|
|
258
|
+
def ssh_type
|
|
259
|
+
"ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
alias ssh_signature_type ssh_type
|
|
263
|
+
|
|
264
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
|
265
|
+
def to_blob
|
|
266
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
|
|
267
|
+
:string, CurveNameAliasInv[group.curve_name],
|
|
268
|
+
:mstring, to_bn.to_s(2)).to_s
|
|
269
|
+
@blob
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
require 'net/ssh/buffered_io'
|
|
2
|
+
require 'net/ssh/errors'
|
|
3
|
+
require 'net/ssh/packet'
|
|
4
|
+
require 'net/ssh/transport/cipher_factory'
|
|
5
|
+
require 'net/ssh/transport/hmac'
|
|
6
|
+
require 'net/ssh/transport/state'
|
|
7
|
+
|
|
8
|
+
module Net
|
|
9
|
+
module SSH
|
|
10
|
+
module Transport
|
|
11
|
+
# A module that builds additional functionality onto the Net::SSH::BufferedIo
|
|
12
|
+
# module. It adds SSH encryption, compression, and packet validation, as
|
|
13
|
+
# per the SSH2 protocol. It also adds an abstraction for polling packets,
|
|
14
|
+
# to allow for both blocking and non-blocking reads.
|
|
15
|
+
module PacketStream # rubocop:disable Metrics/ModuleLength
|
|
16
|
+
PROXY_COMMAND_HOST_IP = '<no hostip for proxy command>'.freeze
|
|
17
|
+
|
|
18
|
+
include BufferedIo
|
|
19
|
+
|
|
20
|
+
def self.extended(object)
|
|
21
|
+
object.__send__(:initialize_ssh)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The map of "hints" that can be used to modify the behavior of the packet
|
|
25
|
+
# stream. For instance, when authentication succeeds, an "authenticated"
|
|
26
|
+
# hint is set, which is used to determine whether or not to compress the
|
|
27
|
+
# data when using the "delayed" compression algorithm.
|
|
28
|
+
attr_reader :hints
|
|
29
|
+
|
|
30
|
+
# The server state object, which encapsulates the algorithms used to interpret
|
|
31
|
+
# packets coming from the server.
|
|
32
|
+
attr_reader :server
|
|
33
|
+
|
|
34
|
+
# The client state object, which encapsulates the algorithms used to build
|
|
35
|
+
# packets to send to the server.
|
|
36
|
+
attr_reader :client
|
|
37
|
+
|
|
38
|
+
# The name of the client (local) end of the socket, as reported by the
|
|
39
|
+
# socket.
|
|
40
|
+
def client_name
|
|
41
|
+
@client_name ||= begin
|
|
42
|
+
sockaddr = getsockname
|
|
43
|
+
begin
|
|
44
|
+
Socket.getnameinfo(sockaddr, Socket::NI_NAMEREQD).first
|
|
45
|
+
rescue StandardError
|
|
46
|
+
begin
|
|
47
|
+
Socket.getnameinfo(sockaddr).first
|
|
48
|
+
rescue StandardError
|
|
49
|
+
begin
|
|
50
|
+
Socket.gethostbyname(Socket.gethostname).first
|
|
51
|
+
rescue StandardError
|
|
52
|
+
lwarn { "the client ipaddr/name could not be determined" }
|
|
53
|
+
"unknown"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The IP address of the peer (remote) end of the socket, as reported by
|
|
61
|
+
# the socket.
|
|
62
|
+
def peer_ip
|
|
63
|
+
@peer_ip ||=
|
|
64
|
+
if respond_to?(:getpeername)
|
|
65
|
+
addr = getpeername
|
|
66
|
+
Socket.getnameinfo(addr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).first
|
|
67
|
+
else
|
|
68
|
+
PROXY_COMMAND_HOST_IP
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns true if the IO is available for reading, and false otherwise.
|
|
73
|
+
def available_for_read?
|
|
74
|
+
result = IO.select([self], nil, nil, 0)
|
|
75
|
+
result && result.first.any?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns the next full packet. If the mode parameter is :nonblock (the
|
|
79
|
+
# default), then this will return immediately, whether a packet is
|
|
80
|
+
# available or not, and will return nil if there is no packet ready to be
|
|
81
|
+
# returned. If the mode parameter is :block, then this method will block
|
|
82
|
+
# until a packet is available or timeout seconds have passed.
|
|
83
|
+
def next_packet(mode = :nonblock, timeout = nil)
|
|
84
|
+
case mode
|
|
85
|
+
when :nonblock then
|
|
86
|
+
packet = poll_next_packet
|
|
87
|
+
return packet if packet
|
|
88
|
+
|
|
89
|
+
if available_for_read?
|
|
90
|
+
if fill <= 0
|
|
91
|
+
result = poll_next_packet
|
|
92
|
+
if result.nil?
|
|
93
|
+
raise Net::SSH::Disconnect, "connection closed by remote host"
|
|
94
|
+
else
|
|
95
|
+
return result
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
poll_next_packet
|
|
100
|
+
|
|
101
|
+
when :block then
|
|
102
|
+
loop do
|
|
103
|
+
packet = poll_next_packet
|
|
104
|
+
return packet if packet
|
|
105
|
+
|
|
106
|
+
result = IO.select([self], nil, nil, timeout)
|
|
107
|
+
raise Net::SSH::ConnectionTimeout, "timeout waiting for next packet" unless result
|
|
108
|
+
raise Net::SSH::Disconnect, "connection closed by remote host" if fill <= 0
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
else
|
|
112
|
+
raise ArgumentError, "expected :block or :nonblock, got #{mode.inspect}"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Enqueues a packet to be sent, and blocks until the entire packet is
|
|
117
|
+
# sent.
|
|
118
|
+
def send_packet(payload)
|
|
119
|
+
enqueue_packet(payload)
|
|
120
|
+
wait_for_pending_sends
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Enqueues a packet to be sent, but does not immediately send the packet.
|
|
124
|
+
# The given payload is pre-processed according to the algorithms specified
|
|
125
|
+
# in the client state (compression, cipher, and hmac).
|
|
126
|
+
def enqueue_packet(payload) # rubocop:disable Metrics/AbcSize
|
|
127
|
+
# try to compress the packet
|
|
128
|
+
payload = client.compress(payload)
|
|
129
|
+
|
|
130
|
+
# the length of the packet, minus the padding
|
|
131
|
+
actual_length = (client.hmac.etm ? 0 : 4) + payload.bytesize + 1
|
|
132
|
+
|
|
133
|
+
# compute the padding length
|
|
134
|
+
padding_length = client.block_size - (actual_length % client.block_size)
|
|
135
|
+
padding_length += client.block_size if padding_length < 4
|
|
136
|
+
|
|
137
|
+
# compute the packet length (sans the length field itself)
|
|
138
|
+
packet_length = payload.bytesize + padding_length + 1
|
|
139
|
+
|
|
140
|
+
if packet_length < 16
|
|
141
|
+
padding_length += client.block_size
|
|
142
|
+
packet_length = payload.bytesize + padding_length + 1
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
padding = Array.new(padding_length) { rand(256) }.pack("C*")
|
|
146
|
+
|
|
147
|
+
if client.cipher.implicit_mac?
|
|
148
|
+
unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
|
|
149
|
+
message = client.cipher.update_cipher_mac(unencrypted_data, client.sequence_number)
|
|
150
|
+
elsif client.hmac.etm
|
|
151
|
+
debug { "using encrypt-then-mac" }
|
|
152
|
+
|
|
153
|
+
# Encrypt padding_length, payload, and padding. Take MAC
|
|
154
|
+
# from the unencrypted packet_lenght and the encrypted
|
|
155
|
+
# data.
|
|
156
|
+
length_data = [packet_length].pack("N")
|
|
157
|
+
|
|
158
|
+
unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
|
|
159
|
+
|
|
160
|
+
encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
|
|
161
|
+
|
|
162
|
+
mac_data = length_data + encrypted_data
|
|
163
|
+
|
|
164
|
+
mac = client.hmac.digest([client.sequence_number, mac_data].pack("NA*"))
|
|
165
|
+
|
|
166
|
+
message = mac_data + mac
|
|
167
|
+
else
|
|
168
|
+
unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*")
|
|
169
|
+
|
|
170
|
+
mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*"))
|
|
171
|
+
|
|
172
|
+
encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
|
|
173
|
+
|
|
174
|
+
message = encrypted_data + mac
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
debug { "queueing packet nr #{client.sequence_number} type #{payload.getbyte(0)} len #{packet_length}" }
|
|
178
|
+
enqueue(message)
|
|
179
|
+
|
|
180
|
+
client.increment(packet_length)
|
|
181
|
+
|
|
182
|
+
self
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Performs any pending cleanup necessary on the IO and its associated
|
|
186
|
+
# state objects. (See State#cleanup).
|
|
187
|
+
def cleanup
|
|
188
|
+
client.cleanup
|
|
189
|
+
server.cleanup
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# If the IO object requires a rekey operation (as indicated by either its
|
|
193
|
+
# client or server state objects, see State#needs_rekey?), this will
|
|
194
|
+
# yield. Otherwise, this does nothing.
|
|
195
|
+
def if_needs_rekey?
|
|
196
|
+
if client.needs_rekey? || server.needs_rekey?
|
|
197
|
+
yield
|
|
198
|
+
client.reset! if client.needs_rekey?
|
|
199
|
+
server.reset! if server.needs_rekey?
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
protected
|
|
204
|
+
|
|
205
|
+
# Called when this module is used to extend an object. It initializes
|
|
206
|
+
# the states and generally prepares the object for use as a packet stream.
|
|
207
|
+
def initialize_ssh
|
|
208
|
+
@hints = {}
|
|
209
|
+
@server = State.new(self, :server)
|
|
210
|
+
@client = State.new(self, :client)
|
|
211
|
+
@packet = nil
|
|
212
|
+
initialize_buffered_io
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Tries to read the next packet. If there is insufficient data to read
|
|
216
|
+
# an entire packet, this returns immediately, otherwise the packet is
|
|
217
|
+
# read, post-processed according to the cipher, hmac, and compression
|
|
218
|
+
# algorithms specified in the server state object, and returned as a
|
|
219
|
+
# new Packet object.
|
|
220
|
+
# rubocop:disable Metrics/AbcSize
|
|
221
|
+
def poll_next_packet
|
|
222
|
+
aad_length = server.hmac.etm ? 4 : 0
|
|
223
|
+
|
|
224
|
+
if @packet.nil?
|
|
225
|
+
minimum = server.block_size < 4 ? 4 : server.block_size
|
|
226
|
+
return nil if available < minimum + aad_length
|
|
227
|
+
|
|
228
|
+
data = read_available(minimum + aad_length)
|
|
229
|
+
|
|
230
|
+
# decipher it
|
|
231
|
+
if server.cipher.implicit_mac?
|
|
232
|
+
@packet_length = server.cipher.read_length(data[0...4], server.sequence_number)
|
|
233
|
+
@packet = Net::SSH::Buffer.new
|
|
234
|
+
@mac_data = data
|
|
235
|
+
elsif server.hmac.etm
|
|
236
|
+
@packet_length = data.unpack("N").first
|
|
237
|
+
@mac_data = data
|
|
238
|
+
@packet = Net::SSH::Buffer.new(server.update_cipher(data[aad_length..-1]))
|
|
239
|
+
else
|
|
240
|
+
@packet = Net::SSH::Buffer.new(server.update_cipher(data))
|
|
241
|
+
@packet_length = @packet.read_long
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
need = @packet_length + 4 - aad_length - server.block_size
|
|
246
|
+
raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0
|
|
247
|
+
|
|
248
|
+
if server.cipher.implicit_mac?
|
|
249
|
+
return nil if available < need + server.cipher.mac_length
|
|
250
|
+
else
|
|
251
|
+
return nil if available < need + server.hmac.mac_length # rubocop:disable Style/IfInsideElse
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
if need > 0
|
|
255
|
+
# read the remainder of the packet and decrypt it.
|
|
256
|
+
data = read_available(need)
|
|
257
|
+
@mac_data += data if server.hmac.etm || server.cipher.implicit_mac?
|
|
258
|
+
unless server.cipher.implicit_mac?
|
|
259
|
+
@packet.append(
|
|
260
|
+
server.update_cipher(data)
|
|
261
|
+
)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
if server.cipher.implicit_mac?
|
|
266
|
+
real_hmac = read_available(server.cipher.mac_length) || ""
|
|
267
|
+
@packet = Net::SSH::Buffer.new(server.cipher.read_and_mac(@mac_data, real_hmac, server.sequence_number))
|
|
268
|
+
padding_length = @packet.read_byte
|
|
269
|
+
payload = @packet.read(@packet_length - padding_length - 1)
|
|
270
|
+
else
|
|
271
|
+
# get the hmac from the tail of the packet (if one exists), and
|
|
272
|
+
# then validate it.
|
|
273
|
+
real_hmac = read_available(server.hmac.mac_length) || ""
|
|
274
|
+
|
|
275
|
+
@packet.append(server.final_cipher)
|
|
276
|
+
padding_length = @packet.read_byte
|
|
277
|
+
|
|
278
|
+
payload = @packet.read(@packet_length - padding_length - 1)
|
|
279
|
+
|
|
280
|
+
my_computed_hmac = if server.hmac.etm
|
|
281
|
+
server.hmac.digest([server.sequence_number, @mac_data].pack("NA*"))
|
|
282
|
+
else
|
|
283
|
+
server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
|
|
284
|
+
end
|
|
285
|
+
raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
|
|
286
|
+
end
|
|
287
|
+
# try to decompress the payload, in case compression is active
|
|
288
|
+
payload = server.decompress(payload)
|
|
289
|
+
|
|
290
|
+
debug { "received packet nr #{server.sequence_number} type #{payload.getbyte(0)} len #{@packet_length}" }
|
|
291
|
+
|
|
292
|
+
server.increment(@packet_length)
|
|
293
|
+
@packet = nil
|
|
294
|
+
|
|
295
|
+
return Packet.new(payload)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
# rubocop:enable Metrics/AbcSize
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|