瀏覽代碼

Wait up to 3 seconds for encryption keys to arrive

Tulir Asokan 4 年之前
父節點
當前提交
d67c3a8c96
共有 8 個文件被更改,包括 38 次插入13 次删除
  1. 6 0
      crypto.go
  2. 2 2
      go.mod
  3. 4 0
      go.sum
  4. 3 2
      main.go
  5. 13 2
      matrix.go
  6. 2 0
      no-crypto.go
  7. 6 5
      portal.go
  8. 2 2
      user.go

+ 6 - 0
crypto.go

@@ -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)
 }

+ 2 - 2
go.mod

@@ -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 - 0
go.sum

@@ -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=

+ 3 - 2
main.go

@@ -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()

+ 13 - 2
matrix.go

@@ -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
 	}

+ 2 - 0
no-crypto.go

@@ -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")

+ 6 - 5
portal.go

@@ -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
 		}

+ 2 - 2
user.go

@@ -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 {