1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 17:10:10 +00:00

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) LDFLAGS := $(LDFLAGS) -X main.updater=$(UPDATER)
endif endif
INTERNAL ?= on INTERNAL ?= on
TRAY ?= off
E2EE ?= off
TAGS := -tags "
ifeq ($(INTERNAL), on) ifeq ($(INTERNAL), on)
TAGS :=
DATA := data DATA := data
else else
DATA := build/data DATA := build/data
TAGS := -tags external TAGS := $(TAGS) external
endif endif
TRAY ?= off ifeq ($(TRAY), on)
ifeq ($(INTERNAL)$(TRAY), offon)
TAGS := $(TAGS) tray TAGS := $(TAGS) tray
else ifeq ($(INTERNAL)$(TRAY), onon)
TAGS := -tags tray
endif endif
ifeq ($(E2EE), on)
TAGS := $(TAGS) e2ee
endif
TAGS := $(TAGS)"
OS := $(shell go env GOOS) OS := $(shell go env GOOS)
ifeq ($(TRAY)$(OS), onwindows) ifeq ($(TRAY)$(OS), onwindows)
LDFLAGS := $(LDFLAGS) -H=windowsgui 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 sectName, section := range resp.Sections {
for settingName, setting := range section.Settings { for settingName, setting := range section.Settings {
val := app.config.Section(sectName).Key(settingName) val := app.config.Section(sectName).Key(settingName)

View File

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

View File

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