summaryrefslogtreecommitdiff
path: root/test/ssh/ssh_auth_test.exs
blob: c3ced2082d2776d921b613aae4a7916947456685 (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
defmodule Chessh.SSH.AuthTest do
  use ExUnit.Case
  alias Chessh.{Player, Repo, Key}

  @localhost '127.0.0.1'
  @key_name "The Gamer Machine"
  @valid_user %{username: "logan", password: "password"}
  @client_test_keys_dir Path.join(Application.compile_env!(:chessh, :key_dir), "client_keys")
  @client_pub_key 'id_ed25519.pub'

  setup_all do
    case Ecto.Adapters.SQL.Sandbox.checkout(Repo) do
      :ok -> nil
      {:already, :owner} -> nil
    end

    Ecto.Adapters.SQL.Sandbox.mode(Repo, {:shared, self()})

    {:ok, player} = Repo.insert(Player.registration_changeset(%Player{}, @valid_user))

    {:ok, key_text} = File.read(Path.join(@client_test_keys_dir, @client_pub_key))

    {:ok, _key} =
      Repo.insert(
        Key.changeset(%Key{}, %{key: key_text, name: @key_name})
        |> Ecto.Changeset.put_assoc(:player, player)
      )

    :ok
  end

  test "Fails to authenticate after configured max password attempt" do
    assert :disconnect ==
             Enum.reduce(
               1..Application.fetch_env!(:chessh, :max_password_attempts),
               %{attempts: 0},
               fn acc, _ ->
                 case Chessh.SSH.Daemon.pwd_authenticate(
                        @valid_user.username,
                        'wrong_password',
                        @localhost,
                        acc
                      ) do
                   {false, state} -> state
                   x -> x
                 end
               end
             )
  end

  test "INTEGRATION TEST - Can ssh into daemon with password or public key" do
    {:ok, sup} = Task.Supervisor.start_link()
    test_pid = self()

    Task.Supervisor.start_child(sup, fn ->
      {:ok, _pid} =
        :ssh.connect(@localhost, Application.fetch_env!(:chessh, :port),
          user: String.to_charlist(@valid_user.username),
          password: String.to_charlist(@valid_user.password),
          auth_methods: 'password',
          silently_accept_hosts: true
        )

      send(test_pid, :connected_via_password)
    end)

    Task.Supervisor.start_child(sup, fn ->
      {:ok, _pid} =
        :ssh.connect(@localhost, Application.fetch_env!(:chessh, :port),
          user: String.to_charlist(@valid_user.username),
          auth_methods: 'publickey',
          silently_accept_hosts: true,
          user_dir: String.to_charlist(@client_test_keys_dir)
        )

      send(test_pid, :connected_via_public_key)
    end)

    assert_receive(:connected_via_password, 500)
    assert_receive(:connected_via_public_key, 500)
  end

  test "Hosts are rate limited via password attempts" do
    :ok
  end

  test "Hosts are also rate limited with public keys" do
    :ok
  end

  test "User cannot have more than one current session" do
    :ok
  end
end