diff --git a/clients/clients.go b/clients/clients.go index 6d7e502..31a1560 100644 --- a/clients/clients.go +++ b/clients/clients.go @@ -16,6 +16,7 @@ import ( shellwords "github.com/mattn/go-shellwords" log "github.com/sirupsen/logrus" "maunium.net/go/mautrix" + "maunium.net/go/mautrix/crypto" mevt "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -72,8 +73,9 @@ func (c *Clients) Start() error { } type clientEntry struct { - config api.ClientConfig - client *mautrix.Client + config api.ClientConfig + client *mautrix.Client + olmMachine *crypto.OlmMachine } func (c *Clients) getClient(userID id.UserID) clientEntry { @@ -104,7 +106,7 @@ func (c *Clients) loadClientFromDB(userID id.UserID) (entry clientEntry, err err return } - if entry.client, err = c.newClient(entry.config); err != nil { + if err = c.initClient(&entry); err != nil { return } @@ -125,7 +127,7 @@ func (c *Clients) updateClientInDB(newConfig api.ClientConfig) (new clientEntry, new.config = newConfig - if new.client, err = c.newClient(new.config); err != nil { + if err = c.initClient(&new); err != nil { return } @@ -206,7 +208,35 @@ func (c *Clients) onMessageEvent(client *mautrix.Client, event *mevt.Event) { } for _, content := range responses { - if _, err := client.SendMessageEvent(event.RoomID, mevt.EventMessage, content); err != nil { + evtType := mevt.EventMessage + curClient := c.clients[client.UserID] + olmMachine := curClient.olmMachine + if olmMachine.StateStore.IsEncrypted(event.RoomID) { + fmt.Println(event.RoomID, "is enc") + if sess, err := olmMachine.CryptoStore.GetOutboundGroupSession(event.RoomID); err != nil { + fmt.Println("Error getting outbound", err) + } else if sess == nil { + if membs, err := client.JoinedMembers(event.RoomID); err != nil { + fmt.Println(err) + } else { + memberIDs := make([]id.UserID, 0, len(membs.Joined)) + for member := range membs.Joined { + memberIDs = append(memberIDs, member) + } + if err = olmMachine.ShareGroupSession(event.RoomID, memberIDs); err != nil { + fmt.Println(err) + } + } + } + msgContent := mevt.Content{Parsed: content} + if enc, err := olmMachine.EncryptMegolmEvent(event.RoomID, mevt.EventMessage, msgContent); err != nil { + fmt.Println("error encoding", err) + } else { + content = enc + evtType = mevt.EventEncrypted + } + } + if _, err := client.SendMessageEvent(event.RoomID, evtType, content); err != nil { log.WithFields(log.Fields{ log.ErrorKey: err, "room_id": event.RoomID, @@ -341,35 +371,37 @@ func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { } } -func (c *Clients) newClient(config api.ClientConfig) (*mautrix.Client, error) { +func (c *Clients) initClient(clientEntry *clientEntry) error { + config := clientEntry.config client, err := mautrix.NewClient(config.HomeserverURL, config.UserID, config.AccessToken) if err != nil { - return nil, err + return err } + client.Client = c.httpClient client.DeviceID = config.DeviceID syncer := client.Syncer.(*mautrix.DefaultSyncer) + nebStore := &matrix.NEBStore{ InMemoryStore: *mautrix.NewInMemoryStore(), Database: c.db, ClientConfig: config, } client.Store = nebStore - syncer.Store = nebStore // TODO: Check that the access token is valid for the userID by peforming // a request against the server. - syncer.OnEventType(mevt.EventMessage, func(event *mevt.Event) { + syncer.OnEventType(mevt.EventMessage, func(_ mautrix.EventSource, event *mevt.Event) { c.onMessageEvent(client, event) }) - syncer.OnEventType(mevt.Type{Type: "m.room.bot.options", Class: mevt.UnknownEventType}, func(event *mevt.Event) { + syncer.OnEventType(mevt.Type{Type: "m.room.bot.options", Class: mevt.UnknownEventType}, func(_ mautrix.EventSource, event *mevt.Event) { c.onBotOptionsEvent(client, event) }) if config.AutoJoinRooms { - syncer.OnEventType(mevt.StateMember, func(event *mevt.Event) { + syncer.OnEventType(mevt.StateMember, func(_ mautrix.EventSource, event *mevt.Event) { c.onRoomMemberEvent(client, event) }) } @@ -398,5 +430,53 @@ func (c *Clients) newClient(config api.ClientConfig) (*mautrix.Client, error) { }() } - return client, nil + clientEntry.client = client + + gobStore, err := crypto.NewGobStore("crypto.gob") + if err != nil { + return err + } + + stateStore := StateStore{&nebStore.InMemoryStore} + olmMachine := crypto.NewOlmMachine(client, CryptoMachineLogger{}, gobStore, &stateStore) + olmMachine.Load() + clientEntry.olmMachine = olmMachine + + syncer.OnSync(stateStore.UpdateStateStore) + // Process sync response with olm machine + syncer.OnSync(func(resp *mautrix.RespSync, since string) bool { + olmMachine.ProcessSyncResponse(resp, since) + if err := olmMachine.CryptoStore.Flush(); err != nil { + fmt.Println("cryptostore flush err", err) + } + return true + }) + + syncer.OnEventType(mevt.StateMember, func(_ mautrix.EventSource, evt *mevt.Event) { + olmMachine.HandleMemberEvent(evt) + }) + + syncer.OnEventType(mevt.EventEncrypted, func(source mautrix.EventSource, evt *mevt.Event) { + evt.Content.ParseRaw(mevt.EventEncrypted) + evt, err := olmMachine.DecryptMegolmEvent(evt) + if err != nil { + fmt.Println("decryption err", err) + } else { + if evt.Type == mevt.EventMessage { + err = evt.Content.ParseRaw(mevt.EventMessage) + if err != nil { + fmt.Println("parsing msg err", err) + } else { + c.onMessageEvent(client, evt) + } + } + fmt.Println("decrypted type", evt.Type) + } + }) + + // Ignore events before neb's join event. + eventIgnorer := mautrix.OldEventIgnorer{UserID: config.UserID} + eventIgnorer.Register(syncer) + + return nil } diff --git a/go.mod b/go.mod index 24d8f26..e5796a2 100644 --- a/go.mod +++ b/go.mod @@ -45,12 +45,11 @@ require ( github.com/sirupsen/logrus v1.4.2 github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect golang.org/dl v0.0.0-20200601221412-a954fa24b3e5 // indirect - golang.org/x/net v0.0.0-20200505041828-1ed23360d12c + golang.org/x/net v0.0.0-20200602114024-627f9648deb9 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/tools v0.0.0-20200311090712-aafaee8bce8c // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.8 - maunium.net/go/gomuks v0.1.0 - maunium.net/go/mautrix v0.4.7 + gopkg.in/yaml.v2 v2.3.0 + maunium.net/go/mautrix v0.5.0-rc.1 ) diff --git a/go.sum b/go.sum index 982e162..d285f74 100644 --- a/go.sum +++ b/go.sum @@ -173,6 +173,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc= github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= @@ -209,6 +210,8 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3ob golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M= golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -224,6 +227,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -251,11 +255,14 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -maunium.net/go/gomuks v0.1.0 h1:Ra0But5Cr3UfCSzd456x8MzV6jXLisZG0gW7RZY1xnk= -maunium.net/go/gomuks v0.1.0/go.mod h1:UWB7mC4OcKINQ2+ygalRSsSvnROoiwdSxdVLrWTeco4= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/maulogger/v2 v2.1.1/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A= maunium.net/go/mautrix v0.4.2/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= maunium.net/go/mautrix v0.4.7 h1:jpclbeGcuiHPIWZFZhQJoxgZKP9f+9OLBPtcDNMFV/o= maunium.net/go/mautrix v0.4.7/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= +maunium.net/go/mautrix v0.5.0-rc.1 h1:Ux2rwQfgf044lXjzCXmaY6VVJPcLioNzdN3okbOVIlg= +maunium.net/go/mautrix v0.5.0-rc.1/go.mod h1:LnkFnB1yjCbb8V+upoEHDGvI/F38NHSTWYCe2RRJgSY= maunium.net/go/mauview v0.1.1/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o= maunium.net/go/tcell v0.2.0/go.mod h1:9Apcb3lNNS6C6lCqKT9UFp7BTRzHXfWE+/tgufsAMho= diff --git a/services/echo/echo.go b/services/echo/echo.go index ca9b3a0..f10de5a 100644 --- a/services/echo/echo.go +++ b/services/echo/echo.go @@ -23,7 +23,7 @@ type Service struct { // Responds with a notice of "some message". func (e *Service) Commands(cli *mautrix.Client) []types.Command { return []types.Command{ - types.Command{ + { Path: []string{"echo"}, Command: func(roomID id.RoomID, userID id.UserID, args []string) (interface{}, error) { return &mevt.MessageEventContent{