Wait up to 3 seconds for encryption keys to arrive

This commit is contained in:
Tulir Asokan 2020-09-24 15:25:36 +03:00
parent 0b2fd69bf1
commit d67c3a8c96
8 changed files with 38 additions and 13 deletions

View file

@ -36,6 +36,8 @@ import (
"maunium.net/go/mautrix-whatsapp/database"
)
var NoSessionFound = crypto.NoSessionFound
var levelTrace = maulogger.Level{
Name: "Trace",
Severity: -10,
@ -183,6 +185,10 @@ func (helper *CryptoHelper) Encrypt(roomID id.RoomID, evtType event.Type, conten
return encrypted, nil
}
func (helper *CryptoHelper) WaitForSession(roomID id.RoomID, senderKey id.SenderKey, sessionID id.SessionID, timeout time.Duration) bool {
return helper.mach.WaitForSession(roomID, senderKey, sessionID, timeout)
}
func (helper *CryptoHelper) HandleMemberEvent(evt *event.Event) {
helper.mach.HandleMemberEvent(evt)
}

4
go.mod
View file

@ -16,7 +16,7 @@ require (
gopkg.in/yaml.v2 v2.3.0
maunium.net/go/mauflag v1.0.0
maunium.net/go/maulogger/v2 v2.1.1
maunium.net/go/mautrix v0.7.4
maunium.net/go/mautrix v0.7.7
)
replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.3.8
replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.3.9

4
go.sum
View file

@ -125,6 +125,8 @@ github.com/tulir/go-whatsapp v0.3.7 h1:6YoHsAlO+Y1SnU0bOntDmuvJQziEnBjFKO+1fOH2V
github.com/tulir/go-whatsapp v0.3.7/go.mod h1:7yGOBdWidM6gsmbAFwgkwHEIhzVrm01+6UbImpMWfTM=
github.com/tulir/go-whatsapp v0.3.8 h1:cRPyYhtgokUyeE2wsSlRpsw9qddi0Giun+kn9fGsl/M=
github.com/tulir/go-whatsapp v0.3.8/go.mod h1:7yGOBdWidM6gsmbAFwgkwHEIhzVrm01+6UbImpMWfTM=
github.com/tulir/go-whatsapp v0.3.9 h1:fs2G8TMsSJ2y93UxM9pnFHGxMjKrdFAyavqG8MxpNQA=
github.com/tulir/go-whatsapp v0.3.9/go.mod h1:U5+sm33vrv3wz62YyRM/VS7q2ObXkxU4Xqj/3KOmN9o=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
@ -227,3 +229,5 @@ maunium.net/go/mautrix v0.7.2 h1:ru//jj7Y5Xj9CXBpeNyWCoxjq8iT0d+a2lNeSiN9P/o=
maunium.net/go/mautrix v0.7.2/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
maunium.net/go/mautrix v0.7.4 h1:MDjrvDyHcu5ozKAa80ohcXmYAXZTHgHxrhiERtvkEdY=
maunium.net/go/mautrix v0.7.4/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
maunium.net/go/mautrix v0.7.7 h1:yfpTizagog8NRHcMjxkCyY7Vreb0OEXaessaJBaLQrw=
maunium.net/go/mautrix v0.7.7/go.mod h1:FpsAvwNdG3Zeup7Y2Nlv81Lk0h6iVRPoIy6D7g/7YCE=

View file

@ -44,7 +44,7 @@ var (
Name = "mautrix-whatsapp"
URL = "https://github.com/tulir/mautrix-whatsapp"
// This is changed when making a release
Version = "0.1.4"
Version = "0.1.4"
// This is filled by init()
WAVersion = ""
// These are filled at build time with the -X linker flag
@ -134,7 +134,7 @@ type Bridge struct {
Formatter *Formatter
Relaybot *User
Crypto Crypto
Metrics *MetricsHandler
Metrics *MetricsHandler
usersByMXID map[id.UserID]*User
usersByJID map[types.WhatsAppID]*User
@ -153,6 +153,7 @@ type Crypto interface {
HandleMemberEvent(*event.Event)
Decrypt(*event.Event) (*event.Event, error)
Encrypt(id.RoomID, event.Type, event.Content) (*event.EncryptedEventContent, error)
WaitForSession(id.RoomID, id.SenderKey, id.SessionID, time.Duration) bool
Init() error
Start()
Stop()

View file

@ -17,12 +17,14 @@
package main
import (
"errors"
"fmt"
"strings"
"time"
"maunium.net/go/maulogger/v2"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
@ -330,6 +332,8 @@ func (mx *MatrixHandler) shouldIgnoreEvent(evt *event.Event) bool {
return false
}
const sessionWaitTimeout = 3 * time.Second
func (mx *MatrixHandler) HandleEncrypted(evt *event.Event) {
defer mx.bridge.Metrics.TrackEvent(evt.Type)()
if mx.shouldIgnoreEvent(evt) || mx.bridge.Crypto == nil {
@ -337,10 +341,17 @@ func (mx *MatrixHandler) HandleEncrypted(evt *event.Event) {
}
decrypted, err := mx.bridge.Crypto.Decrypt(evt)
if err != nil {
content := evt.Content.AsEncrypted()
if errors.Is(err, NoSessionFound) && mx.bridge.Crypto.WaitForSession(evt.RoomID, content.SenderKey, content.SessionID, sessionWaitTimeout) {
mx.log.Debugfln("Got session %s to decrypt %s after waiting a while, trying to decrypt again", evt.ID, content.SessionID)
decrypted, err = mx.bridge.Crypto.Decrypt(evt)
}
}
if err != nil {
mx.log.Warnfln("Failed to decrypt %s: %v", evt.ID, err)
_, _ = mx.bridge.Bot.SendNotice(evt.RoomID, fmt.Sprintf(
"\u26a0 Your message was not bridged: %v. " +
"\u26a0 Your message was not bridged: %v. "+
"Try restarting your client if this error keeps happening.", err))
return
}

View file

@ -9,3 +9,5 @@ func NewCryptoHelper(bridge *Bridge) Crypto {
bridge.Log.Debugln("Bridge built without end-to-bridge encryption")
return nil
}
var NoSessionFound = errors.New("nil")

View file

@ -1129,7 +1129,7 @@ func (portal *Portal) HandleMessageRevoke(user *User, message whatsappExt.Messag
msg.Delete()
}
func (portal *Portal) HandleFakeMessage(source *User, message FakeMessage) {
func (portal *Portal) HandleFakeMessage(_ *User, message FakeMessage) {
if portal.isRecentlyHandled(message.ID) {
return
}
@ -1465,9 +1465,10 @@ func (portal *Portal) HandleMediaMessage(source *User, msg mediaMessage) {
uploaded, err := intent.UploadBytes(data, uploadMimeType)
if err != nil {
httpErr := err.(mautrix.HTTPError)
if httpErr.Code == 413 {
portal.sendMediaBridgeFailure(source, intent, msg.info, errors.New("server rejected too large file"))
if errors.Is(err, mautrix.MTooLarge) {
portal.sendMediaBridgeFailure(source, intent, msg.info, errors.New("homeserver rejected too large file"))
} else if httpErr := err.(mautrix.HTTPError); httpErr.IsStatus(413) {
portal.sendMediaBridgeFailure(source, intent, msg.info, errors.New("proxy rejected too large file"))
} else {
portal.sendMediaBridgeFailure(source, intent, msg.info, errors.Wrap(err, "failed to upload media"))
}
@ -2100,7 +2101,7 @@ func (portal *Portal) Cleanup(puppetsOnly bool) {
portal.log.Errorln("Failed to get portal members for cleanup:", err)
return
}
for member, _ := range members.Joined {
for member := range members.Joined {
if member == intent.UserID {
continue
}

View file

@ -18,6 +18,7 @@ package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"sort"
@ -26,7 +27,6 @@ import (
"sync"
"time"
"github.com/pkg/errors"
"github.com/skip2/go-qrcode"
log "maunium.net/go/maulogger/v2"
@ -683,7 +683,7 @@ func (user *User) updateLastConnectionIfNecessary() {
}
func (user *User) HandleError(err error) {
if errors.Cause(err) != whatsapp.ErrInvalidWsData {
if !errors.Is(err, whatsapp.ErrInvalidWsData) {
user.log.Errorfln("WhatsApp error: %v", err)
}
if closed, ok := err.(*whatsapp.ErrConnectionClosed); ok {