This patch changes hdb.c such that the application will exit with an error if the specified HDB driver cannot be found. The logic looks like this: IF a driver has not been specified explicitly using driver: THEN driver = HDB_DEFAULT_DRIVER END IF IF we find a matching driver in our builtin list THEN use that driver ELSE IF we are able to load an appropriate dynamic module THEN use that driver ELSE exit with an error END IF diff -ru heimdal-0.7.1/lib/hdb/hdb.c heimdal-0.7.1-lks/lib/hdb/hdb.c --- heimdal-0.7.1/lib/hdb/hdb.c 2005-09-09 08:12:09.000000000 -0400 +++ heimdal-0.7.1-lks/lib/hdb/hdb.c 2005-11-02 19:27:19.000000000 -0500 @@ -44,22 +44,31 @@ krb5_error_code (*create)(krb5_context, HDB **, const char *filename); }; +/* + * Define the default HDB backend driver (used when + * dbname does not start with a "backend:" prefix). + */ +#ifndef HDB_DEFAULT_DRIVER +# if defined(HAVE_DB1) || defined(HAVE_DB3) +# define HDB_DEFAULT_DRIVER "db" +# elif defined(HAVE_NDBM) +# define HDB_DEFAULT_DRIVER "ndbm" +# elif defined(HAVE_OPENLDAP) +# define HDB_DEFAULT_DRIVER "ldap" +# else +# error "No default HDB driver!" +# endif +#endif // HDB_DEFAULT_DRIVER + static struct hdb_method methods[] = { #if HAVE_DB1 || HAVE_DB3 - {"db:", hdb_db_create}, + {"db", hdb_db_create}, #endif #if HAVE_NDBM - {"ndbm:", hdb_ndbm_create}, + {"ndbm", hdb_ndbm_create}, #endif #if defined(OPENLDAP) && !defined(OPENLDAP_MODULE) - {"ldap:", hdb_ldap_create}, -#endif -#if HAVE_DB1 || HAVE_DB3 - {"", hdb_db_create}, -#elif defined(HAVE_NDBM) - {"", hdb_ndbm_create}, -#elif defined(OPENLDAP) && !defined(OPENLDAP_MODULE) - {"", hdb_ldap_create}, + {"ldap", hdb_ldap_create}, #endif {NULL, NULL} }; @@ -210,38 +219,26 @@ } #ifdef HAVE_DLOPEN - /* * Load a dynamic backend from /usr/heimdal/lib/hdb_NAME.so, * looking for the hdb_NAME_create symbol. */ static const struct hdb_method * -find_dynamic_method (krb5_context context, - const char *filename, +find_dynamic_hdb (krb5_context context, + const char *driver, const char **rest) { static struct hdb_method method; struct hdb_so_method *mso; - char *prefix, *path, *symbol; - const char *p; + char *path, *symbol; void *dl; - size_t len; - p = strchr(filename, ':'); + /* if no driver, don't know what module to load, just ignore it */ + if (driver == NULL) + return NULL; - /* if no prefix, don't know what module to load, just ignore it */ - if (p == NULL) - return NULL; - - len = p - filename; - *rest = filename + len + 1; - - prefix = strndup(filename, len); - if (prefix == NULL) - krb5_errx(context, 1, "out of memory"); - - if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1) + if (asprintf(&path, LIBDIR "/hdb_%s.so", driver) == -1) krb5_errx(context, 1, "out of memory"); #ifndef RTLD_NOW @@ -255,12 +252,11 @@ if (dl == NULL) { krb5_warnx(context, "error trying to load dynamic module %s: %s\n", path, dlerror()); - free(prefix); free(path); return NULL; } - if (asprintf(&symbol, "hdb_%s_interface", prefix) == -1) + if (asprintf(&symbol, "hdb_%s_interface", driver) == -1) krb5_errx(context, 1, "out of memory"); mso = dlsym(dl, symbol); @@ -269,7 +265,6 @@ symbol, path, dlerror()); dlclose(dl); free(symbol); - free(prefix); free(path); return NULL; } @@ -280,45 +275,95 @@ krb5_warnx(context, "error wrong version in shared module %s " "version: %d should have been %d\n", - prefix, mso->version, HDB_INTERFACE_VERSION); + driver, mso->version, HDB_INTERFACE_VERSION); dlclose(dl); - free(prefix); return NULL; } if (mso->create == NULL) { krb5_errx(context, 1, "no entry point function in shared mod %s ", - prefix); + driver); dlclose(dl); - free(prefix); return NULL; } method.create = mso->create; - method.prefix = prefix; + method.prefix = driver; return &method; } #endif /* HAVE_DLOPEN */ /* + * Search method list for matching method. + */ +static const struct hdb_method * +find_builtin_hdb (krb5_context context, const char *driver, const char **rest) +{ + const struct hdb_method *h; + + for (h=methods; h->prefix != NULL; ++h) { + if (strlen(h->prefix) == strlen(driver) && + strncmp (driver, h->prefix, strlen(h->prefix)) == 0) { + return h; + } + } + + return NULL; +} + +/* * find the relevant method for `filename', returning a pointer to the * rest in `rest'. * return NULL if there's no such method. */ static const struct hdb_method * -find_method (const char *filename, const char **rest) +find_method (krb5_context context, const char *filename, const char **rest) { - const struct hdb_method *h; + const struct hdb_method *h = NULL; + char *driver; + size_t len; - for (h = methods; h->prefix != NULL; ++h) - if (strncmp (filename, h->prefix, strlen(h->prefix)) == 0) { - *rest = filename + strlen(h->prefix); - return h; - } - return NULL; + driver = strchr(filename, ':'); + + /* + * If the filename doesn't provide an explicit driver, use + * the default. + */ + if (driver == NULL) { + driver = strdup(HDB_DEFAULT_DRIVER); + *rest = filename; + } else { + len = driver - filename; + *rest = filename + len + 1; + driver = strndup(filename, len); + if (driver == NULL) + krb5_errx(context, 1, "out of memory"); + } + + /* + * Look for a match in the list of builtin HDB + * drivers. + */ + h = find_builtin_hdb(context, driver, rest); + +#ifdef HAVE_DLOPEN + /* + * If we support loadable modules, attempt to load + * an appropriately named driver. + */ + if (h == NULL) + h = find_dynamic_hdb(context, driver, rest); +#endif //HAVE_DLOPEN + + if (h == NULL) + krb5_warnx(context, "Unable to find HDB driver for \"%s\".\n", + driver); + + free(driver); + return h; } krb5_error_code @@ -362,12 +407,9 @@ if(filename == NULL) filename = HDB_DEFAULT_DB; krb5_add_et_list(context, initialize_hdb_error_table_r); - h = find_method (filename, &residual); -#ifdef HAVE_DLOPEN + h = find_method (context, filename, &residual); if (h == NULL) - h = find_dynamic_method (context, filename, &residual); -#endif - if (h == NULL) - krb5_errx(context, 1, "No database support! (hdb_create)"); + krb5_errx(context, 1, "No database support! (hdb_create)"); return (*h->create)(context, db, residual); } +