OMEMO cannot bootstrap against prosody-class servers #169
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
OMEMO does not work at all between two fresh cproof accounts on a prosody server:
/omemo gennever publishes the device list or the key bundle, so/omemo starton the peer ends withCan't find a OMEMO device id for <jid>/This message cannot be encrypted for any recipient. Both root causes are ejabberd-isms in the client (the OMEMO guide examples useejabberd.local, which is presumably why this was never hit). Found by live-testing two client instances against prosody 13 in Docker; both fixes below were validated in that setup (encrypted exchange works both ways with them).Bug 1: "node does not exist" is only recognized via the legacy
code="404"error attribute_omemo_receive_devicelist()(src/xmpp/omemo.c, around line 449) handles an error reply to the device-list fetch like this:ejabberd attaches the legacy numeric
codeattribute, prosody sends the plain RFC 6120 defined condition:so the empty-list bootstrap (
omemo_set_device_list(from, NULL)) never runs, the own device id is never merged, and/omemo gennever publishes the device list.Validated fix: also accept the defined condition:
(
omemo_set_device_list()is NULL-from-safe — it falls back toconnection_get_fulljid()— so the reply arriving without afromattribute is fine here.)Bug 2: PEP features are discovered only on the server domain, so the bundle is never published
omemo_bundle_publish()(src/xmpp/omemo.c, around line 91) silently returns whenconnection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)is false.connection_request_features()(src/xmpp/connection.c, around line 655) only ever sends disco#info toconn.domain, but per XEP-0163 §4 the PEP service — includinghttp://jabber.org/protocol/pubsub#publish-options— is announced on the account's own bare JID. prosody announces it only there; ejabberd happens to also expose pubsub features on the domain. Result on prosody: the feature is never seen, the bundle is never published, and even after fixing Bug 1 the peer fails withitem-not-foundon the bundle node.Validated fix: disco the own bare JID as well (mirroring how the domain entry is registered):
The bare JID is deliberately not added to
requested_features, matching the existing comment about not firingsv_ev_connection_features_receivedearly.Reproduction
Two fresh accounts with a mutual presence subscription on any prosody (a stock prosody with
mod_pepon localhost is enough), client started with-l DEBUG:/omemo genon both accounts./omemo starton either side →Can't find a OMEMO device id for <peer>, and after the fallback hint (/omemo end+/omemo start) →This message cannot be encrypted for any recipient.[OMEMO] can't get OMEMO device list, the device-list fetch answered with<item-not-found/>(no legacycodeattribute), and no pubsub publish is ever sent (noSENT: <iq ...><pubsub ...><publishlines).item-not-foundon the bundle node) because the bundle publish is skipped — the sender's log shows no[OMEMO] publish own OMEMO bundleline (Bug 2).With both fixes applied the full flow works: device lists and bundles are published, sessions build on both sides, and messages travel only inside
<encrypted>payloads (verified against the rawSENT:stanzas in the debug log).Notes / related observations from the same test session
can't get OMEMO device listfor a not-yet-created node,[OMEMO][STORE] SG_ERR_INVALID_KEY_IDon the very first session build, item-not-found IQ errors). They are normal-flow noise and would be less alarming at INF/DBG.p_ox_gpg_signcrypt()encrypts withflags = 0(noGPGME_ENCRYPT_ALWAYS_TRUST, unlike the XEP-0027 PGP path), so a key imported via/ox requestis unusable until the user sets ownertrust manually with gpg. That matchesman profanity-ox-setup, but the UX is rough: the client imports the key itself and then refuses to encrypt to it, with an error (Unable to send OX message...) that does not mention trust. Suggestion: mention ownertrust in the error text, or offer an/ox trustcommand. OTR and classic PGP were exercised the same way with no findings.