Merge branch 'bugfix/captcha-nil-answer_data' into 'develop'

Bugfix: return invalid when answer_data is nil

Closes #1585

See merge request pleroma/pleroma!2236
This commit is contained in:
lain 2020-02-24 14:54:22 +00:00
commit 81f29e7c6a
3 changed files with 80 additions and 18 deletions

View file

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Captcha do defmodule Pleroma.Captcha do
@ -50,7 +50,7 @@ def handle_call(:new, _from, state) do
token = new_captcha[:token] token = new_captcha[:token]
secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt") secret = KeyGenerator.generate(secret_key_base, token <> "_encrypt")
sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign") sign_secret = KeyGenerator.generate(secret_key_base, token <> "_sign")
# Basicallty copy what Phoenix.Token does here, add the time to # Basically copy what Phoenix.Token does here, add the time to
# the actual data and make it a binary to then encrypt it # the actual data and make it a binary to then encrypt it
encrypted_captcha_answer = encrypted_captcha_answer =
%{ %{
@ -62,7 +62,7 @@ def handle_call(:new, _from, state) do
{ {
:reply, :reply,
# Repalce the answer with the encrypted answer # Replace the answer with the encrypted answer
%{new_captcha | answer_data: encrypted_captcha_answer}, %{new_captcha | answer_data: encrypted_captcha_answer},
state state
} }
@ -82,7 +82,8 @@ def handle_call({:validate, token, captcha, answer_data}, _from, state) do
valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid) valid_if_after = DateTime.subtract!(DateTime.now_utc(), seconds_valid)
result = result =
with {:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret), with false <- is_nil(answer_data),
{:ok, data} <- MessageEncryptor.decrypt(answer_data, secret, sign_secret),
%{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do %{at: at, answer_data: answer_md5} <- :erlang.binary_to_term(data) do
try do try do
if DateTime.before?(at, valid_if_after), if DateTime.before?(at, valid_if_after),

View file

@ -1,17 +1,20 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.CaptchaTest do defmodule Pleroma.CaptchaTest do
use ExUnit.Case use Pleroma.DataCase
import Tesla.Mock import Tesla.Mock
alias Pleroma.Captcha
alias Pleroma.Captcha.Kocaptcha alias Pleroma.Captcha.Kocaptcha
alias Pleroma.Captcha.Native alias Pleroma.Captcha.Native
@ets_options [:ordered_set, :private, :named_table, {:read_concurrency, true}] @ets_options [:ordered_set, :private, :named_table, {:read_concurrency, true}]
clear_config([Pleroma.Captcha, :enabled])
describe "Kocaptcha" do describe "Kocaptcha" do
setup do setup do
ets_name = Kocaptcha.Ets ets_name = Kocaptcha.Ets
@ -31,17 +34,18 @@ defmodule Pleroma.CaptchaTest do
test "new and validate" do test "new and validate" do
new = Kocaptcha.new() new = Kocaptcha.new()
assert new[:type] == :kocaptcha
assert new[:token] == "afa1815e14e29355e6c8f6b143a39fa2"
assert new[:url] == token = "afa1815e14e29355e6c8f6b143a39fa2"
"https://captcha.kotobank.ch/captchas/afa1815e14e29355e6c8f6b143a39fa2.png" url = "https://captcha.kotobank.ch/captchas/afa1815e14e29355e6c8f6b143a39fa2.png"
assert Kocaptcha.validate( assert %{
new[:token], answer_data: answer,
"7oEy8c", token: ^token,
new[:answer_data] url: ^url,
) == :ok type: :kocaptcha
} = new
assert Kocaptcha.validate(token, "7oEy8c", answer) == :ok
end end
end end
@ -61,4 +65,52 @@ test "new and validate" do
assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar") assert {:error, "Invalid CAPTCHA"} == Native.validate(token, answer, answer <> "foobar")
end end
end end
describe "Captcha Wrapper" do
test "validate" do
Pleroma.Config.put([Pleroma.Captcha, :enabled], true)
new = Captcha.new()
assert %{
answer_data: answer,
token: token
} = new
assert is_binary(answer)
assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
end
test "doesn't validate invalid answer" do
Pleroma.Config.put([Pleroma.Captcha, :enabled], true)
new = Captcha.new()
assert %{
answer_data: answer,
token: token
} = new
assert is_binary(answer)
assert {:error, "Invalid answer data"} =
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer <> "foobar")
end
test "nil answer_data" do
Pleroma.Config.put([Pleroma.Captcha, :enabled], true)
new = Captcha.new()
assert %{
answer_data: answer,
token: token
} = new
assert is_binary(answer)
assert {:error, "Invalid answer data"} =
Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", nil)
end
end
end end

View file

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Captcha.Mock do defmodule Pleroma.Captcha.Mock do
@ -7,8 +7,17 @@ defmodule Pleroma.Captcha.Mock do
@behaviour Service @behaviour Service
@impl Service @impl Service
def new, do: %{type: :mock} def new,
do: %{
type: :mock,
token: "afa1815e14e29355e6c8f6b143a39fa2",
answer_data: "63615261b77f5354fb8c4e4986477555",
url: "https://example.org/captcha.png"
}
@impl Service @impl Service
def validate(_token, _captcha, _data), do: :ok def validate(_token, captcha, captcha) when not is_nil(captcha), do: :ok
def validate(_token, captcha, answer),
do: {:error, "Invalid CAPTCHA captcha: #{inspect(captcha)} ; answer: #{inspect(answer)}"}
end end