Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for state_key size #642

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions tests/federation_room_get_missing_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"encoding/json"
"fmt"
"net/http"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -465,3 +466,132 @@
})
}
}

// This test verifies that an event with a too large state_key can be used as a prev_event
// it is returned by a call to /get_missing_events and should pass event size checks.
// TODO: Do the same checks for type, user_id and sender
func TestOutboundFederationEventSizeGetMissingEvents(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)

alice := deployment.Client(t, "hs1", "@alice:hs1")

srv := federation.NewServer(t, deployment,
federation.HandleKeyRequests(),
federation.HandleMakeSendJoinRequests(),
// Handle any transactions that the homeserver may send when connecting to another homeserver (such as presence)
federation.HandleTransactionRequests(nil, nil),
)
cancel := srv.Listen()
defer cancel()

// register a handler for /get_missing_events, via a shim so that we can
// behave differently as the test progresses.
var onGetMissingEvents func(w http.ResponseWriter, req *http.Request)
srv.Mux().HandleFunc("/_matrix/federation/v1/get_missing_events/{roomID}", func(w http.ResponseWriter, req *http.Request) {
onGetMissingEvents(w, req)
}).Methods("POST")

ver := alice.GetDefaultRoomVersion(t)
charlie := srv.UserID("charlie")
room := srv.MustMakeRoom(t, ver, federation.InitialRoomEvents(ver, charlie))
roomAlias := srv.MakeAliasMapping("flibble", room.RoomID)
// join the room
alice.JoinRoom(t, roomAlias, nil)

latestEvent := room.Timeline[len(room.Timeline)-1]

// Sign this bad event which has a too large stateKey
// Synapse always enforced 255 codepoints, but accepts events > 255 bytes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/events/state_keys?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or "events with state keys"?

// Dendrite would fail to parse this event because it enforced 255 bytes, breaking older rooms.
stateKey := strings.Repeat("💥", 70) // 280 bytes, 70 codepoints
badEvent := b.Event{
Type: "my.room.breaker",
StateKey: &stateKey,
Sender: charlie,
Content: map[string]interface{}{},
}
content, err := json.Marshal(badEvent.Content)
if err != nil {
t.Fatalf("failed to marshal badEvent content %+v", badEvent.Content)
}
eb := gomatrixserverlib.EventBuilder{
Sender: badEvent.Sender,

Check failure on line 519 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

unknown field Sender in struct literal of type gomatrixserverlib.EventBuilder

Check failure on line 519 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

unknown field Sender in struct literal of type gomatrixserverlib.EventBuilder
Depth: int64(room.Depth + 1), // depth starts at 1
Type: badEvent.Type,
StateKey: badEvent.StateKey,
Content: content,
RoomID: room.RoomID,
PrevEvents: room.ForwardExtremities,
}
stateNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(&eb)

Check failure on line 527 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.StateNeededForEventBuilder

Check failure on line 527 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.StateNeededForEventBuilder
if err != nil {
t.Fatalf("failed to work out auth_events : %s", err)
}
eb.AuthEvents = room.AuthEvents(stateNeeded)

signedBadEvent, err := eb.Build(time.Now(), gomatrixserverlib.ServerName(srv.ServerName()), srv.KeyID, srv.Priv, ver)

Check failure on line 533 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.ServerName

Check failure on line 533 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.ServerName
switch e := err.(type) {
case nil:
case gomatrixserverlib.EventValidationError:
// ignore for now
t.Logf("EventValidationError: %v", e)
default:
t.Fatalf("failed to sign event: %s: %s", err, signedBadEvent.JSON())
}
room.AddEvent(signedBadEvent)

// send the first "good" event, referencing the broken event as a prev_event
sentEvent := srv.MustCreateEvent(t, room, b.Event{

Check failure on line 545 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

cannot use b.Event{…} (value of type b.Event) as federation.Event value in argument to srv.MustCreateEvent

Check failure on line 545 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

cannot use b.Event{…} (value of type b.Event) as federation.Event value in argument to srv.MustCreateEvent
Type: "m.room.message",
Sender: charlie,
Content: map[string]interface{}{
"body": "Message 2",
},
})
room.AddEvent(sentEvent)

waiter := NewWaiter()

Check failure on line 554 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: NewWaiter

Check failure on line 554 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: NewWaiter
onGetMissingEvents = func(w http.ResponseWriter, req *http.Request) {
defer waiter.Finish()
must.MatchRequest(t, req, match.HTTPRequest{
JSON: []match.JSON{
match.JSONKeyEqual("earliest_events", []interface{}{latestEvent.EventID()}),
match.JSONKeyEqual("latest_events", []interface{}{sentEvent.EventID()}),
},
})
// return the bad event, which should result in the transaction failing.
w.WriteHeader(200)
res := struct {
Events []*gomatrixserverlib.Event `json:"events"`

Check failure on line 566 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.Event

Check failure on line 566 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.Event
}{
Events: []*gomatrixserverlib.Event{signedBadEvent},

Check failure on line 568 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.Event

Check failure on line 568 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.Event
}
var responseBytes []byte
responseBytes, err = json.Marshal(&res)
must.NotError(t, "failed to marshal response", err)
w.Write(responseBytes)
}

fedClient := srv.FederationClient(deployment)
resp, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{
TransactionID: "wut",
Origin: gomatrixserverlib.ServerName(srv.ServerName()),

Check failure on line 579 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.ServerName

Check failure on line 579 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.ServerName
Destination: gomatrixserverlib.ServerName("hs1"),

Check failure on line 580 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Synapse)

undefined: gomatrixserverlib.ServerName

Check failure on line 580 in tests/federation_room_get_missing_events_test.go

View workflow job for this annotation

GitHub Actions / Complement (Dendrite)

undefined: gomatrixserverlib.ServerName
PDUs: []json.RawMessage{
sentEvent.JSON(),
},
})
waiter.Wait(t, 5*time.Second)
must.NotError(t, "SendTransaction errored", err)
if len(resp.PDUs) != 1 {
t.Fatalf("got %d errors, want 1", len(resp.PDUs))
}
_, ok := resp.PDUs[sentEvent.EventID()]
if !ok {
t.Fatalf("wrong PDU returned from send transaction, got %v want %s", resp.PDUs, sentEvent.EventID())
}

// Alice should receive the sent event, even though the "bad" event has a too large state key
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncTimelineHasEventID(room.RoomID, sentEvent.EventID()))
}
Loading