diff --git a/src/github.com/matrix-org/dendrite/appservice/consumers/roomserver.go b/src/github.com/matrix-org/dendrite/appservice/consumers/roomserver.go index cafd229c4..1a0404ac5 100644 --- a/src/github.com/matrix-org/dendrite/appservice/consumers/roomserver.go +++ b/src/github.com/matrix-org/dendrite/appservice/consumers/roomserver.go @@ -105,12 +105,15 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error { return err } - if err = s.db.UpdateMemberships(context.TODO(), events, output.NewRoomEvent.RemovesStateEventIDs); err != nil { + // Create a context to thread through the whole filtering process + ctx := context.TODO() + + if err = s.db.UpdateMemberships(ctx, events, output.NewRoomEvent.RemovesStateEventIDs); err != nil { return err } // Check if any events need to passed on to external application services - return s.filterRoomserverEvents(append(events, ev)) + return s.filterRoomserverEvents(ctx, append(events, ev)) } // lookupStateEvents looks up the state events that are added by a new event. @@ -162,11 +165,11 @@ func (s *OutputRoomEventConsumer) lookupStateEvents( // each namespace of each registered application service, and if there is a // match, adds the event to the queue for events to be sent to a particular // application service. -func (s *OutputRoomEventConsumer) filterRoomserverEvents(events []gomatrixserverlib.Event) error { +func (s *OutputRoomEventConsumer) filterRoomserverEvents(ctx context.Context, events []gomatrixserverlib.Event) error { for _, event := range events { for _, appservice := range appServices { // Check if this event is interesting to this application service - if s.appserviceIsInterestedInEvent(event, appservice) { + if s.appserviceIsInterestedInEvent(ctx, event, appservice) { // TODO: Queue this event to be sent off to the application service fmt.Println(appservice.ID, "was interested in", event.Sender(), event.Type(), event.RoomID()) } @@ -178,7 +181,7 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(events []gomatrixserver // appserviceIsInterestedInEvent returns a boolean depending on whether a given // event falls within one of a given application service's namespaces. -func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(event gomatrixserverlib.Event, appservice config.ApplicationService) bool { +func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event gomatrixserverlib.Event, appservice config.ApplicationService) bool { // Check sender of the event for _, userNamespace := range appservice.NamespaceMap["users"] { if userNamespace.RegexpObject.MatchString(event.Sender()) { @@ -196,7 +199,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(event gomatrixse // Check all known room aliases of the room the event came from queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID()} var queryRes api.GetAliasesForRoomIDResponse - if err := s.alias.GetAliasesForRoomID(context.TODO(), &queryReq, &queryRes); err == nil { + if err := s.alias.GetAliasesForRoomID(ctx, &queryReq, &queryRes); err == nil { for _, alias := range queryRes.Aliases { for _, aliasNamespace := range appservice.NamespaceMap["aliases"] { if aliasNamespace.RegexpObject.MatchString(alias) { @@ -205,7 +208,9 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(event gomatrixse } } } else { - log.WithError(err).Errorf("Unable to get aliases for Room with ID: %s", event.RoomID()) + log.WithFields(log.Fields{ + "room_id": event.RoomID(), + }).WithError(err).Errorf("Unable to get aliases for room") } return false diff --git a/src/github.com/matrix-org/dendrite/common/config/appservice.go b/src/github.com/matrix-org/dendrite/common/config/appservice.go index c644e6a1f..0cc3c0b47 100644 --- a/src/github.com/matrix-org/dendrite/common/config/appservice.go +++ b/src/github.com/matrix-org/dendrite/common/config/appservice.go @@ -92,10 +92,11 @@ func loadAppservices(config *Dendrite) error { // methods can quickly check if a particular string matches any of them. func setupRegexps(cfg *Dendrite) (err error) { // Combine all exclusive namespaces for later string checking - var exclusiveUsernameStrings, exclusiveAliasStrings, exclusiveRoomStrings []string + var exclusiveUsernameStrings, exclusiveAliasStrings []string // If an application service's regex is marked as exclusive, add - // it's contents to the overall exlusive regex string + // its contents to the overall exlusive regex string. Room regex + // not necessary as we aren't denying exclusive room ID creation for _, appservice := range cfg.Derived.ApplicationServices { for key, namespaceSlice := range appservice.NamespaceMap { switch key { @@ -103,19 +104,18 @@ func setupRegexps(cfg *Dendrite) (err error) { appendExclusiveNamespaceRegexs(&exclusiveUsernameStrings, namespaceSlice) case "aliases": appendExclusiveNamespaceRegexs(&exclusiveAliasStrings, namespaceSlice) - case "rooms": - appendExclusiveNamespaceRegexs(&exclusiveRoomStrings, namespaceSlice) } } } + fmt.Println(exclusiveUsernameStrings, exclusiveAliasStrings) + // Join the regexes together into one big regex. // i.e. "app1.*", "app2.*" -> "(app1.*)|(app2.*)" - // Later we can check if a username or some other string matches any exclusive - // regex and deny access if it isn't from an application service + // Later we can check if a username or alias matches any exclusive regex and + // deny access if it isn't from an application service exclusiveUsernames := strings.Join(exclusiveUsernameStrings, "|") exclusiveAliases := strings.Join(exclusiveAliasStrings, "|") - exclusiveRooms := strings.Join(exclusiveRoomStrings, "|") // If there are no exclusive regexes, compile string so that it will not match // any valid usernames/aliases/roomIDs @@ -125,9 +125,6 @@ func setupRegexps(cfg *Dendrite) (err error) { if exclusiveAliases == "" { exclusiveAliases = "^$" } - if exclusiveRooms == "" { - exclusiveRooms = "^$" - } // Store compiled Regex if cfg.Derived.ExclusiveApplicationServicesUsernameRegexp, err = regexp.Compile(exclusiveUsernames); err != nil { @@ -136,9 +133,6 @@ func setupRegexps(cfg *Dendrite) (err error) { if cfg.Derived.ExclusiveApplicationServicesAliasRegexp, err = regexp.Compile(exclusiveAliases); err != nil { return err } - if cfg.Derived.ExclusiveApplicationServicesRoomRegexp, err = regexp.Compile(exclusiveRooms); err != nil { - return err - } return nil } @@ -167,14 +161,16 @@ func checkErrors(config *Dendrite) (err error) { var idMap = make(map[string]bool) var tokenMap = make(map[string]bool) - // Check that no two application services have the same as_token or id + // Check each application service for any config errors for _, appservice := range config.Derived.ApplicationServices { - // Check if we've already seen this ID + // Check if we've already seen this ID. No two application services + // can have the same ID or token. if idMap[appservice.ID] { return configErrors([]string{fmt.Sprintf( "Application Service ID %s must be unique", appservice.ID, )}) } + // Check if we've already seen this token if tokenMap[appservice.ASToken] { return configErrors([]string{fmt.Sprintf( "Application Service Token %s must be unique", appservice.ASToken, @@ -185,6 +181,18 @@ func checkErrors(config *Dendrite) (err error) { // seen them. idMap[appservice.ID] = true tokenMap[appservice.ID] = true + + // Check if more than one regex exists per namespace + for _, namespace := range appservice.NamespaceMap { + if len(namespace) > 1 { + // It's quite easy to accidentally make multiple regex objects per + // namespace, which often ends up in an application service receiving events + // it doesn't want, as an empty regex will match all events. + return configErrors([]string{fmt.Sprintf( + "Application Service namespace can only contain a single regex tuple. Check your YAML.", + )}) + } + } } // Check that namespace(s) are valid regex @@ -200,8 +208,7 @@ func checkErrors(config *Dendrite) (err error) { } } - err = setupRegexps(config) - return err + return setupRegexps(config) } // IsValidRegex returns true or false based on whether the diff --git a/src/github.com/matrix-org/dendrite/common/config/config.go b/src/github.com/matrix-org/dendrite/common/config/config.go index b21c2a061..8bbac80c6 100644 --- a/src/github.com/matrix-org/dendrite/common/config/config.go +++ b/src/github.com/matrix-org/dendrite/common/config/config.go @@ -244,10 +244,8 @@ type Dendrite struct { // When a user creates a room alias, we check that it isn't already // reserved by an application service ExclusiveApplicationServicesAliasRegexp *regexp.Regexp - // TODO: Huh? When a room ID is created, we block the client from - // creating it if it falls under an application service's exclusive - // roomID regex? But why tho - ExclusiveApplicationServicesRoomRegexp *regexp.Regexp + // Note: An Exclusive Regex for room ID isn't necessary as we aren't blocking + // servers from creating RoomIDs in exclusive application service namespaces } `yaml:"-"` }