summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2008-11-06 15:45:24 -0500
committerSimo Sorce <idra@samba.org>2008-11-07 16:51:21 -0500
commit9396e620134760e7b562b5452f34ec80dc6f2af7 (patch)
treede226c456d579270d20be914af9fddb961ca4d73
parent5851bf4d73fdab8634e2098e73eaef396504ed74 (diff)
downloadsssd-9396e620134760e7b562b5452f34ec80dc6f2af7.tar.gz
sssd-9396e620134760e7b562b5452f34ec80dc6f2af7.tar.bz2
sssd-9396e620134760e7b562b5452f34ec80dc6f2af7.zip
Store all domains served by the SSSD to a binary-tree map for fast NSS lookup.
Changed the "section" feature of confdb.c to use '/' as a delimiter instead of '.', because this conflicted with the ability to use dots in domain names.
-rw-r--r--server/confdb/confdb.c93
-rw-r--r--server/confdb/confdb.h8
-rw-r--r--server/examples/config.ldif18
-rw-r--r--server/monitor.c8
-rw-r--r--server/nss/nsssrv.c58
-rw-r--r--server/nss/nsssrv.h1
-rw-r--r--server/nss/nsssrv_ldb.c2
-rw-r--r--server/server.mk1
8 files changed, 179 insertions, 10 deletions
diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c
index bab94b3f..3064101a 100644
--- a/server/confdb/confdb.c
+++ b/server/confdb/confdb.c
@@ -27,6 +27,8 @@
#include "util/util.h"
#define CONFDB_VERSION "0.1"
#define CONFDB_FILE "/var/lib/sss/db/config.ldb"
+#define CONFDB_DOMAIN_BASEDN "cn=domains,cn=config"
+#define CONFDB_DOMAIN_ATTR "cn"
#define CONFDB_ZERO_CHECK_OR_JUMP(var, ret, err, label) do { \
if (!var) { \
@@ -67,15 +69,15 @@ static int parse_section(TALLOC_CTX *mem_ctx, const char *section,
const char *s;
int l, ret;
- /* section must be a non null string and must not start with '.' */
- if (!section || !*section || *section == '.') return EINVAL;
+ /* section must be a non null string and must not start with '/' */
+ if (!section || !*section || *section == '/') return EINVAL;
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) return ENOMEM;
s = section;
l = 0;
- while ((p = strchrnul(s, '.'))) {
+ while ((p = strchrnul(s, '/'))) {
if (l == 0) {
dn = talloc_asprintf(tmp_ctx, "cn=%s", s);
l = 3 + (p-s);
@@ -446,3 +448,88 @@ int confdb_init(TALLOC_CTX *mem_ctx,
return EOK;
}
+
+int confdb_get_domains(struct confdb_ctx *cdb,
+ TALLOC_CTX *mem_ctx,
+ char ***values)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_dn *dn;
+ struct ldb_result *res;
+ struct ldb_message_element *el;
+ int ret, i;
+ const char *attrs[] = {CONFDB_DOMAIN_ATTR, NULL};
+ char **vals;
+ int val_count;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ dn = ldb_dn_new(tmp_ctx,cdb->ldb, CONFDB_DOMAIN_BASEDN);
+ if (!dn) {
+ ret = EIO;
+ goto done;
+ }
+
+ ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
+ LDB_SCOPE_ONELEVEL, attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+
+ val_count = 1;
+ vals = talloc(mem_ctx, char *);
+ if (!vals) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ i = 0;
+ while (i < res->count) {
+ el = ldb_msg_find_element(res->msgs[i], CONFDB_DOMAIN_ATTR);
+ if (el && el->num_values > 0) {
+ if (el->num_values > 1) {
+ DEBUG(0, ("Error, domains should not have multivalued cn\n"));
+ ret = EINVAL;
+ goto done;
+ }
+ val_count++;
+ vals = talloc_realloc(mem_ctx, vals, char *, val_count);
+ if (!vals) {
+ DEBUG(0, ("realloc failed\n"));
+ ret = ENOMEM;
+ 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]) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ i++;
+ }
+ vals[i] = NULL;
+
+ *values = vals;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+int confdb_get_domain_basedn(struct confdb_ctx *cdb,
+ TALLOC_CTX *mem_ctx,
+ const char *domain,
+ char **basedn)
+{
+ char *section;
+ int ret;
+
+ section = talloc_asprintf(mem_ctx, "config/domains/%s", domain);
+ ret = confdb_get_string(cdb, mem_ctx, section, "basedn", "cn=local", basedn);
+
+ talloc_free(section);
+ return ret;
+}
diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h
index 7841d4c1..62ab45c7 100644
--- a/server/confdb/confdb.h
+++ b/server/confdb/confdb.h
@@ -45,3 +45,11 @@ int confdb_get_int(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
int confdb_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct confdb_ctx **cdb_ctx);
+
+int confdb_get_domains(struct confdb_ctx *cdb,
+ TALLOC_CTX *mem_ctx,
+ char ***values);
+int confdb_get_domain_basedn(struct confdb_ctx *cdb,
+ TALLOC_CTX *mem_ctx,
+ const char *domain,
+ char **basedn);
diff --git a/server/examples/config.ldif b/server/examples/config.ldif
index 9548d907..13ddb026 100644
--- a/server/examples/config.ldif
+++ b/server/examples/config.ldif
@@ -20,3 +20,21 @@ description: Monitor Configuration
sbusTimeout: 10
sbusAddress: unix:path=/var/lib/sss/pipes/private/dbus
servicePingTime: 10
+
+dn: cn=domains,cn=config
+cn: domains
+description: Domains served by SSSD
+
+dn: cn=LOCAL,cn=domains,cn=config
+cn: LOCAL
+description: Reserved domain for local configurations
+provider: local
+basedn: cn=local
+
+dn: cn=EXAMPLE.COM,cn=domains,cn=config
+cn: EXAMPLE.COM
+description: Example domain served by IPA
+provider: ipa
+server: ipaserver1.example.com
+server: ipabackupserver.example.com
+basedn: cn=EXAMPLE.COM,cn=ipa,cn=remote
diff --git a/server/monitor.c b/server/monitor.c
index c5d5781f..9eccb0b9 100644
--- a/server/monitor.c
+++ b/server/monitor.c
@@ -112,7 +112,7 @@ static int monitor_dbus_init(struct mt_ctx *ctx)
int ret;
ret = confdb_get_string(ctx->cdb, ctx,
- "config.services.monitor", "sbusAddress",
+ "config/services/monitor", "sbusAddress",
DEFAULT_SBUS_ADDRESS, &sbus_address);
if (ret != EOK) {
return ret;
@@ -253,14 +253,14 @@ int get_monitor_config(struct mt_ctx *ctx)
int ret;
ret = confdb_get_int(ctx->cdb, ctx,
- "config.services.monitor", "sbusTimeout",
+ "config/services/monitor", "sbusTimeout",
-1, &ctx->service_id_timeout);
if (ret != EOK) {
return ret;
}
ret = confdb_get_int(ctx->cdb, ctx,
- "config.services.monitor", "servicePingTime",
+ "config/services/monitor", "servicePingTime",
MONITOR_MIN_PING_TIME, &ctx->service_ping_time);
if (ret != EOK) {
return ret;
@@ -269,7 +269,7 @@ int get_monitor_config(struct mt_ctx *ctx)
ctx->service_ping_time = MONITOR_MIN_PING_TIME;
ret = confdb_get_param(ctx->cdb, ctx,
- "config.services", "activeServices",
+ "config/services", "activeServices",
&ctx->services);
if (ctx->services[0] == NULL) {
diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c
index bd0f761b..93f8d223 100644
--- a/server/nss/nsssrv.c
+++ b/server/nss/nsssrv.c
@@ -38,9 +38,12 @@
#include "dbus/dbus.h"
#include "sbus/sssd_dbus.h"
#include "sbus_interfaces.h"
+#include "util/btreemap.h"
static int provide_identity(DBusMessage *message, void *data, DBusMessage **r);
static int reply_ping(DBusMessage *message, void *data, DBusMessage **r);
+static int nss_init_domains(struct nss_ctx *nctx);
+static int _domain_comparator(void *key1, void *key2);
struct sbus_method nss_sbus_methods[] = {
{SERVICE_METHOD_IDENTITY, provide_identity},
@@ -250,7 +253,7 @@ static int nss_sbus_init(struct nss_ctx *nctx)
int ret;
ret = confdb_get_string(nctx->cdb, nctx,
- "config.services.monitor", "sbusAddress",
+ "config/services/monitor", "sbusAddress",
DEFAULT_SBUS_ADDRESS, &sbus_address);
if (ret != EOK) {
return ret;
@@ -313,7 +316,7 @@ static int set_unix_socket(struct nss_ctx *nctx)
int ret;
ret = confdb_get_string(nctx->cdb, nctx,
- "config.services.nss", "unixSocket",
+ "config/services/nss", "unixSocket",
SSS_NSS_SOCKET_NAME, &nctx->sock_name);
if (ret != EOK) {
return ret;
@@ -363,6 +366,51 @@ failed:
return EIO;
}
+static int _domain_comparator(void *key1, void *key2)
+{
+ return strcmp((char *)key1, (char *)key2);
+}
+
+static int nss_init_domains(struct nss_ctx *nctx)
+{
+ char **domains;
+ char *basedn;
+ TALLOC_CTX *tmp_ctx;
+ int ret, i;
+ int retval;
+
+ tmp_ctx = talloc_new(nctx);
+ ret = confdb_get_domains(nctx->cdb, tmp_ctx, &domains);
+ if (ret != EOK) {
+ retval = ret;
+ goto done;
+ }
+
+ i = 0;
+ while (domains[i] != NULL) {
+ DEBUG(3, ("Adding domain %s to the map\n", domains[i]));
+ /* Look up the appropriate basedn for this domain */
+ ret = confdb_get_domain_basedn(nctx->cdb, tmp_ctx, domains[i], &basedn);
+ DEBUG(3, ("BaseDN: %s\n", basedn));
+ btreemap_set_value(&nctx->domain_map, domains[i], basedn, _domain_comparator);
+ i++;
+ }
+ if (i == 0) {
+ /* No domains configured!
+ * Note: this should never happen, since LOCAL should
+ * always be configured */
+ DEBUG(0, ("No domains configured on this client!\n"));
+ retval = EINVAL;
+ goto done;
+ }
+
+ retval = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return retval;
+}
+
void nss_task_init(struct task_server *task)
{
struct nss_ctx *nctx;
@@ -384,6 +432,12 @@ void nss_task_init(struct task_server *task)
return;
}
+ ret = nss_init_domains(nctx);
+ if (ret != EOK) {
+ task_server_terminate(task, "fatal error setting up domain map\n");
+ return;
+ }
+
ret = nss_sbus_init(nctx);
if (ret != EOK) {
task_server_terminate(task, "fatal error setting up message bus\n");
diff --git a/server/nss/nsssrv.h b/server/nss/nsssrv.h
index 5e264937..5d49e79f 100644
--- a/server/nss/nsssrv.h
+++ b/server/nss/nsssrv.h
@@ -50,6 +50,7 @@ struct nss_ctx {
struct confdb_ctx *cdb;
char *sock_name;
struct nss_sbus_ctx *ns_ctx;
+ struct btreemap *domain_map;
};
struct cli_ctx {
diff --git a/server/nss/nsssrv_ldb.c b/server/nss/nsssrv_ldb.c
index 56cdb5d7..418b16e2 100644
--- a/server/nss/nsssrv_ldb.c
+++ b/server/nss/nsssrv_ldb.c
@@ -600,7 +600,7 @@ int nss_ldb_initgroups(TALLOC_CTX *mem_ctx,
return LDB_SUCCESS;
}
-#define NSS_LDB_CONF_SECTION "config.services.nss"
+#define NSS_LDB_CONF_SECTION "config/services/nss"
static int nss_ldb_read_var(TALLOC_CTX *tmp_ctx,
struct confdb_ctx *cdb,
diff --git a/server/server.mk b/server/server.mk
index 6339791e..6277a559 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -8,6 +8,7 @@ SERVER_OBJ = \
util/signal.o \
util/become_daemon.o \
util/memory.o \
+ util/btreemap.o \
confdb/confdb.o \
nss/nsssrv.o \
nss/nsssrv_packet.o \