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