verificationhelper: better errors/logs and more aggressive cancellations

Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
Sumner Evans 2024-05-21 15:59:48 -06:00
commit 3dbf8ef2f0
No known key found for this signature in database
4 changed files with 119 additions and 62 deletions

View file

@ -35,11 +35,9 @@ func (vh *VerificationHelper) HandleScannedQRData(ctx context.Context, data []by
txn, ok := vh.activeTransactions[qrCode.TransactionID]
if !ok {
log.Warn().Msg("Ignoring QR code scan for an unknown transaction")
return nil
return fmt.Errorf("unknown transaction ID found in QR code")
} else if txn.VerificationState != verificationStateReady {
log.Warn().Msg("Ignoring QR code scan for a transaction that is not in the ready state")
return nil
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "transaction found in the QR code is not in the ready state")
}
txn.VerificationState = verificationStateTheirQRScanned
@ -57,14 +55,14 @@ func (vh *VerificationHelper) HandleScannedQRData(ctx context.Context, data []by
// key, and Key2 is what the other device thinks our device key is.
if vh.client.UserID != txn.TheirUser {
return fmt.Errorf("mode %d is only allowed when the other user is the same as the current user", qrCode.Mode)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "mode %d is only allowed when the other user is the same as the current user", qrCode.Mode)
}
// Verify the master key is correct
if bytes.Equal(ownCrossSigningPublicKeys.MasterKey.Bytes(), qrCode.Key1[:]) {
log.Info().Msg("Verified that the other device has the same master key")
} else {
return fmt.Errorf("the master key does not match")
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeKeyMismatch, "the master key does not match")
}
// Verify that the device key that the other device things we have is
@ -73,11 +71,11 @@ func (vh *VerificationHelper) HandleScannedQRData(ctx context.Context, data []by
if bytes.Equal(myKeys.SigningKey.Bytes(), qrCode.Key2[:]) {
log.Info().Msg("Verified that the other device has the correct key for this device")
} else {
return fmt.Errorf("the other device has the wrong key for this device")
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeKeyMismatch, "the other device has the wrong key for this device")
}
if err := vh.mach.SignOwnMasterKey(ctx); err != nil {
return fmt.Errorf("failed to sign own master key: %w", err)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeKeyMismatch, "failed to sign own master key: %w", err)
}
case QRCodeModeSelfVerifyingMasterKeyUntrusted:
// The QR was created by a device that does not trust the master key,
@ -89,47 +87,47 @@ func (vh *VerificationHelper) HandleScannedQRData(ctx context.Context, data []by
if trusted, err := vh.mach.CryptoStore.IsKeySignedBy(ctx, vh.client.UserID, ownCrossSigningPublicKeys.MasterKey, vh.client.UserID, vh.mach.OwnIdentity().SigningKey); err != nil {
return err
} else if !trusted {
return fmt.Errorf("the master key is not trusted by this device")
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeMasterKeyNotTrusted, "the master key is not trusted by this device, cannot verify device that does not trust the master key")
}
if vh.client.UserID != txn.TheirUser {
return fmt.Errorf("mode %d is only allowed when the other user is the same as the current user", qrCode.Mode)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "mode %d is only allowed when the other user is the same as the current user", qrCode.Mode)
}
// Get their device
theirDevice, err := vh.mach.GetOrFetchDevice(ctx, txn.TheirUser, txn.TheirDevice)
if err != nil {
return err
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeInternalError, "failed to get their device: %w", err)
}
// Verify that the other device's key is what we expect.
if bytes.Equal(theirDevice.SigningKey.Bytes(), qrCode.Key1[:]) {
log.Info().Msg("Verified that the other device key is what we expected")
} else {
return fmt.Errorf("the other device's key is not what we expected")
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeKeyMismatch, "the other device's key is not what we expected")
}
// Verify that what they think the master key is is correct.
if bytes.Equal(vh.mach.GetOwnCrossSigningPublicKeys(ctx).MasterKey.Bytes(), qrCode.Key2[:]) {
log.Info().Msg("Verified that the other device has the correct master key")
} else {
return fmt.Errorf("the master key does not match")
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeKeyMismatch, "the master key does not match")
}
// Trust their device
theirDevice.Trust = id.TrustStateVerified
err = vh.mach.CryptoStore.PutDevice(ctx, txn.TheirUser, theirDevice)
if err != nil {
return fmt.Errorf("failed to update device trust state after verifying: %w", err)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeInternalError, "failed to update device trust state after verifying: %+v", err)
}
// Cross-sign their device with the self-signing key
err = vh.mach.SignOwnDevice(ctx, theirDevice)
if err != nil {
return fmt.Errorf("failed to sign their device: %w", err)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeInternalError, "failed to sign their device: %+v", err)
}
default:
return fmt.Errorf("unknown QR code mode %d", qrCode.Mode)
return vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "unknown QR code mode %d", qrCode.Mode)
}
// Send a m.key.verification.start event with the secret
@ -141,17 +139,20 @@ func (vh *VerificationHelper) HandleScannedQRData(ctx context.Context, data []by
}
err = vh.sendVerificationEvent(ctx, txn, event.InRoomVerificationStart, txn.StartEventContent)
if err != nil {
return err
return fmt.Errorf("failed to send m.key.verification.start event: %w", err)
}
log.Debug().Msg("Successfully sent the m.key.verification.start event")
// Immediately send the m.key.verification.done event, as our side of the
// transaction is done.
err = vh.sendVerificationEvent(ctx, txn, event.InRoomVerificationDone, &event.VerificationDoneEventContent{})
if err != nil {
return err
return fmt.Errorf("failed to send m.key.verification.done event: %w", err)
}
log.Debug().Msg("Successfully sent the m.key.verification.done event")
txn.SentOurDone = true
if txn.ReceivedTheirDone {
log.Debug().Msg("We already received their done event. Setting verification state to done.")
txn.VerificationState = verificationStateDone
vh.verificationDone(ctx, txn.TransactionID)
}
@ -225,15 +226,17 @@ func (vh *VerificationHelper) generateAndShowQRCode(ctx context.Context, txn *ve
Stringer("transaction_id", txn.TransactionID).
Logger()
if vh.showQRCode == nil {
log.Warn().Msg("Ignoring QR code generation request as showing a QR code is not enabled on this device")
log.Info().Msg("Ignoring QR code generation request as showing a QR code is not enabled on this device")
return nil
}
if !slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeScan) {
log.Warn().Msg("Ignoring QR code generation request as other device cannot scan QR codes")
} else if !slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeScan) {
log.Info().Msg("Ignoring QR code generation request as other device cannot scan QR codes")
return nil
}
ownCrossSigningPublicKeys := vh.mach.GetOwnCrossSigningPublicKeys(ctx)
if ownCrossSigningPublicKeys == nil || len(ownCrossSigningPublicKeys.MasterKey) == 0 {
return fmt.Errorf("failed to get own cross-signing master public key")
}
mode := QRCodeModeCrossSigning
if vh.client.UserID == txn.TheirUser {
@ -245,6 +248,8 @@ func (vh *VerificationHelper) generateAndShowQRCode(ctx context.Context, txn *ve
} else {
mode = QRCodeModeSelfVerifyingMasterKeyUntrusted
}
} else {
panic("unimplemented")
}
var key1, key2 []byte
@ -276,7 +281,7 @@ func (vh *VerificationHelper) generateAndShowQRCode(ctx context.Context, txn *ve
// Key 2 is the master signing key.
key2 = ownCrossSigningPublicKeys.MasterKey.Bytes()
default:
log.Fatal().Str("mode", string(mode)).Msg("Unknown QR code mode")
log.Fatal().Int("mode", int(mode)).Msg("Unknown QR code mode")
}
qrCode := NewQRCode(mode, txn.TransactionID, [32]byte(key1), [32]byte(key2))

View file

@ -580,7 +580,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn *verifi
slices.Sort(keyIDs)
expectedKeyMAC, err := vh.verificationMACHKDF(txn, txn.TheirUser, txn.TheirDevice, vh.client.UserID, vh.client.DeviceID, "KEY_IDS", strings.Join(keyIDs, ","))
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeSASMismatch, "failed to calculate key list MAC: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeSASMismatch, "failed to calculate key list MAC: %w", err)
return
}
if !bytes.Equal(expectedKeyMAC, macEvt.Keys) {
@ -607,7 +607,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn *verifi
if kID == txn.TheirDevice.String() {
theirDevice, err = vh.mach.GetOrFetchDevice(ctx, txn.TheirUser, txn.TheirDevice)
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to fetch their device: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to fetch their device: %w", err)
return
}
key = theirDevice.SigningKey.String()
@ -626,7 +626,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn *verifi
expectedMAC, err := vh.verificationMACHKDF(txn, txn.TheirUser, txn.TheirDevice, vh.client.UserID, vh.client.DeviceID, keyID.String(), key)
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to calculate key MAC: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to calculate key MAC: %w", err)
return
}
if !bytes.Equal(expectedMAC, mac) {
@ -639,7 +639,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn *verifi
theirDevice.Trust = id.TrustStateVerified
err = vh.mach.CryptoStore.PutDevice(ctx, txn.TheirUser, theirDevice)
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to update device trust state after verifying: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to update device trust state after verifying: %w", err)
return
}
}
@ -653,7 +653,7 @@ func (vh *VerificationHelper) onVerificationMAC(ctx context.Context, txn *verifi
txn.VerificationState = verificationStateSASMACExchanged
err := vh.sendVerificationEvent(ctx, txn, event.InRoomVerificationDone, &event.VerificationDoneEventContent{})
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to send verification done event: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to send verification done event: %w", err)
return
}
txn.SentOurDone = true

View file

@ -178,31 +178,31 @@ func NewVerificationHelper(client *mautrix.Client, mach *crypto.OlmMachine, call
}
if c, ok := callbacks.(RequiredCallbacks); !ok {
panic("callbacks must implement VerificationRequested")
panic("callbacks must implement RequiredCallbacks")
} else {
helper.verificationRequested = c.VerificationRequested
helper.verificationCancelledCallback = c.VerificationCancelled
helper.verificationDone = c.VerificationDone
}
supportedMethods := map[event.VerificationMethod]struct{}{}
if c, ok := callbacks.(showSASCallbacks); ok {
helper.supportedMethods = append(helper.supportedMethods, event.VerificationMethodSAS)
supportedMethods[event.VerificationMethodSAS] = struct{}{}
helper.showSAS = c.ShowSAS
}
if c, ok := callbacks.(showQRCodeCallbacks); ok {
helper.supportedMethods = append(helper.supportedMethods,
event.VerificationMethodQRCodeShow, event.VerificationMethodReciprocate)
supportedMethods[event.VerificationMethodQRCodeShow] = struct{}{}
supportedMethods[event.VerificationMethodReciprocate] = struct{}{}
helper.scanQRCode = c.ScanQRCode
helper.showQRCode = c.ShowQRCode
helper.qrCodeScaned = c.QRCodeScanned
}
if supportsScan {
helper.supportedMethods = append(helper.supportedMethods,
event.VerificationMethodQRCodeScan, event.VerificationMethodReciprocate)
supportedMethods[event.VerificationMethodQRCodeScan] = struct{}{}
supportedMethods[event.VerificationMethodReciprocate] = struct{}{}
}
slices.Sort(helper.supportedMethods)
helper.supportedMethods = slices.Compact(helper.supportedMethods)
helper.supportedMethods = maps.Keys(supportedMethods)
return &helper
}
@ -332,6 +332,10 @@ func (vh *VerificationHelper) Init(ctx context.Context) error {
// StartVerification starts an interactive verification flow with the given
// user via a to-device event.
func (vh *VerificationHelper) StartVerification(ctx context.Context, to id.UserID) (id.VerificationTransactionID, error) {
if len(vh.supportedMethods) == 0 {
return "", fmt.Errorf("no supported verification methods")
}
txnID := id.NewVerificationTransactionID()
devices, err := vh.mach.CryptoStore.GetDevices(ctx, to)
@ -389,8 +393,8 @@ func (vh *VerificationHelper) StartVerification(ctx context.Context, to id.UserI
return txnID, nil
}
// StartVerification starts an interactive verification flow with the given
// user in the given room.
// StartInRoomVerification starts an interactive verification flow with the
// given user in the given room.
func (vh *VerificationHelper) StartInRoomVerification(ctx context.Context, roomID id.RoomID, to id.UserID) (id.VerificationTransactionID, error) {
log := vh.getLog(ctx).With().
Str("verification_action", "start in-room verification").
@ -441,15 +445,34 @@ func (vh *VerificationHelper) AcceptVerification(ctx context.Context, txnID id.V
txn, ok := vh.activeTransactions[txnID]
if !ok {
return fmt.Errorf("unknown transaction ID")
}
if txn.VerificationState != verificationStateRequested {
} else if txn.VerificationState != verificationStateRequested {
return fmt.Errorf("transaction is not in the requested state")
}
supportedMethods := map[event.VerificationMethod]struct{}{}
for _, method := range txn.TheirSupportedMethods {
switch method {
case event.VerificationMethodSAS:
if slices.Contains(vh.supportedMethods, event.VerificationMethodSAS) {
supportedMethods[event.VerificationMethodSAS] = struct{}{}
}
case event.VerificationMethodQRCodeShow:
if slices.Contains(vh.supportedMethods, event.VerificationMethodQRCodeScan) {
supportedMethods[event.VerificationMethodQRCodeScan] = struct{}{}
supportedMethods[event.VerificationMethodReciprocate] = struct{}{}
}
case event.VerificationMethodQRCodeScan:
if slices.Contains(vh.supportedMethods, event.VerificationMethodQRCodeShow) {
supportedMethods[event.VerificationMethodQRCodeShow] = struct{}{}
supportedMethods[event.VerificationMethodReciprocate] = struct{}{}
}
}
}
log.Info().Msg("Sending ready event")
readyEvt := &event.VerificationReadyEventContent{
FromDevice: vh.client.DeviceID,
Methods: vh.supportedMethods,
Methods: maps.Keys(supportedMethods),
}
err := vh.sendVerificationEvent(ctx, txn, event.InRoomVerificationReady, readyEvt)
if err != nil {
@ -457,7 +480,7 @@ func (vh *VerificationHelper) AcceptVerification(ctx context.Context, txnID id.V
}
txn.VerificationState = verificationStateReady
if slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeShow) {
if vh.scanQRCode != nil && slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeShow) {
vh.scanQRCode(ctx, txn.TransactionID)
}
@ -497,7 +520,7 @@ func (vh *VerificationHelper) sendVerificationEvent(ctx context.Context, txn *ve
Parsed: content,
})
if err != nil {
return fmt.Errorf("failed to send start event: %w", err)
return fmt.Errorf("failed to send %s event to %s: %w", evtType.String(), txn.RoomID, err)
}
} else {
content.(event.VerificationTransactionable).SetTransactionID(txn.TransactionID)
@ -508,15 +531,19 @@ func (vh *VerificationHelper) sendVerificationEvent(ctx context.Context, txn *ve
}}
_, err := vh.client.SendToDevice(ctx, evtType, &req)
if err != nil {
return fmt.Errorf("failed to send start event: %w", err)
return fmt.Errorf("failed to send %s event to %s: %w", evtType.String(), txn.TheirDevice, err)
}
}
return nil
}
// cancelVerificationTxn cancels a verification transaction with the given code
// and reason. It always returns an error, which is the formatted error message
// (this is allows the caller to return the result of this function call
// directly to expose the error to its caller).
func (vh *VerificationHelper) cancelVerificationTxn(ctx context.Context, txn *verificationTransaction, code event.VerificationCancelCode, reasonFmtStr string, fmtArgs ...any) error {
log := vh.getLog(ctx)
reason := fmt.Sprintf(reasonFmtStr, fmtArgs...)
reason := fmt.Errorf(reasonFmtStr, fmtArgs...).Error()
log.Info().
Stringer("transaction_id", txn.TransactionID).
Str("code", string(code)).
@ -528,11 +555,11 @@ func (vh *VerificationHelper) cancelVerificationTxn(ctx context.Context, txn *ve
}
err := vh.sendVerificationEvent(ctx, txn, event.InRoomVerificationCancel, cancelEvt)
if err != nil {
return err
return fmt.Errorf("failed to send cancel verification event (code: %s, reason: %s): %w", code, reason, err)
}
txn.VerificationState = verificationStateCancelled
vh.verificationCancelledCallback(ctx, txn.TransactionID, code, reason)
return nil
return fmt.Errorf("verification cancelled (code: %s): %s", code, reason)
}
func (vh *VerificationHelper) onVerificationRequest(ctx context.Context, evt *event.Event) {
@ -568,7 +595,7 @@ func (vh *VerificationHelper) onVerificationRequest(ctx context.Context, evt *ev
return
}
if verificationRequest.TransactionID == "" {
if len(verificationRequest.TransactionID) == 0 {
log.Warn().Msg("Ignoring verification request without a transaction ID")
return
}
@ -581,11 +608,33 @@ func (vh *VerificationHelper) onVerificationRequest(ctx context.Context, evt *ev
ctx = log.WithContext(ctx)
log.Info().Msg("Received verification request")
// Check if we support any of the methods listed
var supportsAnyMethod bool
for _, method := range verificationRequest.Methods {
switch method {
case event.VerificationMethodSAS:
supportsAnyMethod = slices.Contains(vh.supportedMethods, event.VerificationMethodSAS)
case event.VerificationMethodQRCodeScan:
supportsAnyMethod = slices.Contains(vh.supportedMethods, event.VerificationMethodQRCodeShow) &&
slices.Contains(verificationRequest.Methods, event.VerificationMethodReciprocate)
case event.VerificationMethodQRCodeShow:
supportsAnyMethod = slices.Contains(vh.supportedMethods, event.VerificationMethodQRCodeScan) &&
slices.Contains(verificationRequest.Methods, event.VerificationMethodReciprocate)
}
if supportsAnyMethod {
break
}
}
if !supportsAnyMethod {
log.Warn().Msg("Ignoring verification request that doesn't have any methods we support")
return
}
vh.activeTransactionsLock.Lock()
_, ok := vh.activeTransactions[verificationRequest.TransactionID]
existing, ok := vh.activeTransactions[verificationRequest.TransactionID]
if ok {
vh.activeTransactionsLock.Unlock()
log.Info().Msg("Ignoring verification request for an already active transaction")
vh.cancelVerificationTxn(ctx, existing, event.VerificationCancelCodeUnexpectedMessage, "received a new verification request for the same transaction ID")
return
}
vh.activeTransactions[verificationRequest.TransactionID] = &verificationTransaction{
@ -607,7 +656,7 @@ func (vh *VerificationHelper) onVerificationReady(ctx context.Context, txn *veri
Logger()
if txn.VerificationState != verificationStateRequested {
log.Warn().Msg("Ignoring verification ready event for a transaction that is not in the requested state")
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "verification ready event received for a transaction that is not in the requested state")
return
}
@ -633,7 +682,7 @@ func (vh *VerificationHelper) onVerificationReady(ctx context.Context, txn *veri
}
devices, err := vh.mach.CryptoStore.GetDevices(ctx, txn.TheirUser)
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to get devices for %s: %v", txn.TheirUser, err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to get devices for %s: %w", txn.TheirUser, err)
return
}
req := mautrix.ReqSendToDevice{Messages: map[id.UserID]map[id.DeviceID]*event.Content{txn.TheirUser: {}}}
@ -653,13 +702,13 @@ func (vh *VerificationHelper) onVerificationReady(ctx context.Context, txn *veri
}
}
if slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeShow) {
if vh.scanQRCode != nil && slices.Contains(txn.TheirSupportedMethods, event.VerificationMethodQRCodeShow) {
vh.scanQRCode(ctx, txn.TransactionID)
}
err := vh.generateAndShowQRCode(ctx, txn)
if err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to generate and show QR code: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to generate and show QR code: %w", err)
}
}
@ -680,8 +729,7 @@ func (vh *VerificationHelper) onVerificationStart(ctx context.Context, txn *veri
// We didn't sent a start event yet, so we have gotten ourselves
// into a bad state. They've either sent two start events, or we
// have gone on to a new state.
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage,
"got repeat start event from other user")
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "got repeat start event from other user")
return
}
@ -713,8 +761,7 @@ func (vh *VerificationHelper) onVerificationStart(ctx context.Context, txn *veri
txn.StartEventContent = startEvt
}
} else if txn.VerificationState != verificationStateReady {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage,
"got start event for transaction that is not in ready state")
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "got start event for transaction that is not in ready state")
return
}
@ -722,7 +769,7 @@ func (vh *VerificationHelper) onVerificationStart(ctx context.Context, txn *veri
case event.VerificationMethodSAS:
txn.VerificationState = verificationStateSASStarted
if err := vh.onVerificationStartSAS(ctx, txn, evt); err != nil {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to handle SAS verification start: %v", err)
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUser, "failed to handle SAS verification start: %w", err)
}
case event.VerificationMethodReciprocate:
log.Info().Msg("Received reciprocate start event")
@ -749,9 +796,10 @@ func (vh *VerificationHelper) onVerificationDone(ctx context.Context, txn *verif
vh.activeTransactionsLock.Lock()
defer vh.activeTransactionsLock.Unlock()
if txn.VerificationState != verificationStateTheirQRScanned && txn.VerificationState != verificationStateSASMACExchanged {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage,
"got done event for transaction that is not in QR-scanned or MAC-exchanged state")
if !slices.Contains([]verificationState{
verificationStateTheirQRScanned, verificationStateOurQRScanned, verificationStateSASMACExchanged,
}, txn.VerificationState) {
vh.cancelVerificationTxn(ctx, txn, event.VerificationCancelCodeUnexpectedMessage, "got done event for transaction that is not in QR-scanned or MAC-exchanged state")
return
}

View file

@ -220,6 +220,10 @@ const (
VerificationCancelCodeAccepted VerificationCancelCode = "m.accepted"
VerificationCancelCodeSASMismatch VerificationCancelCode = "m.mismatched_sas"
VerificationCancelCodeCommitmentMismatch VerificationCancelCode = "m.mismatched_commitment"
// Non-spec codes
VerificationCancelCodeInternalError VerificationCancelCode = "com.beeper.internal_error"
VerificationCancelCodeMasterKeyNotTrusted VerificationCancelCode = "com.beeper.master_key_not_trusted" // the master key is not trusted by this device, but the QR code that was scanned was from a device that doesn't trust the master key
)
// VerificationCancelEventContent represents the content of an