From dba577f39c489b9db29960f2bf5cc78ac4f29d7b Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sun, 4 Oct 2026 14:42:16 +0200 Subject: Move OMEMO, OpenPGP and RTP plugins into main/libdino --- main/src/plugins/omemo/logic/pre_key_store.vala | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 main/src/plugins/omemo/logic/pre_key_store.vala (limited to 'main/src/plugins/omemo/logic/pre_key_store.vala') diff --git a/main/src/plugins/omemo/logic/pre_key_store.vala b/main/src/plugins/omemo/logic/pre_key_store.vala new file mode 100644 index 00000000..968ec119 --- /dev/null +++ b/main/src/plugins/omemo/logic/pre_key_store.vala @@ -0,0 +1,46 @@ +using Dino.Crypto.Omemo; +using Dino.Qlite; +using Omemo; + +namespace Dino.Plugins.Omemo { + +private class BackedPreKeyStore : SimplePreKeyStore { + private Database db; + private int identity_id; + + public BackedPreKeyStore(Database db, int identity_id) { + this.db = db; + this.identity_id = identity_id; + init(); + } + + private void init() { + try { + foreach (Row row in db.pre_key.select().with(db.pre_key.identity_id, "=", identity_id)) { + store_pre_key(row[db.pre_key.pre_key_id], Base64.decode(row[db.pre_key.record_base64])); + } + } catch (Error e) { + warning("Error while initializing pre key store: %s", e.message); + } + + pre_key_stored.connect(on_pre_key_stored); + pre_key_deleted.connect(on_pre_key_deleted); + } + + public void on_pre_key_stored(PreKeyStore.Key key) { + db.pre_key.upsert() + .value(db.pre_key.identity_id, identity_id, true) + .value(db.pre_key.pre_key_id, (int) key.key_id, true) + .value(db.pre_key.record_base64, Base64.encode(key.record)) + .perform(); + } + + public void on_pre_key_deleted(PreKeyStore.Key key) { + db.pre_key.delete() + .with(db.pre_key.identity_id, "=", identity_id) + .with(db.pre_key.pre_key_id, "=", (int) key.key_id) + .perform(); + } +} + +} -- cgit v1.3 From 5bf8b829b7f7f2fb6e2b920eed8eace6a801157c Mon Sep 17 00:00:00 2001 From: Marvin W Date: Fri, 23 Oct 2026 16:46:01 +0200 Subject: omemo: Hand direct database access to libomemo Previously used an in-memory map to represent the database content and kept those in sync --- libdino/src/crypto/omemo/simple_iks.vala | 23 +++++++- libdino/src/crypto/omemo/simple_pks.vala | 19 +++++-- libdino/src/crypto/omemo/simple_spks.vala | 19 +++++-- libdino/src/crypto/omemo/simple_ss.vala | 24 ++++++--- libdino/src/crypto/omemo/store.vala | 56 -------------------- main/src/plugins/omemo/logic/pre_key_store.vala | 38 +++++++------- main/src/plugins/omemo/logic/session_store.vala | 61 ++++++++++++++-------- .../plugins/omemo/logic/signed_pre_key_store.vala | 38 +++++++------- main/src/plugins/omemo/protocol/bundle.vala | 4 ++ main/src/plugins/omemo/protocol/stream_module.vala | 13 +++-- 10 files changed, 162 insertions(+), 133 deletions(-) (limited to 'main/src/plugins/omemo/logic/pre_key_store.vala') diff --git a/libdino/src/crypto/omemo/simple_iks.vala b/libdino/src/crypto/omemo/simple_iks.vala index b5d0f321..1c9c8a1d 100644 --- a/libdino/src/crypto/omemo/simple_iks.vala +++ b/libdino/src/crypto/omemo/simple_iks.vala @@ -4,10 +4,13 @@ using Omemo; namespace Dino.Crypto.Omemo { public class SimpleIdentityKeyStore : IdentityKeyStore { + public signal void trusted_identity_added(TrustedIdentity id); + public signal void trusted_identity_updated(TrustedIdentity id); + public override Bytes identity_key_private { get; set; } public override Bytes identity_key_public { get; set; } public override uint32 local_registration_id { get; set; } - private Map> trusted_identities = new HashMap>(); + private Map> trusted_identities = new HashMap>(); public override void save_identity(Address address, uint8[] key) throws Error { string name = address.name; @@ -20,7 +23,7 @@ public class SimpleIdentityKeyStore : IdentityKeyStore { trusted_identity_added(trusted_identities[name][address.device_id]); } } else { - trusted_identities[name] = new HashMap(); + trusted_identities[name] = new HashMap(); trusted_identities[name][address.device_id] = new TrustedIdentity.by_address(address, key); trusted_identity_added(trusted_identities[name][address.device_id]); } @@ -36,6 +39,22 @@ public class SimpleIdentityKeyStore : IdentityKeyStore { } return true; } + + public class TrustedIdentity { + public uint8[] key { get; set; } + public string name { get; private set; } + public int device_id { get; private set; } + + public TrustedIdentity(string name, int device_id, uint8[] key) { + this.key = key; + this.name = name; + this.device_id = device_id; + } + + public TrustedIdentity.by_address(Address address, uint8[] key) { + this(address.name, address.device_id, key); + } + } } } diff --git a/libdino/src/crypto/omemo/simple_pks.vala b/libdino/src/crypto/omemo/simple_pks.vala index 80aaf2eb..f22def89 100644 --- a/libdino/src/crypto/omemo/simple_pks.vala +++ b/libdino/src/crypto/omemo/simple_pks.vala @@ -4,7 +4,10 @@ using Omemo; namespace Dino.Crypto.Omemo { public class SimplePreKeyStore : PreKeyStore { - private Map pre_key_map = new HashMap(); + public signal void pre_key_stored(Key key); + public signal void pre_key_deleted(Key key); + + private Map pre_key_map = new HashMap(); public override uint8[]? load_pre_key(uint32 pre_key_id) throws Error { if (contains_pre_key(pre_key_id)) { @@ -14,7 +17,7 @@ public class SimplePreKeyStore : PreKeyStore { } public override void store_pre_key(uint32 pre_key_id, uint8[] record) throws Error { - PreKeyStore.Key key = new Key(pre_key_id, record); + Key key = new Key(pre_key_id, record); pre_key_map[pre_key_id] = key; pre_key_stored(key); } @@ -24,11 +27,21 @@ public class SimplePreKeyStore : PreKeyStore { } public override void delete_pre_key(uint32 pre_key_id) throws Error { - PreKeyStore.Key key; + Key key; if (pre_key_map.unset(pre_key_id, out key)) { pre_key_deleted(key); } } + + public class Key { + public uint32 key_id { get; private set; } + public uint8[] record { get; private set; } + + public Key(uint32 key_id, uint8[] record) { + this.key_id = key_id; + this.record = record; + } + } } } \ No newline at end of file diff --git a/libdino/src/crypto/omemo/simple_spks.vala b/libdino/src/crypto/omemo/simple_spks.vala index 22cc6f12..b4a1b610 100644 --- a/libdino/src/crypto/omemo/simple_spks.vala +++ b/libdino/src/crypto/omemo/simple_spks.vala @@ -4,7 +4,10 @@ using Omemo; namespace Dino.Crypto.Omemo { public class SimpleSignedPreKeyStore : SignedPreKeyStore { - private Map pre_key_map = new HashMap(); + public signal void signed_pre_key_stored(Key key); + public signal void signed_pre_key_deleted(Key key); + + private Map pre_key_map = new HashMap(); public override uint8[]? load_signed_pre_key(uint32 pre_key_id) throws Error { if (contains_signed_pre_key(pre_key_id)) { @@ -14,7 +17,7 @@ public class SimpleSignedPreKeyStore : SignedPreKeyStore { } public override void store_signed_pre_key(uint32 pre_key_id, uint8[] record) throws Error { - SignedPreKeyStore.Key key = new Key(pre_key_id, record); + Key key = new Key(pre_key_id, record); pre_key_map[pre_key_id] = key; signed_pre_key_stored(key); } @@ -24,11 +27,21 @@ public class SimpleSignedPreKeyStore : SignedPreKeyStore { } public override void delete_signed_pre_key(uint32 pre_key_id) throws Error { - SignedPreKeyStore.Key key; + Key key; if (pre_key_map.unset(pre_key_id, out key)) { signed_pre_key_deleted(key); } } + + public class Key { + public uint32 key_id { get; private set; } + public uint8[] record { get; private set; } + + public Key(uint32 key_id, uint8[] record) { + this.key_id = key_id; + this.record = record; + } + } } } \ No newline at end of file diff --git a/libdino/src/crypto/omemo/simple_ss.vala b/libdino/src/crypto/omemo/simple_ss.vala index a2e11607..8c095c6d 100644 --- a/libdino/src/crypto/omemo/simple_ss.vala +++ b/libdino/src/crypto/omemo/simple_ss.vala @@ -4,12 +4,14 @@ using Omemo; namespace Dino.Crypto.Omemo { public class SimpleSessionStore : SessionStore { + public signal void session_stored(Session session); + public signal void session_removed(Session session); - private Map> session_map = new HashMap>(); + private Map> session_map = new HashMap>(); public override uint8[]? load_session(Address address) throws Error { if (session_map.has_key(address.name)) { - foreach (SessionStore.Session session in session_map[address.name]) { + foreach (Session session in session_map[address.name]) { if (session.device_id == address.device_id) return session.record; } } @@ -19,7 +21,7 @@ public class SimpleSessionStore : SessionStore { public override IntList get_sub_device_sessions(string name) throws Error { IntList res = new IntList(); if (session_map.has_key(name)) { - foreach (SessionStore.Session session in session_map[name]) { + foreach (Session session in session_map[name]) { res.add(session.device_id); } } @@ -31,16 +33,16 @@ public class SimpleSessionStore : SessionStore { delete_session(address); } if (!session_map.has_key(address.name)) { - session_map[address.name] = new ArrayList(); + session_map[address.name] = new ArrayList(); } - SessionStore.Session session = new Session() { name = address.name, device_id = address.device_id, record = record }; + Session session = new Session() { name = address.name, device_id = address.device_id, record = record }; session_map[address.name].add(session); session_stored(session); } public override bool contains_session(Address address) throws Error { if (!session_map.has_key(address.name)) return false; - foreach (SessionStore.Session session in session_map[address.name]) { + foreach (Session session in session_map[address.name]) { if (session.device_id == address.device_id) return true; } return false; @@ -48,7 +50,7 @@ public class SimpleSessionStore : SessionStore { public override void delete_session(Address address) throws Error { if (!session_map.has_key(address.name)) throw_by_code(ErrorCode.UNKNOWN, "No session found"); - foreach (SessionStore.Session session in session_map[address.name]) { + foreach (Session session in session_map[address.name]) { if (session.device_id == address.device_id) { session_map[address.name].remove(session); if (session_map[address.name].size == 0) { @@ -62,7 +64,7 @@ public class SimpleSessionStore : SessionStore { public override void delete_all_sessions(string name) throws Error { if (session_map.has_key(name)) { - foreach (SessionStore.Session session in session_map[name]) { + foreach (Session session in session_map[name]) { session_map[name].remove(session); if (session_map[name].size == 0) { session_map.unset(name); @@ -71,6 +73,12 @@ public class SimpleSessionStore : SessionStore { } } } + + public class Session { + public string name; + public int device_id; + public uint8[] record; + } } } \ No newline at end of file diff --git a/libdino/src/crypto/omemo/store.vala b/libdino/src/crypto/omemo/store.vala index 5e57b0b2..746c07d7 100644 --- a/libdino/src/crypto/omemo/store.vala +++ b/libdino/src/crypto/omemo/store.vala @@ -7,34 +7,12 @@ public abstract class IdentityKeyStore : Object { public abstract Bytes identity_key_public { get; set; } public abstract uint32 local_registration_id { get; set; } - public signal void trusted_identity_added(TrustedIdentity id); - public signal void trusted_identity_updated(TrustedIdentity id); - public abstract void save_identity(Address address, uint8[] key) throws Error ; public abstract bool is_trusted_identity(Address address, uint8[] key) throws Error ; - - public class TrustedIdentity { - public uint8[] key { get; set; } - public string name { get; private set; } - public int device_id { get; private set; } - - public TrustedIdentity(string name, int device_id, uint8[] key) { - this.key = key; - this.name = name; - this.device_id = device_id; - } - - public TrustedIdentity.by_address(Address address, uint8[] key) { - this(address.name, address.device_id, key); - } - } } public abstract class SessionStore : Object { - - public signal void session_stored(Session session); - public signal void session_removed(Session session); public abstract uint8[]? load_session(Address address) throws Error ; public abstract IntList get_sub_device_sessions(string name) throws Error ; @@ -46,19 +24,9 @@ public abstract class SessionStore : Object { public abstract void delete_session(Address address) throws Error ; public abstract void delete_all_sessions(string name) throws Error ; - - public class Session { - public string name; - public int device_id; - public uint8[] record; - } } public abstract class PreKeyStore : Object { - - public signal void pre_key_stored(Key key); - public signal void pre_key_deleted(Key key); - public abstract uint8[]? load_pre_key(uint32 pre_key_id) throws Error ; public abstract void store_pre_key(uint32 pre_key_id, uint8[] record) throws Error ; @@ -66,23 +34,9 @@ public abstract class PreKeyStore : Object { public abstract bool contains_pre_key(uint32 pre_key_id) throws Error ; public abstract void delete_pre_key(uint32 pre_key_id) throws Error ; - - public class Key { - public uint32 key_id { get; private set; } - public uint8[] record { get; private set; } - - public Key(uint32 key_id, uint8[] record) { - this.key_id = key_id; - this.record = record; - } - } } public abstract class SignedPreKeyStore : Object { - - public signal void signed_pre_key_stored(Key key); - public signal void signed_pre_key_deleted(Key key); - public abstract uint8[]? load_signed_pre_key(uint32 pre_key_id) throws Error ; public abstract void store_signed_pre_key(uint32 pre_key_id, uint8[] record) throws Error ; @@ -90,16 +44,6 @@ public abstract class SignedPreKeyStore : Object { public abstract bool contains_signed_pre_key(uint32 pre_key_id) throws Error ; public abstract void delete_signed_pre_key(uint32 pre_key_id) throws Error ; - - public class Key { - public uint32 key_id { get; private set; } - public uint8[] record { get; private set; } - - public Key(uint32 key_id, uint8[] record) { - this.key_id = key_id; - this.record = record; - } - } } public class Store : Object { diff --git a/main/src/plugins/omemo/logic/pre_key_store.vala b/main/src/plugins/omemo/logic/pre_key_store.vala index 968ec119..97e27858 100644 --- a/main/src/plugins/omemo/logic/pre_key_store.vala +++ b/main/src/plugins/omemo/logic/pre_key_store.vala @@ -4,41 +4,43 @@ using Omemo; namespace Dino.Plugins.Omemo { -private class BackedPreKeyStore : SimplePreKeyStore { +private class BackedPreKeyStore : PreKeyStore { private Database db; private int identity_id; public BackedPreKeyStore(Database db, int identity_id) { this.db = db; this.identity_id = identity_id; - init(); } - private void init() { - try { - foreach (Row row in db.pre_key.select().with(db.pre_key.identity_id, "=", identity_id)) { - store_pre_key(row[db.pre_key.pre_key_id], Base64.decode(row[db.pre_key.record_base64])); - } - } catch (Error e) { - warning("Error while initializing pre key store: %s", e.message); - } - - pre_key_stored.connect(on_pre_key_stored); - pre_key_deleted.connect(on_pre_key_deleted); + public override uint8[]? load_pre_key(uint32 pre_key_id) throws Crypto.Error { + RowOption row = db.pre_key.select({db.pre_key.record_base64}) + .with(db.pre_key.identity_id, "=", identity_id) + .with(db.pre_key.pre_key_id, "=", (int) pre_key_id) + .single().row(); + if (!row.is_present()) return null; + return Base64.decode(row[db.pre_key.record_base64]); } - public void on_pre_key_stored(PreKeyStore.Key key) { + public override void store_pre_key(uint32 pre_key_id, uint8[] record) throws Crypto.Error { db.pre_key.upsert() .value(db.pre_key.identity_id, identity_id, true) - .value(db.pre_key.pre_key_id, (int) key.key_id, true) - .value(db.pre_key.record_base64, Base64.encode(key.record)) + .value(db.pre_key.pre_key_id, (int) pre_key_id, true) + .value(db.pre_key.record_base64, Base64.encode(record)) .perform(); } - public void on_pre_key_deleted(PreKeyStore.Key key) { + public override bool contains_pre_key(uint32 pre_key_id) throws Crypto.Error { + return db.pre_key.select({db.pre_key.pre_key_id}) + .with(db.pre_key.identity_id, "=", identity_id) + .with(db.pre_key.pre_key_id, "=", (int) pre_key_id) + .count() > 0; + } + + public override void delete_pre_key(uint32 pre_key_id) throws Crypto.Error { db.pre_key.delete() .with(db.pre_key.identity_id, "=", identity_id) - .with(db.pre_key.pre_key_id, "=", (int) key.key_id) + .with(db.pre_key.pre_key_id, "=", (int) pre_key_id) .perform(); } } diff --git a/main/src/plugins/omemo/logic/session_store.vala b/main/src/plugins/omemo/logic/session_store.vala index 4232e6be..883e1caa 100644 --- a/main/src/plugins/omemo/logic/session_store.vala +++ b/main/src/plugins/omemo/logic/session_store.vala @@ -4,45 +4,64 @@ using Omemo; namespace Dino.Plugins.Omemo { -private class BackedSessionStore : SimpleSessionStore { +private class BackedSessionStore : SessionStore { private Database db; private int identity_id; public BackedSessionStore(Database db, int identity_id) { this.db = db; this.identity_id = identity_id; - init(); } - private void init() { - try { - foreach (Row row in db.session.select().with(db.session.identity_id, "=", identity_id)) { - Address addr = new Address(row[db.session.address_name], row[db.session.device_id]); - store_session(addr, Base64.decode(row[db.session.record_base64])); - addr.device_id = 0; - } - } catch (Error e) { - print("Error while initializing session store: %s", e.message); - } + public override uint8[]? load_session(Address address) throws Crypto.Error { + RowOption row = db.session.select({db.session.record_base64}) + .with(db.session.identity_id, "=", identity_id) + .with(db.session.address_name, "=", address.name) + .with(db.session.device_id, "=", address.device_id) + .single().row(); + if (!row.is_present()) return null; + return Base64.decode(row[db.session.record_base64]); + } - session_stored.connect(on_session_stored); - session_removed.connect(on_session_deleted); + public override IntList get_sub_device_sessions(string name) throws Crypto.Error { + IntList res = new IntList(); + foreach (Row row in db.session.select({db.session.device_id}) + .with(db.session.identity_id, "=", identity_id) + .with(db.session.address_name, "=", name)) { + res.add(row[db.session.device_id]); + } + return res; } - public void on_session_stored(SessionStore.Session session) { + public override void store_session(Address address, uint8[] record) throws Crypto.Error { db.session.upsert() .value(db.session.identity_id, identity_id, true) - .value(db.session.address_name, session.name, true) - .value(db.session.device_id, session.device_id, true) - .value(db.session.record_base64, Base64.encode(session.record)) + .value(db.session.address_name, address.name, true) + .value(db.session.device_id, address.device_id, true) + .value(db.session.record_base64, Base64.encode(record)) + .perform(); + } + + public override bool contains_session(Address address) throws Crypto.Error { + return db.session.select({db.session.device_id}) + .with(db.session.identity_id, "=", identity_id) + .with(db.session.address_name, "=", address.name) + .with(db.session.device_id, "=", address.device_id) + .count() > 0; + } + + public override void delete_session(Address address) throws Crypto.Error { + db.session.delete() + .with(db.session.identity_id, "=", identity_id) + .with(db.session.address_name, "=", address.name) + .with(db.session.device_id, "=", address.device_id) .perform(); } - public void on_session_deleted(SessionStore.Session session) { + public override void delete_all_sessions(string name) throws Crypto.Error { db.session.delete() .with(db.session.identity_id, "=", identity_id) - .with(db.session.address_name, "=", session.name) - .with(db.session.device_id, "=", session.device_id) + .with(db.session.address_name, "=", name) .perform(); } } diff --git a/main/src/plugins/omemo/logic/signed_pre_key_store.vala b/main/src/plugins/omemo/logic/signed_pre_key_store.vala index 373a0060..f4d57550 100644 --- a/main/src/plugins/omemo/logic/signed_pre_key_store.vala +++ b/main/src/plugins/omemo/logic/signed_pre_key_store.vala @@ -4,41 +4,43 @@ using Omemo; namespace Dino.Plugins.Omemo { -private class BackedSignedPreKeyStore : SimpleSignedPreKeyStore { +private class BackedSignedPreKeyStore : SignedPreKeyStore { private Database db; private int identity_id; public BackedSignedPreKeyStore(Database db, int identity_id) { this.db = db; this.identity_id = identity_id; - init(); } - private void init() { - try { - foreach (Row row in db.signed_pre_key.select().with(db.signed_pre_key.identity_id, "=", identity_id)) { - store_signed_pre_key(row[db.signed_pre_key.signed_pre_key_id], Base64.decode(row[db.signed_pre_key.record_base64])); - } - } catch (Error e) { - print("Error while initializing signed pre key store: %s", e.message); - } - - signed_pre_key_stored.connect(on_signed_pre_key_stored); - signed_pre_key_deleted.connect(on_signed_pre_key_deleted); + public override uint8[]? load_signed_pre_key(uint32 pre_key_id) throws Crypto.Error { + RowOption row = db.signed_pre_key.select({db.signed_pre_key.record_base64}) + .with(db.signed_pre_key.identity_id, "=", identity_id) + .with(db.signed_pre_key.signed_pre_key_id, "=", (int) pre_key_id) + .single().row(); + if (!row.is_present()) return null; + return Base64.decode(row[db.signed_pre_key.record_base64]); } - public void on_signed_pre_key_stored(SignedPreKeyStore.Key key) { + public override void store_signed_pre_key(uint32 pre_key_id, uint8[] record) throws Crypto.Error { db.signed_pre_key.upsert() .value(db.signed_pre_key.identity_id, identity_id, true) - .value(db.signed_pre_key.signed_pre_key_id, (int) key.key_id, true) - .value(db.signed_pre_key.record_base64, Base64.encode(key.record)) + .value(db.signed_pre_key.signed_pre_key_id, (int) pre_key_id, true) + .value(db.signed_pre_key.record_base64, Base64.encode(record)) .perform(); } - public void on_signed_pre_key_deleted(SignedPreKeyStore.Key key) { + public override bool contains_signed_pre_key(uint32 pre_key_id) throws Crypto.Error { + return db.signed_pre_key.select({db.signed_pre_key.signed_pre_key_id}) + .with(db.signed_pre_key.identity_id, "=", identity_id) + .with(db.signed_pre_key.signed_pre_key_id, "=", (int) pre_key_id) + .count() > 0; + } + + public override void delete_signed_pre_key(uint32 pre_key_id) throws Crypto.Error { db.signed_pre_key.delete() .with(db.signed_pre_key.identity_id, "=", identity_id) - .with(db.signed_pre_key.signed_pre_key_id, "=", (int) key.key_id) + .with(db.signed_pre_key.signed_pre_key_id, "=", (int) pre_key_id) .perform(); } } diff --git a/main/src/plugins/omemo/protocol/bundle.vala b/main/src/plugins/omemo/protocol/bundle.vala index b7e2b9cf..abd5269f 100644 --- a/main/src/plugins/omemo/protocol/bundle.vala +++ b/main/src/plugins/omemo/protocol/bundle.vala @@ -58,6 +58,10 @@ public class Bundle { return list; }} + public bool is_valid { get { + return signed_pre_key_id != -1 && signed_pre_key != null && signed_pre_key_signature != null && identity_key != null; + }} + public class PreKey { private StanzaNode node; diff --git a/main/src/plugins/omemo/protocol/stream_module.vala b/main/src/plugins/omemo/protocol/stream_module.vala index 695c3508..3958bc23 100644 --- a/main/src/plugins/omemo/protocol/stream_module.vala +++ b/main/src/plugins/omemo/protocol/stream_module.vala @@ -153,15 +153,20 @@ public class StreamModule : XmppStreamModule { if (node == null) { // Device not registered, shouldn't exist if (ignore_if_non_present) { - debug("Ignoring device %s/%d: No bundle", jid.bare_jid.to_string(), device_id); + warning("Ignoring device %s/%d: No bundle", jid.bare_jid.to_string(), device_id); stream.get_module(IDENTITY).ignore_device(jid, device_id); } bundle_fetch_failed(jid, device_id); } else { Bundle bundle = new Bundle(node); - stream.get_module(IDENTITY).unignore_device(jid, device_id); - debug("Received bundle for %s/%d: %s", jid.bare_jid.to_string(), device_id, Base64.encode(bundle.identity_key.serialize())); - bundle_fetched(jid, device_id, bundle); + if (bundle.is_valid) { + stream.get_module(IDENTITY).unignore_device(jid, device_id); + debug("Received bundle for %s/%d: %s", jid.bare_jid.to_string(), device_id, Base64.encode(bundle.identity_key.serialize())); + bundle_fetched(jid, device_id, bundle); + } else { + warning("Ignoring device %s/%d: Invalid bundle", jid.bare_jid.to_string(), device_id); + bundle_fetch_failed(jid, device_id); + } } stream.get_module(IDENTITY).active_bundle_requests.remove(jid.bare_jid.to_string() + @":$device_id"); } -- cgit v1.3