class Net::SSH::Authentication::Session

  1. lib/net/ssh/authentication/session.rb
Parent: Authentication

Represents an authentication session. It manages the authentication of a user over an established connection (the "transport" object, see Net::SSH::Transport::Session).

The use of an authentication session to manage user authentication is internal to Net::SSH (specifically Net::SSH.start). Consumers of the Net::SSH library will never need to access this class directly.

Attributes

allowed_auth_methods [R]

the list of authentication methods that are allowed

auth_methods [R]

the list of authentication methods to try

options [R]

a hash of options, given at construction time

transport [R]

transport layer abstraction

Public Class methods

new (transport, options={})

Instantiates a new Authentication::Session object over the given transport layer abstraction.

[show source]
# File lib/net/ssh/authentication/session.rb, line 41
def initialize(transport, options={})
  self.logger = transport.logger
  @transport = transport

  @auth_methods = options[:auth_methods] || Net::SSH::Config.default_auth_methods
  @options = options

  @allowed_auth_methods = @auth_methods
end

Public Instance methods

authenticate (next_service, username, password=nil)

Attempts to authenticate the given user, in preparation for the next service request. Returns true if an authentication method succeeds in authenticating the user, and false otherwise.

[show source]
# File lib/net/ssh/authentication/session.rb, line 54
def authenticate(next_service, username, password=nil)
  debug { "beginning authentication of `#{username}'" }

  transport.send_message(transport.service_request("ssh-userauth"))
  expect_message(SERVICE_ACCEPT)

  key_manager = KeyManager.new(logger, options)
  keys.each { |key| key_manager.add(key) } unless keys.empty?
  key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty?

  attempted = []

  @auth_methods.each do |name|
    begin
      next unless @allowed_auth_methods.include?(name)
      attempted << name

      debug { "trying #{name}" }
      begin 
        method = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join).new(self, :key_manager => key_manager)
      rescue NameError
        debug{"Mechanism #{name} was requested, but isn't a known type.  Ignoring it."}
        next
      end

      return true if method.authenticate(next_service, username, password)
    rescue Net::SSH::Authentication::DisallowedMethod
    end
  end

  error { "all authorization methods failed (tried #{attempted.join(', ')})" }
  return false
ensure
  key_manager.finish if key_manager
end
expect_message (type)

Blocks until a packet is received, and returns it if it is of the given type. If it is not, an exception is raised.

[show source]
# File lib/net/ssh/authentication/session.rb, line 122
def expect_message(type)
  message = next_message
  unless message.type == type
    raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})"
  end
  message
end
next_message ()

Blocks until a packet is received. It silently handles USERAUTH_BANNER packets, and will raise an error if any packet is received that is not valid during user authentication.

[show source]
# File lib/net/ssh/authentication/session.rb, line 93
def next_message
  loop do
    packet = transport.next_message

    case packet.type
    when USERAUTH_BANNER
      info { packet[:message] }
      # TODO add a hook for people to retrieve the banner when it is sent

    when USERAUTH_FAILURE
      @allowed_auth_methods = packet[:authentications].split(/,/)
      debug { "allowed methods: #{packet[:authentications]}" }
      return packet

    when USERAUTH_METHOD_RANGE, SERVICE_ACCEPT
      return packet

    when USERAUTH_SUCCESS
      transport.hint :authenticated
      return packet

    else
      raise Net::SSH::Exception, "unexpected message #{packet.type} (#{packet})"
    end
  end
end