+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ DBT key, data;
+ DBC *cursor = NULL;
+ uint32_t shortkeyid = 0;
+ int ret = 0;
+ int i;
+
+ if (keyid < 0x100000000LL) {
+ ret = privctx->id32db->cursor(privctx->id32db,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+
+ if (ret != 0) {
+ return 0;
+ }
+
+ shortkeyid = keyid & 0xFFFFFFFF;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &shortkeyid;
+ key.size = sizeof(shortkeyid);
+ data.flags = DB_DBT_MALLOC;
+
+ ret = cursor->c_get(cursor,
+ &key,
+ &data,
+ DB_SET);
+
+ if (ret == 0) {
+ keyid = 0;
+ /* Only works for v4, not v3 or v5 */
+ for (i = 12; i < 20; i++) {
+ keyid <<= 8;
+ keyid |= ((uint8_t *) data.data)[i];
+ }
+
+ if (data.data != NULL) {
+ free(data.data);
+ data.data = NULL;
+ }
+ }
+
+ cursor->c_close(cursor);
+ cursor = NULL;
+ }
+
+ return keyid;
+}
+
+/**
+ * fetch_key_fp - Given a fingerprint fetch the key from storage.
+ */
+static int db4_fetch_key_fp(struct onak_dbctx *dbctx,
+ struct openpgp_fingerprint *fingerprint,
+ struct openpgp_publickey **publickey,
+ bool intrans)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ struct openpgp_packet_list *packets = NULL;
+ DBT key, data;
+ int ret = 0;
+ int numkeys = 0;
+ struct buffer_ctx fetchbuf;
+ struct openpgp_fingerprint subfp;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ data.size = 0;
+ data.data = NULL;
+
+ key.size = fingerprint->length;
+ key.data = fingerprint->fp;
+
+ if (!intrans) {
+ db4_starttrans(dbctx);
+ }
+
+ ret = keydb_fp(privctx, fingerprint)->get(keydb_fp(privctx,
+ fingerprint),
+ privctx->txn,
+ &key,
+ &data,
+ 0); /* flags*/
+
+ if (ret == DB_NOTFOUND) {
+ /* If we didn't find the key ID see if it's a subkey ID */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ data.data = subfp.fp;
+ data.ulen = MAX_FINGERPRINT_LEN;
+ data.flags = DB_DBT_USERMEM;
+ key.data = fingerprint->fp;
+ key.size = fingerprint->length;
+
+ ret = privctx->subkeydb->get(privctx->subkeydb,
+ privctx->txn,
+ &key,
+ &data,
+ 0); /* flags*/
+
+ if (ret == 0) {
+ /* We got a subkey match; retrieve the actual key */
+ memset(&key, 0, sizeof(key));
+ key.size = subfp.length = data.size;
+ key.data = subfp.fp;
+
+ memset(&data, 0, sizeof(data));
+ data.size = 0;
+ data.data = NULL;
+
+ ret = keydb_fp(privctx, &subfp)->get(
+ keydb_fp(privctx, &subfp),
+ privctx->txn,
+ &key,
+ &data,
+ 0); /* flags*/
+ }
+ }
+
+ if (ret == 0) {
+ fetchbuf.buffer = data.data;
+ fetchbuf.offset = 0;
+ fetchbuf.size = data.size;
+ read_openpgp_stream(buffer_fetchchar, &fetchbuf,
+ &packets, 0);
+ parse_keys(packets, publickey);
+ free_packet_list(packets);
+ packets = NULL;
+ numkeys++;
+ } else if (ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem retrieving key: %s",
+ db_strerror(ret));
+ }
+
+ if (!intrans) {
+ db4_endtrans(dbctx);
+ }
+
+ return (numkeys);
+}
+
+/**
+ * fetch_key_id - Given a keyid fetch the key from storage.
+ * @keyid: The keyid to fetch.
+ * @publickey: A pointer to a structure to return the key in.
+ * @intrans: If we're already in a transaction.
+ *
+ * We use the hex representation of the keyid as the filename to fetch the
+ * key from. The key is stored in the file as a binary OpenPGP stream of
+ * packets, so we can just use read_openpgp_stream() to read the packets
+ * in and then parse_keys() to parse the packets into a publickey
+ * structure.
+ */
+static int db4_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
+ struct openpgp_publickey **publickey,
+ bool intrans)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ struct openpgp_packet_list *packets = NULL;
+ DBT key, data;
+ DBC *cursor = NULL;
+ int ret = 0;
+ int numkeys = 0;
+ uint32_t shortkeyid = 0;
+ struct openpgp_fingerprint fingerprint;
+ bool first;
+
+ if (!intrans) {
+ db4_starttrans(dbctx);
+ }
+
+ /* If the key ID fits in 32 bits assume it's a short key id */
+ if (keyid < 0x100000000LL) {
+ ret = privctx->id32db->cursor(privctx->id32db,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+
+ shortkeyid = keyid & 0xFFFFFFFF;
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &shortkeyid;
+ key.size = sizeof(shortkeyid);
+ } else {
+ ret = privctx->id64db->cursor(privctx->id64db,
+ privctx->txn,
+ &cursor,
+ 0); /* flags*/
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ key.data = &keyid;
+ key.size = sizeof(keyid);
+ }
+
+ if (ret != 0) {
+ return 0;
+ }
+
+ memset(&data, 0, sizeof(data));
+ data.ulen = MAX_FINGERPRINT_LEN;
+ data.data = fingerprint.fp;
+ data.flags = DB_DBT_USERMEM;
+
+ first = true;
+ while (cursor->c_get(cursor, &key, &data,
+ first ? DB_SET : DB_NEXT_DUP) == 0) {
+ /* We got a match; retrieve the actual key */
+ fingerprint.length = data.size;
+
+ if (db4_fetch_key_fp(dbctx, &fingerprint,
+ publickey, true))
+ numkeys++;
+
+ memset(&data, 0, sizeof(data));
+ data.ulen = MAX_FINGERPRINT_LEN;
+ data.data = fingerprint.fp;
+ data.flags = DB_DBT_USERMEM;
+ first = false;
+ }
+ cursor->c_close(cursor);
+ cursor = NULL;
+
+ if (!intrans) {
+ db4_endtrans(dbctx);
+ }
+
+ return (numkeys);
+}
+
+
+int worddb_cmp(const void *d1, const void *d2)
+{
+ return memcmp(d1, d2, 12);
+}
+
+/**
+ * fetch_key_text - Trys to find the keys that contain the supplied text.
+ * @search: The text to search for.
+ * @publickey: A pointer to a structure to return the key in.
+ *
+ * This function searches for the supplied text and returns the keys that
+ * contain it.
+ */
+static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
+ struct openpgp_publickey **publickey)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ DBC *cursor = NULL;
+ DBT key, data;
+ int ret;
+ uint64_t keyid;
+ int i;
+ int numkeys;
+ char *searchtext = NULL;
+ struct ll *wordlist = NULL;
+ struct ll *curword = NULL;
+ struct keyarray keylist = { NULL, 0, 0 };