From adc800dbc424a1e246dd4a82a0c2e88eeda25531 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Tue, 9 Apr 2019 20:54:57 +0100 Subject: [PATCH] Add ability to drop overly large packets As per draft-dkg-openpgp-abuse-resistant-keystore add the ability to drop "large" packets. These are defined as UIDs more than 1024 bytes long, UATs greater than 64k in size and all other packets larger than 8383 bytes (the maximum that will fit in a 2 byte new format packet length). Disabled by default, enable with "check_packet_size" in the verification config section. --- cleankey.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--- cleankey.h | 1 + onak-conf.c | 9 +++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/cleankey.c b/cleankey.c index 3ef76f9..fe24c3b 100644 --- a/cleankey.c +++ b/cleankey.c @@ -26,7 +26,7 @@ #include "log.h" #include "mem.h" #include "merge.h" -#include "onak-conf.h" +#include "openpgp.h" #include "sigcheck.h" /** @@ -179,6 +179,54 @@ int clean_key_sighashes(struct openpgp_publickey *key) return removed; } +#define UAT_LIMIT 0xFFFF +#define UID_LIMIT 1024 +#define PACKET_LIMIT 8383 /* Fits in 2 byte packet length */ +int clean_large_packets(struct openpgp_publickey *key) +{ + struct openpgp_signedpacket_list **curuid = NULL; + struct openpgp_signedpacket_list *tmp = NULL; + bool drop; + int dropped = 0; + + log_assert(key != NULL); + curuid = &key->uids; + while (*curuid != NULL) { + drop = false; + switch ((*curuid)->packet->tag) { + case OPENPGP_PACKET_UID: + if ((*curuid)->packet->length > UID_LIMIT) + drop = true; + break; + case OPENPGP_PACKET_UAT: + if ((*curuid)->packet->length > UAT_LIMIT) + drop = true; + break; + default: + if ((*curuid)->packet->length > PACKET_LIMIT) + drop = true; + break; + } + + if (drop) { + logthing(LOGTHING_INFO, + "Dropping large (%d) packet, type %d", + (*curuid)->packet->length, + (*curuid)->packet->tag); + /* Remove the entire large signed packet list */ + tmp = *curuid; + *curuid = (*curuid)->next; + tmp->next = NULL; + free_signedpacket_list(tmp); + dropped++; + } else { + curuid = &(*curuid)->next; + } + } + + return dropped; +} + /** * cleankeys - Apply all available cleaning options on a list of keys. * @policies: The cleaning policies to apply. @@ -192,14 +240,17 @@ int clean_key_sighashes(struct openpgp_publickey *key) int cleankeys(struct openpgp_publickey **keys, uint64_t policies) { struct openpgp_publickey *curkey; - int changed = 0, count; + int changed = 0, count = 0; if (keys == NULL) return 0; curkey = *keys; while (curkey != NULL) { - count = dedupuids(curkey); + if (policies & ONAK_CLEAN_LARGE_PACKETS) { + count += clean_large_packets(curkey); + } + count += dedupuids(curkey); count += dedupsubkeys(curkey); if (policies & ONAK_CLEAN_CHECK_SIGHASH) { count += clean_key_sighashes(curkey); diff --git a/cleankey.h b/cleankey.h index 073ef66..350e75d 100644 --- a/cleankey.h +++ b/cleankey.h @@ -22,6 +22,7 @@ #include "keystructs.h" #define ONAK_CLEAN_CHECK_SIGHASH (1 << 0) +#define ONAK_CLEAN_LARGE_PACKETS (1 << 1) #define ONAK_CLEAN_ALL (uint64_t) -1 /** diff --git a/onak-conf.c b/onak-conf.c index e6b645c..5a44003 100644 --- a/onak-conf.c +++ b/onak-conf.c @@ -288,6 +288,15 @@ static bool parseconfigline(char *line) config.clean_policies &= ~ONAK_CLEAN_CHECK_SIGHASH; } + } else if (MATCH("verification", "check_packet_size")) { + if (parsebool(value, config.clean_policies & + ONAK_CLEAN_LARGE_PACKETS)) { + config.clean_policies |= + ONAK_CLEAN_LARGE_PACKETS; + } else { + config.clean_policies &= + ~ONAK_CLEAN_LARGE_PACKETS; + } } else { return false; } -- 2.39.5