logthing(LOGTHING_INFO, "%d keys cleaned.",
count);
- count = dbctx->update_keys(dbctx, &keys, true);
+ count = dbctx->update_keys(dbctx, &keys,
+ &config.blacklist, true);
logthing(LOGTHING_NOTICE, "Got %d new keys.",
count);
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <ctype.h>
+#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
return;
}
+
+static uint8_t hex2bin(char c)
+{
+ if (c >= '0' && c <= '9') {
+ return (c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ return (c - 'a' + 10);
+ } else if (c >= 'A' && c <= 'F') {
+ return (c - 'A' + 10);
+ }
+
+ return 255;
+}
+
+bool array_load(struct keyarray *array, const char *file)
+{
+ struct openpgp_fingerprint fp;
+ char curline[1024];
+ FILE *fpfile;
+ int i;
+
+ fpfile = fopen(file, "r");
+
+ if (fpfile != NULL) {
+ if (!fgets(curline, sizeof(curline) - 1, fpfile)) {
+ fclose(fpfile);
+ return false;
+ }
+
+ while (!feof(fpfile)) {
+ /* Strip any trailing white space */
+ for (i = strlen(curline) - 1;
+ i >= 0 && isspace(curline[i]); i--) {
+ curline[i] = 0;
+ }
+ i++;
+ //if ((i % 2) != 0) {
+ // break;
+ //}
+ i >>= 1;
+ if (curline[0] == '#') {
+ // Comment line, ignore
+ } else if (i == FINGERPRINT_V3_LEN ||
+ i == FINGERPRINT_V4_LEN ||
+ i == FINGERPRINT_V5_LEN) {
+ fp.length = i;
+ for (i = 0; i < fp.length; i++) {
+ fp.fp[i] = hex2bin(curline[i * 2]);
+ fp.fp[i] <<= 4;
+ fp.fp[i] |=
+ hex2bin(curline[i * 2 + 1]);
+ }
+ array_add(array, &fp);
+ } else {
+ printf("Bad line.\n");
+ }
+
+ if (!fgets(curline, sizeof(curline) - 1, fpfile)) {
+ break;
+ }
+ }
+
+ fclose(fpfile);
+ }
+
+ return (array->count != 0);
+}
*/
bool array_add(struct keyarray *array, struct openpgp_fingerprint *fp);
+/**
+ * @brief Load a file into a keyarray
+ * @param array Pointer to the key array
+ * @param file The full path to the file to load
+ *
+ * Loads fingerprints from the supplied file into the provided keyarray. Does
+ * not re-initialise the array so can be called repeatedly to add multiple
+ * files. The file does not need to be sorted; array_add() is called for each
+ * key to ensure the array is suitable for binary searching with array_find()
+ */
+bool array_load(struct keyarray *array, const char *file);
+
/**
* @brief Compare two OpenPGP fingerprints
* @param a Fingerprint 1
* the DB). Returns the number of entirely new keys added.
*/
int generic_update_keys(struct onak_dbctx *dbctx,
- struct openpgp_publickey **keys, bool sendsync)
+ struct openpgp_publickey **keys,
+ struct keyarray *blacklist,
+ bool sendsync)
{
struct openpgp_publickey **curkey, *tmp = NULL;
struct openpgp_publickey *oldkey = NULL;
curkey = keys;
while (*curkey != NULL) {
get_fingerprint((*curkey)->publickey, &fp);
+ if (blacklist && array_find(blacklist, &fp)) {
+ logthing(LOGTHING_INFO, "Ignoring blacklisted key.");
+ tmp = *curkey;
+ *curkey = (*curkey)->next;
+ tmp->next = NULL;
+ free_publickey(tmp);
+ continue;
+ }
intrans = dbctx->starttrans(dbctx);
#include <stdbool.h>
#include <inttypes.h>
+#include "keyarray.h"
#include "keystructs.h"
#include "ll.h"
/**
* @brief Takes a list of public keys and updates them in the DB.
* @param keys The keys to update in the DB.
+ * @param blacklist A keyarray of fingerprints that shouldn't be added.
* @param sendsync If we should send a keysync mail.
*
* Takes a list of keys and adds them to the database, merging them with
* with the update.
*/
int (*update_keys)(struct onak_dbctx *,
- struct openpgp_publickey **keys, bool sendsync);
+ struct openpgp_publickey **keys,
+ struct keyarray *blacklist,
+ bool sendsync);
/**
* @brief Takes a keyid and returns the primary UID for it.
}
static int dynamic_update_keys(struct onak_dbctx *dbctx,
- struct openpgp_publickey **keys, bool sendsync)
+ struct openpgp_publickey **keys,
+ struct keyarray *blacklist,
+ bool sendsync)
{
struct onak_dynamic_dbctx *privctx =
(struct onak_dynamic_dbctx *) dbctx->priv;
return privctx->loadeddbctx->update_keys(privctx->loadeddbctx,
- keys, sendsync);
+ keys, blacklist, sendsync);
}
static struct ll *dynamic_getkeysigs(struct onak_dbctx *dbctx,
}
static int keyring_update_keys(struct onak_dbctx *dbctx,
- struct openpgp_publickey **keys, bool sendsync)
+ struct openpgp_publickey **keys,
+ struct keyarray *blacklist,
+ bool sendsync)
{
return 0;
}
}
static int stacked_update_keys(struct onak_dbctx *dbctx,
- struct openpgp_publickey **keys, bool sendsync)
+ struct openpgp_publickey **keys,
+ struct keyarray *blacklist,
+ bool sendsync)
{
struct onak_stacked_dbctx *privctx =
(struct onak_stacked_dbctx *) dbctx->priv;
struct onak_dbctx *backend =
(struct onak_dbctx *) privctx->backends->object;
- return backend->update_keys(backend, keys, sendsync);
+ return backend->update_keys(backend, keys, blacklist, sendsync);
}
static int stacked_iterate_keys(struct onak_dbctx *dbctx,
#include "ll.h"
/*
+ * Fingerprint lengths
+ *
* v3 MD5 fingerprint is 16 bytes
* v4 SHA-1 fingerprint is 20
* v5 SHA2-256 fingerprint is 32
*/
-#define MAX_FINGERPRINT_LEN 32
+#define FINGERPRINT_V3_LEN 16
+#define FINGERPRINT_V4_LEN 20
+#define FINGERPRINT_V5_LEN 32
+#define MAX_FINGERPRINT_LEN 32
/**
* @brief Stores the fingerprint of an OpenPGP key
config.syncsites = lladd(config.syncsites,
strdup(value));
/* [verification] section */
+ } else if (MATCH("verification", "blacklist")) {
+ array_load(&config.blacklist, value);
} else if (MATCH("verification", "drop_v3")) {
if (parsebool(value, config.clean_policies &
ONAK_CLEAN_DROP_V3_KEYS)) {
free(config.mail_dir);
config.mail_dir = NULL;
}
+ if (config.blacklist.count != 0) {
+ array_free(&config.blacklist);
+ }
}
#include <stdbool.h>
#include <stdint.h>
+#include "keyarray.h"
#include "ll.h"
/**
/** Pointer to the initialisation function for our loaded DB backend */
struct onak_dbctx *(*dbinit)(struct onak_db_config *, bool);
+ /** Blacklist of fingerprints to reject */
+ struct keyarray blacklist;
+
/** What policies should we use for cleaning keys? */
uint64_t clean_policies;
dbctx = config.dbinit(config.backend, false);
logthing(LOGTHING_NOTICE, "Got %d new keys.",
dbctx->update_keys(dbctx, &keys,
- false));
+ &config.blacklist,
+ false));
if (keys != NULL && update) {
flatten_publickey(keys,
&packets,
; Settings related to key verification options available.
[verification]
+; Blacklist certain fingerprints (e.g. EVIL32). One fingerprint per line,
+; comment lines start with #
+;blacklist=blacklist.txt
; Verify signature hashes - verify that the hash a signature claims to be
; over matches the hash of the data. Does not actually verify the signature.
check_sighash=true
sed -e "s;BUILDDIR;${BUILDDIR};" -e "s;WORKDIR;${WORKDIR};" \
-e "s;DB;${backend};" \
${TESTSDIR}/test-in.ini > ${WORKDIR}/test.ini
+ touch ${WORKDIR}/blacklist
for t in ${TESTSDIR}/$backend-*.t ${TESTSDIR}/all-*.t; do
total=`expr $total + 1`
mkdir ${WORKDIR}/db/
[mail]
bin_dir=BUILDDIR
this_site=pgp-public-keys@localhost
+
+[verification]
+blacklist=WORKDIR/blacklist