aboutsummaryrefslogtreecommitdiff
path: root/federationapi/routing/routing.go
diff options
context:
space:
mode:
Diffstat (limited to 'federationapi/routing/routing.go')
-rw-r--r--federationapi/routing/routing.go118
1 files changed, 93 insertions, 25 deletions
diff --git a/federationapi/routing/routing.go b/federationapi/routing/routing.go
index 51adc279..9f95ed07 100644
--- a/federationapi/routing/routing.go
+++ b/federationapi/routing/routing.go
@@ -18,10 +18,14 @@ import (
"context"
"fmt"
"net/http"
+ "sync"
+ "time"
+ "github.com/getsentry/sentry-go"
"github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
+ fedInternal "github.com/matrix-org/dendrite/federationapi/internal"
"github.com/matrix-org/dendrite/federationapi/producers"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/httputil"
@@ -48,11 +52,11 @@ func Setup(
fedMux, keyMux, wkMux *mux.Router,
cfg *config.FederationAPI,
rsAPI roomserverAPI.FederationRoomserverAPI,
- fsAPI federationAPI.FederationInternalAPI,
+ fsAPI *fedInternal.FederationInternalAPI,
keys gomatrixserverlib.JSONVerifier,
federation *gomatrixserverlib.FederationClient,
userAPI userapi.FederationUserAPI,
- keyAPI keyserverAPI.KeyInternalAPI,
+ keyAPI keyserverAPI.FederationKeyAPI,
mscCfg *config.MSCs,
servers federationAPI.ServersInRoomProvider,
producer *producers.SyncAPIProducer,
@@ -65,7 +69,7 @@ func Setup(
v1fedmux := fedMux.PathPrefix("/v1").Subrouter()
v2fedmux := fedMux.PathPrefix("/v2").Subrouter()
- wakeup := &httputil.FederationWakeups{
+ wakeup := &FederationWakeups{
FsAPI: fsAPI,
}
@@ -119,7 +123,7 @@ func Setup(
v2keysmux.Handle("/query/{serverName}/{keyID}", notaryKeys).Methods(http.MethodGet)
mu := internal.NewMutexByRoom()
- v1fedmux.Handle("/send/{txnID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send/{txnID}", MakeFedAPI(
"federation_send", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return Send(
@@ -129,7 +133,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v1fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -145,7 +149,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v2fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/invite/{roomID}/{eventID}", MakeFedAPI(
"federation_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -167,7 +171,7 @@ func Setup(
},
)).Methods(http.MethodPost, http.MethodOptions)
- v1fedmux.Handle("/exchange_third_party_invite/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/exchange_third_party_invite/{roomID}", MakeFedAPI(
"exchange_third_party_invite", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return ExchangeThirdPartyInvite(
@@ -176,7 +180,7 @@ func Setup(
},
)).Methods(http.MethodPut, http.MethodOptions)
- v1fedmux.Handle("/event/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/event/{eventID}", MakeFedAPI(
"federation_get_event", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetEvent(
@@ -185,7 +189,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/state/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/state/{roomID}", MakeFedAPI(
"federation_get_state", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -200,7 +204,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/state_ids/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/state_ids/{roomID}", MakeFedAPI(
"federation_get_state_ids", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -215,7 +219,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/event_auth/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/event_auth/{roomID}/{eventID}", MakeFedAPI(
"federation_get_event_auth", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -230,7 +234,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/query/directory", httputil.MakeFedAPI(
+ v1fedmux.Handle("/query/directory", MakeFedAPI(
"federation_query_room_alias", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return RoomAliasToID(
@@ -239,7 +243,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/query/profile", httputil.MakeFedAPI(
+ v1fedmux.Handle("/query/profile", MakeFedAPI(
"federation_query_profile", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetProfile(
@@ -248,7 +252,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/user/devices/{userID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/devices/{userID}", MakeFedAPI(
"federation_user_devices", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return GetUserDevices(
@@ -258,7 +262,7 @@ func Setup(
)).Methods(http.MethodGet)
if mscCfg.Enabled("msc2444") {
- v1fedmux.Handle("/peek/{roomID}/{peekID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/peek/{roomID}/{peekID}", MakeFedAPI(
"federation_peek", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -289,7 +293,7 @@ func Setup(
)).Methods(http.MethodPut, http.MethodDelete)
}
- v1fedmux.Handle("/make_join/{roomID}/{userID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/make_join/{roomID}/{userID}", MakeFedAPI(
"federation_make_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -320,7 +324,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -352,7 +356,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v2fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/send_join/{roomID}/{eventID}", MakeFedAPI(
"federation_send_join", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -369,7 +373,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v1fedmux.Handle("/make_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/make_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_make_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -386,7 +390,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -418,7 +422,7 @@ func Setup(
},
)).Methods(http.MethodPut)
- v2fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI(
+ v2fedmux.Handle("/send_leave/{roomID}/{eventID}", MakeFedAPI(
"federation_send_leave", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -442,7 +446,7 @@ func Setup(
},
)).Methods(http.MethodGet)
- v1fedmux.Handle("/get_missing_events/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/get_missing_events/{roomID}", MakeFedAPI(
"federation_get_missing_events", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -455,7 +459,7 @@ func Setup(
},
)).Methods(http.MethodPost)
- v1fedmux.Handle("/backfill/{roomID}", httputil.MakeFedAPI(
+ v1fedmux.Handle("/backfill/{roomID}", MakeFedAPI(
"federation_backfill", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) {
@@ -474,14 +478,14 @@ func Setup(
}),
).Methods(http.MethodGet, http.MethodPost)
- v1fedmux.Handle("/user/keys/claim", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/keys/claim", MakeFedAPI(
"federation_keys_claim", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return ClaimOneTimeKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
},
)).Methods(http.MethodPost)
- v1fedmux.Handle("/user/keys/query", httputil.MakeFedAPI(
+ v1fedmux.Handle("/user/keys/query", MakeFedAPI(
"federation_keys_query", cfg.Matrix.ServerName, keys, wakeup,
func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse {
return QueryDeviceKeys(httpReq, request, keyAPI, cfg.Matrix.ServerName)
@@ -518,3 +522,67 @@ func ErrorIfLocalServerNotInRoom(
}
return nil
}
+
+// MakeFedAPI makes an http.Handler that checks matrix federation authentication.
+func MakeFedAPI(
+ metricsName string,
+ serverName gomatrixserverlib.ServerName,
+ keyRing gomatrixserverlib.JSONVerifier,
+ wakeup *FederationWakeups,
+ f func(*http.Request, *gomatrixserverlib.FederationRequest, map[string]string) util.JSONResponse,
+) http.Handler {
+ h := func(req *http.Request) util.JSONResponse {
+ fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
+ req, time.Now(), serverName, keyRing,
+ )
+ if fedReq == nil {
+ return errResp
+ }
+ // add the user to Sentry, if enabled
+ hub := sentry.GetHubFromContext(req.Context())
+ if hub != nil {
+ hub.Scope().SetTag("origin", string(fedReq.Origin()))
+ hub.Scope().SetTag("uri", fedReq.RequestURI())
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ if hub != nil {
+ hub.CaptureException(fmt.Errorf("%s panicked", req.URL.Path))
+ }
+ // re-panic to return the 500
+ panic(r)
+ }
+ }()
+ go wakeup.Wakeup(req.Context(), fedReq.Origin())
+ vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
+ if err != nil {
+ return util.MatrixErrorResponse(400, "M_UNRECOGNISED", "badly encoded query params")
+ }
+
+ jsonRes := f(req, fedReq, vars)
+ // do not log 4xx as errors as they are client fails, not server fails
+ if hub != nil && jsonRes.Code >= 500 {
+ hub.Scope().SetExtra("response", jsonRes)
+ hub.CaptureException(fmt.Errorf("%s returned HTTP %d", req.URL.Path, jsonRes.Code))
+ }
+ return jsonRes
+ }
+ return httputil.MakeExternalAPI(metricsName, h)
+}
+
+type FederationWakeups struct {
+ FsAPI *fedInternal.FederationInternalAPI
+ origins sync.Map
+}
+
+func (f *FederationWakeups) Wakeup(ctx context.Context, origin gomatrixserverlib.ServerName) {
+ key, keyok := f.origins.Load(origin)
+ if keyok {
+ lastTime, ok := key.(time.Time)
+ if ok && time.Since(lastTime) < time.Minute {
+ return
+ }
+ }
+ f.FsAPI.MarkServersAlive([]gomatrixserverlib.ServerName{origin})
+ f.origins.Store(origin, time.Now())
+}