From a44d40439f02ff71a054a84c01ec3052a644d73a Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 30 Oct 2024 20:30:43 +0300 Subject: Jabber: patch for OMEMO --- protocols/JabberG/src/jabber_omemo.cpp | 101 +++++++++++++++++++++----------- protocols/JabberG/src/jabber_omemo.h | 2 + protocols/JabberG/src/jabber_thread.cpp | 10 +++- protocols/JabberG/src/jabber_util.cpp | 4 ++ 4 files changed, 79 insertions(+), 38 deletions(-) diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index 81bc0a43a5..7a01603a1e 100644 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -966,8 +966,11 @@ complete: if (val == FP_ABSENT) { uint32_t count = 0; db_enum_settings(hContact, omemo::db_enum_settings_fps_cb, proto->m_szModuleName, &count); - if (count) - proto->MsgPopup(hContact, omemo::FormatFingerprint(fp_hex), TranslateT("Unknown device added")); + if (count) { + proto->MsgPopup(hContact, TranslateT("Unknown OMEMO device added!"), + hContact ? Clist_GetContactDisplayName(hContact) : TranslateT("(My devices)")); + proto->setByte(hContact, TrustSettingName, FP_BAD); + } } //always return true to decrypt incoming messages from untrusted devices @@ -1164,6 +1167,38 @@ complete: return CMStringA(suffix); } + int omemo_impl::TOFUAllDevices(MCONTACT hContact) + { + int i; + for (i = 0;; i++) { + int device_id = dbGetDeviceId(hContact, i); + if (device_id == 0) + break; + + MBinBuffer fp(proto->getBlob(hContact, IdentityPrefix + dbGetSuffix(hContact, device_id))); + CMStringA fp_hex(hex_string(fp.data(), fp.length())); + proto->setByte(hContact, "OmemoFingerprintTrusted_" + fp_hex, FP_TOFU); + } + + if (i) { + POPUPDATAW ppd; + ppd.lchIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_HTTP_AUTH)); + if (hContact) { + ppd.lchContact = hContact; + wcsncpy(ppd.lpwzContactName, Clist_GetContactDisplayName(hContact), MAX_CONTACTNAME - 1); + } + else + wcsncpy(ppd.lpwzContactName, TranslateT("(My devices)"), MAX_CONTACTNAME - 1); + + wcsncpy(ppd.lpwzText, + CMStringW(FORMAT, TranslateT("Trust on first use for\n%d devices"), i), + MAX_SECONDLINE - 1); + PUAddPopupW(&ppd); + } + + return i; + } + CMStringA hex_string(const uint8_t *pData, const size_t length) { CMStringA hexstr; @@ -1555,9 +1590,6 @@ bool CJabberProto::OmemoCheckSession(MCONTACT hContact, bool requestBundles) MCONTACT _hContact = !c ? hContact : 0; ptrA jid(ContactToJID(_hContact)); - uint32_t count = 0; - db_enum_settings(_hContact, omemo::db_enum_settings_fps_cb, m_szModuleName, &count); - for (int i = 0;; i++) { int device_id = m_omemo.dbGetDeviceId(_hContact, i); if (device_id == 0) @@ -1565,32 +1597,40 @@ bool CJabberProto::OmemoCheckSession(MCONTACT hContact, bool requestBundles) signal_protocol_address address = { jid, mir_strlen(jid), device_id }; if (!signal_protocol_session_contains_session(m_omemo.store_context, &address)) { - if (requestBundles) { - XmlNodeIq iq(AddIQ(&CJabberProto::OmemoOnIqResultGetBundle, JABBER_IQ_TYPE_GET, nullptr, (void *)!count)); - - char szBareJid[JABBER_MAX_JID_LEN]; - iq << XATTR("from", JabberStripJid(m_ThreadInfo->fullJID, szBareJid, _countof(szBareJid))) << XATTR("to", jid); - TiXmlElement *items = iq << XCHILDNS("pubsub", "http://jabber.org/protocol/pubsub") << XCHILD("items"); - CMStringA szBundle(FORMAT, "%s%s%u", JABBER_FEAT_OMEMO, ".bundles:", device_id); - XmlAddAttr(items, "node", szBundle); - m_ThreadInfo->send(iq); - } ok = false; - } - else { - if (count == 0) { - MBinBuffer fp(getBlob(_hContact, omemo::IdentityPrefix + m_omemo.dbGetSuffix(_hContact, device_id))); - CMStringA fp_hex(omemo::hex_string(fp.data(), fp.length())); - setByte(hContact, "OmemoFingerprintTrusted_" + fp_hex, FP_TOFU); - MsgPopup(hContact, omemo::FormatFingerprint(fp_hex), TranslateT("Trust on first use")); - } + + if (!requestBundles) + break; + + XmlNodeIq iq(AddIQ(&CJabberProto::OmemoOnIqResultGetBundle, JABBER_IQ_TYPE_GET, nullptr, (void *)hContact)); + + char szBareJid[JABBER_MAX_JID_LEN]; + iq << XATTR("from", JabberStripJid(m_ThreadInfo->fullJID, szBareJid, _countof(szBareJid))) << XATTR("to", jid); + TiXmlElement *items = iq << XCHILDNS("pubsub", "http://jabber.org/protocol/pubsub") << XCHILD("items"); + CMStringA szBundle(FORMAT, "%s%s%u", JABBER_FEAT_OMEMO, ".bundles:", device_id); + XmlAddAttr(items, "node", szBundle); + m_ThreadInfo->send(iq); } } } - if (ok && !requestBundles) - OmemoHandleMessageQueue(); + if (ok) { + uint32_t count = 0; + db_enum_settings(hContact, omemo::db_enum_settings_fps_cb, m_szModuleName, &count); + if (count == 0) + m_omemo.TOFUAllDevices(hContact); + + count = 0; + db_enum_settings(0, omemo::db_enum_settings_fps_cb, m_szModuleName, &count); + if (enCarbons && count == 0) { + m_omemo.TOFUAllDevices(0); + setByte(0, "OmemoFingerprintTrusted_" "05600dc0ffee", FP_TOFU); + } + + if (!requestBundles) + OmemoHandleMessageQueue(); + } return ok; } @@ -1688,21 +1728,12 @@ void CJabberProto::OmemoOnIqResultGetBundle(const TiXmlElement *iqNode, CJabberI return; } - if (IqInfo->GetUserData()) { - size_t key_len; - uint8_t *key_buf = (uint8_t *)mir_base64_decode(identityKey->GetText(), &key_len); - CMStringA fp_hex(omemo::hex_string(key_buf, key_len)); - mir_free(key_buf); - setByte(hContact, "OmemoFingerprintTrusted_" + fp_hex, FP_TOFU); - MsgPopup(hContact, omemo::FormatFingerprint(fp_hex), TranslateT("Trust on first use")); - } - if (!m_omemo.build_session(jid, device_id, preKeyId, preKeyPublic, signedPreKeyId, signedPreKeyPublic->GetText(), signedPreKeySignature->GetText(), identityKey->GetText())) { debugLogA("Jabber OMEMO: error: omemo::build_session failed"); return; //failed to build signal(omemo) session } - OmemoCheckSession(hContact, false); + OmemoCheckSession((MCONTACT)IqInfo->GetUserData(), false); } int CJabberProto::OmemoEncryptMessage(XmlNode &msg, const char *msg_text, MCONTACT hContact) diff --git a/protocols/JabberG/src/jabber_omemo.h b/protocols/JabberG/src/jabber_omemo.h index 5a8eb8b69a..f6216891a5 100644 --- a/protocols/JabberG/src/jabber_omemo.h +++ b/protocols/JabberG/src/jabber_omemo.h @@ -68,6 +68,8 @@ namespace omemo CMStringA dbGetSuffix(MCONTACT hContact, int device_id); CMStringA dbGetSuffix(const char* jid, int device_id); + int TOFUAllDevices(MCONTACT hContact); + TiXmlDocument doc; private: diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index cbd8708fbf..b1d5eb28cf 100644 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -1417,8 +1417,12 @@ void CJabberProto::OnProcessMessage(const TiXmlElement *node, ThreadData *info) } // Create a temporary contact, if needed - if (hContact == 0) - hContact = CreateTemporaryContact(from, chatItem); + if (hContact == 0) { + if (item) + hContact = item->hContact; + else + hContact = CreateTemporaryContact(from, chatItem); + } if (!bOffline) CallService(MS_PROTO_CONTACTISTYPING, hContact, PROTOTYPE_CONTACTTYPING_OFF); @@ -1588,7 +1592,7 @@ void CJabberProto::OnProcessPresence(const TiXmlElement *node, ThreadData *info) debugLogA("SKIP Receive presence online from %s (who is not in my roster and not in list - skipping)", from); return; } - hContact = DBCreateContact(from, nick, true, true); + hContact = DBCreateContact(from, nick, true, false); } if (!ListGetItemPtr(LIST_ROSTER, from)) { diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp index 6fcedc0a1c..1c2b2936b6 100644 --- a/protocols/JabberG/src/jabber_util.cpp +++ b/protocols/JabberG/src/jabber_util.cpp @@ -81,6 +81,10 @@ MCONTACT CJabberProto::HContactFromJID(const char *jid, bool bStripResource) if (jid == nullptr) return 0; + if (IsMyOwnJID(jid)) + if (bStripResource || !strchr(jid, '/')) + return 0; + JABBER_LIST_ITEM *item = ListGetItemPtr(LIST_ROSTER, jid); if (item != nullptr && item->hContact) return item->hContact; -- cgit v1.2.3