1package gomatrixserverlib
2
3import (
4	"context"
5	"database/sql/driver"
6	"encoding/json"
7	"fmt"
8	"io"
9	"net"
10	"strconv"
11	"strings"
12
13	"github.com/matrix-org/util"
14	"github.com/sirupsen/logrus"
15	"github.com/tidwall/gjson"
16)
17
18// A ServerName is the name a matrix homeserver is identified by.
19// It is a DNS name or IP address optionally followed by a port.
20//
21// https://matrix.org/docs/spec/appendices.html#server-name
22type ServerName string
23
24// ParseAndValidateServerName splits a ServerName into a host and port part,
25// and checks that it is a valid server name according to the spec.
26//
27// if there is no explicit port, returns '-1' as the port.
28func ParseAndValidateServerName(serverName ServerName) (host string, port int, valid bool) {
29	// Don't go any further if the server name is an empty string.
30	if len(serverName) == 0 {
31		return
32	}
33
34	host, port = splitServerName(serverName)
35
36	// the host part must be one of:
37	//  - a valid (ascii) dns name
38	//  - an IPv4 address
39	//  - an IPv6 address
40
41	if host[0] == '[' {
42		// must be a valid IPv6 address
43		if host[len(host)-1] != ']' {
44			return
45		}
46		ip := host[1 : len(host)-1]
47		if net.ParseIP(ip) == nil {
48			return
49		}
50		valid = true
51		return
52	}
53
54	// try parsing as an IPv4 address
55	ip := net.ParseIP(host)
56	if ip != nil && ip.To4() != nil {
57		valid = true
58		return
59	}
60
61	// must be a valid DNS Name
62	for _, r := range host {
63		if !isDNSNameChar(r) {
64			return
65		}
66	}
67
68	valid = true
69	return
70}
71
72func isDNSNameChar(r rune) bool {
73	if r >= 'A' && r <= 'Z' {
74		return true
75	}
76	if r >= 'a' && r <= 'z' {
77		return true
78	}
79	if r >= '0' && r <= '9' {
80		return true
81	}
82	if r == '-' || r == '.' {
83		return true
84	}
85	return false
86}
87
88// splitServerName splits a ServerName into host and port, without doing
89// any validation.
90//
91// if there is no explicit port, returns '-1' as the port
92func splitServerName(serverName ServerName) (string, int) {
93	nameStr := string(serverName)
94
95	lastColon := strings.LastIndex(nameStr, ":")
96	if lastColon < 0 {
97		// no colon: no port
98		return nameStr, -1
99	}
100
101	portStr := nameStr[lastColon+1:]
102	port, err := strconv.ParseUint(portStr, 10, 16)
103	if err != nil {
104		// invalid port (possibly an ipv6 host)
105		return nameStr, -1
106	}
107
108	return nameStr[:lastColon], int(port)
109}
110
111// A RespSend is the content of a response to PUT /_matrix/federation/v1/send/{txnID}/
112type RespSend struct {
113	// Map of event ID to the result of processing that event.
114	PDUs map[string]PDUResult `json:"pdus"`
115}
116
117// A PDUResult is the result of processing a matrix room event.
118type PDUResult struct {
119	// If not empty then this is a human readable description of a problem
120	// encountered processing an event.
121	Error string `json:"error,omitempty"`
122}
123
124// A RespStateIDs is the content of a response to GET /_matrix/federation/v1/state_ids/{roomID}/{eventID}
125type RespStateIDs struct {
126	// A list of state event IDs for the state of the room before the requested event.
127	StateEventIDs []string `json:"pdu_ids"`
128	// A list of event IDs needed to authenticate the state events.
129	AuthEventIDs []string `json:"auth_chain_ids"`
130}
131
132// A RespState is the content of a response to GET /_matrix/federation/v1/state/{roomID}/{eventID}
133type RespState struct {
134	// The room version that dictates the format of the state events.
135	roomVersion RoomVersion
136	// A list of events giving the state of the room before the request event.
137	StateEvents []*Event `json:"pdus"`
138	// A list of events needed to authenticate the state events.
139	AuthEvents []*Event `json:"auth_chain"`
140}
141
142// A RespPeek is the content of a response to GET /_matrix/federation/v1/peek/{roomID}/{peekID}
143type RespPeek struct {
144	// How often should we renew the peek?
145	RenewalInterval int64 `json:"renewal_interval"`
146	// A list of events giving the state of the room at the point of the request
147	StateEvents []*Event `json:"state"`
148	// A list of events needed to authenticate the state events.
149	AuthEvents []*Event `json:"auth_chain"`
150	// The room version that we're trying to peek.
151	RoomVersion RoomVersion `json:"room_version"`
152	// The ID of the event whose state snapshot this is - i.e. the
153	// most recent forward extremity in the room.
154	LatestEvent *Event `json:"latest_event"`
155}
156
157// MissingEvents represents a request for missing events.
158// https://matrix.org/docs/spec/server_server/r0.1.3#post-matrix-federation-v1-get-missing-events-roomid
159type MissingEvents struct {
160	// The maximum number of events to retrieve.
161	Limit int `json:"limit"`
162	// The minimum depth of events to retrieve.
163	MinDepth int `json:"min_depth"`
164	// The latest event IDs that the sender already has.
165	EarliestEvents []string `json:"earliest_events"`
166	// The event IDs to retrieve the previous events for.
167	LatestEvents []string `json:"latest_events"`
168}
169
170// A RespMissingEvents is the content of a response to GET /_matrix/federation/v1/get_missing_events/{roomID}
171type RespMissingEvents struct {
172	// The room version that dictates the format of the missing events.
173	roomVersion RoomVersion
174	// The returned set of missing events.
175	Events []*Event `json:"events"`
176}
177
178// RespPublicRooms is the content of a response to GET /_matrix/federation/v1/publicRooms
179type RespPublicRooms struct {
180	// A paginated chunk of public rooms.
181	Chunk []PublicRoom `json:"chunk"`
182	// A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
183	NextBatch string `json:"next_batch,omitempty"`
184	// A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
185	PrevBatch string `json:"prev_batch,omitempty"`
186	// An estimate on the total number of public rooms, if the server has an estimate.
187	TotalRoomCountEstimate int `json:"total_room_count_estimate,omitempty"`
188}
189
190// PublicRoom stores the info of a room returned by
191// GET /_matrix/federation/v1/publicRooms
192type PublicRoom struct {
193	// Aliases of the room. May be empty.
194	Aliases []string `json:"aliases,omitempty"`
195	// The canonical alias of the room, if any.
196	CanonicalAlias string `json:"canonical_alias,omitempty"`
197	// The name of the room, if any.
198	Name string `json:"name,omitempty"`
199	// The number of members joined to the room.
200	JoinedMembersCount int `json:"num_joined_members"`
201	// The ID of the room.
202	RoomID string `json:"room_id"`
203	// The topic of the room, if any.
204	Topic string `json:"topic,omitempty"`
205	// Whether the room may be viewed by guest users without joining.
206	WorldReadable bool `json:"world_readable"`
207	// Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.
208	GuestCanJoin bool `json:"guest_can_join"`
209	// The URL for the room's avatar, if one is set.
210	AvatarURL string `json:"avatar_url,omitempty"`
211}
212
213// A RespEventAuth is the content of a response to GET /_matrix/federation/v1/event_auth/{roomID}/{eventID}
214type RespEventAuth struct {
215	// A list of events needed to authenticate the state events.
216	AuthEvents []*Event `json:"auth_chain"`
217}
218
219type respStateFields struct {
220	StateEvents []*Event `json:"pdus"`
221	AuthEvents  []*Event `json:"auth_chain"`
222}
223
224// RespUserDevices contains a response to /_matrix/federation/v1/user/devices/{userID}
225// https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-user-devices-userid
226type RespUserDevices struct {
227	UserID         string           `json:"user_id"`
228	StreamID       int              `json:"stream_id"`
229	Devices        []RespUserDevice `json:"devices"`
230	MasterKey      *CrossSigningKey `json:"master_key"`
231	SelfSigningKey *CrossSigningKey `json:"self_signing_key"`
232}
233
234// RespUserDevice are embedded in RespUserDevices
235// https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-user-devices-userid
236type RespUserDevice struct {
237	DeviceID    string             `json:"device_id"`
238	DisplayName string             `json:"device_display_name"`
239	Keys        RespUserDeviceKeys `json:"keys"`
240}
241
242// RespUserDeviceKeys are embedded in RespUserDevice
243// https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-user-devices-userid
244type RespUserDeviceKeys struct {
245	UserID     string   `json:"user_id"`
246	DeviceID   string   `json:"device_id"`
247	Algorithms []string `json:"algorithms"`
248	// E.g "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI"
249	Keys map[KeyID]Base64Bytes `json:"keys"`
250	// E.g "@alice:example.com": {
251	//	"ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
252	// }
253	Signatures map[string]map[KeyID]Base64Bytes `json:"signatures"`
254}
255
256// UnmarshalJSON implements json.Unmarshaller
257func (r *RespMissingEvents) UnmarshalJSON(data []byte) error {
258	r.Events = []*Event{}
259	if _, err := r.roomVersion.EventFormat(); err != nil {
260		return err
261	}
262	var intermediate struct {
263		Events []json.RawMessage `json:"events"`
264	}
265	if err := json.Unmarshal(data, &intermediate); err != nil {
266		return err
267	}
268	for _, raw := range intermediate.Events {
269		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
270		if err != nil {
271			return err
272		}
273		r.Events = append(r.Events, event)
274	}
275	return nil
276}
277
278// MarshalJSON implements json.Marshaller
279func (r RespPeek) MarshalJSON() ([]byte, error) {
280	if len(r.StateEvents) == 0 {
281		r.StateEvents = []*Event{}
282	}
283	if len(r.AuthEvents) == 0 {
284		r.AuthEvents = []*Event{}
285	}
286	return json.Marshal(struct {
287		RenewalInterval int64       `json:"renewal_interval"`
288		StateEvents     []*Event    `json:"state"`
289		AuthEvents      []*Event    `json:"auth_chain"`
290		RoomVersion     RoomVersion `json:"room_version"`
291		LatestEvent     *Event      `json:"latest_event"`
292	}{
293		RenewalInterval: r.RenewalInterval,
294		StateEvents:     r.StateEvents,
295		AuthEvents:      r.AuthEvents,
296		RoomVersion:     r.RoomVersion,
297		LatestEvent:     r.LatestEvent,
298	})
299}
300
301// UnmarshalJSON implements json.Unmarshaller
302func (r *RespPeek) UnmarshalJSON(data []byte) error {
303	r.AuthEvents = []*Event{}
304	r.StateEvents = []*Event{}
305	var intermediate struct {
306		RoomVersion     RoomVersion       `json:"room_version"`
307		StateEvents     []json.RawMessage `json:"state"`
308		AuthEvents      []json.RawMessage `json:"auth_chain"`
309		RenewalInterval int64             `json:"renewal_interval"`
310		LatestEvent     json.RawMessage   `json:"latest_event"`
311	}
312	if err := json.Unmarshal(data, &intermediate); err != nil {
313		return fmt.Errorf("RespPeek UnmarshalJSON(intermediate): %w", err)
314	}
315	r.RoomVersion = intermediate.RoomVersion
316	r.RenewalInterval = intermediate.RenewalInterval
317	if _, err := r.RoomVersion.EventFormat(); err != nil {
318		return fmt.Errorf("RespPeek UnmarshalJSON(roomversion): %w", err)
319	}
320	for _, raw := range intermediate.AuthEvents {
321		event, err := NewEventFromUntrustedJSON([]byte(raw), r.RoomVersion)
322		if err != nil {
323			return fmt.Errorf("RespPeek UnmarshalJSON(AuthEvent): %w", err)
324		}
325		r.AuthEvents = append(r.AuthEvents, event)
326	}
327	for _, raw := range intermediate.StateEvents {
328		event, err := NewEventFromUntrustedJSON([]byte(raw), r.RoomVersion)
329		if err != nil {
330			return fmt.Errorf("RespPeek UnmarshalJSON(StateEvent): %w", err)
331		}
332		r.StateEvents = append(r.StateEvents, event)
333	}
334	latestEvent, err := NewEventFromUntrustedJSON([]byte(intermediate.LatestEvent), r.RoomVersion)
335	if err != nil {
336		return fmt.Errorf("RespPeek UnmarshalJSON(StateEvent): %w", err)
337	}
338	r.LatestEvent = latestEvent
339	return nil
340}
341
342// MarshalJSON implements json.Marshaller
343func (r RespState) MarshalJSON() ([]byte, error) {
344	if len(r.StateEvents) == 0 {
345		r.StateEvents = []*Event{}
346	}
347	if len(r.AuthEvents) == 0 {
348		r.AuthEvents = []*Event{}
349	}
350	return json.Marshal(respStateFields{
351		StateEvents: r.StateEvents,
352		AuthEvents:  r.AuthEvents,
353	})
354}
355
356// UnmarshalJSON implements json.Unmarshaller
357func (r *RespState) UnmarshalJSON(data []byte) error {
358	r.AuthEvents = []*Event{}
359	r.StateEvents = []*Event{}
360	if _, err := r.roomVersion.EventFormat(); err != nil {
361		return err
362	}
363	var intermediate struct {
364		StateEvents []json.RawMessage `json:"pdus"`
365		AuthEvents  []json.RawMessage `json:"auth_chain"`
366	}
367	if err := json.Unmarshal(data, &intermediate); err != nil {
368		return err
369	}
370	for _, raw := range intermediate.AuthEvents {
371		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
372		if err != nil {
373			return err
374		}
375		r.AuthEvents = append(r.AuthEvents, event)
376	}
377	for _, raw := range intermediate.StateEvents {
378		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
379		if err != nil {
380			return err
381		}
382		r.StateEvents = append(r.StateEvents, event)
383	}
384	return nil
385}
386
387// Events combines the auth events and the state events and returns
388// them in an order where every event comes after its auth events.
389// Each event will only appear once in the output list.
390// Returns an error if there are missing auth events or if there is
391// a cycle in the auth events.
392func (r RespState) Events() ([]*Event, error) {
393	if len(r.StateEvents) == 0 {
394		r.StateEvents = []*Event{}
395	}
396	if len(r.AuthEvents) == 0 {
397		r.AuthEvents = []*Event{}
398	}
399	eventsByID := map[string]*Event{}
400	// Collect a map of event reference to event
401	for i := range r.StateEvents {
402		eventsByID[r.StateEvents[i].EventID()] = r.StateEvents[i]
403	}
404	for i := range r.AuthEvents {
405		eventsByID[r.AuthEvents[i].EventID()] = r.AuthEvents[i]
406	}
407
408	queued := map[*Event]bool{}
409	outputted := map[*Event]bool{}
410	var result []*Event
411	for _, event := range eventsByID {
412		if outputted[event] {
413			// If we've already written the event then we can skip it.
414			continue
415		}
416
417		// The code below does a depth first scan through the auth events
418		// looking for events that can be appended to the output.
419
420		// We use an explicit stack rather than using recursion so
421		// that we can check we aren't creating cycles.
422		stack := []*Event{event}
423
424	LoopProcessTopOfStack:
425		for len(stack) > 0 {
426			top := stack[len(stack)-1]
427			// Check if we can output the top of the stack.
428			// We can output it if we have outputted all of its auth_events.
429			for _, ref := range top.AuthEvents() {
430				authEvent := eventsByID[ref.EventID]
431				if authEvent == nil {
432					continue
433				}
434				if outputted[authEvent] {
435					continue
436				}
437				if queued[authEvent] {
438					return nil, fmt.Errorf(
439						"gomatrixserverlib: auth event cycle for ID %q",
440						ref.EventID,
441					)
442				}
443				// If we haven't visited the auth event yet then we need to
444				// process it before processing the event currently on top of
445				// the stack.
446				stack = append(stack, authEvent)
447				queued[authEvent] = true
448				continue LoopProcessTopOfStack
449			}
450			// If we've processed all the auth events for the event on top of
451			// the stack then we can append it to the result and try processing
452			// the item below it in the stack.
453			result = append(result, top)
454			outputted[top] = true
455			stack = stack[:len(stack)-1]
456		}
457	}
458
459	return result, nil
460}
461
462// Check that a response to /state is valid. This function mutates
463// the RespState to remove any events from AuthEvents or StateEvents
464// that do not have valid signatures.
465func (r *RespState) Check(ctx context.Context, keyRing JSONVerifier, missingAuth AuthChainProvider) error {
466	logger := util.GetLogger(ctx)
467	var allEvents []*Event
468	for _, event := range r.AuthEvents {
469		if event.StateKey() == nil {
470			return fmt.Errorf("gomatrixserverlib: event %q does not have a state key", event.EventID())
471		}
472		allEvents = append(allEvents, event)
473	}
474
475	stateTuples := map[StateKeyTuple]bool{}
476	for _, event := range r.StateEvents {
477		if event.StateKey() == nil {
478			return fmt.Errorf("gomatrixserverlib: event %q does not have a state key", event.EventID())
479		}
480		stateTuple := StateKeyTuple{event.Type(), *event.StateKey()}
481		if stateTuples[stateTuple] {
482			return fmt.Errorf(
483				"gomatrixserverlib: duplicate state key tuple (%q, %q)",
484				event.Type(), *event.StateKey(),
485			)
486		}
487		stateTuples[stateTuple] = true
488		allEvents = append(allEvents, event)
489	}
490
491	// Check if the events pass signature checks.
492	logger.Infof("Checking event signatures for %d events of room state", len(allEvents))
493	errors := VerifyAllEventSignatures(ctx, allEvents, keyRing)
494	if len(errors) != len(allEvents) {
495		return fmt.Errorf("expected %d errors but got %d", len(allEvents), len(errors))
496	}
497
498	// Work out which events failed the signature checks.
499	failures := map[string]error{}
500	for i, e := range allEvents {
501		if errors[i] != nil {
502			logrus.WithError(errors[i]).Errorf("Signature validation failed for event %q", e.EventID())
503			failures[e.EventID()] = errors[i]
504		}
505	}
506
507	// Collect a map of event reference to event.
508	eventsByID := map[string]*Event{}
509	for i := range allEvents {
510		if _, ok := failures[allEvents[i].EventID()]; !ok {
511			eventsByID[allEvents[i].EventID()] = allEvents[i]
512		}
513	}
514
515	// Check whether the events are allowed by the auth rules.
516	for _, event := range allEvents {
517		if err := checkAllowedByAuthEvents(event, eventsByID, missingAuth); err != nil {
518			logrus.WithError(err).Errorf("Event %q is not allowed by its auth events", event.EventID())
519			failures[event.EventID()] = err
520		}
521	}
522
523	// For all of the events that weren't verified, remove them
524	// from the RespState. This way they won't be passed onwards.
525	if f := len(failures); f > 0 {
526		logger.Warnf("Discarding %d auth/state event(s) due to invalid signatures", f)
527
528		for i := 0; i < len(r.AuthEvents); i++ {
529			if _, ok := failures[r.AuthEvents[i].EventID()]; ok {
530				r.AuthEvents = append(r.AuthEvents[:i], r.AuthEvents[i+1:]...)
531				i--
532			}
533		}
534		for i := 0; i < len(r.StateEvents); i++ {
535			if _, ok := failures[r.StateEvents[i].EventID()]; ok {
536				r.StateEvents = append(r.StateEvents[:i], r.StateEvents[i+1:]...)
537				i--
538			}
539		}
540	}
541
542	return nil
543}
544
545// A RespMakeJoin is the content of a response to GET /_matrix/federation/v2/make_join/{roomID}/{userID}
546type RespMakeJoin struct {
547	// An incomplete m.room.member event for a user on the requesting server
548	// generated by the responding server.
549	// See https://matrix.org/docs/spec/server_server/unstable.html#joining-rooms
550	JoinEvent   EventBuilder `json:"event"`
551	RoomVersion RoomVersion  `json:"room_version"`
552}
553
554// A RespSendJoin is the content of a response to PUT /_matrix/federation/v2/send_join/{roomID}/{eventID}
555type RespSendJoin struct {
556	// The room version that dictates the format of the state events.
557	roomVersion RoomVersion
558	// A list of events giving the state of the room before the request event.
559	StateEvents []*Event `json:"state"`
560	// A list of events needed to authenticate the state events.
561	AuthEvents []*Event `json:"auth_chain"`
562	// The server that originated the event.
563	Origin ServerName `json:"origin"`
564	// The returned join event from the remote server. Used for restricted joins,
565	// but not guaranteed to be present as it's only since MSC3083.
566	Event *Event `json:"event,omitempty"`
567}
568
569// MarshalJSON implements json.Marshaller
570func (r RespSendJoin) MarshalJSON() ([]byte, error) {
571	fields := respSendJoinFields{
572		StateEvents: r.StateEvents,
573		AuthEvents:  r.AuthEvents,
574		Origin:      r.Origin,
575	}
576	if len(fields.AuthEvents) == 0 {
577		fields.AuthEvents = []*Event{}
578	}
579	if len(fields.StateEvents) == 0 {
580		fields.StateEvents = []*Event{}
581	}
582	return json.Marshal(fields)
583}
584
585// UnmarshalJSON implements json.Unmarshaller
586func (r *RespSendJoin) UnmarshalJSON(data []byte) error {
587	r.AuthEvents = []*Event{}
588	r.StateEvents = []*Event{}
589	if _, err := r.roomVersion.EventFormat(); err != nil {
590		return err
591	}
592	var intermediate struct {
593		StateEvents []json.RawMessage `json:"state"`
594		AuthEvents  []json.RawMessage `json:"auth_chain"`
595		Origin      ServerName        `json:"origin"`
596	}
597	if err := json.Unmarshal(data, &intermediate); err != nil {
598		return err
599	}
600	for _, raw := range intermediate.AuthEvents {
601		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
602		if err != nil {
603			return err
604		}
605		r.AuthEvents = append(r.AuthEvents, event)
606	}
607	for _, raw := range intermediate.StateEvents {
608		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
609		if err != nil {
610			return err
611		}
612		r.StateEvents = append(r.StateEvents, event)
613	}
614	return nil
615}
616
617// ToRespState returns a new RespState with the same data from the given RespPeek
618func (r RespPeek) ToRespState() RespState {
619	if len(r.StateEvents) == 0 {
620		r.StateEvents = []*Event{}
621	}
622	if len(r.AuthEvents) == 0 {
623		r.AuthEvents = []*Event{}
624	}
625	return RespState{
626		roomVersion: r.RoomVersion,
627		StateEvents: r.StateEvents,
628		AuthEvents:  r.AuthEvents,
629	}
630}
631
632type respSendJoinFields struct {
633	StateEvents []*Event   `json:"state"`
634	AuthEvents  []*Event   `json:"auth_chain"`
635	Origin      ServerName `json:"origin"`
636}
637
638// ToRespState returns a new RespState with the same data from the given RespSendJoin
639func (r RespSendJoin) ToRespState() RespState {
640	if len(r.StateEvents) == 0 {
641		r.StateEvents = []*Event{}
642	}
643	if len(r.AuthEvents) == 0 {
644		r.AuthEvents = []*Event{}
645	}
646	return RespState{
647		StateEvents: r.StateEvents,
648		AuthEvents:  r.AuthEvents,
649	}
650}
651
652// Check that a response to /send_join is valid. If it is then it
653// returns a reference to the RespState that contains the room state
654// excluding any events that failed signature checks.
655// This checks that it would be valid as a response to /state.
656// This also checks that the join event is allowed by the state.
657// This function mutates the RespSendJoin to remove any events from
658// AuthEvents or StateEvents that do not have valid signatures.
659func (r *RespSendJoin) Check(ctx context.Context, keyRing JSONVerifier, joinEvent *Event, missingAuth AuthChainProvider) (*RespState, error) {
660	// First check that the state is valid and that the events in the response
661	// are correctly signed.
662	//
663	// The response to /send_join has the same data as a response to /state
664	// and the checks for a response to /state also apply.
665	rs := r.ToRespState()
666	if err := rs.Check(ctx, keyRing, missingAuth); err != nil {
667		return nil, err
668	}
669
670	// The RespState check can mutate the auth events and state events by
671	// removing events which didn't pass signature checks. Use those.
672	r.AuthEvents = rs.AuthEvents
673	r.StateEvents = rs.StateEvents
674
675	eventsByID := map[string]*Event{}
676	authEventProvider := NewAuthEvents(nil)
677
678	// Since checkAllowedByAuthEvents needs to be able to look up any of the
679	// auth events by ID only, we will build a map which contains references
680	// to all of the auth events.
681	for i, event := range r.AuthEvents {
682		eventsByID[event.EventID()] = r.AuthEvents[i]
683	}
684
685	// Then we add the current state events too, since our newly formed
686	// membership event will likely refer to these as auth events too.
687	for i, event := range r.StateEvents {
688		eventsByID[event.EventID()] = r.StateEvents[i]
689	}
690
691	// Now check that the join event is valid against its auth events.
692	if err := checkAllowedByAuthEvents(joinEvent, eventsByID, missingAuth); err != nil {
693		return nil, fmt.Errorf(
694			"gomatrixserverlib: event with ID %q is not allowed by its auth events: %w",
695			joinEvent.EventID(), err,
696		)
697	}
698
699	// Add all of the current state events to an auth provider, allowing us
700	// to check specifically that the join event is allowed by the supplied
701	// state (and not by former auth events).
702	for i := range r.StateEvents {
703		if err := authEventProvider.AddEvent(r.StateEvents[i]); err != nil {
704			return nil, err
705		}
706	}
707
708	// Now check that the join event is valid against the supplied state.
709	if err := Allowed(joinEvent, &authEventProvider); err != nil {
710		return nil, fmt.Errorf(
711			"gomatrixserverlib: event with ID %q is not allowed by the current room state: %w",
712			joinEvent.EventID(), err,
713		)
714	}
715
716	return &rs, nil
717}
718
719// A RespMakeLeave is the content of a response to GET /_matrix/federation/v2/make_leave/{roomID}/{userID}
720type RespMakeLeave struct {
721	// An incomplete m.room.member event for a user on the requesting server
722	// generated by the responding server.
723	// See https://matrix.org/docs/spec/server_server/r0.1.1.html#get-matrix-federation-v1-make-leave-roomid-userid
724	LeaveEvent EventBuilder `json:"event"`
725	// The room version that we're trying to leave.
726	RoomVersion RoomVersion `json:"room_version"`
727}
728
729// A RespDirectory is the content of a response to GET  /_matrix/federation/v1/query/directory
730// This is returned when looking up a room alias from a remote server.
731// See https://matrix.org/docs/spec/server_server/unstable.html#directory
732type RespDirectory struct {
733	// The matrix room ID the room alias corresponds to.
734	RoomID string `json:"room_id"`
735	// A list of matrix servers that the directory server thinks could be used
736	// to join the room. The joining server may need to try multiple servers
737	// before it finds one that it can use to join the room.
738	Servers []ServerName `json:"servers"`
739}
740
741// RespProfile is the content of a response to GET /_matrix/federation/v1/query/profile
742type RespProfile struct {
743	DisplayName string `json:"displayname,omitempty"`
744	AvatarURL   string `json:"avatar_url,omitempty"`
745}
746
747func checkAllowedByAuthEvents(event *Event, eventsByID map[string]*Event, missingAuth AuthChainProvider) error {
748	authEvents := NewAuthEvents(nil)
749
750	for _, ae := range event.AuthEventIDs() {
751	retryEvent:
752		authEvent, ok := eventsByID[ae]
753		if !ok {
754			// We don't have an entry in the eventsByID map - neither an event nor nil.
755			if missingAuth != nil {
756				// If we have a AuthChainProvider then ask it for the missing event.
757				if ev, err := missingAuth(event.roomVersion, []string{ae}); err == nil && len(ev) > 0 {
758					// It claims to have returned events - populate the eventsByID
759					// map and the authEvents provider so that we can retry with the
760					// new events.
761					for _, e := range ev {
762						if err := authEvents.AddEvent(e); err == nil {
763							eventsByID[e.EventID()] = e
764						} else {
765							eventsByID[e.EventID()] = nil
766						}
767					}
768				} else {
769					// It claims to have not returned an event - put a nil into the
770					// eventsByID map instead. This signals that we tried to retrieve
771					// the event but failed, so we don't keep retrying.
772					eventsByID[ae] = nil
773				}
774				goto retryEvent
775			} else {
776				// If we didn't have a AuthChainProvider then we can't get the event
777				// so just carry on without it. If it was important for anything then
778				// Check() below will catch it.
779				continue
780			}
781		} else if authEvent != nil {
782			// We had an entry in the map and it contains an actual event, so add it to
783			// the auth events provider.
784			if err := authEvents.AddEvent(authEvent); err != nil {
785				return err
786			}
787		} else {
788			// We had an entry in the map but it contains nil, which means that we tried
789			// to use the AuthChainProvider to retrieve it and failed, so at this point
790			// we just have to ignore the event.
791			continue
792		}
793	}
794
795	// If we made it this far then we've successfully got as many of the auth events as
796	// as described by AuthEventIDs(). Check if they allow the event.
797	if err := Allowed(event, &authEvents); err != nil {
798		return fmt.Errorf(
799			"gomatrixserverlib: event with ID %q is not allowed by its auth_events: %s",
800			event.EventID(), err.Error(),
801		)
802	}
803	return nil
804}
805
806// RespInvite is the content of a response to PUT /_matrix/federation/v1/invite/{roomID}/{eventID}
807type RespInvite struct {
808	// The invite event signed by recipient server.
809	Event *Event
810}
811
812// MarshalJSON implements json.Marshaller
813func (r RespInvite) MarshalJSON() ([]byte, error) {
814	// The wire format of a RespInvite is slightly is sent as the second element
815	// of a two element list where the first element is the constant integer 200.
816	// (This protocol oddity is the result of a typo in the synapse matrix
817	//  server, and is preserved to maintain compatibility.)
818	return json.Marshal([]interface{}{200, respInviteFields(r)})
819}
820
821// UnmarshalJSON implements json.Unmarshaller
822func (r *RespInvite) UnmarshalJSON(data []byte) error {
823	var tuple []RawJSON
824	if err := json.Unmarshal(data, &tuple); err != nil {
825		return err
826	}
827	if len(tuple) != 2 {
828		return fmt.Errorf("gomatrixserverlib: invalid invite response, invalid length: %d != 2", len(tuple))
829	}
830	if jr := gjson.GetBytes(tuple[1], "event"); jr.Exists() {
831		event, err := NewEventFromUntrustedJSON([]byte(jr.Raw), RoomVersionV1)
832		if err != nil {
833			return err
834		}
835		r.Event = event
836	}
837	return nil
838}
839
840type respInviteFields struct {
841	Event *Event `json:"event"`
842}
843
844// RespInvite is the content of a response to PUT /_matrix/federation/v2/invite/{roomID}/{eventID}
845type RespInviteV2 struct {
846	// The room version that dictates the format of the state events.
847	roomVersion RoomVersion
848	// The invite event signed by recipient server.
849	Event *Event `json:"event"`
850}
851
852// UnmarshalJSON implements json.Unmarshaller
853func (r *RespInviteV2) UnmarshalJSON(data []byte) error {
854	if _, err := r.roomVersion.EventFormat(); err != nil {
855		return err
856	}
857	var intermediate struct {
858		Event json.RawMessage `json:"event"`
859	}
860	if err := json.Unmarshal(data, &intermediate); err != nil {
861		return err
862	}
863	event, err := NewEventFromUntrustedJSON([]byte(intermediate.Event), r.roomVersion)
864	if err != nil {
865		return err
866	}
867	r.Event = event
868	return nil
869}
870
871// RespClaimKeys is the response for https://matrix.org/docs/spec/server_server/latest#post-matrix-federation-v1-user-keys-claim
872type RespClaimKeys struct {
873	// Required. One-time keys for the queried devices. A map from user ID, to a map from devices to a map
874	// from <algorithm>:<key_id> to the key object or a string.
875	OneTimeKeys map[string]map[string]map[string]json.RawMessage `json:"one_time_keys"`
876}
877
878// RespQueryKeys is the response for https://matrix.org/docs/spec/server_server/latest#post-matrix-federation-v1-user-keys-query
879type RespQueryKeys struct {
880	DeviceKeys      map[string]map[string]DeviceKeys `json:"device_keys"`
881	MasterKeys      map[string]CrossSigningKey       `json:"master_keys"`
882	SelfSigningKeys map[string]CrossSigningKey       `json:"self_signing_keys"`
883}
884
885// DeviceKeys as per https://matrix.org/docs/spec/server_server/latest#post-matrix-federation-v1-user-keys-query
886type DeviceKeys struct {
887	RespUserDeviceKeys
888	// Additional data added to the device key information by intermediate servers, and not covered by the signatures.
889	// E.g { "device_display_name": "Alice's mobile phone" }
890	Unsigned map[string]interface{} `json:"unsigned"`
891}
892
893func (s *DeviceKeys) isCrossSigningBody() {} // implements CrossSigningBody
894
895func (s *DeviceKeys) Scan(src interface{}) error {
896	switch v := src.(type) {
897	case string:
898		return json.Unmarshal([]byte(v), s)
899	case []byte:
900		return json.Unmarshal(v, s)
901	}
902	return fmt.Errorf("unsupported source type")
903}
904
905func (s DeviceKeys) Value() (driver.Value, error) {
906	return json.Marshal(s)
907}
908
909// MSC2836EventRelationshipsRequest is a request to /event_relationships from
910// https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md
911// nolint:maligned
912type MSC2836EventRelationshipsRequest struct {
913	EventID         string `json:"event_id"`
914	MaxDepth        int    `json:"max_depth"`
915	MaxBreadth      int    `json:"max_breadth"`
916	Limit           int    `json:"limit"`
917	DepthFirst      bool   `json:"depth_first"`
918	RecentFirst     bool   `json:"recent_first"`
919	IncludeParent   bool   `json:"include_parent"`
920	IncludeChildren bool   `json:"include_children"`
921	Direction       string `json:"direction"`
922	Batch           string `json:"batch"`
923	AutoJoin        bool   `json:"auto_join"`
924}
925
926// NewMSC2836EventRelationshipsRequest creates a new MSC2836 /event_relationships request with defaults set.
927// https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md
928func NewMSC2836EventRelationshipsRequest(body io.Reader) (*MSC2836EventRelationshipsRequest, error) {
929	var relation MSC2836EventRelationshipsRequest
930	relation.Defaults()
931	if err := json.NewDecoder(body).Decode(&relation); err != nil {
932		return nil, err
933	}
934	return &relation, nil
935}
936
937// Defaults sets default values.
938func (r *MSC2836EventRelationshipsRequest) Defaults() {
939	r.Limit = 100
940	r.MaxBreadth = 10
941	r.MaxDepth = 3
942	r.DepthFirst = false
943	r.RecentFirst = true
944	r.IncludeParent = false
945	r.IncludeChildren = false
946	r.Direction = "down"
947}
948
949// MSC2836EventRelationshipsResponse is a response to /event_relationships from
950// https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md
951type MSC2836EventRelationshipsResponse struct {
952	Events      []*Event `json:"events"`
953	NextBatch   string   `json:"next_batch"`
954	Limited     bool     `json:"limited"`
955	AuthChain   []*Event `json:"auth_chain"`
956	roomVersion RoomVersion
957}
958
959// SetRoomVersion can be called prior to unmarshalling JSON to control how events should be deserialised.
960func (r *MSC2836EventRelationshipsResponse) SetRoomVersion(roomVer RoomVersion) {
961	r.roomVersion = roomVer
962}
963
964// UnmarshalJSON implements json.Unmarshaller
965func (r *MSC2836EventRelationshipsResponse) UnmarshalJSON(data []byte) error {
966	r.Events = []*Event{}
967	r.AuthChain = []*Event{}
968	if _, err := r.roomVersion.EventFormat(); err != nil {
969		return err
970	}
971	var intermediate struct {
972		Events    []json.RawMessage `json:"events"`
973		NextBatch string            `json:"next_batch"`
974		Limited   bool              `json:"limited"`
975		AuthChain []json.RawMessage `json:"auth_chain"`
976	}
977	if err := json.Unmarshal(data, &intermediate); err != nil {
978		return err
979	}
980	r.NextBatch = intermediate.NextBatch
981	r.Limited = intermediate.Limited
982	for _, raw := range intermediate.Events {
983		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
984		if err != nil {
985			return err
986		}
987		r.Events = append(r.Events, event)
988	}
989	for _, raw := range intermediate.AuthChain {
990		event, err := NewEventFromUntrustedJSON([]byte(raw), r.roomVersion)
991		if err != nil {
992			return err
993		}
994		r.AuthChain = append(r.AuthChain, event)
995	}
996	return nil
997}
998
999// MSC2946SpacesRequest is the HTTP body for the federated /unstable/spaces/{roomID} endpoint
1000// See https://github.com/matrix-org/matrix-doc/pull/2946
1001type MSC2946SpacesRequest struct {
1002	ExcludeRooms     []string `json:"exclude_rooms,omitempty"`
1003	MaxRoomsPerSpace int      `json:"max_rooms_per_space,omitempty"`
1004	Limit            int      `json:"limit"`
1005	Batch            string   `json:"batch"`
1006}
1007
1008// MSC2946Room represents a public room with additional metadata on the space directory
1009type MSC2946Room struct {
1010	PublicRoom
1011	NumRefs  int    `json:"num_refs"`
1012	RoomType string `json:"room_type,omitempty"`
1013}
1014
1015// MSC2946SpacesResponse is the HTTP response body for the federation /unstable/spaces/{roomID} endpoint
1016// See https://github.com/matrix-org/matrix-doc/pull/2946
1017type MSC2946SpacesResponse struct {
1018	Rooms     []MSC2946Room          `json:"rooms"`
1019	Events    []MSC2946StrippedEvent `json:"events"`
1020	NextBatch string                 `json:"next_batch"`
1021}
1022
1023// MSC2946StrippedEvent is the format of events returned in the HTTP response body
1024type MSC2946StrippedEvent struct {
1025	Type     string          `json:"type"`
1026	StateKey string          `json:"state_key"`
1027	Content  json.RawMessage `json:"content"`
1028	Sender   string          `json:"sender"`
1029	RoomID   string          `json:"room_id"`
1030}
1031