Browse Source

Add mediaproxy whitelist capability

tags/v1.1.4
Mark Felder 5 years ago
parent
commit
24c3e2db2c
4 changed files with 43 additions and 20 deletions
  1. +2
    -1
      config/config.exs
  2. +1
    -0
      docs/config.md
  3. +31
    -19
      lib/pleroma/web/media_proxy/media_proxy.ex
  4. +9
    -0
      test/media_proxy_test.exs

+ 2
- 1
config/config.exs View File

@@ -326,7 +326,8 @@ config :pleroma, :media_proxy,
follow_redirect: true,
pool: :media
]
]
],
whitelist: []

config :pleroma, :chat, enabled: true



+ 1
- 0
docs/config.md View File

@@ -205,6 +205,7 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i
* `enabled`: Enables proxying of remote media to the instance’s proxy
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
* `whitelist`: List of domains to bypass the mediaproxy

## :gopher
* `enabled`: Enables the gopher interface


+ 31
- 19
lib/pleroma/web/media_proxy/media_proxy.ex View File

@@ -13,32 +13,44 @@ defmodule Pleroma.Web.MediaProxy do

def url(url) do
config = Application.get_env(:pleroma, :media_proxy, [])
domain = URI.parse(url).host

if !Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) do
url
else
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]

# Must preserve `%2F` for compatibility with S3
# https://git.pleroma.social/pleroma/pleroma/issues/580
replacement = get_replacement(url, ":2F:")

# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
base64 =
cond do
!Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) ->
url
|> String.replace("%2F", replacement)
|> URI.decode()
|> URI.encode()
|> String.replace(replacement, "%2F")
|> Base.url_encode64(@base64_opts)

sig = :crypto.hmac(:sha, secret, base64)
sig64 = sig |> Base.url_encode64(@base64_opts)
Enum.any?(Pleroma.Config.get([:media_proxy, :whitelist]), fn pattern ->
String.equivalent?(domain, pattern)
end) ->
url

build_url(sig64, base64, filename(url))
true ->
encode_url(url)
end
end

def encode_url(url) do
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]

# Must preserve `%2F` for compatibility with S3
# https://git.pleroma.social/pleroma/pleroma/issues/580
replacement = get_replacement(url, ":2F:")

# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
base64 =
url
|> String.replace("%2F", replacement)
|> URI.decode()
|> URI.encode()
|> String.replace(replacement, "%2F")
|> Base.url_encode64(@base64_opts)

sig = :crypto.hmac(:sha, secret, base64)
sig64 = sig |> Base.url_encode64(@base64_opts)

build_url(sig64, base64, filename(url))
end

def decode_url(sig, url) do
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
sig = Base.url_decode64!(sig, @base64_opts)


+ 9
- 0
test/media_proxy_test.exs View File

@@ -177,4 +177,13 @@ defmodule Pleroma.MediaProxyTest do
{:ok, decoded} = decode_url(sig, base64)
decoded
end

test "mediaproxy whitelist" do
Pleroma.Config.put([:media_proxy, :enabled], true)
Pleroma.Config.put([:media_proxy, :whitelist], ["google.com", "feld.me"])
url = "https://feld.me/foo.png"

unencoded = url(url)
assert unencoded == url
end
end

Loading…
Cancel
Save