module Net::SSH

def self._sanitize_options(options)

def self._sanitize_options(options)
  invalid_option_values = [nil, [nil]]
  unless (options.values & invalid_option_values).empty?
    nil_options = options.select { |_k, v| invalid_option_values.include?(v) }.map(&:first)
    Kernel.warn "#{caller_locations(2, 1)[0]}: Passing nil, or [nil] to Net::SSH.start is deprecated for keys: #{nil_options.join(', ')}"
  end
end

def self._support_deprecated_option_paranoid(options)

def self._support_deprecated_option_paranoid(options)
  if options.key?(:paranoid)
    Kernel.warn(
      ":paranoid is deprecated, please use :verify_host_key. Supported " \
      "values are exactly the same, only the name of the option has changed."
    )
    if options.key?(:verify_host_key)
      Kernel.warn(
        "Both :paranoid and :verify_host_key were specified. " \
        ":verify_host_key takes precedence, :paranoid will be ignored."
      )
    else
      options[:verify_host_key] = options.delete(:paranoid)
    end
  end
end

def self.assign_defaults(options)

def self.assign_defaults(options)
  if !options[:logger]
    options[:logger] = Logger.new(STDERR)
    options[:logger].level = Logger::FATAL
  end
  options[:password_prompt] ||= Prompt.default(options)
  %i[password passphrase].each do |key|
    options.delete(key) if options.key?(key) && options[key].nil?
  end
end

def self.configuration_for(host, use_ssh_config)

See Net::SSH::Config for the full description of all supported options.

to read.
be a file name (or array of file names) of SSH configuration file(s)
loaded (and an empty hash returned). Otherwise, +use_ssh_config+ may
/etc/ssh_config. If +use_ssh_config+ is nil or false, nothing will be
default), this will load configuration from both ~/.ssh/config and
from the SSH configuration file(s). If +use_ssh_config+ is true (the
Returns a hash of the configuration options for the given host, as read
def self.configuration_for(host, use_ssh_config)
  files = case use_ssh_config
          when true then Net::SSH::Config.expandable_default_files
          when false, nil then return {}
          else Array(use_ssh_config)
          end
  Net::SSH::Config.for(host, files)
end

def self.start(host, user = nil, options = {}, &block)

local username
If +user+ parameter is nil it defaults to USER from ssh_config, or
* :fingerprint_hash => 'MD5' or 'SHA256', defaults to 'SHA256'
returning false declines it and closes the connection.
the +:fingerprint+ and the +:session+. Returning true accepts the host key,
given to +verify+ is a hash consisting of the +:key+, the +:key_blob+,
You can also provide an own Object which responds to +verify+. The argument
* :always (secure) ::Net::SSH::Verifiers::Always
* :accept_new (insecure) ::Net::SSH::Verifiers::AcceptNew
* :accept_new_or_local_tunnel (insecure) ::Net::SSH::Verifiers::AcceptNewOrLocalTunnel
* :never (very insecure) ::Net::SSH::Verifiers::Never
In order of increasing strictness:
* :verify_host_key => specify how strict host-key verification should be.
example: ->{ UNIXSocket.open('/foo/bar')}
Net::SSH.start(host,user,agent_socket_factory: ->{ UNIXSocket.open('/foo/bar') })
* :agent_socket_factory => enables the user to pass a lambda/block that will serve as the socket factory

* :password_prompt => a custom prompt object with ask method. See Net::SSH::Prompt
password auth method
authentication method defaults to 3 set to 0 to disable prompt for
* :number_of_password_prompts => Number of prompts for the password
algorithms by net-ssh. Was the default behaviour until 2.10
* :append_all_supported_algorithms => set to +true+ to append all supported
supported and are translated to the corresponding Logger constant.
default. The symbols :debug, :info, :warn, :error, and :fatal are also
is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the
* :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG
* :identity_agent => the path to the ssh-agent's UNIX socket
true
* :use_agent => Set false to disable the use of ssh-agent. Defaults to
Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2).
Set to an array to specify multiple user known hosts files.
* :user_known_hosts_file => the location of the user known hosts file.
* :remote_user => used for substitution into the '%r' part of a ProxyCommand
configuration file.
parameter, and is primarily only useful when provided via an SSH
* :user => the user name to log in as; this overrides the +user+
* :timeout => how long to wait for the initial connection to be made
remote environment. Override the ones if specified in +send_env+.
* :set_env => a hash of environment variable names and values to set to the
remote environment. Names may be given as String or Regexp.
* :send_env => an array of local environment variable names to export to the
* :rekey_packet_limit => the max number of packets to process before rekeying
* :rekey_limit => the max number of bytes to process before rekeying
* :rekey_blocks_limit => the max number of blocks to process before rekeying
types.
option is only used for RSA public key authentication and ignored for other
'ssh-rsa-cert-v01@openssh.com', 'rsa-sha2-256', 'ssh-rsa'. Currently, this
this connection. Valid values are 'rsa-sha2-256-cert-v01@openssh.com',
* :pubkey_algorithms => the public key authentication algorithms to use for
* :proxy => a proxy instance (see Proxy) to use when connecting
properties (see Net::SSH::Connection::Session#properties)
* :properties => a hash of key/value pairs to add to the new connection's
* :port => the port to use when connecting to the remote host
* :password => the password to use to login
is +nil+, for no passphrase)
* :passphrase => the passphrase to use when loading a private key (default
* :paranoid => deprecated alias for :verify_host_key
asking for password.
should set it to true to prefer failing a password/etc auth methods vs.
authentication failure vs password prompt. Non-interactive applications
* :non_interactive => set to true if your app is non interactive and prefers
the window.
* :max_win_size => maximum size we tell the other side that is supported for
for better performance if your SSH server supports it (most do).
packet. Default is 0x8000 (32768 bytes). Increase to 0x10000 (65536 bytes)
* :max_pkt_size => maximum size we tell the other side that is supported per
* :logger => the logger instance to use when logging
identites.
option is intended for situations where ssh-agent offers many different
+key_data+ parameters, even if ssh-agent offers more identities. This
* :keys_only => set to +true+ to use only private keys from +keys+ and
a raw private key in PEM format.
* :key_data => an array of strings, with each element of the array being
being a key certificate to use with publickey authentication
* :keycert_data => an array of strings, which each element of the array
with publickey authentication
* :keycerts => an array of file names of key certificates to use
and hostbased authentication
* :keys => an array of file names of private keys to use for publickey
* :kex => the key exchange algorithm (or algorithms) to use
Defaults to 3
* :keepalive_maxcount => the maximun number of keepalive packet miss allowed.
Defaults to +300+ seconds.
* :keepalive_interval => the interval seconds for keepalive.
the keepalive_interval seconds. Defaults to +false+.
when there's no traffic between the SSH server and Net::SSH client for
* :keepalive => set to +true+ to send a keepalive packet to the SSH server
to modify /etc/hosts.
"alias", similarly to adding an entry in /etc/hosts but without needing
specified in an SSH configuration file. It lets you specify an
instead of the +host+ parameter, and is primarily only useful when
* :host_name => the real host name or IP to log into. This is used
host to a known_hosts dictionary file
* :host_key_alias => the host name to use when looking up or adding a
* :host_key => the host key algorithm (or algorithms) to use
* :hmac => the hmac algorithm (or algorithms) to use
hosts files. Defaults to %w(/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2).
file. Set to an array if you want to specify multiple global known
* :global_known_hosts_file => the location of the global known hosts
It must implement #search_for and `add` in a similiar manner as KnownHosts.
* :known_hosts => a custom object holding known hosts records.
be forwarded
* :forward_agent => set to true if you want the SSH agent connection to
* :encryption => the encryption cipher (or ciphers) to use
files. Defaults to +true+.
a file-name (or array of file-names) to load those specific configuration
(~/.ssh/config, /etc/ssh_config), or to +false+ to not load them, or to
* :config => set to +true+ to load the default OpenSSH config files
* :compression_level => the compression level to use when sending data
whatever is supported.
* :compression => the compression algorithm to use, or +true+ to use
Defaults to +true+.
* :check_host_ip => Also ckeck IP address when connecting to remote host.
is set.)
establishing connection. (:bind_address is discarded if :proxy
* :bind_address => the IP address on the connecting machine to use in
* :auth_methods => an array of authentication methods to try

This method accepts the following options (all are optional):

end
ssh.loop

end
end
end
end
ch.send_data("password\n")
if data =~ /sudo password: /
print data
ch.on_data do |ch, data|

abort "could not execute sudo ls" unless success
ch.exec "sudo -p 'sudo password: ' ls" do |ch, success|
ssh.open_channel do |ch|

hostname = ssh.exec!("hostname")
ssh.exec! "cp /some/file /another/location"
Net::SSH.start("host", "user") do |ssh|

Net::SSH::Connection::Channel and Net::SSH::Service::Forward.)
will be an instance of Net::SSH::Connection::Session (q.v.). (See also
the connection will just be returned. The yielded (or returned) value
block, the connection will be closed when the block terminates, otherwise
The standard means of starting a new SSH connection. When used with a
def self.start(host, user = nil, options = {}, &block)
  invalid_options = options.keys - VALID_OPTIONS
  if invalid_options.any?
    raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}"
  end
  assign_defaults(options)
  _sanitize_options(options)
  options[:user] = user if user
  options = configuration_for(host, options.fetch(:config, true)).merge(options)
  host = options.fetch(:host_name, host)
  options[:check_host_ip] = true unless options.key?(:check_host_ip)
  if options[:non_interactive]
    options[:number_of_password_prompts] = 0
  end
  _support_deprecated_option_paranoid(options)
  if options[:verbose]
    options[:logger].level = case options[:verbose]
                             when Integer then options[:verbose]
                             when :debug then Logger::DEBUG
                             when :info  then Logger::INFO
                             when :warn  then Logger::WARN
                             when :error then Logger::ERROR
                             when :fatal then Logger::FATAL
                             else raise ArgumentError, "can't convert #{options[:verbose].inspect} to any of the Logger level constants"
                             end
  end
  transport = Transport::Session.new(host, options)
  auth = Authentication::Session.new(transport, options)
  user = options.fetch(:user, user) || Etc.getpwuid.name
  if auth.authenticate("ssh-connection", user, options[:password])
    connection = Connection::Session.new(transport, options)
    if block_given?
      begin
        yield connection
      ensure
        connection.close unless connection.closed?
      end
    else
      return connection
    end
  else
    transport.close
    raise AuthenticationFailed, "Authentication failed for user #{user}@#{host}"
  end
end