diff options
| -rw-r--r-- | plugins/openpgp/meson.build | 1 | ||||
| -rw-r--r-- | plugins/openpgp/src/database.vala | 74 | ||||
| -rw-r--r-- | plugins/openpgp/src/encryption_preferences_entry.vala | 6 | ||||
| -rw-r--r-- | plugins/openpgp/src/manager.vala | 29 | ||||
| -rw-r--r-- | plugins/openpgp/src/plugin.vala | 8 | ||||
| -rw-r--r-- | plugins/openpgp/src/stream_flag.vala | 21 | ||||
| -rw-r--r-- | plugins/openpgp/src/stream_module.vala | 42 | ||||
| -rw-r--r-- | plugins/openpgp/src/util.vala | 9 |
8 files changed, 116 insertions, 74 deletions
diff --git a/plugins/openpgp/meson.build b/plugins/openpgp/meson.build index ec7e1014..5d6635e3 100644 --- a/plugins/openpgp/meson.build +++ b/plugins/openpgp/meson.build @@ -22,7 +22,6 @@ sources = files( 'src/manager.vala', 'src/plugin.vala', 'src/register_plugin.vala', - 'src/stream_flag.vala', 'src/stream_module.vala', 'src/util.vala', 'vapi/gpg-error.vapi', diff --git a/plugins/openpgp/src/database.vala b/plugins/openpgp/src/database.vala index f488078c..fb575a3b 100644 --- a/plugins/openpgp/src/database.vala +++ b/plugins/openpgp/src/database.vala @@ -6,25 +6,46 @@ using Xmpp; namespace Dino.Plugins.OpenPgp { public class Database : Qlite.Database { - private const int VERSION = 0; + private const int VERSION = 1; public class AccountSetting : Table { public Column<int> account_id = new Column.Integer("account_id") { primary_key = true }; public Column<string> key = new Column.Text("key") { not_null = true }; + public Column<string> signed_data = new Column.Text("signed_data") { min_version = 1 }; + public Column<string> sig = new Column.Text("sig") { min_version = 1 }; internal AccountSetting(Database db) { base(db, "account_setting"); - init({account_id, key}); + init({account_id, key, signed_data, sig}); } } public class ContactKey : Table { public Column<string> jid = new Column.Text("jid") { primary_key = true }; - public Column<string> key = new Column.Text("key") { not_null = true }; + public Column<string> key = new Column.Text("key"); + public Column<string> sig = new Column.Text("sig") { min_version = 1 }; + public Column<string> signed_data = new Column.Text("signed_data") { min_version = 1 }; internal ContactKey(Database db) { base(db, "contact_key"); - init({jid, key}); + init({jid, key, sig, signed_data}); + } + + internal void migrate_from_v0(Database db) { + string column_list = ""; + foreach (Column c in columns) { + if (c.min_version <= VERSION && c.max_version >= VERSION) { + if (column_list == "") { + column_list = c.name; + } else { + column_list += ", " + c.name; + } + } + } + db.exec(@"ALTER TABLE $name RENAME TO _$(name)_1"); + create_table_at_version(VERSION); + db.exec(@"INSERT INTO $name ($column_list) SELECT $column_list FROM _$(name)_1"); + db.exec(@"DROP TABLE _$(name)_1"); } } @@ -46,6 +67,23 @@ public class Database : Qlite.Database { } } + public void set_contact_signature(Jid jid, string sig, string signed_data) { + contact_key_table.upsert() + .value(contact_key_table.jid, jid.to_string(), true) + .value(contact_key_table.sig, sig) + .value(contact_key_table.signed_data, signed_data) + .value_null(contact_key_table.key) + .perform(); + } + + public void clear_contact_signature(Jid jid) { + contact_key_table.upsert() + .value(contact_key_table.jid, jid.to_string(), true) + .value_null(contact_key_table.sig) + .value_null(contact_key_table.signed_data) + .perform(); + } + public void set_contact_key(Jid jid, string key) { contact_key_table.upsert() .value(contact_key_table.jid, jid.to_string(), true) @@ -54,23 +92,47 @@ public class Database : Qlite.Database { } public string? get_contact_key(Jid jid) { + return get_contact_key_row(jid)[contact_key_table.key]; + } + + public RowOption get_contact_key_row(Jid jid) { return contact_key_table.select({contact_key_table.key}) - .with(contact_key_table.jid, "=", jid.to_string())[contact_key_table.key]; + .with(contact_key_table.jid, "=", jid.to_string()).row(); } public void set_account_key(Account account, string key) { account_setting_table.upsert() .value(account_setting_table.account_id, account.id, true) .value(account_setting_table.key, key) + .value_null(account_setting_table.signed_data) + .value_null(account_setting_table.sig) + .perform(); + } + + public void set_account_signature(Account account, string signed_data, string sig) { + account_setting_table.update() + .with(account_setting_table.account_id, "=", account.id) + .set(account_setting_table.signed_data, signed_data) + .set(account_setting_table.sig, sig) .perform(); } + public string? get_account_signature(Account account, string signed_data) { + return account_setting_table.select({account_setting_table.sig}) + .with(account_setting_table.account_id, "=", account.id) + .with(account_setting_table.signed_data, "=", signed_data)[account_setting_table.sig]; + } + public string? get_account_key(Account account) { return account_setting_table.select({account_setting_table.key}) .with(account_setting_table.account_id, "=", account.id)[account_setting_table.key]; } - public override void migrate(long oldVersion) { } + public override void migrate(long oldVersion) { + if (oldVersion < 1) { + contact_key_table.migrate_from_v0(this); + } + } } } diff --git a/plugins/openpgp/src/encryption_preferences_entry.vala b/plugins/openpgp/src/encryption_preferences_entry.vala index 28b253fc..b03f6acd 100644 --- a/plugins/openpgp/src/encryption_preferences_entry.vala +++ b/plugins/openpgp/src/encryption_preferences_entry.vala @@ -52,10 +52,14 @@ namespace Dino.Plugins.OpenPgp { drop_down.notify["selected"].connect(() => { var key_id = drop_down.selected == 0 ? "" : keys[(int)drop_down.selected - 1].fpr; + string? signed_data = null, sig = null; if (plugin.modules.has_key(account)) { - plugin.modules[account].set_private_key_id(key_id); + plugin.modules[account].set_private_key_id(key_id, ref signed_data, ref sig); } plugin.db.set_account_key(account, key_id); + if (signed_data != null && sig != null) { + plugin.db.set_account_signature(account, signed_data, sig); + } }); } diff --git a/plugins/openpgp/src/manager.vala b/plugins/openpgp/src/manager.vala index 6ec30acc..23cc93c2 100644 --- a/plugins/openpgp/src/manager.vala +++ b/plugins/openpgp/src/manager.vala @@ -14,7 +14,6 @@ public class Manager : StreamInteractionModule, Object { private StreamInteractor stream_interactor; private Database db; - private HashMap<Jid, string> pgp_key_ids = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func); private ReceivedMessageListener received_message_listener = new ReceivedMessageListener(); public static void start(StreamInteractor stream_interactor, Database db) { @@ -81,23 +80,29 @@ public class Manager : StreamInteractionModule, Object { public string? get_key_id(Account account, Jid jid) { Jid search_jid = stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account) ? jid : jid.bare_jid; - return db.get_contact_key(search_jid); + Qlite.RowOption key_row = db.get_contact_key_row(search_jid); + if (!key_row.is_present()) return null; + string? key_id = key_row.get(db.contact_key_table.key); + if (key_id != null) return key_id; + string? sig = key_row.get(db.contact_key_table.sig); + string? signed_data = key_row.get(db.contact_key_table.signed_data); + if (sig == null || signed_data == null) return null; + key_id = get_sign_key(sig, signed_data); + if (key_id != null) { + db.set_contact_key(search_jid, key_id); + } + return key_id; } private void on_account_added(Account account) { - stream_interactor.module_manager.get_module(account, Module.IDENTITY).received_jid_key_id.connect((stream, jid, key_id) => { - on_jid_key_received(account, jid, key_id); + stream_interactor.module_manager.get_module(account, Module.IDENTITY).received_jid_presence_signature.connect((stream, jid, sig, signed_data) => { + on_jid_signature_received(account, jid, sig, signed_data); }); } - private void on_jid_key_received(Account account, Jid jid, string key_id) { - lock (pgp_key_ids) { - if (!pgp_key_ids.has_key(jid) || pgp_key_ids[jid] != key_id) { - Jid set_jid = stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account) ? jid : jid.bare_jid; - db.set_contact_key(set_jid, key_id); - } - pgp_key_ids[jid] = key_id; - } + private void on_jid_signature_received(Account account, Jid jid, string sig, string signed_data) { + Jid set_jid = stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account) ? jid : jid.bare_jid; + db.set_contact_signature(set_jid, sig, signed_data); } private class ReceivedMessageListener : MessageListener { diff --git a/plugins/openpgp/src/plugin.vala b/plugins/openpgp/src/plugin.vala index 463058f3..32542c21 100644 --- a/plugins/openpgp/src/plugin.vala +++ b/plugins/openpgp/src/plugin.vala @@ -37,7 +37,13 @@ public class Plugin : Plugins.RootInterface, Object { public void shutdown() { } private void on_initialize_account_modules(Account account, ArrayList<Xmpp.XmppStreamModule> modules) { - Module module = new Module(db.get_account_key(account)); + string signed_data = ""; + string? sig = db.get_account_signature(account, signed_data); + bool sig_was_unknown = sig == null; + Module module = new Module(db.get_account_key(account), ref signed_data, ref sig); + if (sig_was_unknown && sig != null) { + db.set_account_signature(account, signed_data, sig); + } this.modules[account] = module; modules.add(module); } diff --git a/plugins/openpgp/src/stream_flag.vala b/plugins/openpgp/src/stream_flag.vala deleted file mode 100644 index df598625..00000000 --- a/plugins/openpgp/src/stream_flag.vala +++ /dev/null @@ -1,21 +0,0 @@ -using Gee; - -using Xmpp; - -namespace Dino.Plugins.OpenPgp { - -public class Flag : XmppStreamFlag { - public static FlagIdentity<Flag> IDENTITY = new FlagIdentity<Flag>(NS_URI, "pgp"); - - public HashMap<Jid, string> key_ids = new HashMap<Jid, string>(Jid.hash_bare_func, Jid.equals_bare_func); - - public string? get_key_id(Jid jid) { return key_ids[jid]; } - - public void set_key_id(Jid jid, string key) { key_ids[jid] = key; } - - public override string get_ns() { return NS_URI; } - - public override string get_id() { return IDENTITY.id; } -} - -} diff --git a/plugins/openpgp/src/stream_module.vala b/plugins/openpgp/src/stream_module.vala index 32a77580..9985df26 100644 --- a/plugins/openpgp/src/stream_module.vala +++ b/plugins/openpgp/src/stream_module.vala @@ -10,26 +10,28 @@ namespace Dino.Plugins.OpenPgp { public class Module : XmppStreamModule { public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0027_current_pgp_usage"); - public signal void received_jid_key_id(XmppStream stream, Jid jid, string key_id); + public signal void received_jid_presence_signature(XmppStream stream, Jid jid, string sig, string signed_data); private string? signed_status = null; private Key? own_key = null; private ReceivedPipelineDecryptListener received_pipeline_decrypt_listener = new ReceivedPipelineDecryptListener(); - public Module(string? own_key_id = null) { - set_private_key_id(own_key_id); + public Module(string? own_key_id = null, ref string? signed_data, ref string? sig) { + set_private_key_id(own_key_id, ref signed_data, ref sig); } - public void set_private_key_id(string? own_key_id) { - if (own_key_id != null) { + public void set_private_key_id(string? own_key_id, ref string? signed_data, ref string? sig) { + if (own_key_id != null && sig == null) { try { own_key = GPGHelper.get_private_key(own_key_id); if (own_key == null) warning("Can't get PGP private key"); } catch (Error e) { } if (own_key != null) { - signed_status = gpg_sign("", own_key); + if (signed_data == null) signed_data = ""; + sig = gpg_sign(signed_data, own_key); } } + signed_status = own_key_id != null ? sig : null; } public bool encrypt(MessageStanza message, GPG.Key[] keys) { @@ -47,7 +49,6 @@ namespace Dino.Plugins.OpenPgp { stream.get_module(Presence.Module.IDENTITY).received_presence.connect(on_received_presence); stream.get_module(Presence.Module.IDENTITY).pre_send_presence_stanza.connect(on_pre_send_presence_stanza); stream.get_module(MessageModule.IDENTITY).received_pipeline.connect(received_pipeline_decrypt_listener); - stream.add_flag(new Flag()); } public override void detach(XmppStream stream) { @@ -56,10 +57,6 @@ namespace Dino.Plugins.OpenPgp { stream.get_module(MessageModule.IDENTITY).received_pipeline.disconnect(received_pipeline_decrypt_listener); } - public static void require(XmppStream stream) { - if (stream.get_module(IDENTITY) == null) stream.add_module(new Module()); - } - public override string get_ns() { return NS_URI; } public override string get_id() { return IDENTITY.id; } @@ -68,18 +65,8 @@ namespace Dino.Plugins.OpenPgp { if (x_node == null) return; string? sig = x_node.get_string_content(); if (sig == null) return; - new Thread<void*> (null, () => { - string signed_data = presence.status == null ? "" : presence.status; - string? key_id = get_sign_key(sig, signed_data); - if (key_id != null) { - stream.get_flag(Flag.IDENTITY).set_key_id(presence.from, key_id); - Idle.add(() => { - received_jid_key_id(stream, presence.from, key_id); - return false; - }); - } - return null; - }); + string signed_data = presence.status == null ? "" : presence.status; + received_jid_presence_signature(stream, presence.from, sig, signed_data); } private void on_pre_send_presence_stanza(XmppStream stream, Presence.Stanza presence) { @@ -99,15 +86,6 @@ namespace Dino.Plugins.OpenPgp { return encr.substring(encryption_start, encr.length - "\n-----END PGP MESSAGE-----".length - encryption_start); } - private static string? get_sign_key(string sig, string signed_text) { - string armor = "-----BEGIN PGP MESSAGE-----\n\n" + sig + "\n-----END PGP MESSAGE-----"; - string? sign_key = null; - try { - sign_key = GPGHelper.get_sign_key(armor, signed_text); - } catch (Error e) { } - return sign_key; - } - private static string? gpg_sign(string str, Key key) { string signed; try { diff --git a/plugins/openpgp/src/util.vala b/plugins/openpgp/src/util.vala index 9cba9b2f..3c7a7594 100644 --- a/plugins/openpgp/src/util.vala +++ b/plugins/openpgp/src/util.vala @@ -17,4 +17,13 @@ public static string markup_id(string s, bool is_fingerprint) { return "<span font_family='monospace' font='9'>" + markup + "</span>"; } +private static string? get_sign_key(string sig, string signed_text) { + string armor = "-----BEGIN PGP MESSAGE-----\n\n" + sig + "\n-----END PGP MESSAGE-----"; + string? sign_key = null; + try { + sign_key = GPGHelper.get_sign_key(armor, signed_text); + } catch (Error e) { } + return sign_key; +} + } |
