End to bridge encryption implementation
So far this is passing my basic tests, but could use some testing from people that are much more familiar with how this is supposed to work. Refs #27
This commit is contained in:
@@ -35,6 +35,7 @@ type Portal struct {
|
||||
log log.Logger
|
||||
|
||||
roomCreateLock sync.Mutex
|
||||
encryptLock sync.Mutex
|
||||
|
||||
discordMessages chan portalDiscordMessage
|
||||
matrixMessages chan portalMatrixMessage
|
||||
@@ -144,7 +145,7 @@ func (p *Portal) handleMatrixInvite(sender *User, evt *event.Event) {
|
||||
p.log.Infoln("no puppet for %v", sender)
|
||||
// Open a conversation on the discord side?
|
||||
}
|
||||
p.log.Infoln("puppet:", puppet)
|
||||
p.log.Infoln("matrixInvite: puppet:", puppet)
|
||||
}
|
||||
|
||||
func (p *Portal) messageLoop() {
|
||||
@@ -212,14 +213,25 @@ func (p *Portal) createMatrixRoom(user *User, channel *discordgo.Channel) error
|
||||
|
||||
var invite []id.UserID
|
||||
|
||||
if p.IsPrivateChat() {
|
||||
invite = append(invite, p.bridge.bot.UserID)
|
||||
if p.bridge.Config.Bridge.Encryption.Default {
|
||||
initialState = append(initialState, &event.Event{
|
||||
Type: event.StateEncryption,
|
||||
Content: event.Content{
|
||||
Parsed: event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1},
|
||||
},
|
||||
})
|
||||
p.Encrypted = true
|
||||
|
||||
if p.IsPrivateChat() {
|
||||
invite = append(invite, p.bridge.bot.UserID)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := intent.CreateRoom(&mautrix.ReqCreateRoom{
|
||||
Visibility: "private",
|
||||
Name: p.Name,
|
||||
Topic: p.Topic,
|
||||
Invite: invite,
|
||||
Preset: "private_chat",
|
||||
IsDirect: p.IsPrivateChat(),
|
||||
InitialState: initialState,
|
||||
@@ -325,7 +337,7 @@ func (p *Portal) sendMediaFailedMessage(intent *appservice.IntentAPI, bridgeErr
|
||||
MsgType: event.MsgNotice,
|
||||
}
|
||||
|
||||
_, err := intent.SendMessageEvent(p.MXID, event.EventMessage, content)
|
||||
_, err := p.sendMatrixMessage(intent, event.EventMessage, content, nil, time.Now().UTC().UnixMilli())
|
||||
if err != nil {
|
||||
p.log.Warnfln("failed to send error message to matrix: %v", err)
|
||||
}
|
||||
@@ -379,7 +391,7 @@ func (p *Portal) handleDiscordAttachment(intent *appservice.IntentAPI, msgID str
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := intent.SendMessageEvent(p.MXID, event.EventMessage, content)
|
||||
resp, err := p.sendMatrixMessage(intent, event.EventMessage, content, nil, time.Now().UTC().UnixMilli())
|
||||
if err != nil {
|
||||
p.log.Warnfln("failed to send media message to matrix: %v", err)
|
||||
}
|
||||
@@ -426,7 +438,7 @@ func (p *Portal) handleDiscordMessageCreate(user *User, msg *discordgo.Message)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := intent.SendMessageEvent(p.MXID, event.EventMessage, content)
|
||||
resp, err := p.sendMatrixMessage(intent, event.EventMessage, content, nil, time.Now().UTC().UnixMilli())
|
||||
if err != nil {
|
||||
p.log.Warnfln("failed to send message %q to matrix: %v", msg.ID, err)
|
||||
|
||||
@@ -498,7 +510,7 @@ func (p *Portal) handleDiscordMessagesUpdate(user *User, msg *discordgo.Message)
|
||||
|
||||
content.SetEdit(existing.MatrixID)
|
||||
|
||||
resp, err := intent.SendMessageEvent(p.MXID, event.EventMessage, content)
|
||||
resp, err := p.sendMatrixMessage(intent, event.EventMessage, content, nil, time.Now().UTC().UnixMilli())
|
||||
if err != nil {
|
||||
p.log.Warnfln("failed to send message %q to matrix: %v", msg.ID, err)
|
||||
|
||||
@@ -567,6 +579,57 @@ func (p *Portal) syncParticipants(source *User, participants []*discordgo.User)
|
||||
}
|
||||
}
|
||||
|
||||
func (portal *Portal) encrypt(content *event.Content, eventType event.Type) (event.Type, error) {
|
||||
if portal.Encrypted && portal.bridge.crypto != nil {
|
||||
// TODO maybe the locking should be inside mautrix-go?
|
||||
portal.encryptLock.Lock()
|
||||
encrypted, err := portal.bridge.crypto.Encrypt(portal.MXID, eventType, *content)
|
||||
portal.encryptLock.Unlock()
|
||||
if err != nil {
|
||||
return eventType, fmt.Errorf("failed to encrypt event: %w", err)
|
||||
}
|
||||
eventType = event.EventEncrypted
|
||||
content.Parsed = encrypted
|
||||
}
|
||||
return eventType, nil
|
||||
}
|
||||
|
||||
const doublePuppetKey = "fi.mau.double_puppet_source"
|
||||
const doublePuppetValue = "mautrix-discord"
|
||||
|
||||
func (portal *Portal) sendMatrixMessage(intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent, extraContent map[string]interface{}, timestamp int64) (*mautrix.RespSendEvent, error) {
|
||||
wrappedContent := event.Content{Parsed: content, Raw: extraContent}
|
||||
if timestamp != 0 && intent.IsCustomPuppet {
|
||||
if wrappedContent.Raw == nil {
|
||||
wrappedContent.Raw = map[string]interface{}{}
|
||||
}
|
||||
if intent.IsCustomPuppet {
|
||||
wrappedContent.Raw[doublePuppetKey] = doublePuppetValue
|
||||
}
|
||||
}
|
||||
var err error
|
||||
eventType, err = portal.encrypt(&wrappedContent, eventType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if eventType == event.EventEncrypted {
|
||||
// Clear other custom keys if the event was encrypted, but keep the double puppet identifier
|
||||
if intent.IsCustomPuppet {
|
||||
wrappedContent.Raw = map[string]interface{}{doublePuppetKey: doublePuppetValue}
|
||||
} else {
|
||||
wrappedContent.Raw = nil
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = intent.UserTyping(portal.MXID, false, 0)
|
||||
if timestamp == 0 {
|
||||
return intent.SendMessageEvent(portal.MXID, eventType, &wrappedContent)
|
||||
} else {
|
||||
return intent.SendMassagedMessageEvent(portal.MXID, eventType, &wrappedContent, timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Portal) handleMatrixMessages(msg portalMatrixMessage) {
|
||||
switch msg.evt.Type {
|
||||
case event.EventMessage:
|
||||
|
||||
Reference in New Issue
Block a user