diff --git a/vendor/manifest b/vendor/manifest index 317c8023..645998df 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -135,7 +135,7 @@ { "importpath": "github.com/matrix-org/gomatrixserverlib", "repository": "https://github.com/matrix-org/gomatrixserverlib", - "revision": "8540d3dfc13c797cd3200640bc06e0286ab355aa", + "revision": "afa71391f946312c40639a419045e06b8ff2309a", "branch": "master" }, { diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/base64.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/base64.go index 38ae7695..dc895d17 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/base64.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/base64.go @@ -53,6 +53,12 @@ func (b64 Base64String) MarshalJSON() ([]byte, error) { return json.Marshal(b64.Encode()) } +// MarshalYAML implements yaml.Marshaller +// It just encodes the bytes as base64, which is a valid YAML string +func (b64 Base64String) MarshalYAML() (interface{}, error) { + return b64.Encode(), nil +} + // UnmarshalJSON decodes a JSON string and then decodes the resulting base64. // This takes a pointer receiver because it needs to write the result of decoding. func (b64 *Base64String) UnmarshalJSON(raw []byte) (err error) { @@ -65,3 +71,14 @@ func (b64 *Base64String) UnmarshalJSON(raw []byte) (err error) { err = b64.Decode(str) return } + +// UnmarshalYAML implements yaml.Unmarshaller +// it unmarshals the input as a yaml string and then base64-decodes the result +func (b64 *Base64String) UnmarshalYAML(unmarshal func(interface{}) error) (err error) { + var str string + if err = unmarshal(&str); err != nil { + return + } + err = b64.Decode(str) + return +} diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/base64_test.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/base64_test.go index 9ef94046..e0a8beb0 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/base64_test.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/base64_test.go @@ -18,6 +18,8 @@ package gomatrixserverlib import ( "encoding/json" "testing" + + "gopkg.in/yaml.v2" ) func TestMarshalBase64(t *testing.T) { @@ -93,3 +95,58 @@ func TestMarshalBase64Slice(t *testing.T) { t.Fatalf("json.Marshal(%v): wanted %q got %q", input, want, string(got)) } } + +func TestMarshalYAMLBase64(t *testing.T) { + input := Base64String("this\xffis\xffa\xfftest") + want := "dGhpc/9pc/9h/3Rlc3Q\n" + got, err := yaml.Marshal(input) + if err != nil { + t.Fatal(err) + } + if string(got) != want { + t.Fatalf("yaml.Marshal(%v): wanted %q got %q", input, want, string(got)) + } +} + +func TestMarshalYAMLBase64Struct(t *testing.T) { + input := struct{ Value Base64String }{Base64String("this\xffis\xffa\xfftest")} + want := "value: dGhpc/9pc/9h/3Rlc3Q\n" + got, err := yaml.Marshal(input) + if err != nil { + t.Fatal(err) + } + if string(got) != want { + t.Fatalf("yaml.Marshal(%v): wanted %q got %q", input, want, string(got)) + } +} + +func TestUnmarshalYAMLBase64(t *testing.T) { + input := []byte("dGhpc/9pc/9h/3Rlc3Q") + want := Base64String("this\xffis\xffa\xfftest") + var got Base64String + err := yaml.Unmarshal(input, &got) + if err != nil { + t.Fatal(err) + } + if string(got) != string(want) { + t.Fatalf("yaml.Unmarshal(%q): wanted %q got %q", string(input), want, string(got)) + } +} + +func TestUnmarshalYAMLBase64Struct(t *testing.T) { + // var u yaml.Unmarshaler + u := Base64String("this\xffis\xffa\xfftest") + + input := []byte(`value: dGhpc/9pc/9h/3Rlc3Q`) + want := struct{ Value Base64String }{u} + result := struct { + Value Base64String `yaml:"value"` + }{} + err := yaml.Unmarshal(input, &result) + if err != nil { + t.Fatal(err) + } + if string(result.Value) != string(want.Value) { + t.Fatalf("yaml.Unmarshal(%v): wanted %q got %q", input, want, result) + } +} diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/client.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/client.go index e47be7fd..20f84283 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/client.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/client.go @@ -80,7 +80,7 @@ func newFederationTripper() *federationTripper { ServerName: "", // TODO: We should be checking that the TLS certificate we see here matches // one of the allowed SHA-256 fingerprints for the server. - InsecureSkipVerify: true, + InsecureSkipVerify: true, // nolint: gas }) if err := conn.Handshake(); err != nil { return nil, err diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go index f873cb5b..71ec3b5f 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/event.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "github.com/tidwall/gjson" "github.com/tidwall/sjson" "golang.org/x/crypto/ed25519" ) @@ -306,6 +307,33 @@ func (e Event) SetUnsigned(unsigned interface{}) (Event, error) { return result, nil } +// SetUnsignedField takes a path and value to insert into the unsigned dict of +// the event. +// path is a dot separated path into the unsigned dict (see gjson package +// for details on format). In particular some characters like '.' and '*' must +// be escaped. +func (e *Event) SetUnsignedField(path string, value interface{}) error { + // The safest way is to change the unsigned json and then reparse the + // event fully. But since we are only changing the unsigned section, + // which doesn't affect the signatures or hashes, we can cheat and + // just fiddle those bits directly. + + path = "unsigned." + path + eventJSON, err := sjson.SetBytes(e.eventJSON, path, value) + if err != nil { + return err + } + eventJSON = CanonicalJSONAssumeValid(eventJSON) + + res := gjson.GetBytes(eventJSON, "unsigned") + unsigned := rawJSONFromResult(res, eventJSON) + + e.eventJSON = eventJSON + e.fields.Unsigned = unsigned + + return nil +} + // EventReference returns an EventReference for the event. // The reference can be used to refer to this event from other events. func (e Event) EventReference() EventReference { diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/event_test.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/event_test.go index d5c715da..cb5d4f84 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/event_test.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/event_test.go @@ -50,3 +50,32 @@ func BenchmarkParseSmallerEventFailedHash(b *testing.B) { func BenchmarkParseSmallerEventRedacted(b *testing.B) { benchmarkParse(b, `{"event_id":"$yvN1b43rlmcOs5fY:localhost","sender":"@test:localhost","room_id":"!19Mp0U9hjajeIiw1:localhost","hashes":{"sha256":"Oh1mwI1jEqZ3tgJ+V1Dmu5nOEGpCE4RFUqyJv2gQXKs"},"signatures":{"localhost":{"ed25519:u9kP":"5IzSuRXkxvbTp0vZhhXYZeOe+619iG3AybJXr7zfNn/4vHz4TH7qSJVQXSaHHvcTcDodAKHnTG1WDulgO5okAQ"}},"content":{},"type":"m.room.name","state_key":"","depth":7,"prev_events":[["$FqI6TVvWpcbcnJ97:localhost",{"sha256":"upCsBqUhNUgT2/+zkzg8TbqdQpWWKQnZpGJc6KcbUC4"}]],"prev_state":[],"auth_events":[["$oXL79cT7fFxR7dPH:localhost",{"sha256":"abjkiDSg1RkuZrbj2jZoGMlQaaj1Ue3Jhi7I7NlKfXY"}],["$IVUsaSkm1LBAZYYh:localhost",{"sha256":"X7RUj46hM/8sUHNBIFkStbOauPvbDzjSdH4NibYWnko"}],["$VS2QT0EeArZYi8wf:localhost",{"sha256":"k9eM6utkCH8vhLW9/oRsH74jOBS/6RVK42iGDFbylno"}]],"origin":"localhost","origin_server_ts":1510854416361}`) } + +func TestAddUnsignedField(t *testing.T) { + initialEventJSON := `{"auth_events":[["$oXL79cT7fFxR7dPH:localhost",{"sha256":"abjkiDSg1RkuZrbj2jZoGMlQaaj1Ue3Jhi7I7NlKfXY"}],["$IVUsaSkm1LBAZYYh:localhost",{"sha256":"X7RUj46hM/8sUHNBIFkStbOauPvbDzjSdH4NibYWnko"}],["$VS2QT0EeArZYi8wf:localhost",{"sha256":"k9eM6utkCH8vhLW9/oRsH74jOBS/6RVK42iGDFbylno"}]],"content":{"name":"test3"},"depth":7,"event_id":"$yvN1b43rlmcOs5fY:localhost","hashes":{"sha256":"Oh1mwI1jEqZ3tgJ+V1Dmu5nOEGpCE4RFUqyJv2gQXKs"},"origin":"localhost","origin_server_ts":1510854416361,"prev_events":[["$FqI6TVvWpcbcnJ97:localhost",{"sha256":"upCsBqUhNUgT2/+zkzg8TbqdQpWWKQnZpGJc6KcbUC4"}]],"prev_state":[],"room_id":"!19Mp0U9hjajeIiw1:localhost","sender":"@test:localhost","signatures":{"localhost":{"ed25519:u9kP":"5IzSuRXkxvbTp0vZhhXYZeOe+619iG3AybJXr7zfNn/4vHz4TH7qSJVQXSaHHvcTcDodAKHnTG1WDulgO5okAQ"}},"state_key":"","type":"m.room.name"}` + expectedEventJSON := `{"auth_events":[["$oXL79cT7fFxR7dPH:localhost",{"sha256":"abjkiDSg1RkuZrbj2jZoGMlQaaj1Ue3Jhi7I7NlKfXY"}],["$IVUsaSkm1LBAZYYh:localhost",{"sha256":"X7RUj46hM/8sUHNBIFkStbOauPvbDzjSdH4NibYWnko"}],["$VS2QT0EeArZYi8wf:localhost",{"sha256":"k9eM6utkCH8vhLW9/oRsH74jOBS/6RVK42iGDFbylno"}]],"content":{"name":"test3"},"depth":7,"event_id":"$yvN1b43rlmcOs5fY:localhost","hashes":{"sha256":"Oh1mwI1jEqZ3tgJ+V1Dmu5nOEGpCE4RFUqyJv2gQXKs"},"origin":"localhost","origin_server_ts":1510854416361,"prev_events":[["$FqI6TVvWpcbcnJ97:localhost",{"sha256":"upCsBqUhNUgT2/+zkzg8TbqdQpWWKQnZpGJc6KcbUC4"}]],"prev_state":[],"room_id":"!19Mp0U9hjajeIiw1:localhost","sender":"@test:localhost","signatures":{"localhost":{"ed25519:u9kP":"5IzSuRXkxvbTp0vZhhXYZeOe+619iG3AybJXr7zfNn/4vHz4TH7qSJVQXSaHHvcTcDodAKHnTG1WDulgO5okAQ"}},"state_key":"","type":"m.room.name","unsigned":{"foo":"bar","x":1}}` + + var event Event + if err := json.Unmarshal([]byte(initialEventJSON), &event); err != nil { + t.Error("Failed to parse event") + } + + err := event.SetUnsignedField("foo", "bar") + if err != nil { + t.Error("Failed to insert foo") + } + + err = event.SetUnsignedField("x", 1) + if err != nil { + t.Error("Failed to insert x") + } + + bytes, err := json.Marshal(event) + if err != nil { + t.Error("Failed to marshal x") + } + + if expectedEventJSON != string(bytes) { + t.Fatalf("Serialized event does not match expected: %s != %s", string(bytes), initialEventJSON) + } +} diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go index 6b11ed44..7b56d9e0 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto.go @@ -179,12 +179,21 @@ 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 JSONVerifier) error { // nolint: gocyclo - var toVerify []VerifyJSONRequest - for _, event := range events { +// +// returns an array with either an error or nil for each event. +func VerifyEventSignatures(ctx context.Context, events []Event, keyRing JSONVerifier) ([]error, error) { // nolint: gocyclo + // we will end up doing at least as many verifications as we have events. + // some events require multiple verifications, as they are signed by multiple + // servers. + toVerify := make([]VerifyJSONRequest, 0, len(events)) + + // for each entry in 'events', a list of corresponding indexes in toVerify + verificationMap := make([][]int, len(events)) + + for evtIdx, event := range events { redactedJSON, err := redactEvent(event.eventJSON) if err != nil { - return err + return nil, err } domains := make(map[ServerName]bool) @@ -203,7 +212,7 @@ func VerifyEventSignatures(ctx context.Context, events []Event, keyRing JSONVeri // senderDomain, err := domainFromID(event.Sender()) if err != nil { - return err + return nil, err } domains[ServerName(senderDomain)] = true @@ -212,12 +221,12 @@ func VerifyEventSignatures(ctx context.Context, events []Event, keyRing JSONVeri if event.Type() == MRoomMember && event.StateKey() != nil { targetDomain, err := domainFromID(*event.StateKey()) if err != nil { - return err + return nil, err } if ServerName(targetDomain) != event.Origin() { c, err := newMemberContentFromEvent(event) if err != nil { - return err + return nil, err } if c.Membership == invite { domains[ServerName(targetDomain)] = true @@ -231,22 +240,45 @@ func VerifyEventSignatures(ctx context.Context, events []Event, keyRing JSONVeri AtTS: event.OriginServerTS(), ServerName: domain, } + verificationMap[evtIdx] = append(verificationMap[evtIdx], len(toVerify)) toVerify = append(toVerify, v) } } results, err := keyRing.VerifyJSONs(ctx, toVerify) if err != nil { - return err + return nil, err } - // Check that all the event JSON was correctly signed. - for _, result := range results { - if result.Error != nil { - return result.Error + // Check that all the event JSON was correctly signed + verificationErrors := make([]error, len(events)) + for evtIdx := range events { + for _, verificationIdx := range verificationMap[evtIdx] { + result := results[verificationIdx] + if result.Error != nil { + verificationErrors[evtIdx] = result.Error + break // break inner loop; continue with outer + } } } - // Everything was okay. + return verificationErrors, nil +} + +// VerifyAllEventSignatures checks that each event in a list of events has valid +// signatures from the server that sent it. +// +// returns an error if any event fails verifications +func VerifyAllEventSignatures(ctx context.Context, events []Event, keyRing JSONVerifier) error { + verificationErrors, err := VerifyEventSignatures(ctx, events, keyRing) + if err != nil { + return err + } + for idx := range events { + ve := verificationErrors[idx] + if ve != nil { + return ve + } + } return nil } 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 72d86881..34595004 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/eventcrypto_test.go @@ -272,8 +272,10 @@ func (v *StubVerifier) VerifyJSONs(ctx context.Context, requests []VerifyJSONReq return v.results, nil } -func TestVerifyEventSignatures(t *testing.T) { - verifier := StubVerifier{} +func TestVerifyAllEventSignatures(t *testing.T) { + verifier := StubVerifier{ + results: make([]VerifyJSONResult, 2), + } eventJSON := []byte(`{ "type": "m.room.name", @@ -295,7 +297,7 @@ func TestVerifyEventSignatures(t *testing.T) { event.eventJSON = eventJSON events := []Event{event} - if err := VerifyEventSignatures(context.Background(), events, &verifier); err != nil { + if err := VerifyAllEventSignatures(context.Background(), events, &verifier); err != nil { t.Fatal(err) } @@ -329,8 +331,10 @@ func TestVerifyEventSignatures(t *testing.T) { } } -func TestVerifyEventSignaturesForInvite(t *testing.T) { - verifier := StubVerifier{} +func TestVerifyAllEventSignaturesForInvite(t *testing.T) { + verifier := StubVerifier{ + results: make([]VerifyJSONResult, 2), + } eventJSON := []byte(`{ "type": "m.room.member", @@ -352,7 +356,7 @@ func TestVerifyEventSignaturesForInvite(t *testing.T) { event.eventJSON = eventJSON events := []Event{event} - if err := VerifyEventSignatures(context.Background(), events, &verifier); err != nil { + if err := VerifyAllEventSignatures(context.Background(), events, &verifier); err != nil { t.Fatal(err) } diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go index 299f0841..bcc68b2e 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationclient.go @@ -2,7 +2,6 @@ package gomatrixserverlib import ( "context" - "net/http" "net/url" "golang.org/x/crypto/ed25519" @@ -22,7 +21,7 @@ func NewFederationClient( serverName ServerName, keyID KeyID, privateKey ed25519.PrivateKey, ) *FederationClient { return &FederationClient{ - Client: Client{client: http.Client{Transport: newFederationTripper()}}, + Client: *NewClient(), serverName: serverName, serverKeyID: keyID, serverPrivateKey: privateKey, diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go index ac734ed0..2fd2f53b 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/federationtypes.go @@ -138,7 +138,7 @@ func (r RespState) Check(ctx context.Context, keyRing JSONVerifier) error { // Check if the events pass signature checks. logger.Infof("Checking event signatures for %d events of room state", len(allEvents)) - if err := VerifyEventSignatures(ctx, allEvents, keyRing); err != nil { + if err := VerifyAllEventSignatures(ctx, allEvents, keyRing); err != nil { return err } diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/keys.go b/vendor/src/github.com/matrix-org/gomatrixserverlib/keys.go index 98ff87fd..fab72b3d 100644 --- a/vendor/src/github.com/matrix-org/gomatrixserverlib/keys.go +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/keys.go @@ -110,8 +110,10 @@ func FetchKeysDirect(serverName ServerName, addr, sni string) (*ServerKeys, *tls } defer tcpconn.Close() // nolint: errcheck tlsconn := tls.Client(tcpconn, &tls.Config{ - ServerName: sni, - InsecureSkipVerify: true, // This must be specified even though the TLS library will ignore it. + ServerName: sni, + + // This must be specified even though the TLS library will ignore it. + InsecureSkipVerify: true, // nolint: gas }) if err = tlsconn.Handshake(); err != nil { return nil, nil, err diff --git a/vendor/src/github.com/matrix-org/gomatrixserverlib/travis.sh b/vendor/src/github.com/matrix-org/gomatrixserverlib/travis.sh new file mode 100644 index 00000000..3ba23b61 --- /dev/null +++ b/vendor/src/github.com/matrix-org/gomatrixserverlib/travis.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +set -eux + +cd `dirname $0` + +# -u so that if this is run on a dev box, we get the latest deps, as +# we do on travis. + +go get -u \ + github.com/alecthomas/gometalinter \ + golang.org/x/crypto/ed25519 \ + github.com/matrix-org/util \ + github.com/matrix-org/gomatrix \ + github.com/tidwall/gjson \ + github.com/tidwall/sjson \ + github.com/pkg/errors \ + gopkg.in/yaml.v2 \ + +./hooks/pre-commit