]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
lib/ldap: parse naming contexts into a pooled string list
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 17 Jul 2026 22:24:42 +0000 (18:24 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 17 Jul 2026 22:24:51 +0000 (18:24 -0400)
One allocation now covers the pointer array and the strings. Parse failures are warned about instead of being silently ignored.

src/lib/ldap/base.h
src/lib/ldap/directory.c
src/listen/ldap_sync/proto_ldap_sync_ldap.c

index aadd3fcd55c00fe6797014650f3939193110cb9e..c6a6a4d327b79f162b7ae0ae85e05021f1a91ee6 100644 (file)
@@ -215,7 +215,8 @@ typedef struct {
                                                        ///< Defaults to RFC 5020 entryDN, distinguishedName
                                                        ///< on Active Directory and Samba.
 
-       char const              **naming_contexts;      //!< Databases served by this directory.
+       char const              **naming_contexts;      //!< NULL terminated array of databases
+                                                       ///< served by this directory.
        fr_hash_table_t         *naming_contexts_ht;    //!< For resolving DNs to the naming context
                                                        ///< containing them.
 
index 0430084ffe5207c4569f52a6d70c81c66659c75b..8cf014313e7680ae4f6b9b1a2721b899bda20b9a 100644 (file)
@@ -72,6 +72,8 @@ int fr_ldap_directory_result_parse(fr_ldap_directory_t *directory, LDAP *handle,
        LDAPMessage             *entry;
        struct berval           **values = NULL;
        struct berval           value;
+       talloc_str_list_t       *list;
+       char const * const      *context_p;
 
        /*
         *      Connections spawned concurrently may each run discovery
@@ -242,18 +244,22 @@ found:
        /*
         *      Extract naming contexts
         */
-       values = ldap_get_values_len(handle, entry, "namingContexts");
-       if (!values) return 0;
+       list = fr_ldap_str_list_afrom_result(directory, handle, result, "namingContexts", 0);
+       if (unlikely(!list)) {
+               WARN("Capability check failed: %s", fr_strerror());
+               return 1;
+       }
+       if (talloc_str_list_num(list) == 0) {
+               talloc_free(list);
+               return 0;
+       }
 
-       num = ldap_count_values_len(values);
-       MEM(directory->naming_contexts = talloc_array(directory, char const *, num));
+       directory->naming_contexts = list->strings;
        MEM(directory->naming_contexts_ht = fr_hash_table_alloc(directory, _naming_context_hash,
                                                                _naming_context_cmp, NULL));
-       for (i = 0; i < num; i++) {
-               directory->naming_contexts[i] = fr_ldap_berval_to_string(directory, values[i]);
-               fr_hash_table_insert(directory->naming_contexts_ht, directory->naming_contexts[i]);
+       for (context_p = list->strings; context_p < list->p; context_p++) {
+               fr_hash_table_insert(directory->naming_contexts_ht, *context_p);
        }
-       ldap_value_free_len(values);
 
        return 0;
 }
index 570eaaa6e953dbf1e6c7ef40132fcd9718eb98ed..2859d501e51f2f647ed840cd23f8a35ff0a09ebc 100644 (file)
@@ -779,7 +779,7 @@ static ssize_t proto_ldap_child_mod_read(fr_listen_t *li, UNUSED void **packet_c
  */
 static int proto_ldap_cookie_load_send(TALLOC_CTX *ctx, proto_ldap_sync_ldap_t const *inst, size_t sync_no,
                                       proto_ldap_sync_ldap_thread_t *thread) {
-       size_t                  j, len;
+       size_t                  len;
        sync_config_t           *config = inst->parent->sync_config[sync_no];
        fr_pair_list_t          pairs;
        fr_pair_t               *vp;
@@ -798,15 +798,19 @@ static int proto_ldap_cookie_load_send(TALLOC_CTX *ctx, proto_ldap_sync_ldap_t c
        /*
         *      Assess the namingContext which applies to this sync
         */
-       for (j = 0; j < talloc_array_length(ldap_conn->directory->naming_contexts); j++) {
-               len = strlen(ldap_conn->directory->naming_contexts[j]);
-               if (strlen(config->base_dn) < len) continue;
-
-               if (strncasecmp(&config->base_dn[strlen(config->base_dn)-len],
-                               ldap_conn->directory->naming_contexts[j],
-                               strlen(ldap_conn->directory->naming_contexts[j])) == 0) {
-                       config->root_dn = ldap_conn->directory->naming_contexts[j];
-                       break;
+       if (ldap_conn->directory->naming_contexts) {
+               char const * const      *contexts = ldap_conn->directory->naming_contexts;
+               size_t                  j, num = talloc_str_array_len(contexts);
+               size_t                  base_dn_len = talloc_strlen(config->base_dn);
+
+               for (j = 0; j < num; j++) {
+                       len = talloc_strlen(contexts[j]);
+                       if (base_dn_len < len) continue;
+
+                       if (strncasecmp(&config->base_dn[base_dn_len - len], contexts[j], len) == 0) {
+                               config->root_dn = contexts[j];
+                               break;
+                       }
                }
        }