summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/common/ldb_dn.c471
-rw-r--r--source4/lib/ldb/common/ldb_explode_dn.c512
-rw-r--r--source4/lib/ldb/include/ldb_dn.h (renamed from source4/lib/ldb/include/ldb_explode_dn.h)26
3 files changed, 482 insertions, 527 deletions
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
new file mode 100644
index 0000000000..7ae314e46c
--- /dev/null
+++ b/source4/lib/ldb/common/ldb_dn.c
@@ -0,0 +1,471 @@
+/*
+ ldb database library
+
+ Copyright (C) Simo Sorce 2004
+
+ ** NOTE! The following LGPL license applies to the ldb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb dn explode and utility functions
+ *
+ * Description: - explode a dn into it's own basic elements
+ * and put them in a structure
+ * - manipulate ldb_dn structures
+ *
+ * Author: Simo Sorce
+ */
+
+#include "includes.h"
+#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_private.h"
+#include "ldb/include/ldb_dn.h"
+
+
+#define LDB_DN_NULL_RETURN(x) do { if (!x) return NULL; } while(0)
+
+static char *escape_string(void *mem_ctx, const char *src)
+{
+ const char *p, *s;
+ char *d, *dst;
+
+ LDB_DN_NULL_RETURN(src);
+
+ /* allocate destination string, it will be at most 3 times the source */
+ dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1);
+ LDB_DN_NULL_RETURN(dst);
+
+ p = s = src;
+
+ while (p) {
+ p += strcspn(p, ",=\n+<>#;\\\"");
+ if (*p == '\0') /* no special s found, all ok */
+ break;
+
+ if (*p) { /* copy part of the string and escape */
+ memcpy(d, s, p - s);
+ d += (p - s);
+ *d++ = '\\';
+ *d++ = *p++;
+ s = p;
+ }
+ }
+
+ /* copy the last part (with zero) and return */
+ memcpy(d, s, &src[strlen(src)] - s + 1);
+
+ return dst;
+}
+
+static char *unescape_string(void *mem_ctx, const char *src)
+{
+ unsigned x;
+ char *p, *dst, *end;
+
+ LDB_DN_NULL_RETURN(src);
+
+ dst = p = talloc_strdup(mem_ctx, src);
+ LDB_DN_NULL_RETURN(dst);
+
+ end = &dst[strlen(dst)];
+
+ while (*p) {
+ p += strcspn(p, ",=\n+<>#;\\\"");
+ if (*p == '\0') /* no escapes or specials found, all ok */
+ return dst;
+
+ if (*p == '\\') {
+ if (strchr(",=\n+<>#;\\\"", p[1])) {
+ memmove(p, p + 1, end - (p + 1) + 1);
+ end--;
+ p++;
+ continue;
+ }
+
+ if (sscanf(p + 1, "%02x", &x) == 1) {
+ *p = (unsigned char)x;
+ memmove(p + 1, p + 3, end - (p + 3) + 1);
+ end -= 2;
+ p++;
+ continue;
+ }
+ }
+
+ /* a string with not escaped specials is invalid */
+
+ return NULL;
+ }
+
+ return dst;
+}
+
+static char *seek_to_separator(char *string, const char *separator)
+{
+ char *p;
+
+ p = strchr(string, '=');
+
+ LDB_DN_NULL_RETURN(p);
+
+ p++;
+
+ /* check if there are quotes surrounding the value */
+ p += strspn(p, " \n"); /* skip white spaces after '=' */
+
+ if (*p == '\"') {
+ p++;
+ while (*p != '\"') {
+ p = strchr(p, '\"');
+ LDB_DN_NULL_RETURN(p);
+
+ if (*(p - 1) == '\\')
+ p++;
+ }
+ }
+
+ p += strcspn(p, separator);
+
+ return p;
+}
+
+static char *ldb_dn_trim_string(char *string, const char *edge)
+{
+ char *s, *p;
+
+ /* seek out edge from start of string */
+ s = string + strspn(string, edge);
+
+ /* backwards skip from end of string */
+ p = &s[strlen(s) - 1];
+ while (p > s && strchr(edge, *p)) {
+ *p = '\0';
+ p--;
+ }
+
+ return s;
+}
+
+static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *raw_attribute)
+{
+ struct ldb_dn_attribute *at;
+ char *p;
+
+ at = talloc(mem_ctx, struct ldb_dn_attribute);
+ LDB_DN_NULL_RETURN(at);
+
+ p = strchr(raw_attribute, '=');
+
+ LDB_DN_NULL_RETURN(p);
+
+ *p = '\0';
+
+ at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n"));
+ LDB_DN_NULL_RETURN(at->name);
+
+ p++;
+
+ p = ldb_dn_trim_string(p, " \n");
+
+ if (*p == '\"') { /* quotes at start means there must be quotes at the end */
+ if (p[strlen(p) - 1] != '\"') /* malformed value */
+ return NULL;
+
+ p++;
+ p[strlen(p) - 1] = '\0';
+ at->value = talloc_strdup(at, p);
+
+ return at;
+ }
+ /* no quotes means we must unescape the string */
+ at->value = unescape_string(at, p);
+ LDB_DN_NULL_RETURN(at->value);
+
+ return at;
+}
+
+static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component)
+{
+ struct ldb_dn_component *dc;
+ char *p;
+
+ dc = talloc(mem_ctx, struct ldb_dn_component);
+ LDB_DN_NULL_RETURN(dc);
+
+ dc->attr_num = 0;
+ dc->attributes = NULL;
+
+ p = raw_component;
+
+ /* get the components */
+ do {
+ char *t;
+
+ /* terminate the current attribute and return pointer to the next one */
+ t = seek_to_separator(p, "+");
+ LDB_DN_NULL_RETURN(t);
+
+ if (*t) { /* here there is a separator */
+ *t = '\0'; /*terminate */
+ t++; /* a separtor means there's another attribute that follows */
+ }
+
+ /* allocate attributes pointer */
+ dc->attributes = talloc_realloc(dc, dc->attributes,
+ struct ldb_dn_attribute *,
+ dc->attr_num + 1);
+ LDB_DN_NULL_RETURN(dc->attributes);
+
+ /* store the exploded attirbute in the main structure */
+ dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p);
+ LDB_DN_NULL_RETURN(dc->attributes[dc->attr_num]);
+
+ dc->attr_num++;
+
+ /* jump to the next attribute if any */
+ p = t;
+
+ } while(*p);
+
+ return dc;
+}
+
+/* FIXME: currently consider a dn composed of only case insensitive attributes
+ this is not correct and need to be fixed soon */
+static void ldb_dn_sort_attributes(struct ldb_dn *edn)
+{
+ struct ldb_dn_attribute *at0, *at1;
+ int i, j, k, l;
+
+ for (i = 0; i < edn->comp_num; i++) {
+ if (edn->components[i]->attr_num > 1) {
+
+ /* it is very unlikely that there is a multivalued RDN. In that
+ unlikely case it is very unlikely you will find more than 2
+ values. So the use of bubble sort here seem to be acceptable */
+ for (j = 0; (j + 1) < edn->components[i]->attr_num; j++) {
+ for (k = j; k >= 0; k--) {
+ at0 = edn->components[i]->attributes[k];
+ at1 = edn->components[i]->attributes[k + 1];
+ l = ldb_caseless_cmp(at0->name, at1->name);
+ if (l > 0) {
+ /* already sorted, so no bubbles to move exit inner loop */
+ break;
+ }
+ if (l == 0) {
+ if (ldb_caseless_cmp(at0->value, at1->value) >= 0) {
+ /* already sorted, so no bubbles to move exit inner loop */
+ break;
+ }
+ }
+
+ edn->components[i]->attributes[k] = at1;
+ edn->components[i]->attributes[k + 1] = at0;
+ }
+ }
+ }
+ }
+}
+
+struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
+{
+ struct ldb_dn *edn; /* the exploded dn */
+ char *pdn, *p;
+
+ /* Allocate a structure to hold the exploded DN */
+ edn = talloc(mem_ctx, struct ldb_dn);
+ LDB_DN_NULL_RETURN(edn);
+
+ /* Initially there are no components */
+ edn->comp_num = 0;
+ edn->components = NULL;
+
+ pdn = p = talloc_strdup(edn, dn);
+ if (!pdn)
+ goto error;
+
+ /* get the components */
+ do {
+ char *t;
+
+ /* terminate the current component and return pointer to the next one */
+ t = seek_to_separator(p, ",;");
+ if (t == NULL)
+ goto error;
+
+ if (*t) { /* here there is a separator */
+ *t = '\0'; /*terminate */
+ t++; /* a separtor means there's another component that follows */
+ }
+
+ /* allocate space to hold the dn component */
+ edn->components = talloc_realloc(edn, edn->components,
+ struct ldb_dn_component *,
+ edn->comp_num + 1);
+ if (edn->components == NULL)
+ goto error;
+
+ /* store the exploded component in the main structure */
+ edn->components[edn->comp_num] = explode_component(edn->components, p);
+ if (edn->components[edn->comp_num] == NULL)
+ goto error;
+
+ edn->comp_num++;
+
+ /* jump to the next component if any */
+ p = t;
+
+ } while(*p);
+
+ /* sort attributes if there's any multivalued component */
+ ldb_dn_sort_attributes(edn);
+
+ talloc_free(pdn);
+ return edn;
+
+error:
+ talloc_free(edn);
+ return NULL;
+}
+
+char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn)
+{
+ char *dn, *format, *ename, *evalue;
+ int i, j;
+
+ dn = talloc_strdup(mem_ctx, "");
+ LDB_DN_NULL_RETURN(dn);
+
+ for (i = 0; i < edn->comp_num; i++) {
+ if (i != 0) {
+ dn = talloc_append_string(mem_ctx, dn, ",");
+ }
+ for (j = 0; j < edn->components[i]->attr_num; j++) {
+ if (i != 0 && j == 0)
+ format = ",%s=%s";
+ else if (i == 0 && j == 0)
+ format = "%s=%s";
+ else
+ format = "+%s=%s";
+
+ ename = escape_string(mem_ctx, edn->components[i]->attributes[j]->name);
+ LDB_DN_NULL_RETURN(ename);
+
+ evalue = escape_string(mem_ctx, edn->components[i]->attributes[j]->value);
+ LDB_DN_NULL_RETURN(evalue);
+
+ dn = talloc_asprintf_append(dn, format, ename, evalue);
+ LDB_DN_NULL_RETURN(dn);
+
+ talloc_free(ename);
+ talloc_free(evalue);
+ }
+ }
+
+ return dn;
+}
+
+/* FIXME: currently consider a dn composed of only case insensitive attributes
+ this is not correct and need to be fixed soon */
+int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1)
+{
+ struct ldb_dn_attribute *at0, *at1;
+ int i, j, k;
+
+ /* if the number of components doesn't match they differ */
+ if (edn0->comp_num != edn1->comp_num)
+ return (edn1->comp_num - edn0->comp_num);
+
+ for (i = 0; i < edn0->comp_num; i++) {
+
+ /* if the number of attributes per component doesn't match they differ */
+ if (edn0->components[i]->attr_num != edn1->components[i]->attr_num)
+ return (edn1->components[i]->attr_num - edn0->components[i]->attr_num);
+
+ for (j = 0; j < edn0->components[i]->attr_num; j++) {
+ at0 = edn0->components[i]->attributes[j];
+ at1 = edn1->components[i]->attributes[j];
+
+ /* compare names */
+ k = ldb_caseless_cmp(at0->name, at1->name);
+ if (k)
+ return k;
+
+ /* names match, compare values */
+ k = ldb_caseless_cmp(at0->value, at1->value);
+ if (k)
+ return k;
+ }
+ }
+}
+
+/*
+ casefold a dn. We need to uppercase the attribute names, and the
+ attribute values of case insensitive attributes. We also need to remove
+ extraneous spaces between elements
+*/
+struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data,
+ int (* case_fold_attr_fn)(void * user_data, char * attr))
+{
+ struct ldb_dn *cedn;
+ int i, j;
+
+ cedn = talloc(mem_ctx, struct ldb_dn);
+ LDB_DN_NULL_RETURN(cedn);
+
+ cedn->comp_num = edn->comp_num;
+ cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num);
+ LDB_DN_NULL_RETURN(cedn->components);
+
+ for (i = 0; i < edn->comp_num; i++) {
+ struct ldb_dn_component *dc;
+
+ dc = talloc(cedn->components, struct ldb_dn_component);
+ LDB_DN_NULL_RETURN(dc);
+
+ dc->attr_num = edn->components[i]->attr_num;
+ dc->attributes = edn->components[i]->attributes;
+ LDB_DN_NULL_RETURN(dc->attributes);
+
+ for (j = 0; j < edn->components[i]->attr_num; j++) {
+ struct ldb_dn_attribute *at;
+
+ at = talloc(dc->attributes, struct ldb_dn_attribute);
+ LDB_DN_NULL_RETURN(at);
+
+ at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name);
+ LDB_DN_NULL_RETURN(at->name);
+
+ if (case_fold_attr_fn(user_data, at->name)) {
+ at->value = ldb_casefold(at, edn->components[i]->attributes[j]->value);
+ } else {
+ at->value = talloc_strdup(at, edn->components[i]->attributes[j]->value);
+ }
+ LDB_DN_NULL_RETURN(at->value);
+
+ dc->attributes[j] = at;
+ }
+
+ cedn->components[i] = dc;
+ }
+
+ return cedn;
+}
+
diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c
deleted file mode 100644
index 0e2efa876c..0000000000
--- a/source4/lib/ldb/common/ldb_explode_dn.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Simo Sorce 2004
- Copyright (C) Derrell Lipman 2005
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb dn parsing
- *
- * Description: explode a dn into it's own basic elements
- * and put them in a structure
- *
- * Author: Simo Sorce
- * Author: Derrell Lipman
- */
-
-#include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_private.h"
-#include "ldb/include/ldb_explode_dn.h"
-
-#define LDB_PARSE_DN_INVALID(x) do { \
- if (x) { \
- goto failed; \
- } \
-} while(0)
-
-
-/*
- * Forward declarations
- */
-
-static char *
-parse_slash(char *p,
- char *end);
-
-
-
-/*
- * Public functions
- */
-
-/*
- * ldb_explode_dn()
- *
- * Explode, normalize, and optionally case-fold a DN string. The result is a
- * structure containing arrays of the constituent RDNs.
- *
- * Parameters:
- * mem_ctx -
- * talloc context on which all allocated memory is hung
- *
- * orig_dn -
- * The distinguished name, in string format, to be exploded
- *
- * hUserData -
- * Data handle provided by the caller, and passed back to the caller in
- * the case_fold_attr_fn callback function. This handle is not otherwise
- * used within this function.
- *
- * case_fold_attr_fn -
- * Pointer to a callback function which will be called to determine if a
- * particular attribute type (name) requires case-folding of its values.
- * If this function pointer is non-null, then attribute names will always
- * be case-folded. Additionally, the function pointed to by
- * case_fold_attr_fn will be called with the data handle (hUserData) and
- * an attribute name as its parameters, and should return TRUE or FALSE to
- * indicate whether values of that attribute type should be case-folded.
- *
- * If case_fold_attr_fn is null, then neither attribute names nor
- * attribute values will be case-folded.
- *
- * Returns:
- * Upon success, an ldb_dn structure pointer is returned, containing the
- * exploded DN.
- *
- * If memory could not be allocated or if the DN was improperly formatted,
- * NULL is returned.
- */
-struct ldb_dn *
-ldb_explode_dn(void * mem_ctx,
- const char * orig_dn,
- void * hUserData,
- int (*case_fold_attr_fn)(void * hUserData,
- char * attr))
-{
- struct ldb_dn * dn;
- struct ldb_dn_component * component;
- struct ldb_dn_attribute * attribute;
- char * p;
- char * start;
- char * separator;
- char * src;
- char * dest;
- char * dn_copy;
- char * dn_end;
- int i;
- int size;
- int orig_len;
-
- /* Allocate a structure to hold the exploded DN */
- if ((dn = talloc(mem_ctx, struct ldb_dn)) == NULL) {
- return NULL;
- }
-
- /* Initially there are no components */
- dn->comp_num = 0;
-
- /* Allocate the component array, with space for one component */
- if ((dn->components =
- talloc_array(dn, struct ldb_dn_component *, 1)) == NULL) {
-
- goto failed;
- }
-
- /* Allocate the first component */
- if ((component = talloc(dn, struct ldb_dn_component)) == NULL) {
- goto failed;
- }
-
- /* This component has no attributes yet */
- component->attr_num = 0;
-
- /* Get the length of the provided DN */
- if ((orig_len = strlen(orig_dn)) == 0) {
-
- /* We found a zero-length DN. Return it. */
- if ((dn->dn = talloc_strdup(dn, orig_dn)) == NULL) {
- goto failed;
- }
- return dn;
- }
-
- /* Copy the provided DN so we can manipulate it */
- if ((dn_copy = talloc_strdup(mem_ctx, orig_dn)) == NULL) {
- goto failed;
- }
-
- p = dn_copy;
-
- /* Our copy may end shorter than the original as we unescape chars */
- dn_end = dn_copy + orig_len + 1;
-
- /* For each attribute/value pair... */
- do {
- /* Allocate an array to hold the attributes, initially len 1 */
- if ((component->attributes =
- talloc_array(component,
- struct ldb_dn_attribute *, 1)) == NULL) {
- goto failed;
- }
-
- /* Allocate this attribute */
- if ((attribute =
- talloc(component, struct ldb_dn_attribute)) == NULL) {
- goto failed;
- }
-
- /* skip white space */
- while (*p == ' ' || *p == '\n') {
- p++;
- }
-
- /* start parsing this component */
- do {
- /* Save pointer to beginning of attribute name */
- start = p;
-
- /* find our attribute/value separator '=' */
- while (*p != '\0' && *p != '=') {
- if (*p == '\\') {
- if ((dn_end =
- parse_slash(p, dn_end)) == NULL) {
- goto failed;
- }
- }
- p++;
- }
-
- /* Ensure we found the attribute/value separator */
- if (*p != '=') {
- goto failed;
- }
-
- /* Save pointer to separator */
- separator = p;
-
- /* remove trailing white space from attribute name */
- while (p > start &&
- (*(p - 1) == ' ' || *(p - 1) == '\n')) {
-
- p--;
- }
- LDB_PARSE_DN_INVALID((p - start) < 1);
-
- /* save attribute name */
- if ((attribute->name =
- talloc_strndup(attribute,
- start,
- p - start)) == NULL) {
- goto failed;
- }
-
- /* see if this attribute name needs case folding */
- if (case_fold_attr_fn != NULL &&
- (* case_fold_attr_fn)(hUserData,
- attribute->name)) {
- p = attribute->name;
- if ((attribute->name =
- ldb_casefold(attribute, p)) == NULL) {
- goto failed;
- }
- talloc_free(p);
- }
-
- ldb_debug(mem_ctx,
- LDB_DEBUG_TRACE,
- "attribute name: [%s]\n", attribute->name);
-
- /* skip white space after the separator */
- p = separator + 1;
- p += strspn(p, " \n");
-
- /* ensure there's a value here */
- if (*p == '\0') {
- goto failed;
- }
-
- /* check if the value is enclosed in QUOTATION */
- if (*p == '"') {
- /* save pointer to beginning of attr value */
- start = p + 1;
-
- /* find the trailing QUOTE */
- while (*p != '\0' && *p != '"') {
- if (*p == '\\') {
- if ((dn_end =
- parse_slash(p, dn_end)) == NULL) {
- goto failed;
- }
- }
-
- p++;
- }
-
- /* skip spaces until the separator */
- if (*p == '\0') {
- /* We're already at end of string */
- separator = p;
- } else {
- /* Skip spaces */
- separator = p + 1 + strspn(p+1, " \n");
- }
-
- /* must be end of string or a separator here */
- if (*separator != '\0' &&
- *separator != ',' &&
- *separator != ';' &&
- *separator != '+') {
- /* Error Malformed DN */
- goto failed;
- }
- } else {
- /*
- * Value is not quouted.
- */
-
- /* save pointer to beginning of value */
- start = p;
-
- /* find end of value */
- while (*p != '\0' &&
- *p != ',' &&
- *p != ';' &&
- *p != '+') {
-
- if (*p == '\\') {
- if ((dn_end =
- parse_slash(p, dn_end)) == NULL) {
- goto failed;
- }
- }
-
- p++;
- }
-
- /* save pointer to the terminating separator */
- separator = p;
-
- /* remove trailing whitespace */
- while (p > start &&
- (*(p - 1) == ' ' ||
- *(p - 1) == '\n')) {
-
- p--;
- }
- }
- LDB_PARSE_DN_INVALID((p - start) < 1);
-
- /* save the value */
- if ((attribute->value =
- talloc_strndup(attribute,
- start,
- p - start)) == NULL) {
- goto failed;
- }
-
- /* see if this attribute value needs case folding */
- if (case_fold_attr_fn != NULL &&
- (* case_fold_attr_fn)(hUserData,
- attribute->name)) {
- /* yup, case-fold it. */
- p = attribute->value;
- if ((attribute->value =
- ldb_casefold(attribute, p)) == NULL) {
- goto failed;
- }
- talloc_free(p);
- }
-
- ldb_debug(mem_ctx,
- LDB_DEBUG_TRACE,
- "attribute value: [%s]\n", attribute->value);
-
- /* save the entire RDN */
- if ((attribute->rdn =
- talloc_asprintf(attribute,
- "%s=%s",
- attribute->name,
- attribute->value)) == NULL) {
- goto failed;
- }
-
- ldb_debug(mem_ctx,
- LDB_DEBUG_TRACE,
- "attribute: [%s]\n", attribute->rdn);
-
- /* add this attribute to the attribute list */
- component->attributes[component->attr_num] = attribute;
- component->attr_num++;
-
- /* is this a multi-valued attribute? */
- if (*separator == '+') {
- /* Yup. prepare for the next value. */
- if ((component->attributes =
- talloc_realloc(component,
- component->attributes,
- struct ldb_dn_attribute *,
- component->attr_num + 1)) == NULL) {
- goto failed;
- }
-
- /* allocate new attribute structure */
- if ((attribute =
- talloc(component,
- struct ldb_dn_attribute)) == NULL) {
- goto failed;
- }
- }
-
- /* if we're not at end of string, skip white space */
- if (*separator != '\0') {
- /* skip spaces past the separator */
- p = separator + 1;
- p += strspn(p, " \n");
- }
-
- } while (*separator == '+');
-
- /* find total length of all attributes */
- for (i = 0, size = 0; i < component->attr_num; i++) {
- size += strlen(component->attributes[i]->rdn) + 1;
- }
-
- /*
- * rebuild the normalized component
- */
-
- /* allocate space for the normalized component */
- if ((dest = talloc_size(component, size)) == NULL) {
-
- goto failed;
- }
-
- /* Save the pointer to the beginning of the string */
- component->component = dest;
-
- /* copy each of the attributes to the normalized component */
- for (i = 0; i < component->attr_num; i++) {
- if (i != 0) {
- *dest++ = '+';
- }
- src = component->attributes[i]->rdn;
-
- /* we are guaranteed to have enough space in dest */
- size = strlen(src);
- strncpy(dest, src, size + 1);
- dest += size;
- }
-
- ldb_debug(mem_ctx,
- LDB_DEBUG_TRACE,
- "component: [%s]\n", component->component);
-
- /* insert the component into the component list */
- dn->components[dn->comp_num] = component;
- dn->comp_num++;
-
- /* if there are additional components... */
- if (*separator == ',' || *separator == ';') {
- /* ... then prepare to parse them */
- if ((dn->components =
- talloc_realloc(dn,
- dn->components,
- struct ldb_dn_component *,
- dn->comp_num + 1)) == NULL ||
- (component =
- talloc(dn, struct ldb_dn_component)) == NULL) {
-
- goto failed;
- }
-
- component->attr_num = 0;
- }
-
- /* update pointer to after the separator */
- p = separator + 1;
-
- } while(*separator == ',' || *separator == ';');
-
- /* find total length of all components */
- for (i = 0, size = 0; i < dn->comp_num; i++) {
- size = size + strlen(dn->components[i]->component) + 1;
- }
-
- /* rebuild the normalized DN */
- if ((dest = talloc_size(dn, size)) == NULL) {
- goto failed;
- }
-
- /* Save the pointer to the beginning of the */
- dn->dn = dest;
-
- /* copy the normalized components into the DN */
- for (i = 0; i < dn->comp_num; i++) {
-
- /* add a separator between DN components */
- if (i != 0) {
- *dest++ = ',';
- }
-
- /* point to this component of the DN */
- src = dn->components[i]->component;
-
- /* we are guaranteed to have enough space in dest */
- size = strlen(src);
- strncpy(dest, src, size + 1);
- dest += size;
- }
-
- ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn);
-
- /* we don't need the copy of the DN any more */
- talloc_free(dn_copy);
-
- /* give 'em what they came for! */
- return dn;
-
-failed:
- /* something went wrong. free memory and tell 'em it failed */
- talloc_free(dn);
- ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn);
- return NULL;
-}
-
-
-static char *parse_slash(char *p, char *end)
-{
- unsigned x;
- if (strchr(",=\n+<>#;\\\"", p[1])) {
- memmove(p, p + 1, end - (p + 1));
- return (end - 1);
- }
- if (sscanf(p + 1, "%02x", &x) == 1) {
- *p = (unsigned char)x;
- memmove(p + 1, p + 3, end - (p + 3));
- return (end - 2);
- }
- return NULL;
-}
-
diff --git a/source4/lib/ldb/include/ldb_explode_dn.h b/source4/lib/ldb/include/ldb_dn.h
index af9829ba40..f355ee4879 100644
--- a/source4/lib/ldb/include/ldb_explode_dn.h
+++ b/source4/lib/ldb/include/ldb_dn.h
@@ -20,27 +20,23 @@
*/
struct ldb_dn_attribute {
- char * rdn;
- char * name;
- char * value;
+ char *name;
+ char *value;
};
struct ldb_dn_component {
- char * component;
- int attr_num;
- struct ldb_dn_attribute ** attributes;
+ int attr_num;
+ struct ldb_dn_attribute **attributes;
};
struct ldb_dn {
- char * dn;
- int comp_num;
- struct ldb_dn_component ** components;
+ int comp_num;
+ struct ldb_dn_component **components;
};
-extern struct ldb_dn *
-ldb_explode_dn(void * mem_ctx,
- const char * orig_dn,
- void * hUserData,
- int (*case_fold_attr_fn)(void * hUserData,
- char * attr));
+struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn);
+char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn);
+int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1);
+struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data,
+ int (* case_fold_attr_fn)(void * user_data, char * attr));