From f7aa96fc9e5030e2a1446e82836b6ffac89354a8 Mon Sep 17 00:00:00 2001
From: Richard van der Hoff <richard@matrix.org>
Date: Tue, 26 Sep 2017 12:54:22 +0100
Subject: [PATCH] gb vendor update github.com/matrix-org/gomatrixserverlib

---
 vendor/manifest                               |   2 +-
 .../matrix-org/gomatrixserverlib/event.go     |  31 ++---
 .../gomatrixserverlib/eventcrypto.go          |  38 ++++--
 .../gomatrixserverlib/eventcrypto_test.go     | 127 ++++++++++++++++++
 .../gomatrixserverlib/federationtypes.go      |   8 +-
 .../matrix-org/gomatrixserverlib/keyring.go   |  18 ++-
 .../matrix-org/gomatrixserverlib/request.go   |   4 +-
 7 files changed, 193 insertions(+), 35 deletions(-)

diff --git a/vendor/manifest b/vendor/manifest
index 9200690e8..5bd25a50e 100644
--- a/vendor/manifest
+++ b/vendor/manifest
@@ -116,7 +116,7 @@
 		{
 			"importpath": "github.com/matrix-org/gomatrixserverlib",
 			"repository": "https://github.com/matrix-org/gomatrixserverlib",
-			"revision": "ce6f4766251e31487906dfaaebd7d7cfea147252",
+			"revision": "f3be4cb492f23eb30a9f2ab5fc5bd85ee9c3add6",
 			"branch": "master"
 		},
 		{
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go
index 71c065603..2a26e7af9 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go
@@ -389,6 +389,8 @@ func (e Event) CheckFields() error { // nolint: gocyclo
 		return err
 	}
 
+	origin := e.fields.Origin
+
 	senderDomain, err := checkID(e.fields.Sender, "user", '@')
 	if err != nil {
 		return err
@@ -406,34 +408,33 @@ func (e Event) CheckFields() error { // nolint: gocyclo
 	// Since both domains must be valid domains, and there is no good reason for them
 	// to be different we might as well ensure that they are the same since it
 	// makes the signature checks simpler.
-	if e.fields.Origin != ServerName(eventDomain) {
+	if origin != ServerName(eventDomain) {
 		return fmt.Errorf(
 			"gomatrixserverlib: event ID domain doesn't match origin: %q != %q",
-			eventDomain, e.fields.Origin,
+			eventDomain, origin,
 		)
 	}
 
-	if eventDomain != senderDomain {
+	if origin != ServerName(senderDomain) {
 		// For the most part all events should be sent by a user on the
-		// originating server
+		// originating server.
+		//
 		// However "m.room.member" events created from third-party invites
 		// are allowed to have a different sender because they have the same
 		// sender as the "m.room.third_party_invite" event they derived from.
 		// https://github.com/matrix-org/synapse/blob/v0.21.0/synapse/event_auth.py#L58-L64
+		//
+		// Also, some old versions of synapse had a bug wherein some
+		// joins/leaves used the origin and event id supplied by the helping
+		// server instead of the joining/leaving server.
+		//
+		// So in general we allow the sender to be different from the
+		// origin for m.room.member events. In any case, we check it was
+		// signed by both servers later.
 		if e.fields.Type != MRoomMember {
 			return fmt.Errorf(
 				"gomatrixserverlib: sender domain doesn't match origin: %q != %q",
-				senderDomain, e.fields.Origin,
-			)
-		}
-		c, err := newMemberContentFromEvent(e)
-		if err != nil {
-			return err
-		}
-		if c.Membership != invite || c.ThirdPartyInvite == nil {
-			return fmt.Errorf(
-				"gomatrixserverlib: sender domain doesn't match origin: %q != %q",
-				senderDomain, e.fields.Origin,
+				senderDomain, origin,
 			)
 		}
 	}
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go
index 7d5f417c9..255b269d4 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go
@@ -189,19 +189,33 @@ func verifyEventSignature(signingName string, keyID KeyID, publicKey ed25519.Pub
 
 // VerifyEventSignatures checks that each event in a list of events has valid
 // signatures from the server that sent it.
-func VerifyEventSignatures(ctx context.Context, events []Event, keyRing KeyRing) error { // nolint: gocyclo
+func VerifyEventSignatures(ctx context.Context, events []Event, keyRing JSONVerifier) error { // nolint: gocyclo
 	var toVerify []VerifyJSONRequest
 	for _, event := range events {
 		redactedJSON, err := redactEvent(event.eventJSON)
 		if err != nil {
 			return err
 		}
-		v := VerifyJSONRequest{
-			Message:    redactedJSON,
-			AtTS:       event.OriginServerTS(),
-			ServerName: event.Origin(),
+
+		domains := make(map[ServerName]bool)
+		domains[event.Origin()] = true
+
+		// in general, we expect the domain of the sender id to be the
+		// same as the origin; however there was a bug in an old version
+		// of synapse which meant that some joins/leaves used the origin
+		// and event id supplied by the helping server instead of the
+		// joining/leaving server.
+		//
+		// That's ok, provided it's signed by the sender's server too.
+		//
+		// XXX we may have to exclude 3pid invites here, as per
+		// https://github.com/matrix-org/synapse/blob/v0.21.0/synapse/event_auth.py#L58-L64.
+		//
+		senderDomain, err := domainFromID(event.Sender())
+		if err != nil {
+			return err
 		}
-		toVerify = append(toVerify, v)
+		domains[ServerName(senderDomain)] = true
 
 		// MRoomMember invite events are signed by both the server sending
 		// the invite and the server the invite is for.
@@ -216,11 +230,19 @@ func VerifyEventSignatures(ctx context.Context, events []Event, keyRing KeyRing)
 					return err
 				}
 				if c.Membership == invite {
-					v.ServerName = ServerName(targetDomain)
-					toVerify = append(toVerify, v)
+					domains[ServerName(targetDomain)] = true
 				}
 			}
 		}
+
+		for domain := range domains {
+			v := VerifyJSONRequest{
+				Message:    redactedJSON,
+				AtTS:       event.OriginServerTS(),
+				ServerName: domain,
+			}
+			toVerify = append(toVerify, v)
+		}
 	}
 
 	results, err := keyRing.VerifyJSONs(ctx, toVerify)
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go
index f97d0c1d4..72d868818 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go
@@ -17,7 +17,10 @@ package gomatrixserverlib
 
 import (
 	"bytes"
+	"context"
 	"encoding/base64"
+	"encoding/json"
+	"sort"
 	"testing"
 
 	"golang.org/x/crypto/ed25519"
@@ -258,3 +261,127 @@ func TestSignEventTestVectors(t *testing.T) {
    	 	}
 	}`)
 }
+
+type StubVerifier struct {
+	requests []VerifyJSONRequest
+	results  []VerifyJSONResult
+}
+
+func (v *StubVerifier) VerifyJSONs(ctx context.Context, requests []VerifyJSONRequest) ([]VerifyJSONResult, error) {
+	v.requests = append(v.requests, requests...)
+	return v.results, nil
+}
+
+func TestVerifyEventSignatures(t *testing.T) {
+	verifier := StubVerifier{}
+
+	eventJSON := []byte(`{
+		"type": "m.room.name",
+		"state_key": "",
+		"event_id": "$test:localhost",
+		"room_id": "!test:localhost",
+		"sender": "@test:localhost",
+		"origin": "originserver",
+		"content": {
+			"name": "Hello World"
+		},
+		"origin_server_ts": 123456
+	}`)
+
+	var event Event
+	if err := json.Unmarshal(eventJSON, &event.fields); err != nil {
+		t.Fatal(err)
+	}
+	event.eventJSON = eventJSON
+
+	events := []Event{event}
+	if err := VerifyEventSignatures(context.Background(), events, &verifier); err != nil {
+		t.Fatal(err)
+	}
+
+	// There should be two verification requests
+	if len(verifier.requests) != 2 {
+		t.Fatalf("Number of requests: got %d, want 2", len(verifier.requests))
+	}
+	wantContent, err := redactEvent(eventJSON)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	servers := []string{}
+
+	for i, rq := range verifier.requests {
+		if !bytes.Equal(rq.Message, wantContent) {
+			t.Errorf("Verify content %d: got %s, want %s", i, rq.Message, wantContent)
+		}
+		if rq.AtTS != 123456 {
+			t.Errorf("Verify time %d: got %d, want %d", i, rq.AtTS, 123456)
+		}
+		servers = append(servers, string(rq.ServerName))
+	}
+
+	sort.Strings(servers)
+	if servers[0] != "localhost" {
+		t.Errorf("Verify server 0: got %s, want %s", servers[0], "localhost")
+	}
+	if servers[1] != "originserver" {
+		t.Errorf("Verify server 1: got %s, want %s", servers[1], "originserver")
+	}
+}
+
+func TestVerifyEventSignaturesForInvite(t *testing.T) {
+	verifier := StubVerifier{}
+
+	eventJSON := []byte(`{
+		"type": "m.room.member",
+		"state_key": "@bob:bobserver",
+		"event_id": "$test:aliceserver",
+		"room_id": "!test:room",
+		"sender": "@alice:aliceserver",
+		"origin": "aliceserver",
+		"content": {
+			"membership": "invite"
+		},
+		"origin_server_ts": 123456
+	}`)
+
+	var event Event
+	if err := json.Unmarshal(eventJSON, &event.fields); err != nil {
+		t.Fatal(err)
+	}
+	event.eventJSON = eventJSON
+
+	events := []Event{event}
+	if err := VerifyEventSignatures(context.Background(), events, &verifier); err != nil {
+		t.Fatal(err)
+	}
+
+	// There should be two verification requests
+	if len(verifier.requests) != 2 {
+		t.Fatalf("Number of requests: got %d, want 2", len(verifier.requests))
+	}
+	wantContent, err := redactEvent(eventJSON)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	servers := []string{}
+
+	for i, rq := range verifier.requests {
+		if !bytes.Equal(rq.Message, wantContent) {
+			t.Errorf("Verify content %d: got %s, want %s", i, rq.Message, wantContent)
+		}
+		if rq.AtTS != 123456 {
+			t.Errorf("Verify time %d: got %d, want %d", i, rq.AtTS, 123456)
+		}
+		servers = append(servers, string(rq.ServerName))
+	}
+
+	sort.Strings(servers)
+	if servers[0] != "aliceserver" {
+		t.Errorf("Verify server 0: got %s, want %s", servers[0], "aliceserver")
+	}
+	if servers[1] != "bobserver" {
+		t.Errorf("Verify server 1: got %s, want %s", servers[1], "bobserver")
+	}
+}
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go
index 58c46ce24..d4cfab867 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go
@@ -108,7 +108,7 @@ func (r RespState) Events() ([]Event, error) {
 }
 
 // Check that a response to /state is valid.
-func (r RespState) Check(ctx context.Context, keyRing KeyRing) error {
+func (r RespState) Check(ctx context.Context, keyRing JSONVerifier) error {
 	var allEvents []Event
 	for _, event := range r.AuthEvents {
 		if event.StateKey() == nil {
@@ -214,8 +214,10 @@ type respSendJoinFields struct {
 // Check that a response to /send_join is valid.
 // This checks that it would be valid as a response to /state
 // This also checks that the join event is allowed by the state.
-func (r RespSendJoin) Check(ctx context.Context, keyRing KeyRing, joinEvent Event) error {
-	// First check that the state is valid.
+func (r RespSendJoin) Check(ctx context.Context, keyRing JSONVerifier, joinEvent Event) error {
+	// First check that the state is valid and that the events in the response
+	// are correctly signed.
+	//
 	// The response to /send_join has the same data as a response to /state
 	// and the checks for a response to /state also apply.
 	if err := RespState(r).Check(ctx, keyRing); err != nil {
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/keyring.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/keyring.go
index 954fc2595..324e59d13 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/keyring.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/keyring.go
@@ -69,12 +69,18 @@ type VerifyJSONResult struct {
 	Error error
 }
 
-// VerifyJSONs performs bulk JSON signature verification for a list of VerifyJSONRequests.
-// Returns a list of VerifyJSONResults with the same length and order as the request list.
-// The caller should check the Result field for each entry to see if it was valid.
-// Returns an error if there was a problem talking to the database or one of the other methods
-// of fetching the public keys.
-func (k *KeyRing) VerifyJSONs(ctx context.Context, requests []VerifyJSONRequest) ([]VerifyJSONResult, error) { // nolint: gocyclo
+// A JSONVerifier is an object which can verify the signatures of JSON messages.
+type JSONVerifier interface {
+	// VerifyJSONs performs bulk JSON signature verification for a list of VerifyJSONRequests.
+	// Returns a list of VerifyJSONResults with the same length and order as the request list.
+	// The caller should check the Result field for each entry to see if it was valid.
+	// Returns an error if there was a problem talking to the database or one of the other methods
+	// of fetching the public keys.
+	VerifyJSONs(ctx context.Context, requests []VerifyJSONRequest) ([]VerifyJSONResult, error)
+}
+
+// VerifyJSONs implements JSONVerifier.
+func (k KeyRing) VerifyJSONs(ctx context.Context, requests []VerifyJSONRequest) ([]VerifyJSONResult, error) { // nolint: gocyclo
 	results := make([]VerifyJSONResult, len(requests))
 	keyIDs := make([][]KeyID, len(requests))
 
diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/request.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/request.go
index 84874ebe0..b7872cbea 100644
--- a/vendor/src/github.com/matrix-org/gomatrixserverlib/request.go
+++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/request.go
@@ -184,7 +184,7 @@ func isSafeInHTTPQuotedString(text string) bool { // nolint: gocyclo
 // It consumes the body of the request.
 // The JSON content can be accessed using FederationRequest.Content()
 // Returns an 400 error if there was a problem parsing the request.
-// It authenticates the request using an ed25519 signature using the KeyRing.
+// It authenticates the request using an ed25519 signature using the JSONVerifier.
 // The origin server can be accessed using FederationRequest.Origin()
 // Returns a 401 error if there was a problem authenticating the request.
 // HTTP handlers using this should be careful that they only use the parts of
@@ -192,7 +192,7 @@ func isSafeInHTTPQuotedString(text string) bool { // nolint: gocyclo
 // the query parameters, and the JSON content. In particular the version of
 // HTTP and the headers aren't protected by the signature.
 func VerifyHTTPRequest(
-	req *http.Request, now time.Time, destination ServerName, keys KeyRing,
+	req *http.Request, now time.Time, destination ServerName, keys JSONVerifier,
 ) (*FederationRequest, util.JSONResponse) {
 	request, err := readHTTPRequest(req)
 	if err != nil {