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.
Included modules
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
Instantiates a new Authentication::Session object over the given transport layer abstraction.
# File lib/net/ssh/authentication/session.rb, line 36 36: def initialize(transport, options={}) 37: self.logger = transport.logger 38: @transport = transport 39: 40: @auth_methods = options[:auth_methods] || %w(publickey hostbased password keyboard-interactive) 41: @options = options 42: 43: @allowed_auth_methods = @auth_methods 44: end
Public instance methods
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.
# File lib/net/ssh/authentication/session.rb, line 49 49: def authenticate(next_service, username, password=nil) 50: debug { "beginning authentication of `#{username}'" } 51: 52: transport.send_message(transport.service_request("ssh-userauth")) 53: message = expect_message(SERVICE_ACCEPT) 54: 55: key_manager = KeyManager.new(logger, options) 56: keys.each { |key| key_manager.add(key) } unless keys.empty? 57: key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty? 58: 59: attempted = [] 60: 61: @auth_methods.each do |name| 62: next unless @allowed_auth_methods.include?(name) 63: attempted << name 64: 65: debug { "trying #{name}" } 66: method = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join).new(self, :key_manager => key_manager) 67: 68: return true if method.authenticate(next_service, username, password) 69: end 70: 71: error { "all authorization methods failed (tried #{attempted.join(', ')})" } 72: return false 73: ensure 74: key_manager.finish if key_manager 75: end
Blocks until a packet is received, and returns it if it is of the given type. If it is not, an exception is raised.
# File lib/net/ssh/authentication/session.rb, line 109 109: def expect_message(type) 110: message = next_message 111: unless message.type == type 112: raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})" 113: end 114: message 115: end
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.
# File lib/net/ssh/authentication/session.rb, line 80 80: def next_message 81: loop do 82: packet = transport.next_message 83: 84: case packet.type 85: when USERAUTH_BANNER 86: info { packet[:message] } 87: # TODO add a hook for people to retrieve the banner when it is sent 88: 89: when USERAUTH_FAILURE 90: @allowed_auth_methods = packet[:authentications].split(/,/) 91: debug { "allowed methods: #{packet[:authentications]}" } 92: return packet 93: 94: when USERAUTH_METHOD_RANGE, SERVICE_ACCEPT 95: return packet 96: 97: when USERAUTH_SUCCESS 98: transport.hint :authenticated 99: return packet 100: 101: else 102: raise Net::SSH::Exception, "unexpected message #{packet.type} (#{packet})" 103: end 104: end 105: end