From 3a753312c1033f6373e3e216398cc01ada68a429 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 14 Feb 2020 09:22:17 +0100 Subject: [PATCH] Validate Date header in HTTPSignatures Signed-off-by: Thomas Citharel --- lib/web/plugs/http_signatures.ex | 14 ++++++- test/web/plugs/http_signatures_test.exs | 52 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/web/plugs/http_signatures_test.exs diff --git a/lib/web/plugs/http_signatures.ex b/lib/web/plugs/http_signatures.ex index fa4ae1fbc..80333a782 100644 --- a/lib/web/plugs/http_signatures.ex +++ b/lib/web/plugs/http_signatures.ex @@ -43,7 +43,8 @@ defmodule Mobilizon.Web.Plugs.HTTPSignatures do signature_valid = HTTPSignatures.validate_conn(conn) Logger.debug("Is signature valid ? #{inspect(signature_valid)}") - assign(conn, :valid_signature, signature_valid) + date_valid = date_valid?(conn) + assign(conn, :valid_signature, signature_valid && date_valid) else Logger.debug("No signature header!") conn @@ -53,4 +54,15 @@ defmodule Mobilizon.Web.Plugs.HTTPSignatures do conn end end + + @spec date_valid?(Plug.Conn.t()) :: boolean() + defp date_valid?(conn) do + with [date | _] <- get_req_header(conn, "date") || [""], + {:ok, date} <- Timex.parse(date, "{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT") do + Timex.diff(date, DateTime.utc_now(), :hours) <= 12 && + Timex.diff(date, DateTime.utc_now(), :hours) >= -12 + else + _ -> false + end + end end diff --git a/test/web/plugs/http_signatures_test.exs b/test/web/plugs/http_signatures_test.exs new file mode 100644 index 000000000..581e4419d --- /dev/null +++ b/test/web/plugs/http_signatures_test.exs @@ -0,0 +1,52 @@ +defmodule Mobilizon.Web.Plug.HTTPSignaturesTest do + use Mobilizon.Web.ConnCase + import Mock + + alias Mobilizon.Federation.HTTPSignatures.Signature + alias Mobilizon.Web.Plugs.HTTPSignatures, as: HTTPSignaturesPlug + + test "tests that date window is acceptable" do + date = NaiveDateTime.utc_now() |> Timex.shift(hours: -3) |> Signature.generate_date_header() + + with_mock HTTPSignatures, validate_conn: fn _ -> true end do + conn = + build_conn() + |> put_req_header("signature", "signature") + |> put_req_header("date", date) + |> HTTPSignaturesPlug.call(%{}) + + assert called(HTTPSignatures.validate_conn(:_)) + assert conn.assigns.valid_signature + end + end + + test "tests that date window is not acceptable (already passed)" do + date = NaiveDateTime.utc_now() |> Timex.shift(hours: -30) |> Signature.generate_date_header() + + with_mock HTTPSignatures, validate_conn: fn _ -> true end do + conn = + build_conn() + |> put_req_header("signature", "signature") + |> put_req_header("date", date) + |> HTTPSignaturesPlug.call(%{}) + + refute conn.assigns.valid_signature + assert called(HTTPSignatures.validate_conn(:_)) + end + end + + test "tests that date window is not acceptable (in the future)" do + date = NaiveDateTime.utc_now() |> Timex.shift(hours: 30) |> Signature.generate_date_header() + + with_mock HTTPSignatures, validate_conn: fn _ -> true end do + conn = + build_conn() + |> put_req_header("signature", "signature") + |> put_req_header("date", date) + |> HTTPSignaturesPlug.call(%{}) + + refute conn.assigns.valid_signature + assert called(HTTPSignatures.validate_conn(:_)) + end + end +end