+static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
+ const struct skshash *hash,
+ struct openpgp_publickey **publickey)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ DBT key, data;
+ DBC *cursor = NULL;
+ uint64_t keyid = 0;
+ int ret;
+ int count = 0;
+ struct openpgp_fingerprint fingerprint;
+
+ ret = privctx->skshashdb->cursor(privctx->skshashdb,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+
+ if (ret != 0) {
+ return 0;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = (void *) hash->hash;
+ key.size = sizeof(hash->hash);
+ data.ulen = MAX_FINGERPRINT_LEN;
+ data.data = fingerprint.fp;
+ data.flags = DB_DBT_USERMEM;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_SET);
+
+ if (ret == 0) {
+ fingerprint.length = data.size;
+ count = db4_fetch_key_fp(dbctx, &fingerprint,
+ publickey, false);
+ }
+
+ cursor->c_close(cursor);
+ cursor = NULL;
+
+ return count;
+}
+
+/**
+ * delete_key - Given a keyid delete the key from storage.
+ * @fp: The fingerprint of the key to delete.
+ * @intrans: If we're already in a transaction.
+ *
+ * This function deletes a public key from whatever storage mechanism we
+ * are using. Returns 0 if the key existed.
+ */
+static int db4_delete_key(struct onak_dbctx *dbctx,
+ struct openpgp_fingerprint *fp,
+ bool intrans)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ struct openpgp_publickey *publickey = NULL;
+ DBT key, data;
+ DBC *cursor = NULL;
+ DBC *cursor64 = NULL;
+ uint32_t shortkeyid = 0;
+ uint64_t subkeyid = 0;
+ struct openpgp_fingerprint *subkeyids = NULL;
+ int ret = 0;
+ int i;
+ char **uids = NULL;
+ char *primary = NULL;
+ struct ll *wordlist = NULL;
+ struct ll *curword = NULL;
+ bool deadlock = false;
+ struct skshash hash;
+ uint64_t keyid;
+
+ if (!intrans) {
+ db4_starttrans(dbctx);
+ }
+
+ if (db4_fetch_key_fp(dbctx, fp, &publickey, true) == 0) {
+ if (!intrans) {
+ db4_endtrans(dbctx);
+ }
+ return 1;
+ }
+
+ if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
+ return 1;
+ }
+
+ /*
+ * Walk through the uids removing the words from the worddb.
+ */
+ if (publickey != NULL) {
+ uids = keyuids(publickey, &primary);
+ }
+ if (uids != NULL) {
+ for (i = 0; ret == 0 && uids[i] != NULL; i++) {
+ wordlist = makewordlist(wordlist, uids[i]);
+ }
+
+ privctx->worddb->cursor(privctx->worddb,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+
+ for (curword = wordlist; curword != NULL && !deadlock;
+ curword = curword->next) {
+ /*
+ * New style uses the fingerprint as the data
+ * Old (unsupported) style was the 64 bit keyid
+ */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = curword->object;
+ key.size = strlen(key.data);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor->c_del(cursor, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting word: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+ }
+ cursor->c_close(cursor);
+ cursor = NULL;
+
+ /*
+ * Free our UID and word lists.
+ */
+ llfree(wordlist, NULL);
+ for (i = 0; uids[i] != NULL; i++) {
+ free(uids[i]);
+ uids[i] = NULL;
+ }
+ free(uids);
+ uids = NULL;
+ }
+
+ if (!deadlock) {
+ privctx->id32db->cursor(privctx->id32db,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+ privctx->id64db->cursor(privctx->id64db,
+ privctx->txn,
+ &cursor64,
+ 0); /* flags */
+
+ /* 32 bit short key mapping to fingerprint */
+ shortkeyid = keyid & 0xFFFFFFFF;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &shortkeyid;
+ key.size = sizeof(shortkeyid);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor->c_del(cursor, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting short keyid: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+
+ /* 64 bit key mapping to fingerprint */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &keyid;
+ key.size = sizeof(keyid);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor64->c_get(cursor64,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor64->c_del(cursor64, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting keyid: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+
+ subkeyids = keysubkeys(publickey);
+ i = 0;
+ while (subkeyids != NULL && subkeyids[i].length != 0) {
+ subkeyid = fingerprint2keyid(&subkeyids[i]);
+ memset(&key, 0, sizeof(key));
+ key.data = subkeyids[i].fp;
+ key.size = subkeyids[i].length;
+ ret = privctx->subkeydb->del(privctx->subkeydb,
+ privctx->txn, &key, 0);
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting subkey id: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+
+ shortkeyid = subkeyid & 0xFFFFFFFF;
+
+ /* Remove 32 bit keyid -> fingerprint mapping */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &shortkeyid;
+ key.size = sizeof(shortkeyid);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor->c_del(cursor, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting short keyid: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+
+ /* Remove 64 bit keyid -> fingerprint mapping */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &subkeyid;
+ key.size = sizeof(subkeyid);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor64->c_get(cursor64,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor64->c_del(cursor64, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting keyid: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+ i++;
+ }
+ if (subkeyids != NULL) {
+ free(subkeyids);
+ subkeyids = NULL;
+ }
+ cursor64->c_close(cursor64);
+ cursor64 = NULL;
+ cursor->c_close(cursor);
+ cursor = NULL;
+ }
+
+ if (!deadlock) {
+ ret = privctx->skshashdb->cursor(privctx->skshashdb,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+ if (ret == 0) {
+ get_skshash(publickey, &hash);
+
+ /* Remove SKS hash -> fingerprint mapping */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = hash.hash;
+ key.size = sizeof(hash.hash);
+ data.data = fp->fp;
+ data.size = fp->length;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_GET_BOTH);
+
+ if (ret == 0) {
+ ret = cursor->c_del(cursor, 0);
+ }
+
+ if (ret != 0 && ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem deleting skshash: %s "
+ "(0x%016" PRIX64 ")",
+ db_strerror(ret),
+ keyid);
+ if (ret == DB_LOCK_DEADLOCK) {
+ deadlock = true;
+ }
+ }
+
+ cursor->c_close(cursor);
+ cursor = NULL;
+ }
+ }
+ free_publickey(publickey);
+ publickey = NULL;
+
+ if (!deadlock) {
+ key.data = fp->fp;
+ key.size = fp->length;
+
+ keydb_fp(privctx, fp)->del(keydb_fp(privctx, fp),
+ privctx->txn,
+ &key,
+ 0); /* flags */
+ }
+
+ if (!intrans) {
+ db4_endtrans(dbctx);
+ }
+
+ return deadlock ? (-1) : (ret == DB_NOTFOUND);
+}
+