summaryrefslogtreecommitdiff
path: root/test/authentication/methods/test_keyboard_interactive.rb
blob: ebe9c1605433affa08626aafd7110301697e4329 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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