diff --git a/src/github.com/matrix-org/dendrite/clientapi/thirdpartyinvites/thirdpartyinvites.go b/src/github.com/matrix-org/dendrite/clientapi/thirdpartyinvites/thirdpartyinvites.go index c998a6522..ba55a7cad 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/thirdpartyinvites/thirdpartyinvites.go +++ b/src/github.com/matrix-org/dendrite/clientapi/thirdpartyinvites/thirdpartyinvites.go @@ -47,7 +47,7 @@ type MembershipRequest struct { Address string `json:"address"` } -// idServerLookupResponse represents the response described at https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-identity-api-v1-lookup +// idServerLookupResponse represents the response described at https://matrix.org/docs/spec/identity_service/unstable.html#get-matrix-identity-api-v1-lookup type idServerLookupResponse struct { TS int64 `json:"ts"` NotBefore int64 `json:"not_before"` @@ -58,7 +58,7 @@ type idServerLookupResponse struct { Signatures map[string]map[string]string `json:"signatures"` } -// idServerLookupResponse represents the response described at https://matrix.org/docs/spec/client_server/r0.2.0.html#invitation-storage +// idServerLookupResponse represents the response described at https://matrix.org/docs/spec/identity_service/unstable.html#invitation-storage type idServerStoreInviteResponse struct { PublicKey string `json:"public_key"` Token string `json:"token"` diff --git a/src/github.com/matrix-org/dendrite/roomserver/input/events.go b/src/github.com/matrix-org/dendrite/roomserver/input/events.go index 88c604478..e7015b587 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/input/events.go +++ b/src/github.com/matrix-org/dendrite/roomserver/input/events.go @@ -22,6 +22,8 @@ import ( "github.com/matrix-org/dendrite/roomserver/state" "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/gomatrixserverlib" + + "github.com/Sirupsen/logrus" ) // A RoomEventDatabase has the storage APIs needed to store a room event. @@ -56,6 +58,15 @@ func processRoomEvent(db RoomEventDatabase, ow OutputRoomEventWriter, input api. // Parse and validate the event JSON event := input.Event + if err := checkThirdPartyKeys(input.Event); err != nil { + // At least one of the key could not be validated. The specification + // says that it should not cause a rejection of the event. + // https://matrix.org/docs/spec/client_server/r0.2.0.html#id58 + // There is no direct way to warn the users that the member's + // membership is questionable, so log the error as a warning. + logrus.Warn(err) + } + // Check that the event passes authentication checks and work out the numeric IDs for the auth events. authEventNIDs, err := checkAuthEvents(db, event, input.AuthEventIDs) if err != nil { diff --git a/src/github.com/matrix-org/dendrite/roomserver/input/thirdpartyinvites.go b/src/github.com/matrix-org/dendrite/roomserver/input/thirdpartyinvites.go new file mode 100644 index 000000000..5023375ce --- /dev/null +++ b/src/github.com/matrix-org/dendrite/roomserver/input/thirdpartyinvites.go @@ -0,0 +1,64 @@ +// Copyright 2017 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package input + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + + "github.com/matrix-org/dendrite/common" + "github.com/matrix-org/gomatrixserverlib" +) + +// checkThirdPartyKeys checks the validity of all the public keys in a given +// m.room.third_party_invite event. +// Returns with an error if a key could not be verified. +func checkThirdPartyKeys(event gomatrixserverlib.Event) error { + if event.Type() == "m.room.third_party_invite" { + var content common.ThirdPartyInviteContent + if err := json.Unmarshal(event.Content(), &content); err != nil { + return err + } + + for _, key := range content.PublicKeys { + url := fmt.Sprintf("%s?public_key=%s", key.KeyValidityURL, key.PublicKey) + resp, err := http.Get(url) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + errMsg := fmt.Sprintf("Could not verify the validity of key %s at %s", key.PublicKey, key.KeyValidityURL) + return errors.New(errMsg) + } + + var validity struct { + Valid bool `json:"valid"` + } + if err := json.NewDecoder(resp.Body).Decode(&validity); err != nil { + return err + } + + if !validity.Valid { + errMsg := fmt.Sprintf("Invalid key %s according to %s", key.PublicKey, key.KeyValidityURL) + return errors.New(errMsg) + } + } + } + + return nil +}