From patchwork Tue Nov 6 17:33:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 197519 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "aserp1040.oracle.com", Issuer "VeriSign Class 3 International Server CA - G3" (not verified)) by ozlabs.org (Postfix) with ESMTPS id DA4542C00D6 for ; Wed, 7 Nov 2012 04:33:54 +1100 (EST) Received: from acsinet21.oracle.com (acsinet21.oracle.com [141.146.126.237]) by aserp1040.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id qA6HXpxi029453 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 6 Nov 2012 17:33:52 GMT Received: from oss.oracle.com (oss-external.oracle.com [137.254.96.51]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id qA6HXp1i019904 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 6 Nov 2012 17:33:51 GMT Received: from localhost ([127.0.0.1] helo=oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1TVn27-0007KG-1b; Tue, 06 Nov 2012 09:33:51 -0800 Received: from acsinet21.oracle.com ([141.146.126.237]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1TVn21-0007Jz-W9 for fedfs-utils-devel@oss.oracle.com; Tue, 06 Nov 2012 09:33:46 -0800 Received: from acsinet13.oracle.com (acsinet13.oracle.com [141.146.126.235]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id qA6HXjJW019748 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 6 Nov 2012 17:33:45 GMT Received: from mail-pb0-f43.google.com ([209.85.160.43]) by acsinet13.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id qA6HWtFv014787 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Tue, 6 Nov 2012 17:33:45 GMT Received: by mail-pb0-f43.google.com with SMTP id jt11so539025pbb.2 for ; Tue, 06 Nov 2012 09:33:44 -0800 (PST) Received: by 10.68.243.10 with SMTP id wu10mr5365747pbc.85.1352223224862; Tue, 06 Nov 2012 09:33:44 -0800 (PST) Received: from seurat.1015granger.net ([2001:df8:0:64:20c:29ff:fe93:815b]) by mx.google.com with ESMTPS id pv8sm2545411pbc.26.2012.11.06.09.33.42 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Nov 2012 09:33:43 -0800 (PST) From: Chuck Lever To: fedfs-utils-devel@oss.oracle.com Date: Tue, 06 Nov 2012 12:33:41 -0500 Message-ID: <20121106173341.26310.45251.stgit@seurat.1015granger.net> In-Reply-To: <20121106172934.26310.10982.stgit@seurat.1015granger.net> References: <20121106172934.26310.10982.stgit@seurat.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Flow-Control-Info: class=Default reputation=ipRepBelow100 ip=209.85.160.43 ct-class=R6 ct-vol1=0 ct-vol2=0 ct-vol3=0 ct-risk=68 ct-spam1=0 ct-spam2=0 ct-bulk=0 rcpts=1 size=8406 X-MM-CT-Classification: not spam X-MM-CT-RefID: str=0001.0A090201.509949F9.002E,ss=1,re=-2.300,fgs=0 Subject: [fedfs-utils] [PATCH 05/11] libnsdb: Add nsdb_find_naming_context_s() X-BeenThere: fedfs-utils-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list Reply-To: fedfs-utils Developers List-Id: fedfs-utils Developers List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: fedfs-utils-devel-bounces@oss.oracle.com Errors-To: fedfs-utils-devel-bounces@oss.oracle.com X-Source-IP: acsinet21.oracle.com [141.146.126.237] 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 --- 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); /**