From cc7f34f098226e12b569906033c45a7787315950 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Fri, 27 Feb 2009 13:35:33 -0500 Subject: [PATCH] Refactor creation of domain_map into confdb The NSS provider, the Data Provider backends and the InfoPipe all need access to the domain map provided by the confdb. Instead of reimplimenting it in multiple places, it is now provided in a pair of helper functions from the confdb. confdb_get_domains() returns a domain map by reference. Always returns the most up-to-date set of domains from the confdb. confdb_get_domains_list() returns an array of strings of all the domain names. Always returns the most up-to-date set of domains from the confdb. --- server/confdb/confdb.c | 137 ++++++++++++++++++++++++---- server/confdb/confdb.h | 22 ++++- server/monitor/monitor.c | 5 +- server/responder/common/responder_common.c | 71 +-------------- server/responder/nss/nsssrv.c | 83 +---------------- server/responder/nss/nsssrv.h | 9 +-- server/responder/nss/nsssrv_cmd.c | 36 +++++--- server/util/btreemap.c | 46 ++++++++-- server/util/btreemap.h | 2 +- 9 files changed, 211 insertions(+), 200 deletions(-) diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c index 0435191..ca335c5 100644 --- a/server/confdb/confdb.c +++ b/server/confdb/confdb.c @@ -24,6 +24,8 @@ #include "ldb_errors.h" #include "util/util.h" #include "confdb/confdb.h" +#include "util/btreemap.h" +#include "db/sysdb.h" #define CONFDB_VERSION "0.1" #define CONFDB_DOMAIN_BASEDN "cn=domains,cn=config" #define CONFDB_DOMAIN_ATTR "cn" @@ -600,9 +602,25 @@ int confdb_init(TALLOC_CTX *mem_ctx, return EOK; } +/* domain names are case insensitive for now + * NOTE: this function is not utf-8 safe, + * only ASCII names for now */ +static int _domain_comparator(const void *key1, const void *key2) +{ + int ret; + + ret = strcasecmp((const char *)key1, (const char *)key2); + if (ret) { + /* special case LOCAL to be always the first domain */ + if (strcmp(key1, "LOCAL") == 0) return 1; + if (strcmp(key2, "LOCAL") == 0) return -1; + } + return ret; +} + int confdb_get_domains(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx, - char ***values) + struct btreemap **domains) { TALLOC_CTX *tmp_ctx; struct ldb_dn *dn; @@ -610,8 +628,9 @@ int confdb_get_domains(struct confdb_ctx *cdb, struct ldb_message_element *el; int ret, i; const char *attrs[] = {CONFDB_DOMAIN_ATTR, NULL}; - char **vals; - int val_count; + char *path; + struct btreemap *domain_map; + struct sss_domain_info *domain; tmp_ctx = talloc_new(mem_ctx); @@ -628,15 +647,13 @@ int confdb_get_domains(struct confdb_ctx *cdb, goto done; } - val_count = 1; - vals = talloc(mem_ctx, char *); - if (!vals) { - ret = ENOMEM; - goto done; - } - + domain_map = NULL; i = 0; while (i < res->count) { + /* allocate the domain on the tmp_ctx. It will be stolen + * by btreemap_set_value + */ + domain = talloc_zero(tmp_ctx, struct sss_domain_info); el = ldb_msg_find_element(res->msgs[i], CONFDB_DOMAIN_ATTR); if (el && el->num_values > 0) { if (el->num_values > 1) { @@ -644,26 +661,106 @@ int confdb_get_domains(struct confdb_ctx *cdb, ret = EINVAL; goto done; } - val_count++; - vals = talloc_realloc(mem_ctx, vals, char *, val_count); - if (!vals) { - DEBUG(0, ("realloc failed\n")); + + /* should always be strings so this should be safe */ + struct ldb_val v = el->values[0]; + domain->name = talloc_strndup(domain, (char *)v.data, v.length); + if (!domain->name) { ret = ENOMEM; + talloc_free(domain_map); goto done; } - /* should always be strings so this should be safe */ - struct ldb_val v = el->values[0]; - vals[i] = talloc_strndup(vals, (char *)v.data, v.length); - if (!vals[i]) { + + /* Create the confdb path for this domain */ + path = talloc_asprintf(tmp_ctx, "config/domains/%s", domain->name); + if (!path) { + ret = ENOMEM; + goto done; + } + + /* Build the BaseDN for this domain */ + domain->basedn = talloc_asprintf(domain, SYSDB_DOM_BASE, domain->name); + if (domain->basedn == NULL) { ret = ENOMEM; goto done; } + DEBUG(3, ("BaseDN: %s\n", domain->basedn)); + + /* Determine if this domain can be enumerated */ + ret = confdb_get_int(cdb, domain, path, + "enumerate", false, &(domain->enumerate)); + if (ret != EOK) { + DEBUG(0, ("Failed to fetch enumerate for [%s]!\n", domain->name)); + goto done; + } + + /* Determine if this is a legacy domain */ + ret = confdb_get_bool(cdb, domain, path, + "legacy", false, &(domain->legacy)); + if (ret != EOK) { + DEBUG(0, ("Failed to fetch legacy for [%s]!\n", domain->name)); + goto done; + } + + /* Determine if this domain is managed by a backend provider */ + ret = confdb_get_string(cdb, domain, path, "provider", + NULL, &domain->provider); + if (ret != EOK) { + DEBUG(0, ("Failed to fetch provider for [%s]!\n", domain->name)); + goto done; + } + if (domain->provider) domain->has_provider = true; + + ret = btreemap_set_value(mem_ctx, &domain_map, + domain->name, domain, + _domain_comparator); + if (ret != EOK) { + DEBUG(1, ("Failed to store domain info for [%s]!\n", domain->name)); + goto done; + } + + talloc_free(path); } i++; } - vals[i] = NULL; - *values = vals; + *domains = domain_map; + +done: + talloc_free(tmp_ctx); + if (ret != EOK) { + talloc_free(domain_map); + *domains = NULL; + } + return ret; +} + +int confdb_get_domains_list(struct confdb_ctx *cdb, + TALLOC_CTX *mem_ctx, + const char ***domain_names, + int *count) +{ + int ret; + struct btreemap *domain_map; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if(tmp_ctx == NULL) { + return ENOMEM; + } + + ret = confdb_get_domains(cdb, tmp_ctx, &domain_map); + if (ret != EOK || domain_map == NULL) { + DEBUG(0, ("Error, no domains were configured\n")); + *domain_names = NULL; + count = 0; + goto done; + } + + ret = btreemap_get_keys(mem_ctx, domain_map, (const void ***)domain_names, count); + if (ret != EOK) { + DEBUG(0, ("Couldn't get domain list\n")); + } done: talloc_free(tmp_ctx); diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h index a1d8085..3bd0d03 100644 --- a/server/confdb/confdb.h +++ b/server/confdb/confdb.h @@ -19,12 +19,25 @@ along with this program. If not, see . */ +#ifndef _CONF_DB_H +#define _CONF_DB_H + #include #include "talloc.h" #include "tevent.h" +#include "util/btreemap.h" #define CONFDB_FILE "config.ldb" +struct sss_domain_info { + char *name; + char *basedn; + int enumerate; + bool has_provider; + char *provider; + bool legacy; +}; + struct confdb_ctx; int confdb_add_param(struct confdb_ctx *cdb, @@ -59,4 +72,11 @@ int confdb_init(TALLOC_CTX *mem_ctx, int confdb_get_domains(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx, - char ***values); + struct btreemap **domains); + +int confdb_get_domains_list(struct confdb_ctx *cdb, + TALLOC_CTX *mem_ctx, + const char ***domain_names, + int *count); + +#endif diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c index ff88b29..a07178f 100644 --- a/server/monitor/monitor.c +++ b/server/monitor/monitor.c @@ -365,6 +365,7 @@ int monitor_process_init(TALLOC_CTX *mem_ctx, struct mt_ctx *ctx; struct mt_svc *svc; char **doms; + int dom_count; char *path; int ret, i; @@ -434,13 +435,13 @@ int monitor_process_init(TALLOC_CTX *mem_ctx, } /* now start the data providers */ - ret = confdb_get_domains(cdb, ctx, &doms); + ret = confdb_get_domains_list(cdb, ctx, (const char ***)&doms, &dom_count); if (ret != EOK) { DEBUG(2, ("No domains configured. LOCAL should always exist!\n")); return ret; } - for (i = 0; doms[i]; i++) { + for (i = 0; i < dom_count; i++) { svc = talloc_zero(ctx, struct mt_svc); if (!svc) { talloc_free(ctx); diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c index 74e0321..f532102 100644 --- a/server/responder/common/responder_common.c +++ b/server/responder/common/responder_common.c @@ -319,85 +319,20 @@ failed: return EIO; } -/* domain names are case insensitive for now - * NOTE: this function is not utf-8 safe, - * only ASCII names for now */ -static int _domain_comparator(const void *key1, const void *key2) -{ - return strcasecmp((const char *)key1, (const char *)key2); -} - static int sss_init_domains(struct nss_ctx *nctx) { - char *path; - char **domains; - char *provider; TALLOC_CTX *tmp_ctx; - struct nss_domain_info *info; - int ret, i, c; + int ret; int retval; tmp_ctx = talloc_new(nctx); - ret = confdb_get_domains(nctx->cdb, tmp_ctx, &domains); + ret = confdb_get_domains(nctx->cdb, nctx, &nctx->domain_map); if (ret != EOK) { retval = ret; goto done; } - i = 0; - c = 0; - while (domains[i] != NULL) { - DEBUG(3, ("Adding domain %s to the map\n", domains[i])); - - path = talloc_asprintf(tmp_ctx, "config/domains/%s", domains[i]); - if (!path) { - retval = ENOMEM; - goto done; - } - - /* alloc on tmp_ctx, it will be stolen by btreemap_set_value */ - info = talloc_zero(tmp_ctx, struct nss_domain_info); - if (!info) { - retval = ENOMEM; - goto done; - } - - /* Build the basedn for this domain */ - info->basedn = talloc_asprintf(info, SYSDB_DOM_BASE, domains[i]); - DEBUG(3, ("BaseDN: %s\n", info->basedn)); - - ret = confdb_get_int(nctx->cdb, tmp_ctx, path, - "enumerate", false, &(info->enumerate)); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch enumerate for [%s]!\n", domains[i])); - } - - ret = confdb_get_bool(nctx->cdb, tmp_ctx, path, - "legacy", false, &(info->legacy)); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch legacy for [%s]!\n", domains[i])); - } - - ret = confdb_get_string(nctx->cdb, tmp_ctx, path, "provider", - NULL, &provider); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch provider for [%s]!\n", domains[i])); - } - if (provider) info->has_provider = true; - - ret = btreemap_set_value(nctx, &nctx->domain_map, - domains[i], info, - _domain_comparator); - if (ret != EOK) { - DEBUG(1, ("Failed to store domain info, aborting!\n")); - retval = ret; - goto done; - } - - i++; - c++; - } - if (c == 0) { + if (nctx->domain_map == NULL) { /* No domains configured! * Note: this should never happen, since LOCAL should * always be configured */ diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c index 2fbe397..7c68ba1 100644 --- a/server/responder/nss/nsssrv.c +++ b/server/responder/nss/nsssrv.c @@ -49,7 +49,6 @@ static int service_identity(DBusMessage *message, struct sbus_conn_ctx *sconn); static int service_pong(DBusMessage *message, struct sbus_conn_ctx *sconn); static int service_reload(DBusMessage *message, struct sbus_conn_ctx *sconn); static int nss_init_domains(struct nss_ctx *nctx); -static int _domain_comparator(const void *key1, const void *key2); struct sbus_method nss_sbus_methods[] = { {SERVICE_METHOD_IDENTITY, service_identity}, @@ -392,93 +391,18 @@ failed: return EIO; } -/* domain names are case insensitive for now - * NOTE: this function is not utf-8 safe, - * only ASCII names for now */ -static int _domain_comparator(const void *key1, const void *key2) -{ - int ret; - - ret = strcasecmp((const char *)key1, (const char *)key2); - if (ret) { - /* special case LOCAL to be always the first domain */ - if (strcmp(key1, "LOCAL") == 0) return 1; - if (strcmp(key2, "LOCAL") == 0) return -1; - } - return ret; -} - static int nss_init_domains(struct nss_ctx *nctx) { - char *path; - char **domains; - char *provider; - TALLOC_CTX *tmp_ctx; - struct nss_domain_info *info; - int ret, i, c; + int ret; int retval; - tmp_ctx = talloc_new(nctx); - ret = confdb_get_domains(nctx->cdb, tmp_ctx, &domains); + ret = confdb_get_domains(nctx->cdb, nctx, &nctx->domain_map); if (ret != EOK) { retval = ret; goto done; } - i = 0; - c = 0; - while (domains[i] != NULL) { - DEBUG(3, ("Adding domain %s to the map\n", domains[i])); - - path = talloc_asprintf(tmp_ctx, "config/domains/%s", domains[i]); - if (!path) { - retval = ENOMEM; - goto done; - } - - /* alloc on tmp_ctx, it will be stolen by btreemap_set_value */ - info = talloc_zero(tmp_ctx, struct nss_domain_info); - if (!info) { - retval = ENOMEM; - goto done; - } - - /* Build the basedn for this domain */ - info->basedn = talloc_asprintf(info, SYSDB_DOM_BASE, domains[i]); - DEBUG(3, ("BaseDN: %s\n", info->basedn)); - - ret = confdb_get_int(nctx->cdb, tmp_ctx, path, - "enumerate", false, &(info->enumerate)); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch enumerate for [%s]!\n", domains[i])); - } - - ret = confdb_get_bool(nctx->cdb, tmp_ctx, path, - "legacy", false, &(info->legacy)); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch legacy for [%s]!\n", domains[i])); - } - - ret = confdb_get_string(nctx->cdb, tmp_ctx, path, "provider", - NULL, &provider); - if (ret != EOK) { - DEBUG(0, ("Failed to fetch provider for [%s]!\n", domains[i])); - } - if (provider) info->has_provider = true; - - ret = btreemap_set_value(nctx, &nctx->domain_map, - domains[i], info, - _domain_comparator); - if (ret != EOK) { - DEBUG(1, ("Failed to store domain info, aborting!\n")); - retval = ret; - goto done; - } - - i++; - c++; - } - if (c == 0) { + if (nctx->domain_map == NULL) { /* No domains configured! * Note: this should never happen, since LOCAL should * always be configured */ @@ -498,7 +422,6 @@ static int nss_init_domains(struct nss_ctx *nctx) retval = EOK; done: - talloc_free(tmp_ctx); return retval; } diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h index 333e428..1431dde 100644 --- a/server/responder/nss/nsssrv.h +++ b/server/responder/nss/nsssrv.h @@ -65,7 +65,7 @@ struct nss_ctx { int cache_timeout; struct sbus_method *sss_sbus_methods; - struct sss_cmd_table *sss_cmds; + struct sss_cmd_table *sss_cmds; const char *sss_pipe_name; const char *confdb_socket_path; struct sbus_method *dp_methods; @@ -81,13 +81,6 @@ struct cli_ctx { struct getent_ctx *gctx; }; -struct nss_domain_info { - char *basedn; - int enumerate; - bool has_provider; - bool legacy; -}; - struct nss_packet; struct cli_request { diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c index 1614658..76da6e0 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -25,6 +25,7 @@ #include "responder/nss/nsssrv.h" #include "db/sysdb.h" #include +#include "confdb/confdb.h" struct nss_cmd_ctx { struct cli_ctx *cctx; @@ -92,7 +93,7 @@ static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname) { struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct nss_ctx *nctx = cmdctx->cctx->nctx; - struct nss_domain_info *info; + struct sss_domain_info *info; struct btreemap *domain_map; char *delim; char *domain; @@ -617,7 +618,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) { struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; - struct nss_domain_info *info; + struct sss_domain_info *info; const char **domains; uint8_t *body; size_t blen; @@ -643,8 +644,10 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) domains = NULL; num = 0; /* get domains list */ - btreemap_get_keys(cmdctx, cctx->nctx->domain_map, - (const void ***)&domains, &num); + ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + (const void ***)&domains, &num); + if (ret != EOK) + return ret; cmdctx->nr = num; @@ -797,7 +800,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) { - struct nss_domain_info *info; + struct sss_domain_info *info; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct getent_ctx *gctx; @@ -832,8 +835,11 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) domains = NULL; num = 0; /* get domains list */ - btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, (const void ***)&domains, &num); + if (ret != EOK) { + return ret; + } /* check if enumeration is enabled in any domain */ for (i = 0; i < num; i++) { @@ -1515,7 +1521,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) { struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; - struct nss_domain_info *info; + struct sss_domain_info *info; const char **domains; uint8_t *body; size_t blen; @@ -1541,8 +1547,11 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) domains = NULL; num = 0; /* get domains list */ - btreemap_get_keys(cmdctx, cctx->nctx->domain_map, - (const void ***)&domains, &num); + ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + (const void ***)&domains, &num); + if (ret != EOK) { + return ret; + } cmdctx->nr = num; @@ -1693,7 +1702,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) { - struct nss_domain_info *info; + struct sss_domain_info *info; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct getent_ctx *gctx; @@ -1728,8 +1737,11 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) domains = NULL; num = 0; /* get domains list */ - btreemap_get_keys(cmdctx, cctx->nctx->domain_map, - (const void ***)&domains, &num); + ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + (const void ***)&domains, &num); + if(ret != EOK) { + return ret; + } /* check if enumeration is enabled in any domain */ for (i = 0; i < num; i++) { diff --git a/server/util/btreemap.c b/server/util/btreemap.c index c9289f5..7bda057 100644 --- a/server/util/btreemap.c +++ b/server/util/btreemap.c @@ -166,21 +166,51 @@ int btreemap_set_value(TALLOC_CTX *mem_ctx, return EOK; } -/* Return an array of keys in sort order - * count should be initialized to zero before calling this function. - */ -void btreemap_get_keys(TALLOC_CTX *mem_ctx, struct btreemap *map, const void ***array, int *count) +static int _btreemap_get_keys(TALLOC_CTX *mem_ctx, struct btreemap *map, const void ***array, int *count, int depth) { - if (map == NULL) return; + int ret; + const void **tmp_array; + + if (map == NULL) { + if (depth == 0) { + /* This is the top-level */ + count = 0; + *array = NULL; + } + return EOK; + } /* Left Node */ - btreemap_get_keys(mem_ctx, map->left, array, count); + ret = _btreemap_get_keys(mem_ctx, map->left, array, count, depth+1); + if (ret != EOK) { + return ret; + } /* Current Node */ (*count)++; - *array = talloc_realloc(mem_ctx, *array, const void *, *count); + tmp_array = talloc_realloc(mem_ctx, *array, const void *, *count); + if (tmp_array == NULL) { + /* Out of memory */ + *count = 0; + talloc_free(*array); + *array = NULL; + return ENOMEM; + } + *array = tmp_array; (*array)[(*count)-1] = map->key; /* Right Node */ - btreemap_get_keys(mem_ctx, map->right, array, count); + ret = _btreemap_get_keys(mem_ctx, map->right, array, count, depth+1); + if (ret != EOK) { + return ret; + } + + return EOK; +} +/* Return an array of keys in sort order + */ +int btreemap_get_keys(TALLOC_CTX *mem_ctx, struct btreemap *map, const void ***array, int *count) +{ + *array = NULL; + return _btreemap_get_keys(mem_ctx, map, array, count, 0); } diff --git a/server/util/btreemap.h b/server/util/btreemap.h index c5c4150..8d7fb15 100644 --- a/server/util/btreemap.h +++ b/server/util/btreemap.h @@ -35,7 +35,7 @@ void *btreemap_get_value(struct btreemap *map, const void *key); int btreemap_set_value(TALLOC_CTX *mem_ctx, struct btreemap **map, const void *key, void *value, btreemap_comparison_fn comparator); -void btreemap_get_keys(TALLOC_CTX *mem_ctx, struct btreemap *map, const void ***array, int *count); +int btreemap_get_keys(TALLOC_CTX *mem_ctx, struct btreemap *map, const void ***array, int *count); #endif /*BTREEMAP_H_*/ -- 1.6.0.6