matrix: E2EE as build option

since this is so broken and requires CGO deps, E2EE support is now only
included with "make E2EE=on ...". The option to enable will then appear
in settings.
This commit is contained in:
Harvey Tindall 2021-07-16 15:41:08 +01:00
parent 7f37633423
commit 762d5325fb
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
6 changed files with 98 additions and 40 deletions

View File

@ -18,22 +18,30 @@ else ifneq ($(UPDATER), off)
LDFLAGS := $(LDFLAGS) -X main.updater=$(UPDATER)
endif
INTERNAL ?= on
TRAY ?= off
E2EE ?= off
TAGS := -tags "
ifeq ($(INTERNAL), on)
TAGS :=
DATA := data
else
DATA := build/data
TAGS := -tags external
TAGS := $(TAGS) external
endif
TRAY ?= off
ifeq ($(INTERNAL)$(TRAY), offon)
ifeq ($(TRAY), on)
TAGS := $(TAGS) tray
else ifeq ($(INTERNAL)$(TRAY), onon)
TAGS := -tags tray
endif
ifeq ($(E2EE), on)
TAGS := $(TAGS) e2ee
endif
TAGS := $(TAGS)"
OS := $(shell go env GOOS)
ifeq ($(TRAY)$(OS), onwindows)
LDFLAGS := $(LDFLAGS) -H=windowsgui

10
api.go
View File

@ -1667,6 +1667,16 @@ func (app *appContext) GetConfig(gc *gin.Context) {
}
}
}
if !MatrixE2EE() {
delete(resp.Sections["matrix"].Settings, "encryption")
for i, v := range resp.Sections["matrix"].Order {
if v == "encryption" {
sect := resp.Sections["matrix"]
sect.Order = append(sect.Order[:i], sect.Order[i+1:]...)
resp.Sections["matrix"] = sect
}
}
}
for sectName, section := range resp.Sections {
for settingName, setting := range section.Settings {
val := app.config.Section(sectName).Key(settingName)

View File

@ -747,6 +747,16 @@
],
"value": "en-us",
"description": "Default Matrix message language. Visit weblate if you'd like to translate."
},
"encryption": {
"name": "End-to-end encryption (experimental)",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"advanced": true,
"type": "bool",
"value": false,
"description": "Enable end-to-end encryption for messages. Very experimental, currently does not support receiving commands (e.g !lang)."
}
}
},

View File

@ -6,7 +6,7 @@ import (
"time"
"github.com/gomarkdown/markdown"
gomatrix "maunium.net/go/mautrix"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
@ -15,7 +15,7 @@ import (
type MatrixDaemon struct {
Stopped bool
ShutdownChannel chan string
bot *gomatrix.Client
bot *mautrix.Client
userID id.UserID
tokens map[string]UnverifiedUser // Map of tokens to users
languages map[id.RoomID]string // Map of roomIDs to language codes
@ -40,9 +40,9 @@ type MatrixUser struct {
Contact bool
}
var matrixFilter = gomatrix.Filter{
Room: gomatrix.RoomFilter{
Timeline: gomatrix.FilterPart{
var matrixFilter = mautrix.Filter{
Room: mautrix.RoomFilter{
Timeline: mautrix.FilterPart{
Types: []event.Type{
event.EventMessage,
event.EventEncrypted,
@ -76,7 +76,7 @@ func newMatrixDaemon(app *appContext) (d *MatrixDaemon, err error) {
app: app,
start: time.Now().UnixNano() / 1e6,
}
d.bot, err = gomatrix.NewClient(homeserver, d.userID, token)
d.bot, err = mautrix.NewClient(homeserver, d.userID, token)
if err != nil {
return
}
@ -96,16 +96,16 @@ func newMatrixDaemon(app *appContext) (d *MatrixDaemon, err error) {
}
func (d *MatrixDaemon) generateAccessToken(homeserver, username, password string) (string, error) {
req := &gomatrix.ReqLogin{
Type: gomatrix.AuthTypePassword,
Identifier: gomatrix.UserIdentifier{
Type: gomatrix.IdentifierTypeUser,
req := &mautrix.ReqLogin{
Type: mautrix.AuthTypePassword,
Identifier: mautrix.UserIdentifier{
Type: mautrix.IdentifierTypeUser,
User: username,
},
Password: password,
DeviceID: id.DeviceID("jfa-go-" + commit),
}
bot, err := gomatrix.NewClient(homeserver, id.UserID(username), "")
bot, err := mautrix.NewClient(homeserver, id.UserID(username), "")
if err != nil {
return "", err
}
@ -119,7 +119,7 @@ func (d *MatrixDaemon) generateAccessToken(homeserver, username, password string
func (d *MatrixDaemon) run() {
startTime := d.start
d.app.info.Println("Starting Matrix bot daemon")
syncer := d.bot.Syncer.(*gomatrix.DefaultSyncer)
syncer := d.bot.Syncer.(*mautrix.DefaultSyncer)
HandleSyncerCrypto(startTime, d, syncer)
syncer.OnEventType(event.EventMessage, d.handleMessage)
@ -135,7 +135,7 @@ func (d *MatrixDaemon) Shutdown() {
close(d.ShutdownChannel)
}
func (d *MatrixDaemon) handleMessage(source gomatrix.EventSource, evt *event.Event) {
func (d *MatrixDaemon) handleMessage(source mautrix.EventSource, evt *event.Event) {
if evt.Timestamp < d.start {
return
}
@ -189,8 +189,8 @@ func (d *MatrixDaemon) commandLang(evt *event.Event, code, lang string) {
}
func (d *MatrixDaemon) CreateRoom(userID string) (roomID id.RoomID, encrypted bool, err error) {
var room *gomatrix.RespCreateRoom
room, err = d.bot.CreateRoom(&gomatrix.ReqCreateRoom{
var room *mautrix.RespCreateRoom
room, err = d.bot.CreateRoom(&mautrix.ReqCreateRoom{
Visibility: "private",
Invite: []id.UserID{id.UserID(userID)},
Topic: d.app.config.Section("matrix").Key("topic").String(),
@ -221,7 +221,7 @@ func (d *MatrixDaemon) SendStart(userID string) (ok bool) {
Encrypted: encrypted,
},
}
err = d.send(
err = d.sendToRoom(
&event.MessageEventContent{
MsgType: event.MsgText,
Body: d.app.storage.lang.Telegram[lang].Strings.get("matrixStartMessage") + "\n\n" + pin + "\n\n" +
@ -237,18 +237,20 @@ func (d *MatrixDaemon) SendStart(userID string) (ok bool) {
return
}
func (d *MatrixDaemon) send(content *event.MessageEventContent, roomID id.RoomID) (err error) {
func (d *MatrixDaemon) sendToRoom(content *event.MessageEventContent, roomID id.RoomID) (err error) {
if encrypted, ok := d.isEncrypted[roomID]; ok && encrypted {
err = SendEncrypted(d, content, roomID)
} else {
_, err = d.bot.SendMessageEvent(roomID, event.NewEventType("m.room.message"), content, gomatrix.ReqSendEvent{})
}
if err != nil {
return
_, err = d.bot.SendMessageEvent(roomID, event.EventMessage, content, mautrix.ReqSendEvent{})
}
return
}
func (d *MatrixDaemon) send(content *event.MessageEventContent, roomID id.RoomID) (err error) {
_, err = d.bot.SendMessageEvent(roomID, event.EventMessage, content, mautrix.ReqSendEvent{})
return
}
func (d *MatrixDaemon) Send(message *Message, users ...MatrixUser) (err error) {
md := ""
if message.Markdown != "" {
@ -264,11 +266,7 @@ func (d *MatrixDaemon) Send(message *Message, users ...MatrixUser) (err error) {
content.Format = "org.matrix.custom.html"
}
for _, user := range users {
if user.Encrypted {
err = SendEncrypted(d, content, id.RoomID(user.RoomID))
} else {
err = d.send(content, id.RoomID(user.RoomID))
}
err = d.sendToRoom(content, id.RoomID(user.RoomID))
if err != nil {
return
}

View File

@ -1,3 +1,5 @@
// +build e2ee
package main
import (
@ -5,19 +7,19 @@ import (
"strings"
"maunium.net/go/mautrix"
gomatrix "maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
func MatrixE2EE() bool { return true }
type stateStore struct {
isEncrypted *map[id.RoomID]bool
}
func (m *stateStore) IsEncrypted(roomID id.RoomID) bool {
// encrypted, ok := (*m.isEncrypted)[roomID]
// fmt.Println("ISENCRYPTED", roomID, ok && encrypted)
// return ok && encrypted
return true
}
@ -117,11 +119,11 @@ func HandleSyncerCrypto(startTime int64, d *MatrixDaemon, syncer *mautrix.Defaul
if !d.Encryption {
return
}
syncer.OnSync(func(resp *gomatrix.RespSync, since string) bool {
syncer.OnSync(func(resp *mautrix.RespSync, since string) bool {
d.olm.ProcessSyncResponse(resp, since)
return true
})
syncer.OnEventType(event.StateMember, func(source gomatrix.EventSource, evt *event.Event) {
syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) {
d.olm.HandleMemberEvent(evt)
// if evt.Content.AsMember().Membership != event.MembershipJoin {
// return
@ -137,7 +139,7 @@ func HandleSyncerCrypto(startTime int64, d *MatrixDaemon, syncer *mautrix.Defaul
// return
// }
})
syncer.OnEventType(event.EventEncrypted, func(source gomatrix.EventSource, evt *event.Event) {
syncer.OnEventType(event.EventEncrypted, func(source mautrix.EventSource, evt *event.Event) {
if evt.Timestamp < startTime {
return
}
@ -147,7 +149,6 @@ func HandleSyncerCrypto(startTime int64, d *MatrixDaemon, syncer *mautrix.Defaul
d.app.err.Printf("Failed to decrypt Matrix message: %v", err)
return
}
fmt.Println("RECV", decrypted.Content.Raw["body"])
d.handleMessage(source, decrypted)
})
}
@ -192,14 +193,12 @@ func SendEncrypted(d *MatrixDaemon, content *event.MessageEventContent, roomID i
var encrypted *event.EncryptedEventContent
encrypted, err = d.olm.EncryptMegolmEvent(roomID, event.EventMessage, content)
if err == crypto.SessionExpired || err == crypto.SessionNotShared || err == crypto.NoGroupSession {
fmt.Println("SGS")
// err = d.olm.ShareGroupSession(id.RoomID(user.RoomID), []id.UserID{id.UserID(user.UserID), d.userID})
var userIDs []id.UserID
userIDs, err = d.getUserIDs(roomID)
if err != nil {
return
}
fmt.Println("SHARETO", userIDs)
err = d.olm.ShareGroupSession(roomID, userIDs)
if err != nil {
return

33
matrix_nocrypto.go Normal file
View File

@ -0,0 +1,33 @@
// +build !e2ee
package main
import (
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
func MatrixE2EE() bool { return false }
func InitMatrixCrypto(d *MatrixDaemon) (err error) {
d.Encryption = false
return
}
func HandleSyncerCrypto(startTime int64, d *MatrixDaemon, syncer *mautrix.DefaultSyncer) {
return
}
func CryptoShutdown(d *MatrixDaemon) {
return
}
func EncryptRoom(d *MatrixDaemon, room *mautrix.RespCreateRoom, userID id.UserID) (encrypted bool) {
return
}
func SendEncrypted(d *MatrixDaemon, content *event.MessageEventContent, roomID id.RoomID) (err error) {
err = d.send(content, roomID)
return
}