diff options
author | George Hazan <ghazan@miranda.im> | 2023-04-17 21:08:49 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2023-04-17 21:08:49 +0300 |
commit | b6bb2574a234f205b4809aa3b4a37788a8a85063 (patch) | |
tree | 0a39715ec76a7d44fe6bdec7a4e2f2367384a297 | |
parent | 84f1eac98d46db881cc5c1cb09939bdae67224a9 (diff) |
Jabber: more OMEMO related fixes
-rw-r--r-- | include/m_database.h | 1 | ||||
-rw-r--r-- | include/m_protosvc.h | 2 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_omemo.cpp | 72 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_omemo.h | 6 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_proto.cpp | 4 | ||||
-rw-r--r-- | protocols/JabberG/src/jabber_userinfo.cpp | 10 | ||||
-rw-r--r-- | src/core/stdmsg/res/private.ico | bin | 0 -> 1150 bytes | |||
-rw-r--r-- | src/core/stdmsg/res/resource.rc | 4 | ||||
-rw-r--r-- | src/core/stdmsg/res/unverified.ico | bin | 0 -> 1150 bytes | |||
-rw-r--r-- | src/core/stdmsg/src/globals.cpp | 8 | ||||
-rw-r--r-- | src/core/stdmsg/src/msgdialog.cpp | 41 | ||||
-rw-r--r-- | src/core/stdmsg/src/msglog.cpp | 7 | ||||
-rw-r--r-- | src/core/stdmsg/src/msgs.h | 1 | ||||
-rw-r--r-- | src/core/stdmsg/src/resource.h | 2 | ||||
-rw-r--r-- | src/mir_app/src/proto_interface.cpp | 4 |
15 files changed, 126 insertions, 36 deletions
diff --git a/include/m_database.h b/include/m_database.h index b55c1abedc..b8a2ce2c86 100644 --- a/include/m_database.h +++ b/include/m_database.h @@ -178,6 +178,7 @@ struct DBVARIANT #define DBEF_ENCRYPTED 0x0020 // event is encrypted (never reported outside a driver)
#define DBEF_HAS_ID 0x0040 // event has unique server id
#define DBEF_SECURE 0x0080 // event is encrypted
+#define DBEF_SECURE_STRONG 0x0100 // event has unique server id
struct DBEVENTINFO
{
diff --git a/include/m_protosvc.h b/include/m_protosvc.h index 11963877d0..e65682d949 100644 --- a/include/m_protosvc.h +++ b/include/m_protosvc.h @@ -144,6 +144,7 @@ static __inline unsigned long Proto_Status2Flag(int status) #define PFLAG_UNIQUEIDTEXT 100 // returns a static buffer of text describing the unique field by which this protocol identifies users (already translated), or NULL
#define PFLAG_MAXCONTACTSPERPACKET 200 // returns the maximum number of contacts which can be sent in a single PSS_CONTACTS, lParam = (LPARAM)hContact.
#define PFLAG_MAXLENOFMESSAGE 400 // return the maximum length of an instant message, lParam = (LPARAM)hContact
+#define PFLAG_GETCURRENTENCRYPTION 800 // returns current encryption name
///////////////////////////////////////////////////////////////////////////////
// A protocol might not support this cap, it allows a protocol to say that
@@ -722,6 +723,7 @@ struct PROTOFILERESUME #define PREF_RTL 4 // 0.5+ addition: support for right-to-left messages
#define PREF_SENT 16 // message will be created with the DBEF_SENT flag
#define PREF_ENCRYPTED 32 // message is encrypted
+#define PREF_ENCRYPTED_STRONG 64// message is encrypted with verified key
struct PROTORECVEVENT
{
diff --git a/protocols/JabberG/src/jabber_omemo.cpp b/protocols/JabberG/src/jabber_omemo.cpp index 06ebb64647..267f5f8608 100644 --- a/protocols/JabberG/src/jabber_omemo.cpp +++ b/protocols/JabberG/src/jabber_omemo.cpp @@ -1007,6 +1007,14 @@ complete: return 0;
}
+ int db_enum_settings_fps_cb(const char *szSetting, void *lParam)
+ {
+ if (strstr(szSetting, "OmemoFingerprintTrusted_") == szSetting)
+ (*(uint32_t*)lParam)++;
+
+ return 0;
+ }
+
int is_trusted_identity(const signal_protocol_address * address, uint8_t * key_data, size_t key_len, void * user_data)
{
/**
@@ -1027,10 +1035,28 @@ complete: */
auto *proto = (CJabberProto *)user_data;
- CMStringA TrustSettingName("OmemoFingerprintTrusted_");
- TrustSettingName.Append(omemo::hex_string(key_data, key_len));
+ CMStringA fp_hex(omemo::hex_string(key_data, key_len));
+ CMStringA TrustSettingName("OmemoFingerprintTrusted_" + fp_hex);
+
+ MCONTACT hContact = proto->HContactFromJID(address->name);
+ char val = proto->getByte(hContact, TrustSettingName, FP_ABSENT);
+ if (val != FP_ABSENT)
+ return (bool)val;
+ else {
+ uint32_t count = 0;
+ db_enum_settings(hContact, db_enum_settings_fps_cb, proto->m_szModuleName, &count);
+ db_set_blob(hContact, proto->m_szModuleName, TrustSettingName, key_data, (int)key_len);
+ if (count == 0) {
+ proto->setByte(hContact, TrustSettingName, FP_TOFU);
+ return true;
+ }
+ else {
+ proto->setByte(hContact, TrustSettingName, FP_BAD);
+ return false;
+ }
+ }
- return proto->getByte(proto->HContactFromJID(address->name), TrustSettingName);
+ return false;
}
bool omemo_impl::create_session_store()
@@ -1119,27 +1145,20 @@ complete: return false; // TODO: cleanup
}
mir_free(key_buf); // TODO: check this
- bool fp_trusted = false;
- {
- // check fingerprint
- SignalBuffer buf(identity_key_p);
- ptrA fingerprint((char *)mir_alloc((buf.len() * 2) + 1));
- bin2hex(buf.data(), buf.len(), fingerprint);
- CMStringA szSetting(FORMAT, "%s%s", "OmemoFingerprintTrusted_", fingerprint);
- char val = proto->getByte(hContact, szSetting, -1);
- if (val == 1)
- fp_trusted = true;
- if (val == -1) {
- CMStringW szMsg(FORMAT, L"%s\n\n", TranslateT("Do you want to create OMEMO session with new device:"));
- int ret = MessageBoxW(nullptr, szMsg + FormatFingerprint(fingerprint), _A2T(jid), MB_YESNO);
- if (ret == IDYES) {
- proto->setByte(hContact, szSetting, 1);
- fp_trusted = true;
- }
- else if (ret == IDNO)
- proto->setByte(hContact, szSetting, 0);
- }
+ // check fingerprint
+ SignalBuffer buf(identity_key_p);
+ ptrA fingerprint((char *)mir_alloc((buf.len() * 2) + 1));
+ bin2hex(buf.data(), buf.len(), fingerprint);
+ CMStringA szSetting(FORMAT, "%s%s", "OmemoFingerprintTrusted_", fingerprint);
+ char val = proto->getByte(hContact, szSetting, -1);
+ if (val == -1) {
+ CMStringW szMsg(FORMAT, L"%s\n\n", TranslateT("Do you want to create OMEMO session with new device:"));
+ int ret = MessageBoxW(nullptr, szMsg + FormatFingerprint(fingerprint), _A2T(jid), MB_YESNO);
+ if (ret == IDYES)
+ proto->setByte(hContact, szSetting, FP_TOFU);
+ else if (ret == IDNO)
+ proto->setByte(hContact, szSetting, FP_BAD);
}
key_buf = (uint8_t*)mir_base64_decode(signed_pre_key_signature, &key_buf_len);
@@ -1307,10 +1326,6 @@ uint32_t JabberGetLastContactMessageTime(MCONTACT hContact); bool CJabberProto::OmemoHandleMessage(const TiXmlElement *node, const char *jid, time_t msgTime)
{
MCONTACT hContact = HContactFromJID(jid);
- if (!OmemoCheckSession(hContact)) {
- debugLogA("Jabber OMEMO: sessions not yet created, session creation launched");
- return false;
- }
auto *header_node = XmlFirstChild(node, "header");
if (!header_node) {
@@ -1513,7 +1528,8 @@ bool CJabberProto::OmemoHandleDeviceList(const char *from, const TiXmlElement *n OmemoSendBundle();
}
- OmemoCheckSession(0);
+ if (m_bEnableCarbons && (m_ThreadInfo->jabberServerCaps & JABBER_CAPS_CARBONS))
+ OmemoCheckSession(0);
}
else {
// store device id's
diff --git a/protocols/JabberG/src/jabber_omemo.h b/protocols/JabberG/src/jabber_omemo.h index 5751c4f823..34881d3217 100644 --- a/protocols/JabberG/src/jabber_omemo.h +++ b/protocols/JabberG/src/jabber_omemo.h @@ -27,6 +27,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <map>
#include <list>
+
+#define FP_BAD 0
+#define FP_TOFU 1
+#define FP_VERIFIED 2
+#define FP_ABSENT -1
+
struct CJabberProto;
struct signal_crypto_provider;
diff --git a/protocols/JabberG/src/jabber_proto.cpp b/protocols/JabberG/src/jabber_proto.cpp index 6ffe603acb..777f37e450 100644 --- a/protocols/JabberG/src/jabber_proto.cpp +++ b/protocols/JabberG/src/jabber_proto.cpp @@ -630,6 +630,10 @@ INT_PTR CJabberProto::GetCaps(int type, MCONTACT hContact) JabberCapsBits jcb = GetResourceCapabilities(szClientJid);
return ((~jcb & JABBER_CAPS_ROSTER_EXCHANGE) ? 0 : 50);
}
+ break;
+
+ case PFLAG_GETCURRENTENCRYPTION:
+ return (INT_PTR)((OmemoIsEnabled(hContact) && m_bUseOMEMO && !isChatRoom(hContact)) ? "OMEMO" : nullptr);
}
return 0;
}
diff --git a/protocols/JabberG/src/jabber_userinfo.cpp b/protocols/JabberG/src/jabber_userinfo.cpp index f340641a3c..9be0712683 100644 --- a/protocols/JabberG/src/jabber_userinfo.cpp +++ b/protocols/JabberG/src/jabber_userinfo.cpp @@ -831,7 +831,11 @@ public: if (!fp.isEmpty()) {
fp_hex = omemo::hex_string(fp.data(), fp.length());
int8_t trusted = ppro->getByte(m_hContact, "OmemoFingerprintTrusted_" + fp_hex);
- wsStatus = trusted ? TranslateT("Trusted") : TranslateT("UNTRUSTED");
+ if (trusted > FP_VERIFIED)
+ trusted = FP_ABSENT;
+
+ const wchar_t *status[] = { L"Bad", L"TOFU", L"Verified" };
+ wsStatus = TranslateW(status[trusted]);
}
MBinBuffer session(ppro->getBlob(m_hContact, "OmemoSignalSession_" + suffix));
@@ -868,9 +872,7 @@ public: int nReturnCmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pos->pt.x, pos->pt.y, 0, m_hwnd, nullptr);
switch (nReturnCmd) {
case 1:
- ppro->setByte(m_hContact, TrustSettingName, !trusted);
- if (trusted)
- ppro->delSetting(m_hContact, "OmemoSignalSession_" + suffix);
+ ppro->setByte(m_hContact, TrustSettingName, trusted ? FP_BAD : FP_VERIFIED);
OnRefresh();
break;
case 2:
diff --git a/src/core/stdmsg/res/private.ico b/src/core/stdmsg/res/private.ico Binary files differnew file mode 100644 index 0000000000..ff23d39b5f --- /dev/null +++ b/src/core/stdmsg/res/private.ico diff --git a/src/core/stdmsg/res/resource.rc b/src/core/stdmsg/res/resource.rc index caf2ea092c..d6cb78f4b7 100644 --- a/src/core/stdmsg/res/resource.rc +++ b/src/core/stdmsg/res/resource.rc @@ -412,6 +412,10 @@ IDI_NICKLIST2 ICON "nicklist2.ico" IDI_FILTER2 ICON "filter2.ico"
+IDI_SECURE ICON "unverified.ico"
+
+IDI_SECURE_STRONG ICON "private.ico"
+
/////////////////////////////////////////////////////////////////////////////
//
diff --git a/src/core/stdmsg/res/unverified.ico b/src/core/stdmsg/res/unverified.ico Binary files differnew file mode 100644 index 0000000000..0595776a28 --- /dev/null +++ b/src/core/stdmsg/res/unverified.ico diff --git a/src/core/stdmsg/src/globals.cpp b/src/core/stdmsg/src/globals.cpp index 38ea6641d2..73972a2312 100644 --- a/src/core/stdmsg/src/globals.cpp +++ b/src/core/stdmsg/src/globals.cpp @@ -23,9 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. IconItem iconList[] =
{
- { LPGEN("Incoming message (10x10)"), "INCOMING", IDI_INCOMING, 10 },
- { LPGEN("Outgoing message (10x10)"), "OUTGOING", IDI_OUTGOING, 10 },
- { LPGEN("Notice (10x10)"), "NOTICE", IDI_NOTICE, 10 },
+ { LPGEN("Incoming message (10x10)"), "INCOMING", IDI_INCOMING, 10 },
+ { LPGEN("Outgoing message (10x10)"), "OUTGOING", IDI_OUTGOING, 10 },
+ { LPGEN("Notice (10x10)"), "NOTICE", IDI_NOTICE, 10 },
+ { LPGEN("Encrypted (10x10)"), "UNVERIFIED", IDI_SECURE, 10 },
+ { LPGEN("Encrypted verified (10x10)"), "PRIVATE", IDI_SECURE_STRONG, 10 },
};
static void InitIcons(void)
diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp index ef28b8fd99..d9c5acbb39 100644 --- a/src/core/stdmsg/src/msgdialog.cpp +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -727,6 +727,40 @@ static const CHARRANGE rangeAll = { 0, -1 }; LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
+ case WM_NCPAINT:
+ if (!m_sEncryption.IsEmpty()) {
+ RECT rect;
+ GetWindowRect(m_message.GetHwnd(), &rect);
+ HRGN region = NULL;
+ if (wParam == NULLREGION) {
+ region = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
+ HRGN region2 = CreateRectRgn(rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1);
+ CombineRgn(region, region, (HRGN)region2, RGN_DIFF);
+ }
+ else {
+ HRGN copy = CreateRectRgn(0, 0, 0, 0);
+ if (CombineRgn(copy, (HRGN)wParam, NULL, RGN_COPY))
+ region = copy;
+ else
+ DeleteObject(copy);
+ }
+
+ HDC dc = GetDCEx(m_message.GetHwnd(), region, DCX_WINDOW | DCX_CACHE | DCX_INTERSECTRGN | DCX_LOCKWINDOWUPDATE);
+ if (region)
+ DeleteObject(region);
+
+ HPEN pen = CreatePen(PS_INSIDEFRAME, 1, RGB(0, 220, 0));
+ HGDIOBJ old = SelectObject(dc, pen);
+ int width = rect.right - rect.left;
+ int height = rect.bottom - rect.top;
+ Rectangle(dc, 0, 0, width, height);
+ SelectObject(dc, old);
+ ReleaseDC(m_message.GetHwnd(), dc);
+ DeleteObject(pen);
+ return 0;
+ }
+ break;
+
case EM_REPLACESEL:
PostMessage(m_message.GetHwnd(), EM_ACTIVATE, 0, 0);
break;
@@ -856,6 +890,13 @@ LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) }
break;
+ case WM_SETFOCUS: {
+ const char* enc = (const char*)CallProtoService(m_szProto, PS_GETCAPS, PFLAG_GETCURRENTENCRYPTION, m_hContact);
+ if (!m_sEncryption.IsEmpty() ^ (bool)enc)
+ RedrawWindow(m_message.GetHwnd(), NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
+ m_sEncryption = enc;
+ }
+
case WM_KEYDOWN:
bool isShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
bool isCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp index 568dec4a5a..ba0d25e44a 100644 --- a/src/core/stdmsg/src/msglog.cpp +++ b/src/core/stdmsg/src/msglog.cpp @@ -27,7 +27,7 @@ extern IconItem iconList[]; #define LOGICON_MSG_OUT 1
#define LOGICON_MSG_NOTICE 2
-static char *pLogIconBmpBits[3];
+static char *pLogIconBmpBits[5];
struct RtfLogStreamData : public RtfLogStreamBase
{
@@ -290,6 +290,11 @@ public: buf.Append("\\f0\\fs14");
buf.Append(pLogIconBmpBits[i]);
+
+ if (dbei.eventType == EVENTTYPE_MESSAGE && dbei.flags & (DBEF_SECURE | DBEF_SECURE_STRONG)) {
+ buf.Append("\\f0\\fs14");
+ buf.Append(pLogIconBmpBits[dbei.flags & DBEF_SECURE ? 3 : 4]);
+ }
}
int showColon = 0;
diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h index ce79ce26fa..ec67524d0c 100644 --- a/src/core/stdmsg/src/msgs.h +++ b/src/core/stdmsg/src/msgs.h @@ -81,6 +81,7 @@ class CMsgDialog : public CSrmmBaseDialog uint16_t m_wMinute = 0;
bool m_bIsMeta = false, m_bWindowCascaded = false, m_bNoActivate = false;
int m_iBBarHeight = 28;
+ CMStringA m_sEncryption;
public:
CMsgDialog(CTabbedWindow *pOwner, MCONTACT hContact);
diff --git a/src/core/stdmsg/src/resource.h b/src/core/stdmsg/src/resource.h index 457d5b3e3b..ba7a9f0c3a 100644 --- a/src/core/stdmsg/src/resource.h +++ b/src/core/stdmsg/src/resource.h @@ -42,6 +42,8 @@ #define IDI_OVERLAY 160
#define IDI_NICKLIST2 161
#define IDI_FILTER2 162
+#define IDI_SECURE 163
+#define IDI_SECURE_STRONG 164
#define IDR_CONTEXT 180
#define IDC_DROP 183
#define IDC_HYPERLINKHAND 214
diff --git a/src/mir_app/src/proto_interface.cpp b/src/mir_app/src/proto_interface.cpp index 71a610d640..b49e9a74ca 100644 --- a/src/mir_app/src/proto_interface.cpp +++ b/src/mir_app/src/proto_interface.cpp @@ -219,6 +219,10 @@ MEVENT PROTO_INTERFACE::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) dbei.flags |= DBEF_READ;
if (pre->flags & PREF_SENT)
dbei.flags |= DBEF_SENT;
+ if (pre->flags & PREF_ENCRYPTED)
+ dbei.flags |= DBEF_SECURE;
+ if (pre->flags & PREF_ENCRYPTED_STRONG)
+ dbei.flags |= DBEF_SECURE_STRONG;
// if it's possible to find an existing event by its id, do that
if ((GetCaps(PFLAGNUM_4) & PF4_SERVERMSGID) && pre->szMsgId != nullptr) {
|