From 1a2bdccf124de6207899f59538cc0ed2efc97b5a Mon Sep 17 00:00:00 2001 From: Simponic Date: Thu, 29 Dec 2022 17:21:20 -0700 Subject: Add scalable nodes and user sessions --- lib/chessh/ssh/daemon.ex | 45 ++++++++++++++++++++++++++++++-------------- lib/chessh/ssh/server_key.ex | 3 ++- 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'lib/chessh/ssh') diff --git a/lib/chessh/ssh/daemon.ex b/lib/chessh/ssh/daemon.ex index acb6bea..cd0d466 100644 --- a/lib/chessh/ssh/daemon.ex +++ b/lib/chessh/ssh/daemon.ex @@ -1,4 +1,5 @@ defmodule Chessh.SSH.Daemon do + alias Chessh.Auth.PasswordAuthenticator use GenServer def start_link(_) do @@ -12,24 +13,39 @@ defmodule Chessh.SSH.Daemon do {: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 + def pwd_authenticate(username, password) do + # TODO - check concurrent sessions + PasswordAuthenticator.authenticate( + String.Chars.to_string(username), + String.Chars.to_string(password) + ) + end + + def pwd_authenticate(username, password, inet) do + [jail_timeout_ms, jail_threshold] = + Application.get_env(:chessh, RateLimits) + |> Keyword.take([:jail_timeout_ms, :jail_threshold]) + |> Keyword.values() + + {ip, _port} = inet + rateId = "failed_password_attempts:#{Enum.join(Tuple.to_list(ip), ".")}" + + case Hammer.check_rate(rateId, jail_timeout_ms, jail_threshold) do + {:allow, _count} -> + pwd_authenticate(username, password) || + (fn -> + Hammer.check_rate_inc(rateId, jail_timeout_ms, jail_threshold, 1) + false + end).() + + {:deny, _limit} -> :disconnect - else - {false, newAttempts + 1} - end end end + def pwd_authenticate(username, password, inet, _address), + do: pwd_authenticate(username, password, inet) + def handle_cast(:start, state) do port = Application.fetch_env!(:chessh, :port) key_dir = String.to_charlist(Application.fetch_env!(:chessh, :key_dir)) @@ -40,6 +56,7 @@ defmodule Chessh.SSH.Daemon do system_dir: key_dir, pwdfun: &pwd_authenticate/4, key_cb: Chessh.SSH.ServerKey, + # disconnectfun: id_string: :random, subsystems: [], parallel_login: true, diff --git a/lib/chessh/ssh/server_key.ex b/lib/chessh/ssh/server_key.ex index 1096e09..72a4fbb 100644 --- a/lib/chessh/ssh/server_key.ex +++ b/lib/chessh/ssh/server_key.ex @@ -1,8 +1,9 @@ defmodule Chessh.SSH.ServerKey do + alias Chessh.Auth.KeyAuthenticator @behaviour :ssh_server_key_api def is_auth_key(key, username, _daemon_options) do - Chessh.Auth.KeyAuthenticator.authenticate(username, key) + KeyAuthenticator.authenticate(username, key) end def host_key(algorithm, daemon_options) do -- cgit v1.2.3-70-g09d2