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
