auth against sha512-crypt password hashes, upgrade to pbkdf2
authorMoon Man <shitposterclub@gmail.com>
Wed, 5 Sep 2018 04:21:44 +0000 (00:21 -0400)
committerMoon Man <shitposterclub@gmail.com>
Wed, 5 Sep 2018 04:21:44 +0000 (00:21 -0400)
lib/pleroma/plugs/authentication_plug.ex
mix.exs
test/plugs/authentication_plug_test.exs

index 86a514541025083c33adec55dda58bb48d0c29f6..616d31df4ba7a2f080e951c1ff6f598e7efc8008 100644 (file)
@@ -14,7 +14,17 @@ defmodule Pleroma.Plugs.AuthenticationPlug 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 @@ defmodule Pleroma.Plugs.AuthenticationPlug 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 6b95eeec38d94e9698ae0df2bd6e021611b8f203..cccb6938f82f4f90d9944a243cdaa1a1bba2911c 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -50,7 +50,8 @@ defmodule Pleroma.Mixfile 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
 
index 729ac8ae5518da97b2cbe1df257e6ce830ca9ad3..fd58d6ab470455caf9c1a5b5c1edec44853dad77 100644 (file)
@@ -21,6 +21,13 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest 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 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest 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