diff options
Diffstat (limited to 'lib/chessh/ssh/daemon.ex')
-rw-r--r-- | lib/chessh/ssh/daemon.ex | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/chessh/ssh/daemon.ex b/lib/chessh/ssh/daemon.ex new file mode 100644 index 0000000..acb6bea --- /dev/null +++ b/lib/chessh/ssh/daemon.ex @@ -0,0 +1,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 |