diff --git a/crypto.go b/crypto.go index 5e1f0d9..6067b99 100644 --- a/crypto.go +++ b/crypto.go @@ -22,6 +22,7 @@ import ( "crypto/hmac" "crypto/sha512" "encoding/hex" + "fmt" "time" "github.com/pkg/errors" @@ -78,7 +79,7 @@ func (helper *CryptoHelper) Init() error { stateStore := &cryptoStateStore{helper.bridge} helper.store = database.NewSQLCryptoStore(helper.bridge.DB, helper.client.DeviceID) helper.store.UserID = helper.client.UserID - helper.store.GhostIDFormat = helper.bridge.Config.Bridge.FormatUsername("%") + helper.store.GhostIDFormat = fmt.Sprintf("@%s:%s", helper.bridge.Config.Bridge.FormatUsername("%"), helper.bridge.AS.HomeserverDomain) helper.mach = crypto.NewOlmMachine(helper.client, logger, helper.store, stateStore) helper.client.Logger = logger.int.Sub("Bot") diff --git a/database/cryptostore.go b/database/cryptostore.go index f044002..5cca49b 100644 --- a/database/cryptostore.go +++ b/database/cryptostore.go @@ -211,6 +211,13 @@ func (store *SQLCryptoStore) AddSession(key id.SenderKey, session *crypto.OlmSes return err } +func (store *SQLCryptoStore) UpdateSession(key id.SenderKey, session *crypto.OlmSession) error { + sessionBytes := session.Internal.Pickle(store.PickleKey) + _, err := store.db.Exec("UPDATE crypto_olm_session SET session=$1, last_used=$2 WHERE session_id=$3", + sessionBytes, session.UseTime, session.ID()) + return err +} + func (store *SQLCryptoStore) PutGroupSession(roomID id.RoomID, senderKey id.SenderKey, sessionID id.SessionID, session *crypto.InboundGroupSession) error { sessionBytes := session.Internal.Pickle(store.PickleKey) forwardingChains := strings.Join(session.ForwardingChains, ",") diff --git a/database/upgrades/2020-05-09-crypto-store.go b/database/upgrades/2020-05-09-crypto-store.go index ea454dc..fd479b0 100644 --- a/database/upgrades/2020-05-09-crypto-store.go +++ b/database/upgrades/2020-05-09-crypto-store.go @@ -18,7 +18,7 @@ func init() { } _, err = tx.Exec(`CREATE TABLE crypto_message_index ( sender_key CHAR(43), - session_id VARCHAR(255), + session_id CHAR(43), "index" INTEGER, event_id VARCHAR(255) NOT NULL, timestamp BIGINT NOT NULL, @@ -49,11 +49,11 @@ func init() { return err } _, err = tx.Exec(`CREATE TABLE crypto_olm_session ( - session_id CHAR(43) PRIMARY KEY, - sender_key VARCHAR(255) NOT NULL, - session bytea NOT NULL, - created_at timestamp NOT NULL, - last_used timestamp NOT NULL + session_id CHAR(43) PRIMARY KEY, + sender_key CHAR(43) NOT NULL, + session bytea NOT NULL, + created_at timestamp NOT NULL, + last_used timestamp NOT NULL )`) if err != nil { return err diff --git a/example-config.yaml b/example-config.yaml index 6b66025..dfe2c25 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -148,6 +148,7 @@ bridge: allow: false # Default to encryption, force-enable encryption in all portals the bridge creates # This will cause the bridge bot to be in private chats for the encryption to work properly. + # It is recommended to also set private_chat_portal_meta to true when using this. default: false # Permissions for using the bridge. diff --git a/go.mod b/go.mod index 38dc65e..f8d6064 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( gopkg.in/yaml.v2 v2.2.8 maunium.net/go/mauflag v1.0.0 maunium.net/go/maulogger/v2 v2.1.1 - maunium.net/go/mautrix v0.4.1 + maunium.net/go/mautrix v0.4.3 ) replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.2.6 diff --git a/go.sum b/go.sum index a109e80..9dbe6fa 100644 --- a/go.sum +++ b/go.sum @@ -88,3 +88,7 @@ maunium.net/go/mautrix v0.4.0 h1:IYfmxCoxR/6UMi92IncsSZeKQbZm8Xa35XIRX814KJ4= maunium.net/go/mautrix v0.4.0/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= maunium.net/go/mautrix v0.4.1 h1:i2lJNT+TE4AAL3cVKUN4jKVRkujCE/oS8aIsj8+7iNE= maunium.net/go/mautrix v0.4.1/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= +maunium.net/go/mautrix v0.4.2 h1:GBU++Z7o/fLPcEsNMkNOUsnDknwV/MGPQ0BN4ikK6tw= +maunium.net/go/mautrix v0.4.2/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= +maunium.net/go/mautrix v0.4.3 h1:fVoJy992TjBEvuK5NeO9fpBh+9JuSFsxaEdGjFp/7h4= +maunium.net/go/mautrix v0.4.3/go.mod h1:8Y+NqmROJyWYvvP4yPfX9tLM59VCfgE/kcQ0SeX68ho= diff --git a/matrix.go b/matrix.go index 3e524f4..42779e2 100644 --- a/matrix.go +++ b/matrix.go @@ -130,6 +130,10 @@ func (mx *MatrixHandler) HandleBotInvite(evt *event.Event) { } func (mx *MatrixHandler) HandleMembership(evt *event.Event) { + if _, isPuppet := mx.bridge.ParsePuppetMXID(evt.Sender); evt.Sender == mx.bridge.Bot.UserID || isPuppet { + return + } + if mx.bridge.Crypto != nil { mx.bridge.Crypto.HandleMemberEvent(evt) } diff --git a/portal.go b/portal.go index ffac2c8..04b6c96 100644 --- a/portal.go +++ b/portal.go @@ -725,7 +725,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error { portal.log.Infoln("Creating Matrix room. Info source:", user.MXID) var metadata *whatsappExt.GroupInfo - isPrivateChat := false if portal.IsPrivateChat() { puppet := portal.bridge.GetPuppetByJID(portal.Key.JID) if portal.bridge.Config.Bridge.PrivateChatPortalMeta { @@ -736,7 +735,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error { portal.Name = "" } portal.Topic = "WhatsApp private chat" - isPrivateChat = true } else if portal.IsStatusBroadcastRoom() { portal.Name = "WhatsApp Status Broadcast" portal.Topic = "WhatsApp status updates from your contacts" @@ -770,13 +768,26 @@ func (portal *Portal) CreateMatrixRoom(user *User) error { invite = portal.bridge.Config.Bridge.Relaybot.InviteUsers } + if portal.bridge.Config.Bridge.Encryption.Default { + initialState = append(initialState, &event.Event{ + Type: event.StateEncryption, + Content: event.Content{ + Parsed: event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1}, + }, + }) + portal.Encrypted = true + if portal.IsPrivateChat() { + invite = append(invite, portal.bridge.Bot.UserID) + } + } + resp, err := intent.CreateRoom(&mautrix.ReqCreateRoom{ Visibility: "private", Name: portal.Name, Topic: portal.Topic, Invite: invite, Preset: "private_chat", - IsDirect: isPrivateChat, + IsDirect: portal.IsPrivateChat(), InitialState: initialState, }) if err != nil { @@ -784,6 +795,12 @@ func (portal *Portal) CreateMatrixRoom(user *User) error { } portal.MXID = resp.RoomID portal.Update() + + // We set the memberships beforehand to make sure the encryption key exchange in initial backfill knows the users are here. + for _, user := range invite { + portal.bridge.StateStore.SetMembership(portal.MXID, user, event.MembershipInvite) + } + if metadata != nil { portal.SyncParticipants(metadata) } else { @@ -796,6 +813,13 @@ func (portal *Portal) CreateMatrixRoom(user *User) error { if portal.IsPrivateChat() { puppet := user.bridge.GetPuppetByJID(portal.Key.JID) user.addPuppetToCommunity(puppet) + + if portal.bridge.Config.Bridge.Encryption.Default { + err = portal.bridge.Bot.EnsureJoined(portal.MXID) + if err != nil { + portal.log.Errorln("Failed to join created portal with bridge bot for e2be:", err) + } + } } err = portal.FillInitialHistory(user) if err != nil {