diff options
Diffstat (limited to 'lib/pleroma')
-rw-r--r-- | lib/pleroma/emoji/pack.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/plugs/http_security_plug.ex | 82 | ||||
-rw-r--r-- | lib/pleroma/user.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/builder.ex | 16 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/side_effects.ex | 7 | ||||
-rw-r--r-- | lib/pleroma/web/admin_api/controllers/admin_api_controller.ex | 9 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/account_view.ex | 12 | ||||
-rw-r--r-- | lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex | 2 |
8 files changed, 95 insertions, 40 deletions
diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index eb7d598c6..14a5185be 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -499,7 +499,7 @@ defmodule Pleroma.Emoji.Pack do if Base.decode16!(sha) == :crypto.hash(:sha256, archive) do {:ok, archive} else - {:error, :imvalid_checksum} + {:error, :invalid_checksum} end end end diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex index 6462797b6..2208d1d6c 100644 --- a/lib/pleroma/plugs/http_security_plug.ex +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -31,7 +31,7 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do {"x-content-type-options", "nosniff"}, {"referrer-policy", referrer_policy}, {"x-download-options", "noopen"}, - {"content-security-policy", csp_string() <> ";"} + {"content-security-policy", csp_string()} ] if report_uri do @@ -43,23 +43,46 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do ] } - headers ++ [{"reply-to", Jason.encode!(report_group)}] + [{"reply-to", Jason.encode!(report_group)} | headers] else headers end end + static_csp_rules = [ + "default-src 'none'", + "base-uri 'self'", + "frame-ancestors 'none'", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "manifest-src 'self'" + ] + + @csp_start [Enum.join(static_csp_rules, ";") <> ";"] + defp csp_string do scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme] static_url = Pleroma.Web.Endpoint.static_url() websocket_url = Pleroma.Web.Endpoint.websocket_url() report_uri = Config.get([:http_security, :report_uri]) - connect_src = "connect-src 'self' #{static_url} #{websocket_url}" + img_src = "img-src 'self' data: blob:" + media_src = "media-src 'self'" + + {img_src, media_src} = + if Config.get([:media_proxy, :enabled]) && + !Config.get([:media_proxy, :proxy_opts, :redirect_on_failure]) do + sources = get_proxy_and_attachment_sources() + {[img_src, sources], [media_src, sources]} + else + {img_src, media_src} + end + + connect_src = ["connect-src 'self' ", static_url, ?\s, websocket_url] connect_src = if Pleroma.Config.get(:env) == :dev do - connect_src <> " http://localhost:3035/" + [connect_src, " http://localhost:3035/"] else connect_src end @@ -71,27 +94,46 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do "script-src 'self'" end - main_part = [ - "default-src 'none'", - "base-uri 'self'", - "frame-ancestors 'none'", - "img-src 'self' data: blob: https:", - "media-src 'self' https:", - "style-src 'self' 'unsafe-inline'", - "font-src 'self'", - "manifest-src 'self'", - connect_src, - script_src - ] + report = if report_uri, do: ["report-uri ", report_uri, ";report-to csp-endpoint"] + insecure = if scheme == "https", do: "upgrade-insecure-requests" + + @csp_start + |> add_csp_param(img_src) + |> add_csp_param(media_src) + |> add_csp_param(connect_src) + |> add_csp_param(script_src) + |> add_csp_param(insecure) + |> add_csp_param(report) + |> :erlang.iolist_to_binary() + end + + defp get_proxy_and_attachment_sources do + media_proxy_whitelist = + Enum.reduce(Config.get([:media_proxy, :whitelist]), [], fn host, acc -> + add_source(acc, host) + end) - report = if report_uri, do: ["report-uri #{report_uri}; report-to csp-endpoint"], else: [] + upload_base_url = + if Config.get([Pleroma.Upload, :base_url]), + do: URI.parse(Config.get([Pleroma.Upload, :base_url])).host - insecure = if scheme == "https", do: ["upgrade-insecure-requests"], else: [] + s3_endpoint = + if Config.get([Pleroma.Upload, :uploader]) == Pleroma.Uploaders.S3, + do: URI.parse(Config.get([Pleroma.Uploaders.S3, :public_endpoint])).host - (main_part ++ report ++ insecure) - |> Enum.join("; ") + [] + |> add_source(upload_base_url) + |> add_source(s3_endpoint) + |> add_source(media_proxy_whitelist) end + defp add_source(iodata, nil), do: iodata + defp add_source(iodata, source), do: [[?\s, source] | iodata] + + defp add_csp_param(csp_iodata, nil), do: csp_iodata + + defp add_csp_param(csp_iodata, param), do: [[param, ?;] | csp_iodata] + def warn_if_disabled do unless Config.get([:http_security, :enabled]) do Logger.warn(" diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 42c4c4e3e..72ee2d58e 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -538,9 +538,10 @@ defmodule Pleroma.User do |> delete_change(:also_known_as) |> unique_constraint(:email) |> validate_format(:email, @email_regex) + |> validate_inclusion(:actor_type, ["Person", "Service"]) end - @spec update_as_admin(%User{}, map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} + @spec update_as_admin(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} def update_as_admin(user, params) do params = Map.put(params, "password_confirmation", params["password"]) changeset = update_as_admin_changeset(user, params) @@ -561,7 +562,7 @@ defmodule Pleroma.User do |> put_change(:password_reset_pending, false) end - @spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} + @spec reset_password(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} def reset_password(%User{} = user, params) do reset_password(user, user, params) end diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 7ece764f5..51b74414a 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do alias Pleroma.Object alias Pleroma.User + alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Visibility @@ -85,15 +86,20 @@ defmodule Pleroma.Web.ActivityPub.Builder do end end + @spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()} def announce(actor, object, options \\ []) do public? = Keyword.get(options, :public, false) - to = [actor.follower_address, object.data["actor"]] to = - if public? do - [Pleroma.Constants.as_public() | to] - else - to + cond do + actor.ap_id == Relay.relay_ap_id() -> + [actor.follower_address] + + public? -> + [actor.follower_address, object.data["actor"], Pleroma.Constants.as_public()] + + true -> + [actor.follower_address, object.data["actor"]] end {:ok, diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 7eae0c52c..fb6275450 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -33,11 +33,14 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do # - Stream out the announce def handle(%{data: %{"type" => "Announce"}} = object, meta) do announced_object = Object.get_by_ap_id(object.data["object"]) + user = User.get_cached_by_ap_id(object.data["actor"]) Utils.add_announce_to_object(object, announced_object) - Notification.create_notifications(object) - ActivityPub.stream_out(object) + if !User.is_internal_user?(user) do + Notification.create_notifications(object) + ActivityPub.stream_out(object) + end {:ok, object, meta} end diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex index 6b1d64a2e..783203c07 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -693,7 +693,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do %{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = params ) do - with {_, user} <- {:user, User.get_cached_by_nickname(nickname)}, + with {_, %User{} = user} <- {:user, User.get_cached_by_nickname(nickname)}, {:ok, _user} <- User.update_as_admin(user, params) do ModerationLog.insert_log(%{ @@ -715,11 +715,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do json(conn, %{status: "success"}) else {:error, changeset} -> - {_, {error, _}} = Enum.at(changeset.errors, 0) - json(conn, %{error: "New password #{error}."}) + errors = Map.new(changeset.errors, fn {key, {error, _}} -> {key, error} end) + + json(conn, %{errors: errors}) _ -> - json(conn, %{error: "Unable to change password."}) + json(conn, %{error: "Unable to update user."}) end end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 45fffaad2..04c419d2f 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -182,12 +182,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do bot = user.actor_type in ["Application", "Service"] emojis = - Enum.map(user.emoji, fn {shortcode, url} -> + Enum.map(user.emoji, fn {shortcode, raw_url} -> + url = MediaProxy.url(raw_url) + %{ - "shortcode" => shortcode, - "url" => url, - "static_url" => url, - "visible_in_picker" => false + shortcode: shortcode, + url: url, + static_url: url, + visible_in_picker: false } end) diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex index 2c53dcde1..d1efdeb5d 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex @@ -106,7 +106,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do |> put_status(:internal_server_error) |> json(%{error: "The requested instance does not support sharing emoji packs"}) - {:error, :imvalid_checksum} -> + {:error, :invalid_checksum} -> conn |> put_status(:internal_server_error) |> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"}) |