aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkegsay <kegan@matrix.org>2021-07-09 16:52:31 +0100
committerGitHub <noreply@github.com>2021-07-09 16:52:31 +0100
commit1ed732cc783e079feeaf637e23120b027fb7d70b (patch)
tree89fedefd5cb5205221d234b6585440c9ab90aabb
parentc8408a6387f6d155fe4e0547cbfdde7123832c84 (diff)
Implement /_synapse/admin/v1/register (#1911)
* Implement /_synapse/admin/v1/register This is implemented identically to Synapse, so scripts which work with Synapse should work with Dendrite. ``` Test 27 POST /_synapse/admin/v1/register with shared secret... OK Test 28 POST /_synapse/admin/v1/register admin with shared secret... OK Test 29 POST /_synapse/admin/v1/register with shared secret downcases capitals... OK Test 30 POST /_synapse/admin/v1/register with shared secret disallows symbols... OK ``` Sytest however has `implementation_specific => "synapse"` which stops these tests from running. * Add missing muxes to gobind * Linting
-rw-r--r--build/gobind-pinecone/monolith.go1
-rw-r--r--build/gobind-yggdrasil/monolith.go1
-rw-r--r--clientapi/clientapi.go3
-rw-r--r--clientapi/routing/register.go92
-rw-r--r--clientapi/routing/register_secret.go99
-rw-r--r--clientapi/routing/register_secret_test.go43
-rw-r--r--clientapi/routing/routing.go29
-rw-r--r--cmd/dendrite-demo-libp2p/main.go1
-rw-r--r--cmd/dendrite-demo-pinecone/main.go1
-rw-r--r--cmd/dendrite-demo-yggdrasil/main.go1
-rw-r--r--cmd/dendrite-monolith-server/main.go1
-rw-r--r--cmd/dendrite-polylith-multi/personalities/clientapi.go2
-rw-r--r--cmd/dendritejs-pinecone/main.go1
-rw-r--r--cmd/dendritejs/main.go1
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--setup/base.go3
-rw-r--r--setup/monolith.go4
18 files changed, 220 insertions, 66 deletions
diff --git a/build/gobind-pinecone/monolith.go b/build/gobind-pinecone/monolith.go
index 09af80f6..e30057ed 100644
--- a/build/gobind-pinecone/monolith.go
+++ b/build/gobind-pinecone/monolith.go
@@ -334,6 +334,7 @@ func (m *DendriteMonolith) Start() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
diff --git a/build/gobind-yggdrasil/monolith.go b/build/gobind-yggdrasil/monolith.go
index 5074f6da..33862804 100644
--- a/build/gobind-yggdrasil/monolith.go
+++ b/build/gobind-yggdrasil/monolith.go
@@ -173,6 +173,7 @@ func (m *DendriteMonolith) Start() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
httpRouter := mux.NewRouter()
diff --git a/clientapi/clientapi.go b/clientapi/clientapi.go
index 2c4fa5d6..562d89d2 100644
--- a/clientapi/clientapi.go
+++ b/clientapi/clientapi.go
@@ -35,6 +35,7 @@ import (
// AddPublicRoutes sets up and registers HTTP handlers for the ClientAPI component.
func AddPublicRoutes(
router *mux.Router,
+ synapseAdminRouter *mux.Router,
cfg *config.ClientAPI,
accountsDB accounts.Database,
federation *gomatrixserverlib.FederationClient,
@@ -56,7 +57,7 @@ func AddPublicRoutes(
}
routing.Setup(
- router, cfg, eduInputAPI, rsAPI, asAPI,
+ router, synapseAdminRouter, cfg, eduInputAPI, rsAPI, asAPI,
accountsDB, userAPI, federation,
syncProducer, transactionsCache, fsAPI, keyAPI, extRoomsProvider, mscCfg,
)
diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go
index 52641866..8823a41e 100644
--- a/clientapi/routing/register.go
+++ b/clientapi/routing/register.go
@@ -17,10 +17,7 @@ package routing
import (
"context"
- "crypto/hmac"
- "crypto/sha1"
"encoding/json"
- "errors"
"fmt"
"io/ioutil"
"net/http"
@@ -594,7 +591,6 @@ func handleRegistrationFlow(
accessToken string,
accessTokenErr error,
) util.JSONResponse {
- // TODO: Shared secret registration (create new user scripts)
// TODO: Enable registration config flag
// TODO: Guest account upgrading
@@ -643,20 +639,6 @@ func handleRegistrationFlow(
// Add Recaptcha to the list of completed registration stages
AddCompletedSessionStage(sessionID, authtypes.LoginTypeRecaptcha)
- case authtypes.LoginTypeSharedSecret:
- // Check shared secret against config
- valid, err := isValidMacLogin(cfg, r.Username, r.Password, r.Admin, r.Auth.Mac)
-
- if err != nil {
- util.GetLogger(req.Context()).WithError(err).Error("isValidMacLogin failed")
- return jsonerror.InternalServerError()
- } else if !valid {
- return util.MessageResponse(http.StatusForbidden, "HMAC incorrect")
- }
-
- // Add SharedSecret to the list of completed registration stages
- AddCompletedSessionStage(sessionID, authtypes.LoginTypeSharedSecret)
-
case authtypes.LoginTypeDummy:
// there is nothing to do
// Add Dummy to the list of completed registration stages
@@ -849,49 +831,6 @@ func completeRegistration(
}
}
-// Used for shared secret registration.
-// Checks if the username, password and isAdmin flag matches the given mac.
-func isValidMacLogin(
- cfg *config.ClientAPI,
- username, password string,
- isAdmin bool,
- givenMac []byte,
-) (bool, error) {
- sharedSecret := cfg.RegistrationSharedSecret
-
- // Check that shared secret registration isn't disabled.
- if cfg.RegistrationSharedSecret == "" {
- return false, errors.New("Shared secret registration is disabled")
- }
-
- // Double check that username/password don't contain the HMAC delimiters. We should have
- // already checked this.
- if strings.Contains(username, "\x00") {
- return false, errors.New("Username contains invalid character")
- }
- if strings.Contains(password, "\x00") {
- return false, errors.New("Password contains invalid character")
- }
- if sharedSecret == "" {
- return false, errors.New("Shared secret registration is disabled")
- }
-
- adminString := "notadmin"
- if isAdmin {
- adminString = "admin"
- }
- joined := strings.Join([]string{username, password, adminString}, "\x00")
-
- mac := hmac.New(sha1.New, []byte(sharedSecret))
- _, err := mac.Write([]byte(joined))
- if err != nil {
- return false, err
- }
- expectedMAC := mac.Sum(nil)
-
- return hmac.Equal(givenMac, expectedMAC), nil
-}
-
// checkFlows checks a single completed flow against another required one. If
// one contains at least all of the stages that the other does, checkFlows
// returns true.
@@ -995,3 +934,34 @@ func RegisterAvailable(
},
}
}
+
+func handleSharedSecretRegistration(userAPI userapi.UserInternalAPI, sr *SharedSecretRegistration, req *http.Request) util.JSONResponse {
+ ssrr, err := NewSharedSecretRegistrationRequest(req.Body)
+ if err != nil {
+ return util.JSONResponse{
+ Code: 400,
+ JSON: jsonerror.BadJSON(fmt.Sprintf("malformed json: %s", err)),
+ }
+ }
+ valid, err := sr.IsValidMacLogin(ssrr.Nonce, ssrr.User, ssrr.Password, ssrr.Admin, ssrr.MacBytes)
+ if err != nil {
+ return util.ErrorResponse(err)
+ }
+ if !valid {
+ return util.JSONResponse{
+ Code: 403,
+ JSON: jsonerror.Forbidden("bad mac"),
+ }
+ }
+ // downcase capitals
+ ssrr.User = strings.ToLower(ssrr.User)
+
+ if resErr := validateUsername(ssrr.User); resErr != nil {
+ return *resErr
+ }
+ if resErr := validatePassword(ssrr.Password); resErr != nil {
+ return *resErr
+ }
+ deviceID := "shared_secret_registration"
+ return completeRegistration(req.Context(), userAPI, ssrr.User, ssrr.Password, "", req.RemoteAddr, req.UserAgent(), false, &ssrr.User, &deviceID)
+}
diff --git a/clientapi/routing/register_secret.go b/clientapi/routing/register_secret.go
new file mode 100644
index 00000000..f0436e32
--- /dev/null
+++ b/clientapi/routing/register_secret.go
@@ -0,0 +1,99 @@
+package routing
+
+import (
+ "context"
+ "crypto/hmac"
+ "crypto/sha1"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+ "time"
+
+ "github.com/matrix-org/dendrite/internal"
+ "github.com/matrix-org/util"
+ cache "github.com/patrickmn/go-cache"
+)
+
+type SharedSecretRegistrationRequest struct {
+ User string `json:"username"`
+ Password string `json:"password"`
+ Nonce string `json:"nonce"`
+ MacBytes []byte
+ MacStr string `json:"mac"`
+ Admin bool `json:"admin"`
+}
+
+func NewSharedSecretRegistrationRequest(reader io.ReadCloser) (*SharedSecretRegistrationRequest, error) {
+ defer internal.CloseAndLogIfError(context.Background(), reader, "NewSharedSecretRegistrationRequest: failed to close request body")
+ var ssrr SharedSecretRegistrationRequest
+ err := json.NewDecoder(reader).Decode(&ssrr)
+ if err != nil {
+ return nil, err
+ }
+ ssrr.MacBytes, err = hex.DecodeString(ssrr.MacStr)
+ return &ssrr, err
+}
+
+type SharedSecretRegistration struct {
+ sharedSecret string
+ nonces *cache.Cache
+}
+
+func NewSharedSecretRegistration(sharedSecret string) *SharedSecretRegistration {
+ return &SharedSecretRegistration{
+ sharedSecret: sharedSecret,
+ // nonces live for 5mins, purge every 10mins
+ nonces: cache.New(5*time.Minute, 10*time.Minute),
+ }
+}
+
+func (r *SharedSecretRegistration) GenerateNonce() string {
+ nonce := util.RandomString(16)
+ r.nonces.Set(nonce, true, cache.DefaultExpiration)
+ return nonce
+}
+
+func (r *SharedSecretRegistration) validNonce(nonce string) bool {
+ _, exists := r.nonces.Get(nonce)
+ return exists
+}
+
+func (r *SharedSecretRegistration) IsValidMacLogin(
+ nonce, username, password string,
+ isAdmin bool,
+ givenMac []byte,
+) (bool, error) {
+ // Check that shared secret registration isn't disabled.
+ if r.sharedSecret == "" {
+ return false, errors.New("Shared secret registration is disabled")
+ }
+ if !r.validNonce(nonce) {
+ return false, fmt.Errorf("Incorrect or expired nonce: %s", nonce)
+ }
+
+ // Check that username/password don't contain the HMAC delimiters.
+ if strings.Contains(username, "\x00") {
+ return false, errors.New("Username contains invalid character")
+ }
+ if strings.Contains(password, "\x00") {
+ return false, errors.New("Password contains invalid character")
+ }
+
+ adminString := "notadmin"
+ if isAdmin {
+ adminString = "admin"
+ }
+ joined := strings.Join([]string{nonce, username, password, adminString}, "\x00")
+
+ mac := hmac.New(sha1.New, []byte(r.sharedSecret))
+ _, err := mac.Write([]byte(joined))
+ if err != nil {
+ return false, err
+ }
+ expectedMAC := mac.Sum(nil)
+
+ return hmac.Equal(givenMac, expectedMAC), nil
+}
diff --git a/clientapi/routing/register_secret_test.go b/clientapi/routing/register_secret_test.go
new file mode 100644
index 00000000..e702b215
--- /dev/null
+++ b/clientapi/routing/register_secret_test.go
@@ -0,0 +1,43 @@
+package routing
+
+import (
+ "bytes"
+ "io/ioutil"
+ "testing"
+
+ "github.com/patrickmn/go-cache"
+)
+
+func TestSharedSecretRegister(t *testing.T) {
+ // these values have come from a local synapse instance to ensure compatibility
+ jsonStr := []byte(`{"admin":false,"mac":"f1ba8d37123866fd659b40de4bad9b0f8965c565","nonce":"759f047f312b99ff428b21d581256f8592b8976e58bc1b543972dc6147e529a79657605b52d7becd160ff5137f3de11975684319187e06901955f79e5a6c5a79","password":"wonderland","username":"alice"}`)
+ sharedSecret := "dendritetest"
+
+ req, err := NewSharedSecretRegistrationRequest(ioutil.NopCloser(bytes.NewBuffer(jsonStr)))
+ if err != nil {
+ t.Fatalf("failed to read request: %s", err)
+ }
+
+ r := NewSharedSecretRegistration(sharedSecret)
+
+ // force the nonce to be known
+ r.nonces.Set(req.Nonce, true, cache.DefaultExpiration)
+
+ valid, err := r.IsValidMacLogin(req.Nonce, req.User, req.Password, req.Admin, req.MacBytes)
+ if err != nil {
+ t.Fatalf("failed to check for valid mac: %s", err)
+ }
+ if !valid {
+ t.Errorf("mac login failed, wanted success")
+ }
+
+ // modify the mac so it fails
+ req.MacBytes[0] = 0xff
+ valid, err = r.IsValidMacLogin(req.Nonce, req.User, req.Password, req.Admin, req.MacBytes)
+ if err != nil {
+ t.Fatalf("failed to check for valid mac: %s", err)
+ }
+ if valid {
+ t.Errorf("mac login succeeded, wanted failure")
+ }
+}
diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go
index 9f980e0a..37279e8e 100644
--- a/clientapi/routing/routing.go
+++ b/clientapi/routing/routing.go
@@ -37,6 +37,7 @@ import (
"github.com/matrix-org/dendrite/userapi/storage/accounts"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
+ "github.com/sirupsen/logrus"
)
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
@@ -46,7 +47,7 @@ import (
// applied:
// nolint: gocyclo
func Setup(
- publicAPIMux *mux.Router, cfg *config.ClientAPI,
+ publicAPIMux, synapseAdminRouter *mux.Router, cfg *config.ClientAPI,
eduAPI eduServerAPI.EDUServerInputAPI,
rsAPI roomserverAPI.RoomserverInternalAPI,
asAPI appserviceAPI.AppServiceQueryAPI,
@@ -88,6 +89,32 @@ func Setup(
}),
).Methods(http.MethodGet, http.MethodOptions)
+ if cfg.RegistrationSharedSecret != "" {
+ logrus.Info("Enabling shared secret registration at /_synapse/admin/v1/register")
+ sr := NewSharedSecretRegistration(cfg.RegistrationSharedSecret)
+ synapseAdminRouter.Handle("/admin/v1/register",
+ httputil.MakeExternalAPI("shared_secret_registration", func(req *http.Request) util.JSONResponse {
+ if req.Method == http.MethodGet {
+ return util.JSONResponse{
+ Code: 200,
+ JSON: struct {
+ Nonce string `json:"nonce"`
+ }{
+ Nonce: sr.GenerateNonce(),
+ },
+ }
+ }
+ if req.Method == http.MethodPost {
+ return handleSharedSecretRegistration(userAPI, sr, req)
+ }
+ return util.JSONResponse{
+ Code: http.StatusMethodNotAllowed,
+ JSON: jsonerror.NotFound("unknown method"),
+ }
+ }),
+ ).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
+ }
+
r0mux := publicAPIMux.PathPrefix("/r0").Subrouter()
unstableMux := publicAPIMux.PathPrefix("/unstable").Subrouter()
diff --git a/cmd/dendrite-demo-libp2p/main.go b/cmd/dendrite-demo-libp2p/main.go
index cc7dcf02..6b0e57d8 100644
--- a/cmd/dendrite-demo-libp2p/main.go
+++ b/cmd/dendrite-demo-libp2p/main.go
@@ -197,6 +197,7 @@ func main() {
base.Base.PublicFederationAPIMux,
base.Base.PublicKeyAPIMux,
base.Base.PublicMediaAPIMux,
+ base.Base.SynapseAdminMux,
)
if err := mscs.Enable(&base.Base, &monolith); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
diff --git a/cmd/dendrite-demo-pinecone/main.go b/cmd/dendrite-demo-pinecone/main.go
index 72936e42..2712ed4a 100644
--- a/cmd/dendrite-demo-pinecone/main.go
+++ b/cmd/dendrite-demo-pinecone/main.go
@@ -210,6 +210,7 @@ func main() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
wsUpgrader := websocket.Upgrader{
diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go
index 2d710ae7..abeefbe5 100644
--- a/cmd/dendrite-demo-yggdrasil/main.go
+++ b/cmd/dendrite-demo-yggdrasil/main.go
@@ -154,6 +154,7 @@ func main() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
if err := mscs.Enable(base, &monolith); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go
index ef349505..5efbe856 100644
--- a/cmd/dendrite-monolith-server/main.go
+++ b/cmd/dendrite-monolith-server/main.go
@@ -149,6 +149,7 @@ func main() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
if len(base.Cfg.MSCs.MSCs) > 0 {
diff --git a/cmd/dendrite-polylith-multi/personalities/clientapi.go b/cmd/dendrite-polylith-multi/personalities/clientapi.go
index ec445ceb..5e0c4354 100644
--- a/cmd/dendrite-polylith-multi/personalities/clientapi.go
+++ b/cmd/dendrite-polylith-multi/personalities/clientapi.go
@@ -33,7 +33,7 @@ func ClientAPI(base *setup.BaseDendrite, cfg *config.Dendrite) {
keyAPI := base.KeyServerHTTPClient()
clientapi.AddPublicRoutes(
- base.PublicClientAPIMux, &base.Cfg.ClientAPI, accountDB, federation,
+ base.PublicClientAPIMux, base.SynapseAdminMux, &base.Cfg.ClientAPI, accountDB, federation,
rsAPI, eduInputAPI, asQuery, transactions.New(), fsAPI, userAPI, keyAPI, nil,
&cfg.MSCs,
)
diff --git a/cmd/dendritejs-pinecone/main.go b/cmd/dendritejs-pinecone/main.go
index 433e9bf8..25e49690 100644
--- a/cmd/dendritejs-pinecone/main.go
+++ b/cmd/dendritejs-pinecone/main.go
@@ -215,6 +215,7 @@ func main() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
diff --git a/cmd/dendritejs/main.go b/cmd/dendritejs/main.go
index 7ece94ff..d5a845ae 100644
--- a/cmd/dendritejs/main.go
+++ b/cmd/dendritejs/main.go
@@ -236,6 +236,7 @@ func main() {
base.PublicFederationAPIMux,
base.PublicKeyAPIMux,
base.PublicMediaAPIMux,
+ base.SynapseAdminMux,
)
httpRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
diff --git a/go.mod b/go.mod
index 6e227e6c..eeb4a784 100644
--- a/go.mod
+++ b/go.mod
@@ -39,6 +39,7 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6
github.com/opentracing/opentracing-go v1.2.0
+ github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/pressly/goose v2.7.0+incompatible
github.com/prometheus/client_golang v1.9.0
diff --git a/go.sum b/go.sum
index 6bf4632e..767826e7 100644
--- a/go.sum
+++ b/go.sum
@@ -1256,6 +1256,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
diff --git a/setup/base.go b/setup/base.go
index 6bdeb80f..7b691608 100644
--- a/setup/base.go
+++ b/setup/base.go
@@ -77,6 +77,7 @@ type BaseDendrite struct {
PublicKeyAPIMux *mux.Router
PublicMediaAPIMux *mux.Router
InternalAPIMux *mux.Router
+ SynapseAdminMux *mux.Router
UseHTTPAPIs bool
apiHttpClient *http.Client
httpClient *http.Client
@@ -199,6 +200,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, useHTTPAPIs boo
PublicKeyAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicKeyPathPrefix).Subrouter().UseEncodedPath(),
PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
InternalAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.InternalPathPrefix).Subrouter().UseEncodedPath(),
+ SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix("/_synapse/").Subrouter().UseEncodedPath(),
apiHttpClient: &apiClient,
httpClient: &client,
}
@@ -391,6 +393,7 @@ func (b *BaseDendrite) SetupAndServeHTTP(
externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux)
externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(federationHandler)
}
+ externalRouter.PathPrefix("/_synapse/").Handler(b.SynapseAdminMux)
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.PublicMediaAPIMux)
if internalAddr != NoListener && internalAddr != externalAddr {
diff --git a/setup/monolith.go b/setup/monolith.go
index 235be447..5ceb4ed3 100644
--- a/setup/monolith.go
+++ b/setup/monolith.go
@@ -57,9 +57,9 @@ type Monolith struct {
}
// AddAllPublicRoutes attaches all public paths to the given router
-func (m *Monolith) AddAllPublicRoutes(process *process.ProcessContext, csMux, ssMux, keyMux, mediaMux *mux.Router) {
+func (m *Monolith) AddAllPublicRoutes(process *process.ProcessContext, csMux, ssMux, keyMux, mediaMux, synapseMux *mux.Router) {
clientapi.AddPublicRoutes(
- csMux, &m.Config.ClientAPI, m.AccountDB,
+ csMux, synapseMux, &m.Config.ClientAPI, m.AccountDB,
m.FedClient, m.RoomserverAPI,
m.EDUInternalAPI, m.AppserviceAPI, transactions.New(),
m.FederationSenderAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider,