diff options
author | Kevin McCarthy <kevin@8t8.us> | 2019-07-15 18:36:57 -0700 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2019-08-03 14:08:09 -0700 |
commit | a2a2e88524eafdbb49bdfdbdab557953a6cc9372 (patch) | |
tree | f4cf706d9303cfce41f24f0d6a6032d1b5399ab1 /autocrypt | |
parent | f0946c86d813ba993d0e7463dfe259831e3e1069 (diff) |
Add gossip header processing.
Diffstat (limited to 'autocrypt')
-rw-r--r-- | autocrypt/autocrypt.c | 139 | ||||
-rw-r--r-- | autocrypt/autocrypt.h | 10 | ||||
-rw-r--r-- | autocrypt/autocrypt_db.c | 84 | ||||
-rw-r--r-- | autocrypt/autocrypt_private.h | 4 |
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); |