[SSSD] [PATCHES] Use namingContext to set empty search bases

Sumit Bose sbose at redhat.com
Tue Nov 2 21:39:45 UTC 2010


On Tue, Nov 02, 2010 at 10:57:23AM +0100, Sumit Bose wrote:
> Hi,
> 
> these two patches make the use of the ldap_search_base option optional
> and should fix ticket #558.
> 
> bye,
> Sumit

selfNACK to the old version. On IRC Simo mentioned that it might be
useful to check defaultNamingContext, too. This attribute is e.g. used
by Active Directoy where namingContexts has multiple values be default.

We also discussed what we can do if there is no defaultNamingContext and
namingContexts has multiple values. I think we cannot do anything in
this case, because there is no ordering in the attributes. If e.g. we
choose always the first we might use a different value at each restart.

New patches are attached which check defaultNamingContext first and use
namingContexts otherwise.

bye,
Sumit
-------------- next part --------------
From a90e03142619e59746dc2032b4d5bed820df07b1 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 2 Nov 2010 21:24:53 +0100
Subject: [PATCH 1/3] Add defaultNamingContext to RootDSE attributes

---
 src/providers/ldap/sdap.h       |    2 ++
 src/providers/ldap/sdap_async.c |    1 +
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index be4cf8a..f4ea109 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -127,6 +127,8 @@ struct sdap_ppolicy_data {
 
 #define SYSDB_PWD_ATTRIBUTE "pwdAttribute"
 
+#define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext"
+
 enum sdap_result {
     SDAP_SUCCESS,
     SDAP_NOT_FOUND,
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 84da288..a3e114a 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -654,6 +654,7 @@ struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx,
 	    "supportedFeatures",
 	    "supportedLDAPVersion",
 	    "supportedSASLMechanisms",
+            SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT,
 	    NULL
     };
 
-- 
1.7.2.3

-------------- next part --------------
From 25ba83556760295058372dd81066971b641c0829 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 2 Nov 2010 09:35:00 +0100
Subject: [PATCH 2/3] Use (default)namingContext to set empty search bases

---
 src/providers/ldap/sdap.c                  |  103 ++++++++++++++++++++++++++++
 src/providers/ldap/sdap.h                  |    5 ++
 src/providers/ldap/sdap_async.c            |    2 +-
 src/providers/ldap/sdap_async_connection.c |    8 ++
 4 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
index 4d911c4..cf4e9ed 100644
--- a/src/providers/ldap/sdap.c
+++ b/src/providers/ldap/sdap.c
@@ -404,6 +404,109 @@ int sdap_set_rootdse_supported_lists(struct sysdb_attrs *rootdse,
 
 }
 
+static char *get_single_value_as_string(TALLOC_CTX *mem_ctx,
+                                        struct ldb_message_element *el)
+{
+    char *str = NULL;
+
+    if (el->num_values == 0) {
+        DEBUG(3, ("Missing value.\n"));
+    } else if (el->num_values == 1) {
+        str = talloc_strndup(mem_ctx, (char *) el->values[0].data,
+                             el->values[0].length);
+        if (str == NULL) {
+            DEBUG(1, ("talloc_strndup failed.\n"));
+        }
+    } else {
+        DEBUG(3, ("More than one value found.\n"));
+    }
+
+    return str;
+}
+
+static char *get_naming_context(TALLOC_CTX *mem_ctx,
+                                struct sysdb_attrs *rootdse)
+{
+    struct ldb_message_element *nc = NULL;
+    struct ldb_message_element *dnc = NULL;
+    int i;
+    char *naming_context = NULL;
+
+    for (i = 0; i < rootdse->num; i++) {
+        if (strcasecmp(rootdse->a[i].name,
+                       SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS) == 0) {
+            nc = &rootdse->a[i];
+        } else if (strcasecmp(rootdse->a[i].name,
+                              SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT) == 0) {
+            dnc = &rootdse->a[i];
+        }
+    }
+
+    if (dnc == NULL && nc == NULL) {
+        DEBUG(3, ("No attributes [%s] or [%s] found in rootDSE.\n",
+                  SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS,
+                  SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT));
+    } else {
+        if (dnc != NULL) {
+            DEBUG(5, ("Using value from [%s] as naming context.\n",
+                      SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT));
+            naming_context = get_single_value_as_string(mem_ctx, dnc);
+        }
+
+        if (naming_context == NULL && nc != NULL) {
+            DEBUG(5, ("Using value from [%s] as naming context.\n",
+                      SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS));
+            naming_context = get_single_value_as_string(mem_ctx, nc);
+        }
+    }
+
+    return naming_context;
+}
+
+errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
+                                             struct sdap_handle *sh,
+                                             struct sdap_options *opts)
+{
+    int ret;
+    char *naming_context = NULL;
+    const int search_base_options[] = { SDAP_SEARCH_BASE,
+                                        SDAP_USER_SEARCH_BASE,
+                                        SDAP_GROUP_SEARCH_BASE,
+                                        SDAP_NETGROUP_SEARCH_BASE,
+                                        -1 };
+    int o;
+
+
+    for (o = 0; search_base_options[o] != -1; o++) {
+        if (dp_opt_get_string(opts->basic, search_base_options[o]) == NULL) {
+            if (naming_context == NULL) {
+                naming_context = get_naming_context(opts->basic, rootdse);
+                if (naming_context == NULL) {
+                    DEBUG(1, ("get_naming_context failed.\n"));
+                    ret = EINVAL;
+                    goto done;
+                }
+            }
+
+            DEBUG(3, ("Setting option [%s] to [%s].\n",
+                      opts->basic[search_base_options[o]].opt_name,
+                      naming_context));
+            ret = dp_opt_set_string(opts->basic, search_base_options[o],
+                                    naming_context);
+            if (ret != EOK) {
+                DEBUG(1, ("dp_opt_set_string failed.\n"));
+                goto done;
+            }
+        }
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(naming_context);
+    return ret;
+}
+
 int build_attrs_from_map(TALLOC_CTX *memctx,
                          struct sdap_attr_map *map,
                          size_t size, const char ***_attrs)
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index f4ea109..945de37 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -127,6 +127,7 @@ struct sdap_ppolicy_data {
 
 #define SYSDB_PWD_ATTRIBUTE "pwdAttribute"
 
+#define SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS "namingContexts"
 #define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext"
 
 enum sdap_result {
@@ -319,4 +320,8 @@ int build_attrs_from_map(TALLOC_CTX *memctx,
 
 int sdap_control_create(struct sdap_handle *sh, const char *oid, int iscritical,
                         struct berval *value, int dupval, LDAPControl **ctrlp);
+
+errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
+                                             struct sdap_handle *sh,
+                                             struct sdap_options *opts);
 #endif /* _SDAP_H_ */
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index a3e114a..01cd967 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -648,7 +648,7 @@ struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx,
     const char *attrs[] = {
 	    "*",
 	    "altServer",
-	    "namingContexts",
+	    SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS,
 	    "supportedControl",
 	    "supportedExtension",
 	    "supportedFeatures",
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index fbbec18..0cb9162 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1277,6 +1277,14 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq)
         return;
     }
 
+    ret = sdap_set_config_options_with_rootdse(rootdse, state->sh,
+                                               state->opts);
+    if (ret) {
+        DEBUG(1, ("sdap_set_config_options_with_rootdse failed.\n"));
+        tevent_req_error(req, ret);
+        return;
+    }
+
     sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
 
     if (sasl_mech && state->use_rootdse) {
-- 
1.7.2.3

-------------- next part --------------
From 2fda77263e40f988eb33771dd8109c4106a8ec90 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 2 Nov 2010 10:06:31 +0100
Subject: [PATCH 3/3] Make ldap_search_base a non-mandatory option

---
 src/config/etc/sssd.api.d/sssd-ldap.conf |    2 +-
 src/man/sssd-ldap.5.xml                  |   19 ++++++++-
 src/providers/ldap/ldap_common.c         |   60 ++++++++++++-----------------
 3 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 1af6b0c..404f4d5 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -1,6 +1,6 @@
 [provider/ldap]
 ldap_uri = str, None, false
-ldap_search_base = str, None, true
+ldap_search_base = str, None, false
 ldap_schema = str, None, true, rfc2307
 ldap_default_bind_dn = str, None, false
 ldap_default_authtok_type = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 8c38ca7..2071eb4 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -76,6 +76,13 @@
                             The default base DN to use for
                             performing LDAP user operations.
                         </para>
+                        <para>
+                            Default: If not set the value of the namingContexts
+                            attribute from the RootDSE of the LDAP server is
+                            used. The namingContexts attribute must have a
+                            single value with the DN of the search base of the
+                            LDAP server to make this work.
+                        </para>
                     </listitem>
                 </varlistentry>
 
@@ -1045,7 +1052,9 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
                         </para>
                         <para>
                             Default: the value of
-                            <emphasis>ldap_search_base</emphasis>
+                            <emphasis>ldap_search_base</emphasis> or the value
+                            of the namingContexts attribute of the RootDSE of the
+                            LDAP server.
                         </para>
                     </listitem>
                 </varlistentry>
@@ -1059,7 +1068,9 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
                         </para>
                         <para>
                             Default: the value of
-                            <emphasis>ldap_search_base</emphasis>
+                            <emphasis>ldap_search_base</emphasis> or the value
+                            of the namingContexts attribute of the RootDSE of the
+                            LDAP server.
                         </para>
                     </listitem>
                 </varlistentry>
@@ -1073,7 +1084,9 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com
                         </para>
                         <para>
                             Default: the value of
-                            <emphasis>ldap_search_base</emphasis>
+                            <emphasis>ldap_search_base</emphasis> or the value
+                            of the namingContexts attribute of the RootDSE of the
+                            LDAP server.
                         </para>
                     </listitem>
                 </varlistentry>
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 543774b..16693a4 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -34,7 +34,7 @@ int ldap_child_debug_fd = -1;
 
 struct dp_option default_basic_opts[] = {
     { "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-    { "ldap_search_base", DP_OPT_STRING, { "dc=example,dc=com" }, NULL_STRING },
+    { "ldap_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_default_authtok_type", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
@@ -185,12 +185,18 @@ int ldap_get_options(TALLOC_CTX *memctx,
     struct sdap_attr_map *default_netgroup_map;
     struct sdap_options *opts;
     char *schema;
+    const char *search_base;
     const char *pwd_policy;
     int ret;
     int account_cache_expiration;
     int offline_credentials_expiration;
     const char *ldap_deref;
     int ldap_deref_val;
+    int o;
+    const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
+                                        SDAP_GROUP_SEARCH_BASE,
+                                        SDAP_NETGROUP_SEARCH_BASE,
+                                        -1 };
 
     opts = talloc_zero(memctx, struct sdap_options);
     if (!opts) return ENOMEM;
@@ -203,41 +209,25 @@ int ldap_get_options(TALLOC_CTX *memctx,
         goto done;
     }
 
-    /* set user/group/netgroup search bases if they are not */
-    if (NULL == dp_opt_get_string(opts->basic, SDAP_USER_SEARCH_BASE)) {
-        ret = dp_opt_set_string(opts->basic, SDAP_USER_SEARCH_BASE,
-                                dp_opt_get_string(opts->basic,
-                                                  SDAP_SEARCH_BASE));
-        if (ret != EOK) {
-            goto done;
-        }
-        DEBUG(6, ("Option %s set to %s\n",
-                  opts->basic[SDAP_USER_SEARCH_BASE].opt_name,
-                  dp_opt_get_string(opts->basic, SDAP_USER_SEARCH_BASE)));
-    }
-
-    if (NULL == dp_opt_get_string(opts->basic, SDAP_GROUP_SEARCH_BASE)) {
-        ret = dp_opt_set_string(opts->basic, SDAP_GROUP_SEARCH_BASE,
-                                dp_opt_get_string(opts->basic,
-                                                  SDAP_SEARCH_BASE));
-        if (ret != EOK) {
-            goto done;
-        }
-        DEBUG(6, ("Option %s set to %s\n",
-                  opts->basic[SDAP_GROUP_SEARCH_BASE].opt_name,
-                  dp_opt_get_string(opts->basic, SDAP_GROUP_SEARCH_BASE)));
-    }
-
-    if (NULL == dp_opt_get_string(opts->basic, SDAP_NETGROUP_SEARCH_BASE)) {
-        ret = dp_opt_set_string(opts->basic, SDAP_NETGROUP_SEARCH_BASE,
-                                dp_opt_get_string(opts->basic,
-                                                  SDAP_SEARCH_BASE));
-        if (ret != EOK) {
-            goto done;
+    search_base = dp_opt_get_string(opts->basic, SDAP_SEARCH_BASE);
+    if (search_base != NULL) {
+        /* set user/group/netgroup search bases if they are not */
+        for (o = 0; search_base_options[o] != -1; o++) {
+            if (NULL == dp_opt_get_string(opts->basic, search_base_options[o])) {
+                ret = dp_opt_set_string(opts->basic, search_base_options[o],
+                                        search_base);
+                if (ret != EOK) {
+                    goto done;
+                }
+                DEBUG(6, ("Option %s set to %s\n",
+                          opts->basic[search_base_options[o]].opt_name,
+                          dp_opt_get_string(opts->basic,
+                                            search_base_options[o])));
+            }
         }
-        DEBUG(6, ("Option %s set to %s\n",
-                  opts->basic[SDAP_NETGROUP_SEARCH_BASE].opt_name,
-                  dp_opt_get_string(opts->basic, SDAP_NETGROUP_SEARCH_BASE)));
+    } else {
+        DEBUG(5, ("Search base not set, trying to discover it later when "
+                  "connecting to the LDAP server.\n"));
     }
 
     pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY);
-- 
1.7.2.3



More information about the sssd-devel mailing list