summaryrefslogtreecommitdiffstats
path: root/autocrypt
diff options
context:
space:
mode:
authorKevin McCarthy <kevin@8t8.us>2019-07-15 18:36:57 -0700
committerKevin McCarthy <kevin@8t8.us>2019-08-03 14:08:09 -0700
commita2a2e88524eafdbb49bdfdbdab557953a6cc9372 (patch)
treef4cf706d9303cfce41f24f0d6a6032d1b5399ab1 /autocrypt
parentf0946c86d813ba993d0e7463dfe259831e3e1069 (diff)
Add gossip header processing.
Diffstat (limited to 'autocrypt')
-rw-r--r--autocrypt/autocrypt.c139
-rw-r--r--autocrypt/autocrypt.h10
-rw-r--r--autocrypt/autocrypt_db.c84
-rw-r--r--autocrypt/autocrypt_private.h4
4 files changed, 237 insertions, 0 deletions
diff --git a/autocrypt/autocrypt.c b/autocrypt/autocrypt.c
index 5207af4b..73fe5364 100644
--- a/autocrypt/autocrypt.c
+++ b/autocrypt/autocrypt.c
@@ -23,6 +23,7 @@
#include "mutt.h"
#include "mutt_curses.h"
#include "mime.h"
+#include "mutt_idna.h"
#include "autocrypt.h"
#include "autocrypt_private.h"
@@ -302,3 +303,141 @@ cleanup:
return rv;
}
+
+static ADDRESS *matching_gossip_address (ENVELOPE *env, const char *addr)
+{
+ ADDRESS *cur;
+
+ for (cur = env->to; cur; cur = cur->next)
+ if (!ascii_strcasecmp (cur->mailbox, addr))
+ return cur;
+
+ for (cur = env->cc; cur; cur = cur->next)
+ if (!ascii_strcasecmp (cur->mailbox, addr))
+ return cur;
+
+ for (cur = env->reply_to; cur; cur = cur->next)
+ if (!ascii_strcasecmp (cur->mailbox, addr))
+ return cur;
+
+ return NULL;
+}
+
+int mutt_autocrypt_process_gossip_header (HEADER *hdr, ENVELOPE *env)
+{
+ AUTOCRYPTHDR *ac_hdr;
+ struct timeval now;
+ AUTOCRYPT_PEER *peer = NULL;
+ AUTOCRYPT_GOSSIP_HISTORY *gossip_hist = NULL;
+ ADDRESS *peer_addr;
+ BUFFER *keyid = NULL;
+ int update_db = 0, insert_db = 0, insert_db_history = 0, import_gpg = 0;
+ int rv = -1;
+
+ if (!option (OPTAUTOCRYPT))
+ return 0;
+
+ if (mutt_autocrypt_init (0))
+ return -1;
+
+ if (!hdr || !hdr->content || !env)
+ return 0;
+
+ if (!env->from)
+ return 0;
+
+ /* Ignore emails that appear to be more than a week in the future,
+ * since they can block all future updates during that time. */
+ gettimeofday (&now, NULL);
+ if (hdr->date_sent > (now.tv_sec + 7 * 24 * 60 * 60))
+ return 0;
+
+ keyid = mutt_buffer_pool_get ();
+
+ /* To ensure the address headers match the gossip header format */
+ mutt_env_to_intl (env, NULL, NULL);
+
+ for (ac_hdr = env->autocrypt_gossip; ac_hdr; ac_hdr = ac_hdr->next)
+ {
+ if (ac_hdr->invalid)
+ continue;
+
+ peer_addr = matching_gossip_address (env, ac_hdr->addr);
+ if (!peer_addr)
+ continue;
+
+ if (mutt_autocrypt_db_peer_get (env->from, &peer) < 0)
+ goto cleanup;
+
+ if (peer)
+ {
+ if (hdr->date_sent <= peer->gossip_timestamp)
+ {
+ mutt_autocrypt_db_peer_free (&peer);
+ continue;
+ }
+
+ update_db = 1;
+ peer->gossip_timestamp = hdr->date_sent;
+ if (mutt_strcmp (peer->gossip_keydata, ac_hdr->keydata))
+ {
+ import_gpg = 1;
+ insert_db_history = 1;
+ mutt_str_replace (&peer->gossip_keydata, ac_hdr->keydata);
+ }
+ }
+ else
+ {
+ import_gpg = 1;
+ insert_db = 1;
+ insert_db_history = 1;
+ }
+
+ if (!peer)
+ {
+ peer = mutt_autocrypt_db_peer_new ();
+ peer->gossip_timestamp = hdr->date_sent;
+ peer->gossip_keydata = safe_strdup (ac_hdr->keydata);
+ }
+
+ if (import_gpg)
+ {
+ if (mutt_autocrypt_gpgme_import_key (peer->gossip_keydata, keyid))
+ goto cleanup;
+ mutt_str_replace (&peer->gossip_keyid, mutt_b2s (keyid));
+ }
+
+ if (insert_db &&
+ mutt_autocrypt_db_peer_insert (peer_addr, peer))
+ goto cleanup;
+
+ if (update_db &&
+ mutt_autocrypt_db_peer_update (peer_addr, peer))
+ goto cleanup;
+
+ if (insert_db_history)
+ {
+ gossip_hist = mutt_autocrypt_db_gossip_history_new ();
+ gossip_hist->sender_email_addr = safe_strdup (env->from->mailbox);
+ gossip_hist->email_msgid = safe_strdup (env->message_id);
+ gossip_hist->timestamp = hdr->date_sent;
+ gossip_hist->gossip_keydata = safe_strdup (peer->gossip_keydata);
+ if (mutt_autocrypt_db_gossip_history_insert (peer_addr, gossip_hist))
+ goto cleanup;
+ }
+
+ mutt_autocrypt_db_peer_free (&peer);
+ mutt_autocrypt_db_gossip_history_free (&gossip_hist);
+ mutt_buffer_clear (keyid);
+ update_db = insert_db = insert_db_history = import_gpg = 0;
+ }
+
+ rv = 0;
+
+cleanup:
+ mutt_autocrypt_db_peer_free (&peer);
+ mutt_autocrypt_db_gossip_history_free (&gossip_hist);
+ mutt_buffer_pool_release (&keyid);
+
+ return rv;
+}
diff --git a/autocrypt/autocrypt.h b/autocrypt/autocrypt.h
index 859a708a..a2401bc3 100644
--- a/autocrypt/autocrypt.h
+++ b/autocrypt/autocrypt.h
@@ -53,8 +53,18 @@ typedef struct
char *keydata;
} AUTOCRYPT_PEER_HISTORY;
+typedef struct
+{
+ char *peer_email_addr;
+ char *sender_email_addr;
+ char *email_msgid;
+ sqlite3_int64 timestamp;
+ char *gossip_keydata;
+} AUTOCRYPT_GOSSIP_HISTORY;
+
int mutt_autocrypt_init (int);
void mutt_autocrypt_cleanup (void);
int mutt_autocrypt_process_autocrypt_header (HEADER *hdr, ENVELOPE *env);
+int mutt_autocrypt_process_gossip_header (HEADER *hdr, ENVELOPE *env);
#endif
diff --git a/autocrypt/autocrypt_db.c b/autocrypt/autocrypt_db.c
index d549d678..8b0ff0b3 100644
--- a/autocrypt/autocrypt_db.c
+++ b/autocrypt/autocrypt_db.c
@@ -32,6 +32,7 @@ static sqlite3_stmt *PeerGetStmt;
static sqlite3_stmt *PeerInsertStmt;
static sqlite3_stmt *PeerUpdateStmt;
static sqlite3_stmt *PeerHistoryInsertStmt;
+static sqlite3_stmt *GossipHistoryInsertStmt;
static int autocrypt_db_create (const char *db_path)
{
@@ -114,6 +115,9 @@ void mutt_autocrypt_db_close (void)
sqlite3_finalize (PeerHistoryInsertStmt);
PeerHistoryInsertStmt = NULL;
+ sqlite3_finalize (GossipHistoryInsertStmt);
+ GossipHistoryInsertStmt = NULL;
+
sqlite3_close_v2 (AutocryptDB);
AutocryptDB = NULL;
}
@@ -611,3 +615,83 @@ cleanup:
sqlite3_reset (PeerHistoryInsertStmt);
return rv;
}
+
+AUTOCRYPT_GOSSIP_HISTORY *mutt_autocrypt_db_gossip_history_new (void)
+{
+ return safe_calloc (1, sizeof(AUTOCRYPT_GOSSIP_HISTORY));
+}
+
+void mutt_autocrypt_db_gossip_history_free (AUTOCRYPT_GOSSIP_HISTORY **gossip_hist)
+{
+ if (!gossip_hist || !*gossip_hist)
+ return;
+ FREE (&(*gossip_hist)->peer_email_addr);
+ FREE (&(*gossip_hist)->sender_email_addr);
+ FREE (&(*gossip_hist)->email_msgid);
+ FREE (&(*gossip_hist)->gossip_keydata);
+ FREE (gossip_hist); /* __FREE_CHECKED__ */
+}
+
+int mutt_autocrypt_db_gossip_history_insert (ADDRESS *addr, AUTOCRYPT_GOSSIP_HISTORY *gossip_hist)
+{
+ int rv = -1;
+ char *email = NULL;
+
+ email = normalize_email_addr (addr);
+
+ if (!GossipHistoryInsertStmt)
+ {
+ if (sqlite3_prepare_v3 (
+ AutocryptDB,
+ "INSERT INTO gossip_history "
+ "(peer_email_addr, "
+ "sender_email_addr, "
+ "email_msgid, "
+ "timestamp, "
+ "gossip_keydata) "
+ "VALUES (?, ?, ?, ?, ?);",
+ -1,
+ SQLITE_PREPARE_PERSISTENT,
+ &GossipHistoryInsertStmt,
+ NULL) != SQLITE_OK)
+ goto cleanup;
+ }
+
+ if (sqlite3_bind_text (GossipHistoryInsertStmt,
+ 1,
+ email,
+ -1,
+ SQLITE_STATIC) != SQLITE_OK)
+ goto cleanup;
+ if (sqlite3_bind_text (GossipHistoryInsertStmt,
+ 2,
+ gossip_hist->sender_email_addr,
+ -1,
+ SQLITE_STATIC) != SQLITE_OK)
+ if (sqlite3_bind_text (GossipHistoryInsertStmt,
+ 3,
+ gossip_hist->email_msgid,
+ -1,
+ SQLITE_STATIC) != SQLITE_OK)
+ goto cleanup;
+ if (sqlite3_bind_int64 (GossipHistoryInsertStmt,
+ 4,
+ gossip_hist->timestamp) != SQLITE_OK)
+ goto cleanup;
+ if (sqlite3_bind_text (GossipHistoryInsertStmt,
+ 5,
+ gossip_hist->gossip_keydata,
+ -1,
+ SQLITE_STATIC) != SQLITE_OK)
+ goto cleanup;
+
+ if (sqlite3_step (GossipHistoryInsertStmt) != SQLITE_DONE)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ FREE (&email);
+ sqlite3_reset (GossipHistoryInsertStmt);
+ return rv;
+}
diff --git a/autocrypt/autocrypt_private.h b/autocrypt/autocrypt_private.h
index d43c9e83..de8638f9 100644
--- a/autocrypt/autocrypt_private.h
+++ b/autocrypt/autocrypt_private.h
@@ -42,6 +42,10 @@ AUTOCRYPT_PEER_HISTORY *mutt_autocrypt_db_peer_history_new (void);
void mutt_autocrypt_db_peer_history_free (AUTOCRYPT_PEER_HISTORY **peerhist);
int mutt_autocrypt_db_peer_history_insert (ADDRESS *addr, AUTOCRYPT_PEER_HISTORY *peerhist);
+AUTOCRYPT_GOSSIP_HISTORY *mutt_autocrypt_db_gossip_history_new (void);
+void mutt_autocrypt_db_gossip_history_free (AUTOCRYPT_GOSSIP_HISTORY **gossip_hist);
+int mutt_autocrypt_db_gossip_history_insert (ADDRESS *addr, AUTOCRYPT_GOSSIP_HISTORY *gossip_hist);
+
int mutt_autocrypt_schema_init (void);
int mutt_autocrypt_schema_update (void);