From 3da9fe3934483b998963deb253743c4ca89f231f Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sat, 10 Nov 2018 17:24:30 -0700
Subject: [PATCH] Send the requesting user's IP address to the homeserver

This is the best fix we can do within our constraints. Fixes https://github.com/turt2live/matrix-media-repo/issues/88
---
 src/github.com/turt2live/matrix-media-repo/api/auth.go    | 4 ++--
 .../turt2live/matrix-media-repo/api/custom/quarantine.go  | 4 ++--
 .../turt2live/matrix-media-repo/matrix/admin.go           | 8 ++++----
 src/github.com/turt2live/matrix-media-repo/matrix/auth.go | 4 ++--
 .../turt2live/matrix-media-repo/matrix/client_server.go   | 6 +++++-
 5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/src/github.com/turt2live/matrix-media-repo/api/auth.go b/src/github.com/turt2live/matrix-media-repo/api/auth.go
index 0bca4171..57fb5701 100644
--- a/src/github.com/turt2live/matrix-media-repo/api/auth.go
+++ b/src/github.com/turt2live/matrix-media-repo/api/auth.go
@@ -17,7 +17,7 @@ func AccessTokenRequiredRoute(next func(r *http.Request, log *logrus.Entry, user
 	return func(r *http.Request, log *logrus.Entry) interface{} {
 		accessToken := util.GetAccessTokenFromRequest(r)
 		appserviceUserId := util.GetAppserviceUserIdFromRequest(r)
-		userId, err := matrix.GetUserIdFromToken(r.Context(), r.Host, accessToken, appserviceUserId)
+		userId, err := matrix.GetUserIdFromToken(r.Context(), r.Host, accessToken, appserviceUserId, r.RemoteAddr)
 		if err != nil || userId == "" {
 			if err != nil && err != matrix.ErrNoToken {
 				log.Error("Error verifying token: ", err)
@@ -37,7 +37,7 @@ func AccessTokenOptionalRoute(next func(r *http.Request, log *logrus.Entry, user
 	return func(r *http.Request, log *logrus.Entry) interface{} {
 		accessToken := util.GetAccessTokenFromRequest(r)
 		appserviceUserId := util.GetAppserviceUserIdFromRequest(r)
-		userId, err := matrix.GetUserIdFromToken(r.Context(), r.Host, accessToken, appserviceUserId)
+		userId, err := matrix.GetUserIdFromToken(r.Context(), r.Host, accessToken, appserviceUserId, r.RemoteAddr)
 		if err != nil {
 			if err != matrix.ErrNoToken {
 				log.Error("Error verifying token: ", err)
diff --git a/src/github.com/turt2live/matrix-media-repo/api/custom/quarantine.go b/src/github.com/turt2live/matrix-media-repo/api/custom/quarantine.go
index 627a1c12..a1cfff12 100644
--- a/src/github.com/turt2live/matrix-media-repo/api/custom/quarantine.go
+++ b/src/github.com/turt2live/matrix-media-repo/api/custom/quarantine.go
@@ -38,7 +38,7 @@ func QuarantineRoomMedia(r *http.Request, log *logrus.Entry, user api.UserInfo)
 		"localAdmin": isLocalAdmin,
 	})
 
-	allMedia, err := matrix.ListMedia(r.Context(), r.Host, user.AccessToken, roomId)
+	allMedia, err := matrix.ListMedia(r.Context(), r.Host, user.AccessToken, roomId, r.RemoteAddr)
 	if err != nil {
 		log.Error("Error while listing media in the room: " + err.Error())
 		return api.InternalServerError("error retrieving media in room")
@@ -158,7 +158,7 @@ func getQuarantineRequestInfo(r *http.Request, log *logrus.Entry, user api.UserI
 	var err error
 	if !isGlobalAdmin {
 		if config.Get().Quarantine.AllowLocalAdmins {
-			isLocalAdmin, err = matrix.IsUserAdmin(r.Context(), r.Host, user.AccessToken)
+			isLocalAdmin, err = matrix.IsUserAdmin(r.Context(), r.Host, user.AccessToken, r.RemoteAddr)
 			if err != nil {
 				log.Error("Error verifying local admin: " + err.Error())
 				canQuarantine = false
diff --git a/src/github.com/turt2live/matrix-media-repo/matrix/admin.go b/src/github.com/turt2live/matrix-media-repo/matrix/admin.go
index f5f2104c..d58dc160 100644
--- a/src/github.com/turt2live/matrix-media-repo/matrix/admin.go
+++ b/src/github.com/turt2live/matrix-media-repo/matrix/admin.go
@@ -5,7 +5,7 @@ import (
 	"time"
 )
 
-func IsUserAdmin(ctx context.Context, serverName string, accessToken string) (bool, error) {
+func IsUserAdmin(ctx context.Context, serverName string, accessToken string, ipAddr string) (bool, error) {
 	fakeUser := "@media.repo.admin.check:" + serverName
 	hs, cb := getBreakerAndConfig(serverName)
 
@@ -15,7 +15,7 @@ func IsUserAdmin(ctx context.Context, serverName string, accessToken string) (bo
 
 		response := &whoisResponse{}
 		url := makeUrl(hs.ClientServerApi, "/_matrix/client/r0/admin/whois/", fakeUser)
-		err := doRequest("GET", url, nil, response, accessToken)
+		err := doRequest("GET", url, nil, response, accessToken, ipAddr)
 		if err != nil {
 			err, replyError = filterError(err)
 			return err
@@ -28,14 +28,14 @@ func IsUserAdmin(ctx context.Context, serverName string, accessToken string) (bo
 	return isAdmin, replyError
 }
 
-func ListMedia(ctx context.Context, serverName string, accessToken string, roomId string) (*mediaListResponse, error) {
+func ListMedia(ctx context.Context, serverName string, accessToken string, roomId string, ipAddr string) (*mediaListResponse, error) {
 	hs, cb := getBreakerAndConfig(serverName)
 
 	response := &mediaListResponse{}
 	var replyError error
 	replyError = cb.CallContext(ctx, func() error {
 		url := makeUrl(hs.ClientServerApi, "/_matrix/client/r0/admin/room/", roomId, "/media")
-		err := doRequest("GET", url, nil, response, accessToken)
+		err := doRequest("GET", url, nil, response, accessToken, ipAddr)
 		if err != nil {
 			err, replyError = filterError(err)
 			return err
diff --git a/src/github.com/turt2live/matrix-media-repo/matrix/auth.go b/src/github.com/turt2live/matrix-media-repo/matrix/auth.go
index 74b370d9..2355be23 100644
--- a/src/github.com/turt2live/matrix-media-repo/matrix/auth.go
+++ b/src/github.com/turt2live/matrix-media-repo/matrix/auth.go
@@ -10,7 +10,7 @@ import (
 
 var ErrNoToken = errors.New("Missing access token")
 
-func GetUserIdFromToken(ctx context.Context, serverName string, accessToken string, appserviceUserId string) (string, error) {
+func GetUserIdFromToken(ctx context.Context, serverName string, accessToken string, appserviceUserId string, ipAddr string) (string, error) {
 	if accessToken == "" {
 		return "", ErrNoToken
 	}
@@ -32,7 +32,7 @@ func GetUserIdFromToken(ctx context.Context, serverName string, accessToken stri
 			q.Set(k, v)
 		}
 		target.RawQuery = q.Encode()
-		err := doRequest("GET", target.String(), nil, response, accessToken)
+		err := doRequest("GET", target.String(), nil, response, accessToken, ipAddr)
 		if err != nil {
 			err, replyError = filterError(err)
 			return err
diff --git a/src/github.com/turt2live/matrix-media-repo/matrix/client_server.go b/src/github.com/turt2live/matrix-media-repo/matrix/client_server.go
index c8b9a8cc..85d859ea 100644
--- a/src/github.com/turt2live/matrix-media-repo/matrix/client_server.go
+++ b/src/github.com/turt2live/matrix-media-repo/matrix/client_server.go
@@ -15,7 +15,7 @@ var matrixHttpClient = &http.Client{
 }
 
 // Based in part on https://github.com/matrix-org/gomatrix/blob/072b39f7fa6b40257b4eead8c958d71985c28bdd/client.go#L180-L243
-func doRequest(method string, urlStr string, body interface{}, result interface{}, accessToken string) (error) {
+func doRequest(method string, urlStr string, body interface{}, result interface{}, accessToken string, ipAddr string) (error) {
 	var bodyBytes []byte
 	if body != nil {
 		jsonStr, err := json.Marshal(body)
@@ -35,6 +35,10 @@ func doRequest(method string, urlStr string, body interface{}, result interface{
 	if accessToken != "" {
 		req.Header.Set("Authorization", "Bearer "+accessToken)
 	}
+	if ipAddr != "" {
+		req.Header.Set("X-Forwarded-For", ipAddr)
+		req.Header.Set("X-Real-IP", ipAddr)
+	}
 
 	res, err := matrixHttpClient.Do(req)
 	if res != nil {
-- 
GitLab