2  * keydb_dynamic.c - backend that can load the other backends
 
   4  * Brett Parker <iDunno@sommitrealweird.co.uk>
 
   6  * Copyright 2005 Project Purple
 
  13 #include "decodekey.h"
 
  17 #include "keystructs.h"
 
  21 #include "onak-conf.h"
 
  25 static struct dbfuncs *loaded_backend = NULL;
 
  26 static char *backendsoname;
 
  27 static void *backend_handle;
 
  29 static bool close_backend(void)
 
  31         loaded_backend = NULL;
 
  32         dlclose(backend_handle);
 
  33         backend_handle = NULL;
 
  38 static bool load_backend(void)
 
  41         char *funcsname = NULL;
 
  43         if (loaded_backend != NULL) {
 
  45                 loaded_backend = NULL;
 
  48         if (config.use_keyd) {
 
  49                 free(config.db_backend);
 
  50                 config.db_backend = strdup("keyd");
 
  53         if (!config.db_backend) {
 
  54                 logthing(LOGTHING_CRITICAL, "No database backend defined.");
 
  58         if (config.backends_dir == NULL) {
 
  59                 soname = malloc(strlen(config.db_backend)
 
  60                         + strlen("./libkeydb_")
 
  64                 sprintf(soname, "./libkeydb_%s.so", config.db_backend);
 
  66                 soname = malloc(strlen(config.db_backend)
 
  67                         + strlen("/libkeydb_")
 
  69                         + strlen(config.backends_dir)
 
  72                 sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
 
  76         logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
 
  78         backend_handle = dlopen(soname, RTLD_LAZY);
 
  79         if (backend_handle == NULL) {
 
  80                 logthing(LOGTHING_CRITICAL,
 
  81                                 "Failed to open handle to library '%s': %s",
 
  88         funcsname = malloc(strlen(config.db_backend)
 
  92         sprintf(funcsname, "keydb_%s_funcs", config.db_backend);
 
  94         loaded_backend = dlsym(backend_handle, funcsname);
 
  97         if (loaded_backend == NULL) {
 
  98                 logthing(LOGTHING_CRITICAL,
 
  99                                 "Failed to find dbfuncs structure in library "
 
 100                                 "'%s' : %s", soname, dlerror());
 
 111 static bool dynamic_starttrans()
 
 113         struct dynamic_backend *backend;
 
 115         if (loaded_backend == NULL) {
 
 119         if (loaded_backend != NULL) {
 
 120                 if (loaded_backend->starttrans != NULL) {
 
 121                         return loaded_backend->starttrans();
 
 128 static void dynamic_endtrans()
 
 130         struct dynamic_backend *backend;
 
 132         if (loaded_backend == NULL) {
 
 136         if (loaded_backend != NULL) {
 
 137                 if (loaded_backend->endtrans != NULL) {
 
 138                         loaded_backend->endtrans();
 
 143 static int dynamic_fetch_key(uint64_t keyid,
 
 144                 struct openpgp_publickey **publickey, bool intrans)
 
 146         struct dynamic_backend *backend;
 
 148         if (loaded_backend == NULL) {
 
 152         if (loaded_backend != NULL) {
 
 153                 if (loaded_backend->fetch_key != NULL) {
 
 154                         return loaded_backend->fetch_key(keyid,publickey,intrans);
 
 161 static int dynamic_store_key(struct openpgp_publickey *publickey, bool intrans,
 
 164         struct dynamic_backend *backend;
 
 166         if (loaded_backend == NULL) {
 
 170         if (loaded_backend != NULL) {
 
 171                 if (loaded_backend->store_key != NULL) {
 
 172                         return loaded_backend->store_key(publickey,intrans,update);
 
 179 static int dynamic_delete_key(uint64_t keyid, bool intrans)
 
 181         struct dynamic_backend *backend;
 
 183         if (loaded_backend == NULL) {
 
 187         if (loaded_backend != NULL) {
 
 188                 if (loaded_backend->delete_key != NULL) {
 
 189                         return loaded_backend->delete_key(keyid, intrans);
 
 196 static int dynamic_fetch_key_text(const char *search,
 
 197                 struct openpgp_publickey **publickey)
 
 199         struct dynamic_backend *backend;
 
 201         if (loaded_backend == NULL) {
 
 205         if (loaded_backend != NULL) {
 
 206                 if (loaded_backend->fetch_key_text != NULL) {
 
 207                         return loaded_backend->fetch_key_text(search, publickey);
 
 214 static int dynamic_iterate_keys(void (*iterfunc)(void *ctx,
 
 215                 struct openpgp_publickey *key), void *ctx)
 
 217         struct dynamic_backend *backend;
 
 219         if (loaded_backend == NULL) {
 
 223         if (loaded_backend != NULL) {
 
 224                 if (loaded_backend->iterate_keys != NULL) {
 
 225                         return loaded_backend->iterate_keys(iterfunc, ctx);
 
 233  *      keyid2uid - Takes a keyid and returns the primary UID for it.
 
 234  *      @keyid: The keyid to lookup.
 
 236 static char *dynamic_keyid2uid(uint64_t keyid)
 
 238         struct openpgp_publickey *publickey = NULL;
 
 239         struct openpgp_signedpacket_list *curuid = NULL;
 
 242         struct dynamic_backend *backend;
 
 243         if (loaded_backend == NULL) {
 
 247         if (loaded_backend != NULL) {
 
 248                 if (loaded_backend->keyid2uid != NULL) {
 
 249                         return loaded_backend->keyid2uid(keyid);
 
 254         if (dynamic_fetch_key(keyid, &publickey, false) && publickey != NULL) {
 
 255                 curuid = publickey->uids;
 
 256                 while (curuid != NULL && buf[0] == 0) {
 
 257                         if (curuid->packet->tag == 13) {
 
 258                                 snprintf(buf, 1023, "%.*s",
 
 259                                                 (int) curuid->packet->length,
 
 260                                                 curuid->packet->data);
 
 262                         curuid = curuid -> next;
 
 264                 free_publickey(publickey);
 
 275  *      getkeysigs - Gets a linked list of the signatures on a key.
 
 276  *      @keyid: The keyid to get the sigs for.
 
 277  *      @revoked: Is the key revoked?
 
 279  *      This function gets the list of signatures on a key. Used for key 
 
 280  *      indexing and doing stats bits. If revoked is non-NULL then if the key
 
 281  *      is revoked it's set to true.
 
 283 static struct ll *dynamic_getkeysigs(uint64_t keyid, bool *revoked)
 
 285         struct ll *sigs = NULL;
 
 286         struct openpgp_signedpacket_list *uids = NULL;
 
 287         struct openpgp_publickey *publickey = NULL;
 
 289         struct dynamic_backend *backend;
 
 290         if ( loaded_backend == NULL ) {
 
 294         if (loaded_backend != NULL) {
 
 295                 if (loaded_backend->getkeysigs != NULL) {
 
 296                         return loaded_backend->getkeysigs(keyid,revoked);
 
 300         dynamic_fetch_key(keyid, &publickey, false);
 
 302         if (publickey != NULL) {
 
 303                 for (uids = publickey->uids; uids != NULL; uids = uids->next) {
 
 304                         sigs = keysigs(sigs, uids->sigs);
 
 306                 if (revoked != NULL) {
 
 307                         *revoked = publickey->revoked;
 
 309                 free_publickey(publickey);
 
 316  *      cached_getkeysigs - Gets the signatures on a key.
 
 317  *      @keyid: The key we want the signatures for.
 
 319  *      This function gets the signatures on a key. It's the same as the
 
 320  *      getkeysigs function above except we use the hash module to cache the
 
 321  *      data so if we need it again it's already loaded.
 
 323 static struct ll *dynamic_cached_getkeysigs(uint64_t keyid)
 
 325         struct stats_key *key = NULL;
 
 326         struct stats_key *signedkey = NULL;
 
 327         struct ll        *cursig = NULL;
 
 328         bool              revoked = false;
 
 330         struct dynamic_backend *backend;
 
 336         if (loaded_backend == NULL) {
 
 340         if (loaded_backend != NULL) {
 
 341                 if (loaded_backend->cached_getkeysigs != NULL) {
 
 342                         return loaded_backend->cached_getkeysigs(keyid);
 
 346         key = createandaddtohash(keyid);
 
 348         if (key->gotsigs == false) {
 
 349                 key->sigs = dynamic_getkeysigs(key->keyid, &revoked);
 
 350                 key->revoked = revoked;
 
 351                 for (cursig = key->sigs; cursig != NULL;
 
 352                                 cursig = cursig->next) {
 
 353                         signedkey = (struct stats_key *) cursig->object;
 
 354                         signedkey->signs = lladd(signedkey->signs, key);
 
 363  *      getfullkeyid - Maps a 32bit key id to a 64bit one.
 
 364  *      @keyid: The 32bit keyid.
 
 366  *      This function maps a 32bit key id to the full 64bit one. It returns the
 
 367  *      full keyid. If the key isn't found a keyid of 0 is returned.
 
 369 static uint64_t dynamic_getfullkeyid(uint64_t keyid)
 
 371         struct openpgp_publickey *publickey = NULL;
 
 372         struct dynamic_backend *backend;
 
 374         if (loaded_backend == NULL) {
 
 378         if (loaded_backend != NULL) {
 
 379                 if (loaded_backend->getfullkeyid != NULL) {
 
 380                         return loaded_backend->getfullkeyid(keyid);
 
 384         if (keyid < 0x100000000LL) {
 
 385                 dynamic_fetch_key(keyid, &publickey, false);
 
 386                 if (publickey != NULL) {
 
 387                         keyid = get_keyid(publickey);
 
 388                         free_publickey(publickey);
 
 399  *      update_keys - Takes a list of public keys and updates them in the DB.
 
 400  *      @keys: The keys to update in the DB.
 
 401  *      @sendsync: Should we send a sync mail to our peers.
 
 403  *      Takes a list of keys and adds them to the database, merging them with
 
 404  *      the key in the database if it's already present there. The key list is
 
 405  *      update to contain the minimum set of updates required to get from what
 
 406  *      we had before to what we have now (ie the set of data that was added to
 
 407  *      the DB). Returns the number of entirely new keys added.
 
 409 static int dynamic_update_keys(struct openpgp_publickey **keys, bool sendsync)
 
 411         struct openpgp_publickey *curkey = NULL;
 
 412         struct openpgp_publickey *oldkey = NULL;
 
 413         struct openpgp_publickey *prev = NULL;
 
 414         struct dynamic_backend *backend;
 
 418         if (loaded_backend == NULL) {
 
 422         if (loaded_backend != NULL) {
 
 423                 if (loaded_backend->update_keys != NULL) {
 
 424                         return loaded_backend->update_keys(keys, sendsync);
 
 428         for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
 
 429                 intrans = dynamic_starttrans();
 
 430                 logthing(LOGTHING_INFO,
 
 431                         "Fetching key 0x%" PRIX64 ", result: %d",
 
 433                         dynamic_fetch_key(get_keyid(curkey), &oldkey, intrans));
 
 436                  * If we already have the key stored in the DB then merge it
 
 437                  * with the new one that's been supplied. Otherwise the key
 
 438                  * we've just got is the one that goes in the DB and also the
 
 439                  * one that we send out.
 
 441                 if (oldkey != NULL) {
 
 442                         merge_keys(oldkey, curkey);
 
 443                         if (curkey->sigs == NULL &&
 
 444                                         curkey->uids == NULL &&
 
 445                                         curkey->subkeys == NULL) {
 
 447                                         *keys = curkey->next;
 
 449                                         prev->next = curkey->next;
 
 451                                         free_publickey(curkey);
 
 456                                 logthing(LOGTHING_INFO,
 
 457                                         "Merged key; storing updated key.");
 
 458                                 dynamic_store_key(oldkey, intrans, true);
 
 460                         free_publickey(oldkey);
 
 464                         logthing(LOGTHING_INFO,
 
 465                                 "Storing completely new key.");
 
 466                         dynamic_store_key(curkey, intrans, false);
 
 473         if (sendsync && keys != NULL) {
 
 480 static void dynamic_initdb(bool readonly)
 
 482         struct dynamic_backend *backend;
 
 484         if (loaded_backend == NULL) {
 
 488         if (loaded_backend != NULL) {
 
 489                 if (loaded_backend->initdb != NULL) {
 
 490                         loaded_backend->initdb(readonly);
 
 495 static void dynamic_cleanupdb(void)
 
 497         struct dynamic_backend *backend;
 
 499         if (loaded_backend != NULL) {
 
 500                 if (loaded_backend->cleanupdb != NULL) {
 
 501                         loaded_backend->cleanupdb();
 
 508 struct dbfuncs keydb_dynamic_funcs = {
 
 509         .initdb                 = dynamic_initdb,
 
 510         .cleanupdb              = dynamic_cleanupdb,
 
 511         .starttrans             = dynamic_starttrans,
 
 512         .endtrans               = dynamic_endtrans,
 
 513         .fetch_key              = dynamic_fetch_key,
 
 514         .fetch_key_text         = dynamic_fetch_key_text,
 
 515         .store_key              = dynamic_store_key,
 
 516         .update_keys            = dynamic_update_keys,
 
 517         .delete_key             = dynamic_delete_key,
 
 518         .getkeysigs             = dynamic_getkeysigs,
 
 519         .cached_getkeysigs      = dynamic_cached_getkeysigs,
 
 520         .keyid2uid              = dynamic_keyid2uid,
 
 521         .getfullkeyid           = dynamic_getfullkeyid,
 
 522         .iterate_keys           = dynamic_iterate_keys,