summaryrefslogtreecommitdiff
path: root/lib/chessh/ssh/daemon.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chessh/ssh/daemon.ex')
-rw-r--r--lib/chessh/ssh/daemon.ex75
1 files changed, 55 insertions, 20 deletions
diff --git a/lib/chessh/ssh/daemon.ex b/lib/chessh/ssh/daemon.ex
index 9f17f75..9ffc538 100644
--- a/lib/chessh/ssh/daemon.ex
+++ b/lib/chessh/ssh/daemon.ex
@@ -1,6 +1,10 @@
defmodule Chessh.SSH.Daemon do
+ alias Chessh.{Repo, PlayerSession, Player, Utils}
alias Chessh.Auth.PasswordAuthenticator
use GenServer
+ import Ecto.Query
+
+ require Logger
def start_link(_) do
GenServer.start_link(__MODULE__, %{
@@ -13,33 +17,33 @@ defmodule Chessh.SSH.Daemon do
{:ok, state}
end
- 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
+ def pwd_authenticate(username, password, {ip, _port}) do
[jail_timeout_ms, jail_attempt_threshold] =
Application.get_env(:chessh, RateLimits)
|> Keyword.take([:jail_timeout_ms, :jail_attempt_threshold])
|> Keyword.values()
- {ip, _port} = inet
rateId = "failed_password_attempts:#{Enum.join(Tuple.to_list(ip), ".")}"
- if pwd_authenticate(username, password) do
- true
- else
- case Hammer.check_rate_inc(rateId, jail_timeout_ms, jail_attempt_threshold, 1) do
- {:allow, _count} ->
- false
+ case PasswordAuthenticator.authenticate(
+ String.Chars.to_string(username),
+ String.Chars.to_string(password)
+ ) do
+ false ->
+ case Hammer.check_rate_inc(rateId, jail_timeout_ms, jail_attempt_threshold, 1) do
+ {:allow, _count} ->
+ false
+
+ {:deny, _limit} ->
+ :disconnect
+ end
- {:deny, _limit} ->
- :disconnect
- end
+ x ->
+ if PlayerSession.player_within_concurrent_sessions_and_satisfies(username, fn _player ->
+ x
+ end),
+ do: true,
+ else: :disconnect
end
end
@@ -53,10 +57,13 @@ defmodule Chessh.SSH.Daemon do
case :ssh.daemon(
port,
+ # shell: fn _username, _peer -> Process.sleep(5000) end,
system_dir: key_dir,
pwdfun: &pwd_authenticate/4,
key_cb: Chessh.SSH.ServerKey,
- # disconnectfun:
+ ssh_cli: {Chessh.SSH.Cli, []},
+ # connectfun: &on_connect/3,
+ disconnectfun: &on_disconnect/1,
id_string: :random,
subsystems: [],
parallel_login: true,
@@ -74,4 +81,32 @@ defmodule Chessh.SSH.Daemon do
end
def handle_info(_, state), do: {:noreply, state}
+
+ # defp on_connect(username, _inet, _method) do
+ # Logger.debug("#{inspect(self())} connected and is authenticated as #{username}")
+ #
+ # case Repo.get_by(Player, username: String.Chars.to_string(username)) do
+ # nil ->
+ # nil
+ #
+ # player ->
+ # Repo.insert(%PlayerSession{
+ # login: DateTime.utc_now(),
+ # node_id: System.fetch_env!("NODE_ID"),
+ # player: player,
+ # process: pid_to_str(self())
+ # })
+ # end
+ # end
+
+ defp on_disconnect(_reason) do
+ Logger.debug("#{inspect(self())} disconnected")
+
+ Repo.delete_all(
+ from(p in PlayerSession,
+ where: p.node_id == ^System.fetch_env!("NODE_ID"),
+ where: p.process == ^Utils.pid_to_str(self())
+ )
+ )
+ end
end