From 219e4bc67ab8e354b263774aca0118332ea48c25 Mon Sep 17 00:00:00 2001 From: Travis Ralston <travpc@gmail.com> Date: Sat, 18 Feb 2023 17:28:07 -0700 Subject: [PATCH] Add config option to prevent serving media from listed homeservers --- CHANGELOG.md | 4 ++++ api/_responses/errors.go | 4 ++++ api/r0/download.go | 6 ++++++ api/r0/thumbnail.go | 6 ++++++ api/unstable/info.go | 6 ++++++ api/unstable/local_copy.go | 6 ++++++ common/config/models_main.go | 3 ++- config.sample.yaml | 12 ++++++++++++ util/config.go | 12 ++++++++++++ 9 files changed, 58 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 999bc9eb..e3f61bf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added + +* Added a `federation.ignoredHosts` config option to block media from individual homeservers. + ### Removed * IPFS support has been removed due to maintenance burden. diff --git a/api/_responses/errors.go b/api/_responses/errors.go index deb93b29..1cee5021 100644 --- a/api/_responses/errors.go +++ b/api/_responses/errors.go @@ -40,6 +40,10 @@ func AuthFailed() *ErrorResponse { return &ErrorResponse{common.ErrCodeUnknownToken, "Authentication Failed", common.ErrCodeUnknownToken} } +func MediaBlocked() *ErrorResponse { + return &ErrorResponse{common.ErrCodeNotFound, "Media blocked or not found", common.ErrCodeForbidden} +} + func GuestAuthFailed() *ErrorResponse { return &ErrorResponse{common.ErrCodeNoGuests, "Guests cannot use this endpoint", common.ErrCodeNoGuests} } diff --git a/api/r0/download.go b/api/r0/download.go index 5b988220..83b9232a 100644 --- a/api/r0/download.go +++ b/api/r0/download.go @@ -8,6 +8,7 @@ import ( "github.com/turt2live/matrix-media-repo/api/_apimeta" "github.com/turt2live/matrix-media-repo/api/_responses" "github.com/turt2live/matrix-media-repo/api/_routers" + "github.com/turt2live/matrix-media-repo/util" "github.com/sirupsen/logrus" "github.com/turt2live/matrix-media-repo/common" @@ -52,6 +53,11 @@ func DownloadMedia(r *http.Request, rctx rcontext.RequestContext, user _apimeta. "allowRemote": downloadRemote, }) + if !util.IsGlobalAdmin(user.UserId) && util.IsHostIgnored(server) { + rctx.Log.Warn("Request blocked due to domain being ignored.") + return _responses.MediaBlocked() + } + streamedMedia, err := download_controller.GetMedia(server, mediaId, downloadRemote, false, rctx) if err != nil { if err == common.ErrMediaNotFound { diff --git a/api/r0/thumbnail.go b/api/r0/thumbnail.go index 7e56131e..86694315 100644 --- a/api/r0/thumbnail.go +++ b/api/r0/thumbnail.go @@ -5,6 +5,7 @@ import ( "github.com/turt2live/matrix-media-repo/api/_apimeta" "github.com/turt2live/matrix-media-repo/api/_responses" "github.com/turt2live/matrix-media-repo/api/_routers" + "github.com/turt2live/matrix-media-repo/util" "net/http" "strconv" @@ -39,6 +40,11 @@ func ThumbnailMedia(r *http.Request, rctx rcontext.RequestContext, user _apimeta "allowRemote": downloadRemote, }) + if !util.IsGlobalAdmin(user.UserId) && util.IsHostIgnored(server) { + rctx.Log.Warn("Request blocked due to domain being ignored.") + return _responses.MediaBlocked() + } + widthStr := r.URL.Query().Get("width") heightStr := r.URL.Query().Get("height") method := r.URL.Query().Get("method") diff --git a/api/unstable/info.go b/api/unstable/info.go index e47542e3..3bdafb24 100644 --- a/api/unstable/info.go +++ b/api/unstable/info.go @@ -12,6 +12,7 @@ import ( "github.com/turt2live/matrix-media-repo/api/_apimeta" "github.com/turt2live/matrix-media-repo/api/_responses" "github.com/turt2live/matrix-media-repo/api/_routers" + "github.com/turt2live/matrix-media-repo/util" "github.com/turt2live/matrix-media-repo/util/stream_util" "github.com/disintegration/imaging" @@ -73,6 +74,11 @@ func MediaInfo(r *http.Request, rctx rcontext.RequestContext, user _apimeta.User "allowRemote": downloadRemote, }) + if !util.IsGlobalAdmin(user.UserId) && util.IsHostIgnored(server) { + rctx.Log.Warn("Request blocked due to domain being ignored.") + return _responses.MediaBlocked() + } + streamedMedia, err := download_controller.GetMedia(server, mediaId, downloadRemote, true, rctx) if err != nil { if err == common.ErrMediaNotFound { diff --git a/api/unstable/local_copy.go b/api/unstable/local_copy.go index 74166e60..fa5a1f03 100644 --- a/api/unstable/local_copy.go +++ b/api/unstable/local_copy.go @@ -5,6 +5,7 @@ import ( "github.com/turt2live/matrix-media-repo/api/_apimeta" "github.com/turt2live/matrix-media-repo/api/_responses" "github.com/turt2live/matrix-media-repo/api/_routers" + "github.com/turt2live/matrix-media-repo/util" "github.com/turt2live/matrix-media-repo/util/stream_util" "net/http" @@ -42,6 +43,11 @@ func LocalCopy(r *http.Request, rctx rcontext.RequestContext, user _apimeta.User "allowRemote": downloadRemote, }) + if !util.IsGlobalAdmin(user.UserId) && util.IsHostIgnored(server) { + rctx.Log.Warn("Request blocked due to domain being ignored.") + return _responses.MediaBlocked() + } + // TODO: There's a lot of room for improvement here. Instead of re-uploading media, we should just update the DB. streamedMedia, err := download_controller.GetMedia(server, mediaId, downloadRemote, true, rctx) diff --git a/common/config/models_main.go b/common/config/models_main.go index bde7479d..d8f5948a 100644 --- a/common/config/models_main.go +++ b/common/config/models_main.go @@ -64,7 +64,8 @@ type SharedSecretConfig struct { } type FederationConfig struct { - BackoffAt int `yaml:"backoffAt"` + BackoffAt int `yaml:"backoffAt"` + IgnoredHosts []string `yaml:"ignoredHosts,flow"` } type PluginConfig struct { diff --git a/config.sample.yaml b/config.sample.yaml index 9837491e..e3570bb4 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -41,6 +41,18 @@ federation: # the remote server do not count towards this. backoffAt: 20 + # The domains the media repo should never serve media for. Existing media already stored from + # these domains will remain, however will not be downloadable without a data export. Media + # repo administrators will bypass this check. Admin APIs will still work for media on these + # domains. + # + # This will not prevent the listed domains from accessing media on this media repo - it only + # stops users on *this* media repo from accessing media originally uploaded to the listed domains. + # + # Note: Adding domains controlled by the media repo itself to this list is not advisable. + ignoredHosts: + - example.org + # The database configuration for the media repository # Do NOT put your homeserver's existing database credentials here. Create a new database and # user instead. Using the same server is fine, just not the same username and database. diff --git a/util/config.go b/util/config.go index 18bd40e1..306495da 100644 --- a/util/config.go +++ b/util/config.go @@ -1,6 +1,8 @@ package util import ( + "strings" + "github.com/turt2live/matrix-media-repo/common/config" ) @@ -18,3 +20,13 @@ func IsGlobalAdmin(userId string) bool { return false } + +func IsHostIgnored(serverName string) bool { + serverName = strings.ToLower(serverName) + for _, host := range config.Get().Federation.IgnoredHosts { + if strings.ToLower(host) == serverName { + return true + } + } + return false +} -- GitLab