]> the.earth.li Git - onak.git/blobdiff - keydb_db4.c
Cleanup postinst to avoid recursive chown of database
[onak.git] / keydb_db4.c
index 25d9183d4bf62c37a512b6db9a64324f347784ca..1f306e267f60e9851c0dd65b0874517ba7afcb39 100644 (file)
@@ -13,8 +13,7 @@
  * more details.
  *
  * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <sys/types.h>
@@ -73,10 +72,13 @@ DB *keydb_fp(struct onak_db4_dbctx *privctx, struct openpgp_fingerprint *fp)
 {
        uint64_t keytrun;
 
-       keytrun = (fp->fp[4] << 24) |
-                       (fp->fp[5] << 16) |
-                       (fp->fp[6] <<  8) |
-                       (fp->fp[7]);
+       keytrun = fp->fp[4];
+       keytrun <<= 8;
+       keytrun |= fp->fp[5];
+       keytrun <<= 8;
+       keytrun |= fp->fp[6];
+       keytrun <<= 8;
+       keytrun |= fp->fp[7];
 
        return(privctx->dbconns[keytrun % privctx->numdbs]);
 }
@@ -290,69 +292,6 @@ static int db4_upgradedb(struct onak_dbctx *dbctx)
        return ret;
 }
 
-/**
- *     getfullkeyid - Maps a 32bit key id to a 64bit one.
- *     @keyid: The 32bit keyid.
- *
- *     This function maps a 32bit key id to the full 64bit one. It returns the
- *     full keyid. If the key isn't found a keyid of 0 is returned.
- */
-static uint64_t db4_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
-{
-       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) {
-                       if (data.size == 8) {
-                               keyid = * (uint64_t *) data.data;
-                       } else {
-                               keyid = 0;
-                               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.
  */
@@ -464,89 +403,69 @@ static int db4_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
                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;
-       struct buffer_ctx fetchbuf;
+       uint32_t  shortkeyid = 0;
        struct openpgp_fingerprint fingerprint;
+       bool first;
 
-       if (keyid < 0x100000000LL) {
-               keyid = db4_getfullkeyid(dbctx, keyid);
+       if (!intrans) {
+               db4_starttrans(dbctx);
        }
 
-       memset(&key, 0, sizeof(key));
-       memset(&data, 0, sizeof(data));
+       /* 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 */
 
-       data.size = 0;
-       data.data = NULL;
+               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*/
 
-       key.size = sizeof(keyid);
-       key.data = &keyid;
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &keyid;
+               key.size = sizeof(keyid);
+       }
 
-       if (!intrans) {
-               db4_starttrans(dbctx);
+       if (ret != 0) {
+               return 0;
        }
 
-       /*
-        * First we try a legacy stored key where we used the 64 bit key ID
-        * as the DB key.
-        */
-       ret = keydb_id(privctx, keyid)->get(keydb_id(privctx, keyid),
-                       privctx->txn,
-                       &key,
-                       &data,
-                       0); /* flags*/
+       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++;
 
-       if (ret == DB_NOTFOUND) {
-               /* If we didn't find the key ID try the 64 bit map DB */
-               memset(&key, 0, sizeof(key));
                memset(&data, 0, sizeof(data));
                data.ulen = MAX_FINGERPRINT_LEN;
                data.data = fingerprint.fp;
                data.flags = DB_DBT_USERMEM;
-               key.size = sizeof(keyid);
-               key.data = &keyid;
-
-               ret = privctx->id64db->get(privctx->id64db,
-                       privctx->txn,
-                       &key,
-                       &data,
-                       0); /* flags*/
-
-               if (ret == 0) {
-                       /* We got a match; retrieve the actual key */
-                       fingerprint.length = data.size;
-
-                       memset(&key, 0, sizeof(key));
-                       memset(&data, 0, sizeof(data));
-                       key.size = fingerprint.length;
-                       key.data = fingerprint.fp;
-
-                       ret = keydb_fp(privctx, &fingerprint)->get(
-                               keydb_fp(privctx, &fingerprint),
-                               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));
+               first = false;
        }
+       cursor->c_close(cursor);
+       cursor = NULL;
 
        if (!intrans) {
                db4_endtrans(dbctx);
@@ -555,12 +474,6 @@ static int db4_fetch_key_id(struct onak_dbctx *dbctx, uint64_t keyid,
        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.
@@ -576,7 +489,6 @@ static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
        DBC *cursor = NULL;
        DBT key, data;
        int ret;
-       uint64_t keyid;
        int i;
        int numkeys;
        char *searchtext = NULL;
@@ -616,18 +528,9 @@ static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
                while (ret == 0 && strncmp(key.data, curword->object,
                                        key.size) == 0 &&
                                ((char *) curword->object)[key.size] == 0) {
-                       if (data.size == 12) {
-                               /* Old style creation + key id */
-                               fingerprint.length = 8;
-                               for (i = 4; i < 12; i++) {
-                                       fingerprint.fp[i - 4] =
-                                               ((unsigned char *)
-                                                       data.data)[i];
-                               }
-                       } else {
-                               fingerprint.length = data.size;
-                               memcpy(fingerprint.fp, data.data, data.size);
-                       }
+
+                       fingerprint.length = data.size;
+                       memcpy(fingerprint.fp, data.data, data.size);
 
                        /*
                         * Only add the keys containing this word if this is
@@ -670,20 +573,9 @@ static int db4_fetch_key_text(struct onak_dbctx *dbctx, const char *search,
 
        db4_starttrans(dbctx);
        for (i = 0; i < keylist.count; i++) {
-               if (keylist.keys[i].length == 8) {
-                       keyid = 0;
-                       for (int j = 0; j < 8; j++) {
-                               keyid <<= 8;
-                               keyid |= keylist.keys[i].fp[j];
-                       }
-                       numkeys += db4_fetch_key_id(dbctx, keyid,
-                               publickey,
-                               true);
-               } else {
-                       numkeys += db4_fetch_key_fp(dbctx, &keylist.keys[i],
-                               publickey,
-                               true);
-               }
+               numkeys += db4_fetch_key_fp(dbctx, &keylist.keys[i],
+                       publickey,
+                       true);
        }
        array_free(&keylist);
        free(searchtext);
@@ -701,7 +593,6 @@ static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
        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;
@@ -719,7 +610,9 @@ static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
        memset(&data, 0, sizeof(data));
        key.data = (void *) hash->hash;
        key.size = sizeof(hash->hash);
-       data.flags = DB_DBT_MALLOC;
+       data.ulen = MAX_FINGERPRINT_LEN;
+       data.data = fingerprint.fp;
+       data.flags = DB_DBT_USERMEM;
 
        ret = cursor->c_get(cursor,
                &key,
@@ -727,22 +620,9 @@ static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
                DB_SET);
 
        if (ret == 0) {
-               if (data.size == 8) {
-                       /* Legacy key ID record */
-                       keyid = *(uint64_t *) data.data;
-                       count = db4_fetch_key_id(dbctx, keyid, publickey,
-                               false);
-               } else {
-                       fingerprint.length = data.size;
-                       memcpy(fingerprint.fp, data.data, data.size);
-                       count = db4_fetch_key_fp(dbctx, &fingerprint,
-                               publickey, false);
-               }
-
-               if (data.data != NULL) {
-                       free(data.data);
-                       data.data = NULL;
-               }
+               fingerprint.length = data.size;
+               count = db4_fetch_key_fp(dbctx, &fingerprint,
+                       publickey, false);
        }
 
        cursor->c_close(cursor);
@@ -753,14 +633,15 @@ static int db4_fetch_key_skshash(struct onak_dbctx *dbctx,
 
 /**
  *     delete_key - Given a keyid delete the key from storage.
- *     @keyid: The keyid to delete.
+ *     @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,
-               uint64_t keyid, bool intrans)
+               struct openpgp_fingerprint *fp,
+               bool intrans)
 {
        struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
        struct openpgp_publickey *publickey = NULL;
@@ -774,25 +655,26 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
        int i;
        char **uids = NULL;
        char *primary = NULL;
-       unsigned char worddb_data[12];
        struct ll *wordlist = NULL;
        struct ll *curword  = NULL;
        bool deadlock = false;
        struct skshash hash;
-       struct openpgp_fingerprint fingerprint;
+       uint64_t keyid;
 
        if (!intrans) {
                db4_starttrans(dbctx);
        }
 
-       if (db4_fetch_key_id(dbctx, keyid, &publickey, true) == 0) {
+       if (db4_fetch_key_fp(dbctx, fp, &publickey, true) == 0) {
                if (!intrans) {
                        db4_endtrans(dbctx);
                }
                return 1;
        }
 
-       get_fingerprint(publickey->publickey, &fingerprint);
+       if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
+               return 1;
+       }
 
        /*
         * Walk through the uids removing the words from the worddb.
@@ -812,46 +694,16 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
 
                for (curword = wordlist; curword != NULL && !deadlock;
                                curword = curword->next) {
-                       memset(&key, 0, sizeof(key));
-                       memset(&data, 0, sizeof(data));
-                       key.data = curword->object;
-                       key.size = strlen(key.data);
-                       data.data = worddb_data;
-                       data.size = sizeof(worddb_data);
-
                        /*
-                        * Old format word db data was the key creation time
-                        * followed by the 64 bit key id.
+                        * New style uses the fingerprint as the data
+                        * Old (unsupported) style was the 64 bit keyid
                         */
-                       worddb_data[ 0] = publickey->publickey->data[1];
-                       worddb_data[ 1] = publickey->publickey->data[2];
-                       worddb_data[ 2] = publickey->publickey->data[3];
-                       worddb_data[ 3] = publickey->publickey->data[4];
-                       worddb_data[ 4] = (keyid >> 56) & 0xFF;
-                       worddb_data[ 5] = (keyid >> 48) & 0xFF;
-                       worddb_data[ 6] = (keyid >> 40) & 0xFF;
-                       worddb_data[ 7] = (keyid >> 32) & 0xFF;
-                       worddb_data[ 8] = (keyid >> 24) & 0xFF;
-                       worddb_data[ 9] = (keyid >> 16) & 0xFF;
-                       worddb_data[10] = (keyid >>  8) & 0xFF;
-                       worddb_data[11] = keyid & 0xFF;
-
-                       ret = cursor->c_get(cursor,
-                               &key,
-                               &data,
-                               DB_GET_BOTH);
-
-                       if (ret == 0) {
-                               cursor->c_del(cursor, 0);
-                       }
-
-                       /* New style just uses the fingerprint as the data */
                        memset(&key, 0, sizeof(key));
                        memset(&data, 0, sizeof(data));
                        key.data = curword->object;
                        key.size = strlen(key.data);
-                       data.data = fingerprint.fp;
-                       data.size = fingerprint.length;
+                       data.data = fp->fp;
+                       data.size = fp->length;
 
                        ret = cursor->c_get(cursor,
                                &key,
@@ -898,32 +750,15 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
                        &cursor64,
                        0);   /* flags */
 
+               /* 32 bit short key mapping to fingerprint */
                shortkeyid = keyid & 0xFFFFFFFF;
 
-               /* Old style mapping to 64 bit key id */
-               memset(&key, 0, sizeof(key));
-               memset(&data, 0, sizeof(data));
-               key.data = &shortkeyid;
-               key.size = sizeof(shortkeyid);
-               data.data = &keyid;
-               data.size = sizeof(keyid);
-
-               ret = cursor->c_get(cursor,
-                       &key,
-                       &data,
-                       DB_GET_BOTH);
-
-               if (ret == 0) {
-                       cursor->c_del(cursor, 0);
-               }
-
-               /* New style mapping to fingerprint */
                memset(&key, 0, sizeof(key));
                memset(&data, 0, sizeof(data));
                key.data = &shortkeyid;
                key.size = sizeof(shortkeyid);
-               data.data = fingerprint.fp;
-               data.size = fingerprint.length;
+               data.data = fp->fp;
+               data.size = fp->length;
 
                ret = cursor->c_get(cursor,
                        &key,
@@ -950,8 +785,8 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
                memset(&data, 0, sizeof(data));
                key.data = &keyid;
                key.size = sizeof(keyid);
-               data.data = fingerprint.fp;
-               data.size = fingerprint.length;
+               data.data = fp->fp;
+               data.size = fp->length;
 
                ret = cursor64->c_get(cursor64,
                        &key,
@@ -980,7 +815,7 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
                        memset(&key, 0, sizeof(key));
                        key.data = subkeyids[i].fp;
                        key.size = subkeyids[i].length;
-                       privctx->subkeydb->del(privctx->subkeydb,
+                       ret = privctx->subkeydb->del(privctx->subkeydb,
                                        privctx->txn, &key, 0);
                        if (ret != 0 && ret != DB_NOTFOUND) {
                                logthing(LOGTHING_ERROR,
@@ -995,30 +830,13 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
 
                        shortkeyid = subkeyid & 0xFFFFFFFF;
 
-                       /* Remove 32 bit keyid -> 64 bit keyid mapping */
-                       memset(&key, 0, sizeof(key));
-                       memset(&data, 0, sizeof(data));
-                       key.data = &shortkeyid;
-                       key.size = sizeof(shortkeyid);
-                       data.data = &keyid;
-                       data.size = sizeof(keyid);
-
-                       ret = cursor->c_get(cursor,
-                               &key,
-                               &data,
-                               DB_GET_BOTH);
-
-                       if (ret == 0) {
-                               cursor->c_del(cursor, 0);
-                       }
-
                        /* 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 = fingerprint.fp;
-                       data.size = fingerprint.length;
+                       data.data = fp->fp;
+                       data.size = fp->length;
 
                        ret = cursor->c_get(cursor,
                                &key,
@@ -1045,8 +863,8 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
                        memset(&data, 0, sizeof(data));
                        key.data = &subkeyid;
                        key.size = sizeof(subkeyid);
-                       data.data = fingerprint.fp;
-                       data.size = fingerprint.length;
+                       data.data = fp->fp;
+                       data.size = fp->length;
 
                        ret = cursor64->c_get(cursor64,
                                &key,
@@ -1087,30 +905,13 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
                if (ret == 0) {
                        get_skshash(publickey, &hash);
 
-                       /* First delete old style keyid mapping */
-                       memset(&key, 0, sizeof(key));
-                       memset(&data, 0, sizeof(data));
-                       key.data = hash.hash;
-                       key.size = sizeof(hash.hash);
-                       data.data = &keyid;
-                       data.size = sizeof(keyid);
-
-                       ret = cursor->c_get(cursor,
-                               &key,
-                               &data,
-                               DB_GET_BOTH);
-
-                       if (ret == 0) {
-                               cursor->c_del(cursor, 0);
-                       }
-
-                       /* Then delete new style fingerprint mapping */
+                       /* 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 = fingerprint.fp;
-                       data.size = fingerprint.length;
+                       data.data = fp->fp;
+                       data.size = fp->length;
 
                        ret = cursor->c_get(cursor,
                                &key,
@@ -1140,20 +941,10 @@ static int db4_delete_key(struct onak_dbctx *dbctx,
        publickey = NULL;
 
        if (!deadlock) {
-               key.data = fingerprint.fp;
-               key.size = fingerprint.length;
-
-               keydb_fp(privctx, &fingerprint)->del(keydb_fp(privctx,
-                                       &fingerprint),
-                               privctx->txn,
-                               &key,
-                               0); /* flags */
-
-               /* Delete old style 64 bit keyid */
-               key.data = &keyid;
-               key.size = sizeof(keyid);
+               key.data = fp->fp;
+               key.size = fp->length;
 
-               keydb_id(privctx, keyid)->del(keydb_id(privctx, keyid),
+               keydb_fp(privctx, fp)->del(keydb_fp(privctx, fp),
                                privctx->txn,
                                &key,
                                0); /* flags */
@@ -1225,7 +1016,7 @@ static int db4_store_key(struct onak_dbctx *dbctx,
         * it definitely needs updated.
         */
        if (update) {
-               deadlock = (db4_delete_key(dbctx, keyid, true) == -1);
+               deadlock = (db4_delete_key(dbctx, &fingerprint, true) == -1);
        }
 
        /*
@@ -1244,8 +1035,8 @@ static int db4_store_key(struct onak_dbctx *dbctx,
                write_openpgp_stream(buffer_putchar, &storebuf, packets);
 
                /*
-                * Now we have the key data store it in the DB; the keyid is
-                * the key.
+                * Now we have the key data store it in the DB; the fingerprint
+                * is the key.
                 */
                memset(&key, 0, sizeof(key));
                memset(&data, 0, sizeof(data));
@@ -1279,7 +1070,8 @@ static int db4_store_key(struct onak_dbctx *dbctx,
        }
 
        /*
-        * Walk through our uids storing the words into the db with the keyid.
+        * Walk through our uids storing the words into the db with the
+        * fingerprint.
         */
        if (!deadlock) {
                uids = keyuids(publickey, &primary);
@@ -1962,7 +1754,6 @@ struct onak_dbctx *keydb_db4_init(struct onak_db_config *dbcfg, bool readonly)
        dbctx->getkeysigs               = generic_getkeysigs;
        dbctx->cached_getkeysigs        = generic_cached_getkeysigs;
        dbctx->keyid2uid                = generic_keyid2uid;
-       dbctx->getfullkeyid             = db4_getfullkeyid;
        dbctx->iterate_keys             = db4_iterate_keys;
 
        return dbctx;