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
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
require 'net/ssh/errors'
|
|
2
|
+
require 'net/ssh/key_factory'
|
|
3
|
+
require 'net/ssh/loggable'
|
|
4
|
+
require 'net/ssh/authentication/agent'
|
|
5
|
+
|
|
6
|
+
module Net
|
|
7
|
+
module SSH
|
|
8
|
+
module Authentication
|
|
9
|
+
# A trivial exception class used to report errors in the key manager.
|
|
10
|
+
class KeyManagerError < Net::SSH::Exception; end
|
|
11
|
+
|
|
12
|
+
# This class encapsulates all operations done by clients on a user's
|
|
13
|
+
# private keys. In practice, the client should never need a reference
|
|
14
|
+
# to a private key; instead, they grab a list of "identities" (public
|
|
15
|
+
# keys) that are available from the KeyManager, and then use
|
|
16
|
+
# the KeyManager to do various private key operations using those
|
|
17
|
+
# identities.
|
|
18
|
+
#
|
|
19
|
+
# The KeyManager also uses the Agent class to encapsulate the
|
|
20
|
+
# ssh-agent. Thus, from a client's perspective it is completely
|
|
21
|
+
# hidden whether an identity comes from the ssh-agent or from a file
|
|
22
|
+
# on disk.
|
|
23
|
+
class KeyManager
|
|
24
|
+
include Loggable
|
|
25
|
+
|
|
26
|
+
# The list of user key files that will be examined
|
|
27
|
+
attr_reader :key_files
|
|
28
|
+
|
|
29
|
+
# The list of user key data that will be examined
|
|
30
|
+
attr_reader :key_data
|
|
31
|
+
|
|
32
|
+
# The list of user key certificate files that will be examined
|
|
33
|
+
attr_reader :keycert_files
|
|
34
|
+
|
|
35
|
+
# The list of user key certificate data that will be examined
|
|
36
|
+
attr_reader :keycert_data
|
|
37
|
+
|
|
38
|
+
# The map of loaded identities
|
|
39
|
+
attr_reader :known_identities
|
|
40
|
+
|
|
41
|
+
# The map of options that were passed to the key-manager
|
|
42
|
+
attr_reader :options
|
|
43
|
+
|
|
44
|
+
# Create a new KeyManager. By default, the manager will
|
|
45
|
+
# use the ssh-agent if it is running and the `:use_agent` option
|
|
46
|
+
# is not false.
|
|
47
|
+
def initialize(logger, options = {})
|
|
48
|
+
self.logger = logger
|
|
49
|
+
@key_files = []
|
|
50
|
+
@key_data = []
|
|
51
|
+
@keycert_files = []
|
|
52
|
+
@keycert_data = []
|
|
53
|
+
@use_agent = options[:use_agent] != false
|
|
54
|
+
@known_identities = {}
|
|
55
|
+
@agent = nil
|
|
56
|
+
@options = options
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Clear all knowledge of any loaded user keys. This also clears the list
|
|
60
|
+
# of default identity files that are to be loaded, thus making it
|
|
61
|
+
# appropriate to use if a client wishes to NOT use the default identity
|
|
62
|
+
# files.
|
|
63
|
+
def clear!
|
|
64
|
+
key_files.clear
|
|
65
|
+
key_data.clear
|
|
66
|
+
keycert_data.clear
|
|
67
|
+
known_identities.clear
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Add the given key_file to the list of key files that will be used.
|
|
72
|
+
def add(key_file)
|
|
73
|
+
key_files.push(File.expand_path(key_file)).uniq!
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Add the given keycert_file to the list of keycert files that will be used.
|
|
78
|
+
def add_keycert(keycert_file)
|
|
79
|
+
keycert_files.push(File.expand_path(keycert_file)).uniq!
|
|
80
|
+
self
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Add the given keycert_data to the list of keycerts that will be used.
|
|
84
|
+
def add_keycert_data(keycert_data_)
|
|
85
|
+
keycert_data.push(keycert_data_).uniq!
|
|
86
|
+
self
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Add the given key_file to the list of keys that will be used.
|
|
90
|
+
def add_key_data(key_data_)
|
|
91
|
+
key_data.push(key_data_).uniq!
|
|
92
|
+
self
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# This is used as a hint to the KeyManager indicating that the agent
|
|
96
|
+
# connection is no longer needed. Any other open resources may be closed
|
|
97
|
+
# at this time.
|
|
98
|
+
#
|
|
99
|
+
# Calling this does NOT indicate that the KeyManager will no longer
|
|
100
|
+
# be used. Identities may still be requested and operations done on
|
|
101
|
+
# loaded identities, in which case, the agent will be automatically
|
|
102
|
+
# reconnected. This method simply allows the client connection to be
|
|
103
|
+
# closed when it will not be used in the immediate future.
|
|
104
|
+
def finish
|
|
105
|
+
@agent.close if @agent
|
|
106
|
+
@agent = nil
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Iterates over all available identities (public keys) known to this
|
|
110
|
+
# manager. As it finds one, it will then yield it to the caller.
|
|
111
|
+
# The origin of the identities may be from files on disk or from an
|
|
112
|
+
# ssh-agent. Note that identities from an ssh-agent are always listed
|
|
113
|
+
# first in the array, with other identities coming after.
|
|
114
|
+
#
|
|
115
|
+
# If key manager was created with :keys_only option, any identity
|
|
116
|
+
# from ssh-agent will be ignored unless it present in key_files or
|
|
117
|
+
# key_data.
|
|
118
|
+
def each_identity
|
|
119
|
+
prepared_identities = prepare_identities_from_files + prepare_identities_from_data
|
|
120
|
+
|
|
121
|
+
user_identities = load_identities(prepared_identities, false, true)
|
|
122
|
+
|
|
123
|
+
if agent
|
|
124
|
+
agent.identities.each do |key|
|
|
125
|
+
corresponding_user_identity = user_identities.detect { |identity|
|
|
126
|
+
identity[:public_key] && identity[:public_key].to_pem == key.to_pem
|
|
127
|
+
}
|
|
128
|
+
user_identities.delete(corresponding_user_identity) if corresponding_user_identity
|
|
129
|
+
|
|
130
|
+
if !options[:keys_only] || corresponding_user_identity
|
|
131
|
+
known_identities[key] = { from: :agent, identity: key }
|
|
132
|
+
yield key
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
user_identities = load_identities(user_identities, !options[:non_interactive], false)
|
|
138
|
+
|
|
139
|
+
user_identities.each do |identity|
|
|
140
|
+
key = identity.delete(:public_key)
|
|
141
|
+
known_identities[key] = identity
|
|
142
|
+
yield key
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
known_identity_blobs = known_identities.keys.map(&:to_blob)
|
|
146
|
+
|
|
147
|
+
keycerts.each do |keycert|
|
|
148
|
+
next if known_identity_blobs.include?(keycert.to_blob)
|
|
149
|
+
|
|
150
|
+
(_, corresponding_identity) = known_identities.detect { |public_key, _|
|
|
151
|
+
public_key.to_pem == keycert.to_pem
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if corresponding_identity
|
|
155
|
+
known_identities[keycert] = corresponding_identity
|
|
156
|
+
yield keycert
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
self
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Sign the given data, using the corresponding private key of the given
|
|
164
|
+
# identity. If the identity was originally obtained from an ssh-agent,
|
|
165
|
+
# then the ssh-agent will be used to sign the data, otherwise the
|
|
166
|
+
# private key for the identity will be loaded from disk (if it hasn't
|
|
167
|
+
# been loaded already) and will then be used to sign the data.
|
|
168
|
+
#
|
|
169
|
+
# Regardless of the identity's origin or who does the signing, this
|
|
170
|
+
# will always return the signature in an SSH2-specified "signature
|
|
171
|
+
# blob" format.
|
|
172
|
+
def sign(identity, data, sig_alg = nil)
|
|
173
|
+
info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager"
|
|
174
|
+
|
|
175
|
+
if info[:key].nil? && info[:from] == :file
|
|
176
|
+
begin
|
|
177
|
+
info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive], options[:password_prompt])
|
|
178
|
+
rescue OpenSSL::OpenSSLError, Exception => e
|
|
179
|
+
raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
if info[:key]
|
|
184
|
+
if sig_alg.nil?
|
|
185
|
+
signed = info[:key].ssh_do_sign(data.to_s)
|
|
186
|
+
sig_alg = identity.ssh_signature_type
|
|
187
|
+
else
|
|
188
|
+
signed = info[:key].ssh_do_sign(data.to_s, sig_alg)
|
|
189
|
+
end
|
|
190
|
+
return Net::SSH::Buffer.from(:string, sig_alg,
|
|
191
|
+
:mstring, signed).to_s
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if info[:from] == :agent
|
|
195
|
+
raise KeyManagerError, "the agent is no longer available" unless agent
|
|
196
|
+
|
|
197
|
+
case sig_alg
|
|
198
|
+
when "rsa-sha2-512"
|
|
199
|
+
return agent.sign(info[:identity], data.to_s, Net::SSH::Authentication::Agent::SSH_AGENT_RSA_SHA2_512)
|
|
200
|
+
when "rsa-sha2-256"
|
|
201
|
+
return agent.sign(info[:identity], data.to_s, Net::SSH::Authentication::Agent::SSH_AGENT_RSA_SHA2_256)
|
|
202
|
+
else
|
|
203
|
+
return agent.sign(info[:identity], data.to_s)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Identifies whether the ssh-agent will be used or not.
|
|
211
|
+
def use_agent?
|
|
212
|
+
@use_agent
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Toggles whether the ssh-agent will be used or not. If true, an
|
|
216
|
+
# attempt will be made to use the ssh-agent. If false, any existing
|
|
217
|
+
# connection to an agent is closed and the agent will not be used.
|
|
218
|
+
def use_agent=(use_agent)
|
|
219
|
+
finish if !use_agent
|
|
220
|
+
@use_agent = use_agent
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Returns an Agent instance to use for communicating with an SSH
|
|
224
|
+
# agent process. Returns nil if use of an SSH agent has been disabled,
|
|
225
|
+
# or if the agent is otherwise not available.
|
|
226
|
+
def agent
|
|
227
|
+
return unless use_agent?
|
|
228
|
+
|
|
229
|
+
@agent ||= Agent.connect(logger, options[:agent_socket_factory], options[:identity_agent])
|
|
230
|
+
rescue AgentNotAvailable
|
|
231
|
+
@use_agent = false
|
|
232
|
+
nil
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def no_keys?
|
|
236
|
+
key_files.empty? && key_data.empty?
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
private
|
|
240
|
+
|
|
241
|
+
# Load keycerts from files and data.
|
|
242
|
+
def keycerts
|
|
243
|
+
keycert_files.map { |keycert_file| KeyFactory.load_public_key(keycert_file) } +
|
|
244
|
+
keycert_data.map { |data| KeyFactory.load_data_public_key(data) }
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Prepares identities from user key_files for loading, preserving their order and sources.
|
|
248
|
+
def prepare_identities_from_files
|
|
249
|
+
key_files.map do |file|
|
|
250
|
+
if readable_file?(file)
|
|
251
|
+
identity = {}
|
|
252
|
+
cert_file = file + "-cert.pub"
|
|
253
|
+
public_key_file = file + ".pub"
|
|
254
|
+
if readable_file?(cert_file)
|
|
255
|
+
identity[:load_from] = :pubkey_file
|
|
256
|
+
identity[:pubkey_file] = cert_file
|
|
257
|
+
elsif readable_file?(public_key_file)
|
|
258
|
+
identity[:load_from] = :pubkey_file
|
|
259
|
+
identity[:pubkey_file] = public_key_file
|
|
260
|
+
else
|
|
261
|
+
identity[:load_from] = :privkey_file
|
|
262
|
+
end
|
|
263
|
+
identity.merge(privkey_file: file)
|
|
264
|
+
end
|
|
265
|
+
end.compact
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def readable_file?(path)
|
|
269
|
+
File.file?(path) && File.readable?(path)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Prepared identities from user key_data, preserving their order and sources.
|
|
273
|
+
def prepare_identities_from_data
|
|
274
|
+
key_data.map do |data|
|
|
275
|
+
{ load_from: :data, data: data }
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Load prepared identities. Private key decryption errors ignored if ignore_decryption_errors
|
|
280
|
+
def load_identities(identities, ask_passphrase, ignore_decryption_errors)
|
|
281
|
+
identities.map do |identity|
|
|
282
|
+
case identity[:load_from]
|
|
283
|
+
when :pubkey_file
|
|
284
|
+
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
|
285
|
+
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
|
286
|
+
when :privkey_file
|
|
287
|
+
private_key = KeyFactory.load_private_key(
|
|
288
|
+
identity[:privkey_file], options[:passphrase], ask_passphrase, options[:password_prompt]
|
|
289
|
+
)
|
|
290
|
+
key = private_key.send(:public_key)
|
|
291
|
+
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
|
292
|
+
when :data
|
|
293
|
+
private_key = KeyFactory.load_data_private_key(
|
|
294
|
+
identity[:data], options[:passphrase], ask_passphrase, "<key in memory>", options[:password_prompt]
|
|
295
|
+
)
|
|
296
|
+
key = private_key.send(:public_key)
|
|
297
|
+
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
|
298
|
+
else
|
|
299
|
+
identity
|
|
300
|
+
end
|
|
301
|
+
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError, OpenSSL::PKey::PKeyError, ArgumentError => e
|
|
302
|
+
if ignore_decryption_errors
|
|
303
|
+
identity
|
|
304
|
+
else
|
|
305
|
+
process_identity_loading_error(identity, e)
|
|
306
|
+
nil
|
|
307
|
+
end
|
|
308
|
+
rescue Exception => e
|
|
309
|
+
process_identity_loading_error(identity, e)
|
|
310
|
+
nil
|
|
311
|
+
end.compact
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def process_identity_loading_error(identity, e)
|
|
315
|
+
case identity[:load_from]
|
|
316
|
+
when :pubkey_file
|
|
317
|
+
error { "could not load public key file `#{identity[:pubkey_file]}': #{e.class} (#{e.message})" }
|
|
318
|
+
when :privkey_file
|
|
319
|
+
error { "could not load private key file `#{identity[:privkey_file]}': #{e.class} (#{e.message})" }
|
|
320
|
+
else
|
|
321
|
+
raise e
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/abstract.rb
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'net/ssh/buffer'
|
|
2
|
+
require 'net/ssh/errors'
|
|
3
|
+
require 'net/ssh/loggable'
|
|
4
|
+
require 'net/ssh/authentication/constants'
|
|
5
|
+
|
|
6
|
+
module Net
|
|
7
|
+
module SSH
|
|
8
|
+
module Authentication
|
|
9
|
+
module Methods
|
|
10
|
+
# The base class of all user authentication methods. It provides a few
|
|
11
|
+
# bits of common functionality.
|
|
12
|
+
class Abstract
|
|
13
|
+
include Loggable
|
|
14
|
+
include Constants
|
|
15
|
+
|
|
16
|
+
# The authentication session object
|
|
17
|
+
attr_reader :session
|
|
18
|
+
|
|
19
|
+
# The key manager object. Not all authentication methods will require
|
|
20
|
+
# this.
|
|
21
|
+
attr_reader :key_manager
|
|
22
|
+
|
|
23
|
+
# So far only affects algorithms used for rsa keys, but can be
|
|
24
|
+
# extended to other keys, e.g after reading of
|
|
25
|
+
# PubkeyAcceptedAlgorithms option from ssh_config file is implemented.
|
|
26
|
+
attr_reader :pubkey_algorithms
|
|
27
|
+
|
|
28
|
+
# Instantiates a new authentication method.
|
|
29
|
+
def initialize(session, options = {})
|
|
30
|
+
@session = session
|
|
31
|
+
@key_manager = options[:key_manager]
|
|
32
|
+
@options = options
|
|
33
|
+
@prompt = options[:password_prompt]
|
|
34
|
+
@pubkey_algorithms = options[:pubkey_algorithms] \
|
|
35
|
+
|| %w[rsa-sha2-256-cert-v01@openssh.com
|
|
36
|
+
ssh-rsa-cert-v01@openssh.com
|
|
37
|
+
rsa-sha2-256
|
|
38
|
+
ssh-rsa]
|
|
39
|
+
self.logger = session.logger
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns the session-id, as generated during the first key exchange of
|
|
43
|
+
# an SSH connection.
|
|
44
|
+
def session_id
|
|
45
|
+
session.transport.algorithms.session_id
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Sends a message via the underlying transport layer abstraction. This
|
|
49
|
+
# will block until the message is completely sent.
|
|
50
|
+
def send_message(msg)
|
|
51
|
+
session.transport.send_message(msg)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Creates a new USERAUTH_REQUEST packet. The extra arguments on the end
|
|
55
|
+
# must be either boolean values or strings, and are tacked onto the end
|
|
56
|
+
# of the packet. The new packet is returned, ready for sending.
|
|
57
|
+
def userauth_request(username, next_service, auth_method, *others)
|
|
58
|
+
buffer = Net::SSH::Buffer.from(:byte, USERAUTH_REQUEST,
|
|
59
|
+
:string, username, :string, next_service, :string, auth_method)
|
|
60
|
+
|
|
61
|
+
others.each do |value|
|
|
62
|
+
case value
|
|
63
|
+
when true, false then buffer.write_bool(value)
|
|
64
|
+
when String then buffer.write_string(value)
|
|
65
|
+
else raise ArgumentError, "don't know how to write #{value.inspect}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
buffer
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
attr_reader :prompt
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/hostbased.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'net/ssh/authentication/methods/abstract'
|
|
2
|
+
|
|
3
|
+
module Net
|
|
4
|
+
module SSH
|
|
5
|
+
module Authentication
|
|
6
|
+
module Methods
|
|
7
|
+
# Implements the host-based SSH authentication method.
|
|
8
|
+
class Hostbased < Abstract
|
|
9
|
+
include Constants
|
|
10
|
+
|
|
11
|
+
# Attempts to perform host-based authorization of the user by trying
|
|
12
|
+
# all known keys.
|
|
13
|
+
def authenticate(next_service, username, password = nil)
|
|
14
|
+
return false unless key_manager
|
|
15
|
+
|
|
16
|
+
key_manager.each_identity do |identity|
|
|
17
|
+
return true if authenticate_with(identity, next_service,
|
|
18
|
+
username, key_manager)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
return false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# Returns the hostname as reported by the underlying socket.
|
|
27
|
+
def hostname
|
|
28
|
+
session.transport.socket.client_name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Attempts to perform host-based authentication of the user, using
|
|
32
|
+
# the given host identity (key).
|
|
33
|
+
def authenticate_with(identity, next_service, username, key_manager)
|
|
34
|
+
debug { "trying hostbased (#{identity.fingerprint})" }
|
|
35
|
+
client_username = ENV['USER'] || username
|
|
36
|
+
|
|
37
|
+
req = build_request(identity, next_service, username, "#{hostname}.", client_username)
|
|
38
|
+
sig_data = Buffer.from(:string, session_id, :raw, req)
|
|
39
|
+
|
|
40
|
+
sig = key_manager.sign(identity, sig_data.to_s)
|
|
41
|
+
|
|
42
|
+
message = Buffer.from(:raw, req, :string, sig)
|
|
43
|
+
|
|
44
|
+
send_message(message)
|
|
45
|
+
message = session.next_message
|
|
46
|
+
|
|
47
|
+
case message.type
|
|
48
|
+
when USERAUTH_SUCCESS
|
|
49
|
+
info { "hostbased succeeded (#{identity.fingerprint})" }
|
|
50
|
+
return true
|
|
51
|
+
when USERAUTH_FAILURE
|
|
52
|
+
info { "hostbased failed (#{identity.fingerprint})" }
|
|
53
|
+
|
|
54
|
+
raise Net::SSH::Authentication::DisallowedMethod unless
|
|
55
|
+
message[:authentications].split(/,/).include? 'hostbased'
|
|
56
|
+
|
|
57
|
+
return false
|
|
58
|
+
else
|
|
59
|
+
raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Build the "core" hostbased request string.
|
|
64
|
+
def build_request(identity, next_service, username, hostname, client_username)
|
|
65
|
+
userauth_request(username, next_service, "hostbased", identity.ssh_type,
|
|
66
|
+
Buffer.from(:key, identity).to_s, hostname, client_username).to_s
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -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
|
data/vendor/bundle/ruby/3.2.0/gems/net-ssh-7.2.1/lib/net/ssh/authentication/methods/password.rb
ADDED
|
@@ -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
|