Thanks to recent changes in the NSDB protocol, we don't need to
compute a DN prefix any more, so introduce a simpler API.

I've prefer to have the LDAP server tell us which root suffix is the
parent of a DN, but I haven't found a way to do this.  The correct
root suffix is still chosen by iteratively comparing the DN's suffix
with the root suffix.

Signed-off-by: Chuck Lever <[email protected]>
---

 src/include/nsdb.h          |    2 +
 src/libnsdb/administrator.c |   10 ++---
 src/libnsdb/fileserver.c    |   82 +++++++++++++++++++++++++++++++++++++++++++
 src/libnsdb/ldap.c          |   79 +++++++++++++++++++++++++++++++++++++++++
 src/libnsdb/nsdb-internal.h |    2 +
 5 files changed, 169 insertions(+), 6 deletions(-)

diff --git a/src/include/nsdb.h b/src/include/nsdb.h
index 89d2505..adb9bfb 100644
--- a/src/include/nsdb.h
+++ b/src/include/nsdb.h
@@ -326,6 +326,8 @@ FedFsStatus  nsdb_get_naming_contexts_s(nsdb_t host, char 
***contexts,
 FedFsStatus     nsdb_split_nce_dn_s(nsdb_t host, const char *nce,
                                char **context, char **prefix,
                                unsigned int *ldap_err);
+FedFsStatus     nsdb_find_naming_context_s(nsdb_t host, const char *entry,
+                               char **context, unsigned int *ldap_err);
 
 /**
  * Resolve an FSN (5.2.2)
diff --git a/src/libnsdb/administrator.c b/src/libnsdb/administrator.c
index 896a8a8..00bdd10 100644
--- a/src/libnsdb/administrator.c
+++ b/src/libnsdb/administrator.c
@@ -1143,8 +1143,8 @@ nsdb_add_nci_attributes_s(LDAP *ld, const char *context,
 FedFsStatus
 nsdb_update_nci_s(nsdb_t host, const char *nce, unsigned int *ldap_err)
 {
-       char *context, *prefix;
        FedFsStatus retval;
+       char *context;
 
        if (host->fn_ldap == NULL) {
                xlog(L_ERROR, "%s: NSDB not open", __func__);
@@ -1156,14 +1156,13 @@ nsdb_update_nci_s(nsdb_t host, const char *nce, 
unsigned int *ldap_err)
                return FEDFS_ERR_INVAL;
        }
 
-       retval = nsdb_split_nce_dn_s(host, nce, &context, &prefix, ldap_err);
+       retval = nsdb_find_naming_context_s(host, nce, &context, ldap_err);
        if (retval != FEDFS_OK)
                return retval;
 
        retval = nsdb_add_nci_attributes_s(host->fn_ldap, context, nce,
                                                ldap_err);
        free(context);
-       free(prefix);
        return retval;
 }
 
@@ -1228,8 +1227,8 @@ nsdb_remove_nci_attributes_s(LDAP *ld, const char 
*context,
 FedFsStatus
 nsdb_remove_nci_s(nsdb_t host, const char *nce, unsigned int *ldap_err)
 {
-       char *context, *prefix;
        FedFsStatus retval;
+       char *context;
 
        if (host->fn_ldap == NULL) {
                xlog(L_ERROR, "%s: NSDB not open", __func__);
@@ -1241,14 +1240,13 @@ nsdb_remove_nci_s(nsdb_t host, const char *nce, 
unsigned int *ldap_err)
                return FEDFS_ERR_INVAL;
        }
 
-       retval = nsdb_split_nce_dn_s(host, nce, &context, &prefix, ldap_err);
+       retval = nsdb_find_naming_context_s(host, nce, &context, ldap_err);
        if (retval != FEDFS_OK)
                return retval;
 
        retval = nsdb_remove_nci_attributes_s(host->fn_ldap, context, ldap_err);
 
        free(context);
-       free(prefix);
        return retval;
 }
 
diff --git a/src/libnsdb/fileserver.c b/src/libnsdb/fileserver.c
index 3cf3673..ad53605 100644
--- a/src/libnsdb/fileserver.c
+++ b/src/libnsdb/fileserver.c
@@ -1653,3 +1653,85 @@ out:
                __func__, nsdb_display_fedfsstatus(retval));
        return retval;
 }
+
+/**
+ * See if "entry" ends with one of the items of "contexts"
+ *
+ * @param entry a NUL-terminated C string containing DN of some entry
+ * @param contexts pointer to an array of NUL-terminated C strings
+ * @param context OUT: a NUL-terminated C string containing a suffix DN
+ * @param ldap_err OUT: possibly an LDAP error code
+ * @return a FedFsStatus code
+ */
+static FedFsStatus
+nsdb_match_root_suffix(const char *entry, char **contexts,
+               char **context, unsigned int *ldap_err)
+{
+       unsigned int i;
+
+       for (i = 0; contexts[i] != NULL; i++) {
+               _Bool result;
+
+               result = nsdb_dn_ends_with(entry, contexts[i], ldap_err);
+               if (*ldap_err != LDAP_SUCCESS)
+                       return FEDFS_ERR_NSDB_LDAP_VAL;
+               if (result)
+                       goto found;
+       }
+
+       xlog(D_CALL, "%s: context not found", __func__);
+       return FEDFS_ERR_NSDB_NONCE;
+
+found:
+       *context = strdup(contexts[i]);
+       if (*context == NULL) {
+               xlog(D_GENERAL, "%s: No memory", __func__);
+               return FEDFS_ERR_SVRFAULT;
+       }
+
+       xlog(D_CALL, "%s: context='%s'", __func__, contexts[i]);
+       return FEDFS_OK;
+}
+
+/**
+ * Discover naming context under which an entry resides
+ *
+ * @param host an initialized and bound nsdb_t object
+ * @param entry a NUL-terminated C string containing DN of some entry
+ * @param context OUT: a NUL-terminated C string containing a suffix DN
+ * @param ldap_err OUT: possibly an LDAP error code
+ * @return a FedFsStatus code
+ *
+ * "entry" must already exist on "host".  Caller must free
+ * "context" with free(3).
+ *
+ * Strategy:
+ *   1. Retrieve the list of root suffixes on "host"
+ *   2. For each root suffix, see if "entry" ends with that suffix
+ */
+FedFsStatus
+nsdb_find_naming_context_s(nsdb_t host, const char *entry, char **context,
+               unsigned int *ldap_err)
+{
+       char **contexts = NULL;
+       FedFsStatus retval;
+
+       if (host->fn_ldap == NULL) {
+               xlog(L_ERROR, "%s: NSDB not open", __func__);
+               return FEDFS_ERR_INVAL;
+       }
+
+       if (context == NULL || ldap_err == NULL) {
+               xlog(L_ERROR, "%s: Invalid parameter", __func__);
+               return FEDFS_ERR_INVAL;
+       }
+
+       retval = nsdb_get_naming_contexts_s(host, &contexts, ldap_err);
+       if (retval != FEDFS_OK)
+               return retval;
+
+       retval = nsdb_match_root_suffix(entry, contexts, context, ldap_err);
+
+       nsdb_free_string_array(contexts);
+       return retval;
+}
diff --git a/src/libnsdb/ldap.c b/src/libnsdb/ldap.c
index 26331d6..404f6d1 100644
--- a/src/libnsdb/ldap.c
+++ b/src/libnsdb/ldap.c
@@ -1178,3 +1178,82 @@ out:
        free(rstr);
        return retval;
 }
+
+/**
+ * Compare two LDAP distinguished names
+ *
+ * @param dn a structured LDAP distinguished name
+ * @param suffix a structured LDAP distinguished name
+ * @return if true, the DNs match
+ */
+static _Bool
+nsdb_ends_with(LDAPDN dn, LDAPDN suffix)
+{
+       unsigned int count_d, count_s;
+
+       for (count_d = 0; dn[count_d] != NULL; count_d++);
+       for (count_s = 0; suffix[count_s] != NULL; count_s++);
+
+       if (count_d < count_s || count_s == 0)
+               return false;
+
+       for (; count_s != 0; count_d--, count_s--)
+               if (!nsdb_compare_rdns(dn[count_d - 1], suffix[count_s - 1]))
+                       return false;
+       return true;
+}
+
+/**
+ * Predicate: See if "dn" ends with "suffix"
+ *
+ * @param dn_in a NUL-terminated C string containing a distinguished name
+ * @param suffix_in a NUL-terminated C string containing a distinguished name
+ * @param ldap_err OUT: possibly an LDAP error code
+ * @return if true, "dn" ends with "suffix"
+ *
+ * On return, the return value is valid only if "ldap_err" is
+ * LDAP_SUCCESS.
+ */
+_Bool
+nsdb_dn_ends_with(const char *dn_in, const char *suffix_in,
+               unsigned int *ldap_err)
+{
+       LDAPDN dn = NULL;
+       LDAPDN suffix = NULL;
+       _Bool result;
+       int rc;
+
+       result = false;
+
+       if (dn_in == NULL || suffix_in == NULL || ldap_err == NULL) {
+               xlog(L_ERROR, "%s: Invalid parameter", __func__);
+               goto out;
+       }
+
+       rc = ldap_str2dn(dn_in, &dn, LDAP_DN_FORMAT_LDAPV3);
+       if (rc != LDAP_SUCCESS) {
+               *ldap_err = rc;
+               goto out;
+       }
+
+       rc = ldap_str2dn(suffix_in, &suffix, LDAP_DN_FORMAT_LDAPV3);
+       if (rc != LDAP_SUCCESS) {
+               *ldap_err = rc;
+               goto out;
+       }
+
+       *ldap_err = LDAP_SUCCESS;
+       result = nsdb_ends_with(dn, suffix);
+
+       if (result)
+               xlog(D_CALL, "%s: dn '%s' ends with '%s'",
+                       __func__, dn_in, suffix_in);
+       else
+               xlog(D_CALL, "%s: dn '%s' does not end with '%s'",
+                       __func__, dn_in, suffix_in);
+
+out:
+       ldap_dnfree(suffix);
+       ldap_dnfree(dn);
+       return result;
+}
diff --git a/src/libnsdb/nsdb-internal.h b/src/libnsdb/nsdb-internal.h
index 969fe48..7defe6d 100644
--- a/src/libnsdb/nsdb-internal.h
+++ b/src/libnsdb/nsdb-internal.h
@@ -112,6 +112,8 @@ _Bool                nsdb_compare_dn_strings(const char 
*dn1_in,
 FedFsStatus     nsdb_left_remove_rdn(LDAPDN *dn, unsigned int *ldap_err);
 FedFsStatus     nsdb_right_append_rdn(LDAPDN *dn, LDAPRDN rdn,
                                unsigned int *ldap_err);
+_Bool           nsdb_dn_ends_with(const char *dn_in, const char *suffix_in,
+                               unsigned int *ldap_err);
 
 
 /**


_______________________________________________
fedfs-utils-devel mailing list
[email protected]
https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel

Reply via email to