From 1a8bc26e52745909d6fc9ca7d04098d0dd247cfa Mon Sep 17 00:00:00 2001 From: Moon Man Date: Wed, 5 Sep 2018 00:21:44 -0400 Subject: [PATCH] auth against sha512-crypt password hashes, upgrade to pbkdf2 --- lib/pleroma/plugs/authentication_plug.ex | 23 ++++++++++++++++++- mix.exs | 3 ++- test/plugs/authentication_plug_test.exs | 28 ++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/plugs/authentication_plug.ex b/lib/pleroma/plugs/authentication_plug.ex index 86a514541..616d31df4 100644 --- a/lib/pleroma/plugs/authentication_plug.ex +++ b/lib/pleroma/plugs/authentication_plug.ex @@ -14,7 +14,17 @@ def call(conn, opts) do {:ok, user} <- opts[:fetcher].(username), false <- !!user.info["deactivated"], saved_user_id <- get_session(conn, :user_id), + legacy_password <- String.starts_with?(user.password_hash, "$6$"), + update_legacy_password <- + !(Map.has_key?(opts, :update_legacy_password) && opts[:update_legacy_password] == false), {:ok, verified_user} <- verify(user, password, saved_user_id) do + if legacy_password and update_legacy_password do + User.reset_password(verified_user, %{ + :password => password, + :password_confirmation => password + }) + end + conn |> assign(:user, verified_user) |> put_session(:user_id, verified_user.id) @@ -34,7 +44,18 @@ defp verify(nil, _password, _user_id) do end defp verify(user, password, _user_id) do - if Pbkdf2.checkpw(password, user.password_hash) do + is_legacy = String.starts_with?(user.password_hash, "$6$") + + valid = + cond do + is_legacy -> + :crypt.crypt(password, user.password_hash) == user.password_hash + + true -> + Pbkdf2.checkpw(password, user.password_hash) + end + + if valid do {:ok, user} else :error diff --git a/mix.exs b/mix.exs index 6b95eeec3..cccb6938f 100644 --- a/mix.exs +++ b/mix.exs @@ -50,7 +50,8 @@ defp deps do {:ex_aws_s3, "~> 2.0"}, {:ex_machina, "~> 2.2", only: :test}, {:credo, "~> 0.9.3", only: [:dev, :test]}, - {:mock, "~> 0.3.1", only: :test} + {:mock, "~> 0.3.1", only: :test}, + {:crypt, git: "https://github.com/msantos/crypt"} ] end diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs index 729ac8ae5..fd58d6ab4 100644 --- a/test/plugs/authentication_plug_test.exs +++ b/test/plugs/authentication_plug_test.exs @@ -21,6 +21,13 @@ defp fetch_nil(_name) do info: %{"deactivated" => true} } + @legacy %User{ + id: 1, + name: "dude", + password_hash: + "$6$9psBWV8gxkGOZWBz$PmfCycChoxeJ3GgGzwvhlgacb9mUoZ.KUXNCssekER4SJ7bOK53uXrHNb2e4i8yPFgSKyzaW9CcmrDXWIEMtD1" + } + @session_opts [ store: :cookie, key: "_test", @@ -139,6 +146,27 @@ test "it assigns the user", %{conn: conn} do assert get_session(conn, :user_id) == @user.id assert conn.halted == false end + + test "it assigns legacy user", %{conn: conn} do + opts = %{ + optional: true, + fetcher: fn _ -> {:ok, @legacy} end, + update_legacy_password: false + } + + header = basic_auth_enc("dude", "password") + + conn = + conn + |> Plug.Session.call(Plug.Session.init(@session_opts)) + |> fetch_session + |> put_req_header("authorization", header) + |> AuthenticationPlug.call(opts) + + assert %{user: @legacy} == conn.assigns + assert get_session(conn, :user_id) == @legacy.id + assert conn.halted == false + end end describe "with a correct authorization header for an deactiviated user" do