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
|
defmodule Chessh.SSH.Daemon do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, %{
pid: nil
})
end
def init(state) do
GenServer.cast(self(), :start)
{:ok, state}
end
def pwd_authenticate(username, password, _address, attempts) do
if Chessh.Auth.PasswordAuthenticator.authenticate(username, password) do
true
else
newAttempts =
case attempts do
:undefined -> 0
_ -> attempts
end
if Application.fetch_env!(:chessh, :max_password_attempts) <= newAttempts do
:disconnect
else
{false, newAttempts + 1}
end
end
end
def handle_cast(:start, state) do
port = Application.fetch_env!(:chessh, :port)
key_dir = String.to_charlist(Application.fetch_env!(:chessh, :key_dir))
max_sessions = Application.fetch_env!(:chessh, :max_sessions)
case :ssh.daemon(
port,
system_dir: key_dir,
pwdfun: &pwd_authenticate/4,
key_cb: Chessh.SSH.ServerKey,
id_string: :random,
subsystems: [],
parallel_login: true,
max_sessions: max_sessions
) do
{:ok, pid} ->
Process.link(pid)
{:noreply, %{state | pid: pid}, :hibernate}
{:error, err} ->
raise inspect(err)
end
{:noreply, state}
end
def handle_info(_, state), do: {:noreply, state}
end
|