s4:ldb: add infrastructure for extended dn handlers
authorAndrew Bartlett <abartlet@samba.org>
Tue, 16 Dec 2008 07:19:07 +0000 (08:19 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 17 Dec 2008 01:29:23 +0000 (12:29 +1100)
This introduces a new set of pluggable syntax, for use on the
extended DN, and uses them when parsing the DN.

If the DN appears to be in the extended form, we no longer return the
full DN 'as is', but only return the normal part from
ldb_dn_get_linearized().

When validating/parsing the DN we validate not only the format of the
DN, but also the contents of the GUID or SID (to ensure they are
plausable).

We also have functions to set and get the extended components on the DN.

For now, extended_dn_get_linearized() returns a newly constructed and
allocated string each time.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
source4/lib/ldb/common/ldb_attributes.c
source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h

index 747f2417811a9069b1ed4391b70672b6d54f590b..48f9e11cafd111f72d2770743d9d1604193e47e4 100644 (file)
@@ -225,3 +225,50 @@ int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
        return LDB_SUCCESS;
 }
 
+
+/*
+  add a extended dn syntax to the ldb_schema
+*/
+int ldb_dn_extended_add_syntax(struct ldb_context *ldb, 
+                              unsigned flags,
+                              const struct ldb_dn_extended_syntax *syntax)
+{
+       int n;
+       struct ldb_dn_extended_syntax *a;
+
+       if (!syntax) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       n = ldb->schema.num_dn_extended_syntax + 1;
+
+       a = talloc_realloc(ldb, ldb->schema.dn_extended_syntax,
+                          struct ldb_dn_extended_syntax, n);
+
+       if (!a) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       a[ldb->schema.num_dn_extended_syntax] = *syntax;
+       ldb->schema.dn_extended_syntax = a;
+
+       ldb->schema.num_dn_extended_syntax = n;
+
+       return 0;
+}
+
+/*
+  return the extended dn syntax for a given name
+*/
+const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb,
+                                                                   const char *name)
+{
+       int i;
+       for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) {
+               if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) {
+                       return &ldb->schema.dn_extended_syntax[i];
+               }
+       }
+       return NULL;
+}
+
index e36aea4e697fd8b2dddf5bdfdcaad64d18aa7c2a..13c01f4e70dcb4d049d697b8e1dd6789b1eb59e6 100644 (file)
@@ -52,6 +52,12 @@ struct ldb_dn_component {
        struct ldb_val cf_value;
 };
 
+struct ldb_dn_extended_component {
+
+       char *name;
+       struct ldb_val value;
+};
+
 struct ldb_dn {
 
        struct ldb_context *ldb;
@@ -63,11 +69,14 @@ struct ldb_dn {
        bool valid_case;
 
        char *linearized;
+       char *extended_linearized;
        char *casefold;
 
        unsigned int comp_num;
        struct ldb_dn_component *components;
 
+       unsigned int extended_comp_num;
+       struct ldb_dn_extended_component *extended_components;
 };
 
 /* strdn may be NULL */
@@ -85,28 +94,34 @@ struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const
        if (strdn->data && strdn->length) {
                if (strdn->data[0] == '@') {
                        dn->special = true;
+               } 
+               dn->extended_linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
+               LDB_DN_NULL_FAILED(dn->extended_linearized);
+       
+               if (strdn->data[0] == '<') {
+                       const char *p_save, *p = dn->extended_linearized;
+                       do {
+                               p_save = p;
+                               p = strstr(p, ">;");
+                               if (p) {
+                                       p = p + 2;
+                               }
+                       } while (p);
+                       
+                       if (p_save == dn->extended_linearized) {
+                               dn->linearized = talloc_strdup(dn, "");
+                       } else {
+                               dn->linearized = talloc_strdup(dn, p_save);
+                       }
+                       LDB_DN_NULL_FAILED(dn->linearized);
+               } else {
+                       dn->linearized = dn->extended_linearized;
+                       dn->extended_linearized = NULL;
                }
-               if (strdn->length >= 6 && strncasecmp((const char *)strdn->data, "<GUID=", 6) == 0) {
-                       /* this is special DN returned when the
-                        * exploded_dn control is used */
-                       dn->special = true;
-                       /* FIXME: add a GUID string to ldb_dn structure */
-               } else if (strdn->length >= 5 && strncasecmp((const char *)strdn->data, "<SID=", 5) == 0) {
-                       /* this is special DN returned when the
-                        * exploded_dn control is used */
-                       dn->special = true;
-                       /* FIXME: add a SID string to ldb_dn structure */
-               } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<WKGUID=", 8) == 0) {
-                       /* this is special DN returned when the
-                        * exploded_dn control is used */
-                       dn->special = true;
-                       /* FIXME: add a WKGUID string to ldb_dn structure */
-               }
-               dn->linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
        } else {
                dn->linearized = talloc_strdup(dn, "");
+               LDB_DN_NULL_FAILED(dn->linearized);
        }
-       LDB_DN_NULL_FAILED(dn->linearized);
 
        return dn;
 
@@ -126,47 +141,21 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
 
 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
 {
-       struct ldb_dn *dn;
        char *strdn;
        va_list ap;
 
        if ( (! mem_ctx) || (! ldb)) return NULL;
 
-       dn = talloc_zero(mem_ctx, struct ldb_dn);
-       LDB_DN_NULL_FAILED(dn);
-
-       dn->ldb = ldb;
-
        va_start(ap, new_fmt);
-       strdn = talloc_vasprintf(dn, new_fmt, ap);
+       strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
        va_end(ap);
-       LDB_DN_NULL_FAILED(strdn);
-
-       if (strdn[0] == '@') {
-               dn->special = true;
-       }
-       if (strncasecmp(strdn, "<GUID=", 6) == 0) {
-               /* this is special DN returned when the
-                * exploded_dn control is used */
-               dn->special = true;
-               /* FIXME: add a GUID string to ldb_dn structure */
-       } else if (strncasecmp(strdn, "<SID=", 5) == 0) {
-               /* this is special DN returned when the
-                * exploded_dn control is used */
-               dn->special = true;
-               /* FIXME: add a SID string to ldb_dn structure */
-       } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
-               /* this is special DN returned when the
-                * exploded_dn control is used */
-               dn->special = true;
-               /* FIXME: add a WKGUID string to ldb_dn structure */
-       }
-       dn->linearized = strdn;
 
-       return dn;
-
-failed:
-       talloc_free(dn);
+       if (strdn) {
+               struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
+               talloc_free(strdn);
+               return dn;
+       }
+       
        return NULL;
 }
 
@@ -235,15 +224,19 @@ char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
 */
 static bool ldb_dn_explode(struct ldb_dn *dn)
 {
-       char *p, *data, *d, *dt, *t;
+       char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
        bool trim = false;
+       bool in_extended = false;
+       bool in_ex_name = false;
+       bool in_ex_value = false;
        bool in_attr = false;
        bool in_value = false;
        bool in_quote = false;
        bool is_oid = false;
        bool escape = false;
        unsigned x;
-       int l;
+       int l, ret;
+       char *parse_dn;
 
        if ( ! dn || dn->invalid) return false;
 
@@ -251,12 +244,18 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                return true;
        }
 
-       if ( ! dn->linearized) {
+       if (dn->extended_linearized) {
+               parse_dn = dn->extended_linearized;
+       } else {
+               parse_dn = dn->linearized;
+       }
+
+       if ( ! parse_dn ) {
                return false;
        }
 
        /* Empty DNs */
-       if (dn->linearized[0] == '\0') {
+       if (parse_dn[0] == '\0') {
                return true;
        }
 
@@ -268,6 +267,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
        /* make sure we free this if alloced previously before replacing */
        talloc_free(dn->components);
 
+       talloc_free(dn->extended_components);
+       dn->extended_components = NULL;
+
        /* in the common case we have 3 or more components */
        /* make sure all components are zeroed, other functions depend on this */
        dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
@@ -277,19 +279,109 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
        dn->comp_num = 0;
 
        /* Components data space is allocated here once */
-       data = talloc_array(dn->components, char, strlen(dn->linearized) + 1);
+       data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
        if (!data) {
                return false;
        }
 
-       p = dn->linearized;
-       in_attr = true;
+       p = parse_dn;
+       in_extended = true;
+       in_ex_name = false;
+       in_ex_value = false;
        trim = true;
        t = NULL;
        d = dt = data;
 
        while (*p) {
+               if (in_extended) {
+
+                       if (!in_ex_name && !in_ex_value) {
+
+                               if (p[0] == '<') {
+                                       p++;
+                                       ex_name = d;
+                                       in_ex_name = true;
+                                       continue;
+                               } else if (p[0] == '\0') {
+                                       p++;
+                                       continue;
+                               } else {
+                                       in_extended = false;
+                                       in_attr = true;
+                                       dt = d;
+
+                                       continue;
+                               }
+                       }
+                       
+                       if (in_ex_name && *p == '=') {
+                               *d++ = '\0';
+                               p++;
+                               ex_value = d;
+                               in_ex_name = false;
+                               in_ex_value = true;
+                               continue;
+                       }
+
+                       if (in_ex_value && *p == '>') {
+                               const struct ldb_dn_extended_syntax *extended_syntax;
+                               struct ldb_val ex_val = {
+                                       .data = ex_value,
+                                       .length = d - ex_value
+                               };
+                                       
+                               *d++ = '\0';
+                               p++;
+                               in_ex_value = false;
+
+                               /* Process name and ex_value */
+
+                               dn->extended_components = talloc_realloc(dn,
+                                                                        dn->extended_components,
+                                                                        struct ldb_dn_extended_component,
+                                                                        dn->extended_comp_num + 1);
+                               if ( ! dn->extended_components) {
+                                       /* ouch ! */
+                                       goto failed;
+                               }
+
+                               extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
+                               if (!extended_syntax) {
+                                       /* We don't know about this type of extended DN */
+                                       goto failed;
+                               }
+
+                               dn->extended_components[dn->extended_comp_num].name = talloc_strdup(dn->extended_components, ex_name);
+                               if (!dn->extended_components[dn->extended_comp_num].name) {
+                                       /* ouch */
+                                       goto failed;
+                               }
+                               ret = extended_syntax->read_fn(dn->ldb, dn->extended_components,
+                                                              &ex_val, &dn->extended_components[dn->extended_comp_num].value);
+                               if (ret != LDB_SUCCESS) {
+                                       dn->invalid = true;
+                                       goto failed;
+                               }
+
+                               dn->extended_comp_num++;
 
+                               if (*p == '\0') {
+                                       /* We have reached the end (extended component only)! */
+                                       talloc_free(data);
+                                       return true;
+
+                               } else if (*p == ';') {
+                                       p++;
+                                       continue;
+                               } else {
+                                       dn->invalid = true;
+                                       goto failed;
+                               }
+                       }
+
+                       *d++ = *p++;
+                       continue;
+               }
                if (in_attr) {
                        if (trim) {
                                if (*p == ' ') {
@@ -315,6 +407,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                        goto failed;
                                }
                                
+                               /* Copy this character across from parse_dn, now we have trimmed out spaces */
                                *d++ = *p++;
                                continue;
                        }
@@ -339,6 +432,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                trim = true;
                                l = 0;
 
+                               /* Terminate this string in d (which is a copy of parse_dn with spaces trimmed) */
                                *d++ = '\0';
                                dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
                                if ( ! dn->components[dn->comp_num].name) {
@@ -614,6 +708,74 @@ const char *ldb_dn_get_linearized(struct ldb_dn *dn)
        return dn->linearized;
 }
 
+char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
+{
+       const char *linearized = ldb_dn_get_linearized(dn);
+       char *p;
+       int i;
+
+       if (!linearized) {
+               return NULL;
+       }
+
+       if (!ldb_dn_has_extended(dn)) {
+               return talloc_strdup(mem_ctx, linearized);
+       }
+       
+       if (!ldb_dn_validate(dn)) {
+               return NULL;
+       }
+
+       for (i=0; i < dn->extended_comp_num; i++) {
+               struct ldb_val val;
+               int ret;
+               const struct ldb_dn_extended_syntax *extended_syntax;
+               const char *name = dn->extended_components[i].name;
+               
+               extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
+
+               if (mode == 1) {
+                       ret = extended_syntax->write_clear_fn(dn->ldb, mem_ctx,
+                                                             &dn->extended_components[i].value,
+                                                             &val);
+               } else if (mode == 0) {
+                       ret = extended_syntax->write_hex_fn(dn->ldb, mem_ctx,
+                                                             &dn->extended_components[i].value,
+                                                             &val);
+               } else {
+                       ret = -1;
+               }
+
+               if (ret != LDB_SUCCESS) {
+                       return NULL;
+               }
+
+               if (i == 0) {
+                       p = talloc_asprintf(mem_ctx, "<%s=%s>", dn->extended_components[i].name, val.data);
+               } else {
+                       p = talloc_asprintf_append(p, ";<%s=%s>",  dn->extended_components[i].name, val.data);
+               }
+
+               talloc_free(val.data);
+
+               if (!p) {
+                       return NULL;
+               }
+       }
+
+       if (dn->extended_comp_num && *linearized) {
+               p = talloc_asprintf_append(p, ";%s", linearized);
+       }
+
+       if (!p) {
+               return NULL;
+       }
+
+       return p;
+}
+
+
+
 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
 {
        return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
@@ -909,6 +1071,30 @@ static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_d
        return dst;
 }
 
+static struct ldb_dn_extended_component ldb_dn_extended_copy_component(void *mem_ctx, struct ldb_dn_extended_component *src)
+{
+       struct ldb_dn_extended_component dst;
+
+       memset(&dst, 0, sizeof(dst));
+
+       if (src == NULL) {
+               return dst;
+       }
+
+       dst.value = ldb_val_dup(mem_ctx, &(src->value));
+       if (dst.value.data == NULL) {
+               return dst;
+       }
+
+       dst.name = talloc_strdup(mem_ctx, src->name);
+       if (dst.name == NULL) {
+               LDB_FREE(dst.value.data);
+               return dst;
+       }
+
+       return dst;
+}
+
 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
 {
        struct ldb_dn *new_dn;
@@ -942,6 +1128,24 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
                }
        }
 
+       if (dn->extended_components) {
+               int i;
+
+               new_dn->extended_components = talloc_zero_array(new_dn, struct ldb_dn_extended_component, dn->extended_comp_num);
+               if ( ! new_dn->extended_components) {
+                       talloc_free(new_dn);
+                       return NULL;
+               }
+
+               for (i = 0; i < dn->extended_comp_num; i++) {
+                       new_dn->extended_components[i] = ldb_dn_extended_copy_component(new_dn->extended_components, &dn->extended_components[i]);
+                       if ( ! new_dn->extended_components[i].value.data) {
+                               talloc_free(new_dn);
+                               return NULL;
+                       }
+               }
+       }
+
        if (dn->casefold) {
                new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
                if ( ! new_dn->casefold) {
@@ -958,6 +1162,14 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
                }
        }
 
+       if (dn->extended_linearized) {
+               new_dn->extended_linearized = talloc_strdup(new_dn, dn->extended_linearized);
+               if ( ! new_dn->extended_linearized) {
+                       talloc_free(new_dn);
+                       return NULL;
+               }
+       }
+
        return new_dn;
 }
 
@@ -1037,6 +1249,13 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                dn->linearized = t;
        }
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       if (dn->extended_linearized) {
+               LDB_FREE(dn->extended_linearized);
+       }
+
+       LDB_FREE(dn->extended_components);
+       dn->extended_comp_num = 0;
        return true;
 }
 
@@ -1149,6 +1368,12 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
                dn->linearized = t;
        }
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       LDB_FREE(dn->extended_linearized);
+
+       LDB_FREE(dn->extended_components);
+       dn->extended_comp_num = 0;
+
        return true;
 }
 
@@ -1218,6 +1443,12 @@ bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
        LDB_FREE(dn->casefold);
        LDB_FREE(dn->linearized);
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       LDB_FREE(dn->extended_linearized);
+
+       LDB_FREE(dn->extended_components);
+       dn->extended_comp_num = 0;
+
        return true;
 }
 
@@ -1256,6 +1487,11 @@ bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
        LDB_FREE(dn->casefold);
        LDB_FREE(dn->linearized);
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       LDB_FREE(dn->extended_linearized);
+
+       LDB_FREE(dn->extended_components);
+       dn->extended_comp_num = 0;
        return true;
 }
 
@@ -1273,6 +1509,11 @@ struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
                return NULL;
        }
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       LDB_FREE(dn->extended_linearized);
+
+       LDB_FREE(dn->extended_components);
+       dn->extended_comp_num = 0;
        return new_dn;
 }
 
@@ -1434,9 +1675,97 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const str
        LDB_FREE(dn->casefold);
        LDB_FREE(dn->linearized);
 
+       /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
+       LDB_FREE(dn->extended_linearized);
+
+       dn->extended_comp_num = 0;
+       LDB_FREE(dn->extended_components);
        return LDB_SUCCESS;
 }
 
+const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name)
+{
+       int i;
+       if ( ! ldb_dn_validate(dn)) {
+               return NULL;
+       }
+       for (i=0; i < dn->extended_comp_num; i++) {
+               if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
+                       return &dn->extended_components[i].value;
+               }
+       }
+       return NULL;
+}
+
+int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val)
+{
+       struct ldb_dn_extended_component *p;
+       int i;
+                               
+       if ( ! ldb_dn_validate(dn)) {
+               return LDB_ERR_OTHER;
+       }
+
+       for (i=0; i < dn->extended_comp_num; i++) {
+               if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
+                       if (val) {
+                               dn->extended_components[i].value = ldb_val_dup(dn->extended_components, val);
+
+                               dn->extended_components[i].name = talloc_strdup(dn->extended_components, name);
+                               if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
+                                       dn->invalid = true;
+                                       return LDB_ERR_OPERATIONS_ERROR;
+                               }
+       
+                       } else {
+                               if (i != (dn->extended_comp_num - 1)) {
+                                       memmove(&dn->extended_components[i], &dn->extended_components[i+1],
+                                               ((dn->extended_comp_num-1) - i)*sizeof(*dn->extended_components));
+                               }
+                               dn->extended_comp_num--;
+                               
+                               dn->extended_components = talloc_realloc(dn,
+                                                  dn->extended_components,
+                                                  struct ldb_dn_extended_component,
+                                                  dn->extended_comp_num);
+                               if (!dn->extended_components) {
+                                       dn->invalid = true;
+                                       return LDB_ERR_OPERATIONS_ERROR;
+                               }
+                               return 0;
+                       }
+               }
+       }
+
+       p = dn->extended_components
+               = talloc_realloc(dn,
+                                dn->extended_components,
+                                struct ldb_dn_extended_component,
+                                dn->extended_comp_num + 1);
+       if (!dn->extended_components) {
+               dn->invalid = true;
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       p[dn->extended_comp_num].value = ldb_val_dup(dn->extended_components, val);
+       p[dn->extended_comp_num].name = talloc_strdup(p, name);
+       
+       if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
+               dn->invalid = true;
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       dn->extended_components = p;
+       dn->extended_comp_num++;
+       
+       return 0;
+}
+
+void ldb_dn_remove_extended_components(struct ldb_dn *dn)
+{
+       dn->extended_comp_num = 0;
+       LDB_FREE(dn->extended_components);      
+}
+
 bool ldb_dn_is_valid(struct ldb_dn *dn)
 {
        if ( ! dn) return false;
@@ -1449,6 +1778,13 @@ bool ldb_dn_is_special(struct ldb_dn *dn)
        return dn->special;
 }
 
+bool ldb_dn_has_extended(struct ldb_dn *dn)
+{
+       if ( ! dn || dn->invalid) return false;
+       if (dn->extended_linearized && (dn->extended_linearized[0] == '<')) return true;
+       return dn->extended_comp_num != 0;
+}
+
 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
 {
        if ( ! dn || dn->invalid) return false;
@@ -1458,6 +1794,7 @@ bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
 bool ldb_dn_is_null(struct ldb_dn *dn)
 {
        if ( ! dn || dn->invalid) return false;
+       if (ldb_dn_has_extended(dn)) return false;
        if (dn->linearized && (dn->linearized[0] == '\0')) return true;
        return false;
 }
index 9bc5c183d842922d6cdab5f2af01d270507856c7..cd7eb06b4d66be79e9f8e574c910ead4b7150240 100644 (file)
@@ -350,6 +350,16 @@ struct ldb_schema_attribute {
 const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
                                                                const char *name);
 
+struct ldb_dn_extended_syntax {
+       const char *name;
+       ldb_attr_handler_t read_fn;
+       ldb_attr_handler_t write_clear_fn;
+       ldb_attr_handler_t write_hex_fn;
+};
+
+const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb,
+                                                                   const char *name);
+
 /**
    The attribute is not returned by default
 */
@@ -1421,15 +1431,82 @@ int ldb_base64_decode(char *s);
 
 /* The following definitions come from lib/ldb/common/ldb_dn.c  */
 
+/**
+  Get the linear form of a DN (without any extended components)
+  
+  \param dn The DN to linearize
+*/
+
+const char *ldb_dn_get_linearized(struct ldb_dn *dn);
+
+/**
+  Allocate a copy of the linear form of a DN (without any extended components) onto the supplied memory context 
+  
+  \param dn The DN to linearize
+  \param mem_ctx TALLOC context to return result on
+*/
+
+char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
+
+/**
+  Get the linear form of a DN (with any extended components)
+  
+  \param mem_ctx TALLOC context to return result on
+  \param dn The DN to linearize
+  \param mode Style of extended DN to return (0 is HEX representation of binary form, 1 is a string form)
+*/
+char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode);
+const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name);
+int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val);
+
+void ldb_dn_remove_extended_components(struct ldb_dn *dn);
+bool ldb_dn_has_extended(struct ldb_dn *dn);
+
+int ldb_dn_extended_add_syntax(struct ldb_context *ldb, 
+                              unsigned flags,
+                              const struct ldb_dn_extended_syntax *syntax);
+
+/** 
+  Allocate a new DN from a string
+
+  \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+  \param dn The new DN 
+
+  \note The DN will not be parsed at this time.  Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
 struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn);
+/** 
+  Allocate a new DN from a printf style format string and arguments
+
+  \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+  \param new_fms The new DN as a format string (plus arguments)
+
+  \note The DN will not be parsed at this time.  Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
 struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4);
+/** 
+  Allocate a new DN from a struct ldb_val (useful to avoid buffer overrun)
+
+  \param mem_ctx TALLOC context to return resulting ldb_dn structure on
+  \param dn The new DN 
+
+  \note The DN will not be parsed at this time.  Use ldb_dn_validate to tell if the DN is syntacticly correct
+*/
+
 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
+
+/**
+  Determine if this DN is syntactically valid 
+
+  \param dn The DN to validate
+*/
+
 bool ldb_dn_validate(struct ldb_dn *dn);
 
 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value);
-const char *ldb_dn_get_linearized(struct ldb_dn *dn);
 const char *ldb_dn_get_casefold(struct ldb_dn *dn);
-char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
 char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
 
 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn);
index 90c49800173d85f24ad2299f10f44c849c3668dd..d1d3587eb7ececc2df7cb72a7bda1828aac76f9c 100644 (file)
@@ -84,6 +84,9 @@ struct ldb_schema {
        /* attribute handling table */
        unsigned num_attributes;
        struct ldb_schema_attribute *attributes;
+
+       unsigned num_dn_extended_syntax;
+       struct ldb_dn_extended_syntax *dn_extended_syntax;
 };
 
 /*