require_relative '../../common' require 'net/ssh/authentication/methods/keyboard_interactive' require_relative 'common' module Authentication module Methods class TestKeyboardInteractive < NetSSHTest include Common USERAUTH_INFO_REQUEST = 60 USERAUTH_INFO_RESPONSE = 61 def setup reset_subject({}) if defined? @subject && !@subject.options.empty? end def test_authenticate_should_raise_if_keyboard_interactive_disallowed transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert_equal "jamis", packet.read_string assert_equal "ssh-connection", packet.read_string assert_equal "keyboard-interactive", packet.read_string assert_equal "", packet.read_string # language tags assert_equal "", packet.read_string # submethods t.return(USERAUTH_FAILURE, :string, "password") end assert_raises Net::SSH::Authentication::DisallowedMethod do subject.authenticate("ssh-connection", "jamis") end end def test_authenticate_should_be_false_if_given_password_is_not_accepted reset_subject(non_interactive: true) transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false) t.expect do |t2, packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 1, packet2.read_long assert_equal "the-password", packet2.read_string t2.return(USERAUTH_FAILURE, :string, "keyboard-interactive") end end assert_equal false, subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_be_true_if_given_password_is_accepted transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false) t.expect do |t2, packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_duplicate_password_as_needed_to_fill_request transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Password:", :bool, false, :string, "Again:", :bool, false) t.expect do |t2, packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 2, packet2.read_long assert_equal "the-password", packet2.read_string assert_equal "the-password", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_not_prompt_for_input_when_in_non_interactive_mode reset_subject(non_interactive: true) transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Name:", :bool, true, :string, "Password:", :bool, false) t.expect do |t2, packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 2, packet2.read_long assert_equal "", packet2.read_string assert_equal "", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", nil) end def test_authenticate_should_prompt_for_input_when_password_is_not_given prompt = MockPrompt.new prompt.expects(:_ask).with("Name:", anything, true).returns("name") prompt.expects(:_ask).with("Password:", anything, false).returns("password") reset_subject(password_prompt: prompt) transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Name:", :bool, true, :string, "Password:", :bool, false) t.expect do |t2, packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 2, packet2.read_long assert_equal "name", packet2.read_string assert_equal "password", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", nil) end private def subject(options = {}) @subject ||= Net::SSH::Authentication::Methods::KeyboardInteractive.new(session(options), options) end def reset_subject(options) @subject = nil reset_session(options) subject(options) end end end end