s4-ldb: Add support for binary blobs in DNs
authorAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 2009 02:03:05 +0000 (12:03 +1000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 2009 02:03:05 +0000 (12:03 +1000)
AD has the concept of a DN prefixed with B:NN:XXXXXX: that contains a
binary blob. We need to support those in order to give correctly
formatted binary blobs for things like wellKnownObjects

This implementation is not ideal, as it allows for binary blobs on all
DNs, whereas it should only allow them on those with a syntax of
2.5.5.7. We should clean this up in the future, but meanwhile this
implementation at least gets us a working DC join of w2k8 to s4.

This patch also uses a static function for marking DNs as invalid,
which is very useful when debugging this code, as you can break on it
in gdb.

source4/dsdb/schema/schema_syntax.c
source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/include/ldb.h

index c564471d4bcfd25ccdd5815c0c408c0f53f0879b..cbbd4a863646c5b7c845868c41bf6bdd4f65c404 100644 (file)
@@ -1204,6 +1204,8 @@ static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb,
        return WERR_OK;
 }
 
+
+
 static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb, 
                                                   const struct dsdb_schema *schema,
                                                   const struct dsdb_attribute *attr,
@@ -1212,6 +1214,7 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
                                                   struct ldb_message_element *out)
 {
        uint32_t i;
+       int ret;
 
        out->flags      = 0;
        out->name       = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
@@ -1222,39 +1225,81 @@ static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
        W_ERROR_HAVE_NO_MEMORY(out->values);
 
        for (i=0; i < out->num_values; i++) {
-               struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
-               char *binary;
-               char *str;
+               struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
                enum ndr_err_code ndr_err;
+               DATA_BLOB guid_blob;
+               struct ldb_dn *dn;
+               TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+               if (!tmp_ctx) {
+                       W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
+               }
 
                if (in->value_ctr.values[i].blob == NULL) {
+                       talloc_free(tmp_ctx);
                        return WERR_FOOBAR;
                }
 
                if (in->value_ctr.values[i].blob->length == 0) {
+                       talloc_free(tmp_ctx);
                        return WERR_FOOBAR;
                }
 
-               ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
-                                                  out->values, schema->iconv_convenience, &id3b,
-                                                  (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
+               
+               /* windows sometimes sends an extra two pad bytes here */
+               ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
+                                              tmp_ctx, schema->iconv_convenience, &id3,
+                                              (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                       talloc_free(tmp_ctx);
                        return ntstatus_to_werror(status);
                }
 
-               /* TODO: handle id3.guid and id3.sid */
-               binary = data_blob_hex_string(out->values, &id3b.binary);
-               W_ERROR_HAVE_NO_MEMORY(binary);
+               dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
+               if (!dn) {
+                       talloc_free(tmp_ctx);
+                       /* If this fails, it must be out of memory, as it does not do much parsing */
+                       W_ERROR_HAVE_NO_MEMORY(dn);
+               }
 
-               str = talloc_asprintf(out->values, "B:%u:%s:%s",
-                                     (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
-                                     binary,
-                                     id3b.dn);
-               W_ERROR_HAVE_NO_MEMORY(str);
+               ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
+                                              (ndr_push_flags_fn_t)ndr_push_GUID);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                       talloc_free(tmp_ctx);
+                       return ntstatus_to_werror(status);
+               }
 
-               /* TODO: handle id3.guid and id3.sid */
-               out->values[i] = data_blob_string_const(str);
+               ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
+               if (ret != LDB_SUCCESS) {
+                       talloc_free(tmp_ctx);
+                       return WERR_FOOBAR;
+               }
+
+               talloc_free(guid_blob.data);
+
+               if (id3.__ndr_size_sid) {
+                       DATA_BLOB sid_blob;
+                       ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
+                                                      (ndr_push_flags_fn_t)ndr_push_dom_sid);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                               talloc_free(tmp_ctx);
+                               return ntstatus_to_werror(status);
+                       }
+
+                       ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
+                       if (ret != LDB_SUCCESS) {
+                               talloc_free(tmp_ctx);
+                               return WERR_FOOBAR;
+                       }
+               }
+
+               /* set binary stuff */
+               ldb_dn_set_binary(dn, &id3.binary);
+
+               out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1));
+               talloc_free(tmp_ctx);
        }
 
        return WERR_OK;
@@ -1285,27 +1330,72 @@ static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb,
        W_ERROR_HAVE_NO_MEMORY(blobs);
 
        for (i=0; i < in->num_values; i++) {
-               struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
+               struct drsuapi_DsReplicaObjectIdentifier3Binary id3;
                enum ndr_err_code ndr_err;
+               const DATA_BLOB *guid_blob, *sid_blob;
+               struct ldb_dn *dn;
+               TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+               W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
 
                out->value_ctr.values[i].blob   = &blobs[i];
 
-               /* TODO: handle id3b.guid and id3b.sid, id3.binary */
-               ZERO_STRUCT(id3b);
-               id3b.dn         = (const char *)in->values[i].data;
-               id3b.binary     = data_blob(NULL, 0);
+               dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
+
+               W_ERROR_HAVE_NO_MEMORY(dn);
+
+               guid_blob = ldb_dn_get_extended_component(dn, "GUID");
 
-               ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
-                                              (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
+               ZERO_STRUCT(id3);
+
+               if (guid_blob) {
+                       ndr_err = ndr_pull_struct_blob_all(guid_blob, 
+                                                          tmp_ctx, schema->iconv_convenience, &id3.guid,
+                                                          (ndr_pull_flags_fn_t)ndr_pull_GUID);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                               talloc_free(tmp_ctx);
+                               return ntstatus_to_werror(status);
+                       }
+               }
+
+               sid_blob = ldb_dn_get_extended_component(dn, "SID");
+               if (sid_blob) {
+                       
+                       ndr_err = ndr_pull_struct_blob_all(sid_blob, 
+                                                          tmp_ctx, schema->iconv_convenience, &id3.sid,
+                                                          (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+                       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                               talloc_free(tmp_ctx);
+                               return ntstatus_to_werror(status);
+                       }
+               }
+
+               id3.dn = ldb_dn_get_linearized(dn);
+               if (strncmp(id3.dn, "B:", 2) == 0) {
+                       id3.dn = strchr(id3.dn, ':');
+                       id3.dn = strchr(id3.dn+1, ':');
+                       id3.dn = strchr(id3.dn+1, ':');
+                       id3.dn++;
+               }
+
+               /* get binary stuff */
+               ldb_dn_get_binary(dn, &id3.binary);
+
+               ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+                       talloc_free(tmp_ctx);
                        return ntstatus_to_werror(status);
                }
+               talloc_free(tmp_ctx);
        }
 
        return WERR_OK;
 }
 
+
+
 static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb, 
                                                              const struct dsdb_schema *schema,
                                                              const struct dsdb_attribute *attr,
index 12a513fc429992fb2e6aa4ce3d5be354d5919406..798b85dc851b459611478d6ac2d4b2a28287349e 100644 (file)
@@ -77,8 +77,17 @@ struct ldb_dn {
 
        unsigned int ext_comp_num;
        struct ldb_dn_ext_component *ext_components;
+
+       char extra_type;
+       struct ldb_val extra_val;
 };
 
+/* it is helpful to be able to break on this in gdb */
+static void ldb_dn_mark_invalid(struct ldb_dn *dn)
+{
+       dn->invalid = true;
+}
+
 /* strdn may be NULL */
 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
                                    struct ldb_context *ldb,
@@ -94,6 +103,13 @@ struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
                return NULL;
        }
 
+       /* if the DN starts with B: then it has a binary blob
+        * attached. Called the binary dn parser, which will call back
+        * here for the rest of the DN */
+       if (strdn->data && strncmp((char *)strdn->data, "B:", 2) == 0) {
+               return ldb_dn_binary_from_ldb_val(mem_ctx, ldb, strdn);
+       }
+
        dn = talloc_zero(mem_ctx, struct ldb_dn);
        LDB_DN_NULL_FAILED(dn);
 
@@ -141,13 +157,180 @@ failed:
        return NULL;
 }
 
+/*
+  a version of strhex_to_str internal to ldb, for use by the binary
+  ldb code
+ */
+static size_t ldb_strhex_to_str(char *p, size_t p_len, const char *strhex, 
+                               size_t strhex_len)
+{
+       size_t i;
+       size_t num_chars = 0;
+       uint8_t   lonybble, hinybble;
+       const char     *hexchars = "0123456789ABCDEF";
+       char           *p1 = NULL, *p2 = NULL;
+
+       for (i = 0; i < strhex_len && strhex[i] != 0; i++) {
+               if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
+                       break;
+
+               i++; /* next hex digit */
+
+               if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
+                       break;
+
+               /* get the two nybbles */
+               hinybble = PTR_DIFF(p1, hexchars);
+               lonybble = PTR_DIFF(p2, hexchars);
+
+               if (num_chars >= p_len) {
+                       break;
+               }
+
+               p[num_chars] = (hinybble << 4) | lonybble;
+               num_chars++;
+
+               p1 = NULL;
+               p2 = NULL;
+       }
+       return num_chars;
+}
+
+/* strdn may be NULL */
+struct ldb_dn *ldb_dn_binary_from_ldb_val(void *mem_ctx,
+                                         struct ldb_context *ldb,
+                                         const struct ldb_val *strdn)
+{
+       struct ldb_dn *dn;
+       const char *data;
+       size_t len;
+       char *linearized;
+       TALLOC_CTX *tmp_ctx;
+       char *p1;
+       char *p2;
+       uint32_t blen;
+       struct ldb_val bval;
+       struct ldb_val dval;
+       char *dn_str;
+       char *old;
+
+       if (strdn && strdn->data
+           && (strlen((const char*)strdn->data) != strdn->length)) {
+               /* The RDN must not contain a character with value 0x0 */
+               return NULL;
+       }
+
+       if (!strdn->data || strdn->length == 0) {
+               return NULL;
+
+       }
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               return NULL;
+       }
+
+       data = (const char *)strdn->data;
+
+       if (data[0] != 'B') {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": no prefix?\n");
+               return NULL;
+       }
+
+       len = strdn->length;
+       linearized = talloc_strndup(tmp_ctx, data, len);
+       if (linearized == NULL) {
+               goto failed;
+       }
+
+       ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": processing DN '%s'\n", linearized);
+
+       p1 = linearized;
+
+       p1++; len--;
+       
+       if (p1[0] != ':') {
+               goto failed;
+       }
+       p1++;
+       len--;
+       
+       errno = 0;
+       blen = strtoul(p1, &p2, 10);
+       if (errno != 0) {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": failed\n");
+               goto failed;
+       }
+       if (p2 == NULL) {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": failed\n");
+               goto failed;
+       }
+       if (p2[0] != ':') {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": failed\n");
+               goto failed;
+       }
+       len -= PTR_DIFF(p2,p1);//???
+       p1 = p2+1;
+       len--;
+       
+       if (blen >= len) {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": blen=%u len=%u\n", (unsigned)blen, (unsigned)len);
+               goto failed;
+       }
+
+       p2 = p1 + blen;
+       if (p2[0] != ':') {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": %s", p2);
+               goto failed;
+       }
+       dn_str = p2+1;
+       
+       bval.length = (blen/2)+1;
+       bval.data = talloc_size(tmp_ctx, bval.length);
+       if (bval.data == NULL) {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": err\n");
+               goto failed;
+       }
+       bval.data[bval.length-1] = 0;
+       
+       bval.length = ldb_strhex_to_str((char *)bval.data, bval.length,
+                                       p1, blen);
+       
+       dval.data = (uint8_t *)dn_str;
+       dval.length = strlen(dn_str);
+       
+       dn = ldb_dn_from_ldb_val(mem_ctx, ldb, &dval);
+       if (dn == NULL) {
+               ldb_debug(ldb, LDB_DEBUG_TRACE, __location__ ": err\n");
+               goto failed;
+       }
+       dn->extra_type = data[0];
+       dn->extra_val = bval;
+       talloc_steal(dn, bval.data);
+
+       *dn_str = '\0';
+       old = dn->linearized;
+       dn->linearized = talloc_asprintf(dn, "%s%s", linearized, dn->linearized);
+       talloc_free(old);
+       if (dn->ext_linearized) {
+               old = dn->ext_linearized;
+               dn->ext_linearized = talloc_asprintf(dn, "%s%s", linearized, dn->ext_linearized);
+               talloc_free(old);
+       }
+       
+       return dn;
+failed:
+       talloc_free(tmp_ctx);
+       return NULL;
+}
+
 /* strdn may be NULL */
 struct ldb_dn *ldb_dn_new(void *mem_ctx,
                          struct ldb_context *ldb,
                          const char *strdn)
 {
        struct ldb_val blob;
-       blob.data = strdn;
+       blob.data = discard_const_p(uint8_t, strdn);
        blob.length = strdn ? strlen(strdn) : 0;
        return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
 }
@@ -273,6 +456,14 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                return false;
        }
 
+
+       if (strncmp(parse_dn, "B:", 2) == 0) {
+               parse_dn = strchr(parse_dn, ':');
+               parse_dn = strchr(parse_dn+1, ':');
+               parse_dn = strchr(parse_dn+1, ':');
+               parse_dn++;
+       }
+
        /* The RDN size must be less than 255 characters */
        if (strlen(parse_dn) > 255) {
                return false;
@@ -383,7 +574,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                ret = ext_syntax->read_fn(dn->ldb, dn->ext_components,
                                                          &ex_val, &dn->ext_components[dn->ext_comp_num].value);
                                if (ret != LDB_SUCCESS) {
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        goto failed;
                                }
 
@@ -398,7 +589,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                        p++;
                                        continue;
                                } else {
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        goto failed;
                                }
                        }
@@ -418,7 +609,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
 
                                if (!isascii(*p)) {
                                        /* attr names must be ascii only */
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        goto failed;
                                }
 
@@ -428,7 +619,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                if ( ! isalpha(*p)) {
                                        /* not a digit nor an alpha,
                                         * invalid attribute name */
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        goto failed;
                                }
 
@@ -447,7 +638,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
 
                        if (trim && (*p != '=')) {
                                /* spaces/tabs are not allowed */
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                goto failed;
                        }
 
@@ -476,19 +667,19 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
 
                        if (!isascii(*p)) {
                                /* attr names must be ascii only */
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                goto failed;
                        }
 
                        if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
                                /* not a digit nor a dot,
                                 * invalid attribute oid */
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                goto failed;
                        } else
                        if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
                                /* not ALPHA, DIGIT or HYPHEN */
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                goto failed;
                        }
 
@@ -588,7 +779,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                        case '\"':
                                /* a string with not escaped specials is invalid (tested) */
                                if ( ! escape) {
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        goto failed;
                                }
                                escape = false;
@@ -617,7 +808,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
                                if (escape) {
                                        if (sscanf(p, "%02x", &x) != 1) {
                                                /* invalid escaping sequence */
-                                               dn->invalid = true;
+                                               ldb_dn_mark_invalid(dn);
                                                goto failed;
                                        }
                                        escape = false;
@@ -647,7 +838,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
 
        if (in_attr || in_quote) {
                /* invalid dn */
-               dn->invalid = true;
+               ldb_dn_mark_invalid(dn);
                goto failed;
        }
 
@@ -683,20 +874,45 @@ bool ldb_dn_validate(struct ldb_dn *dn)
        return ldb_dn_explode(dn);
 }
 
+static char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const struct ldb_val *blob)
+{
+       int i;
+       char *hex_string;
+
+       hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
+       if (!hex_string) {
+               return NULL;
+       }
+
+       for (i = 0; i < blob->length; i++)
+               slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
+
+       hex_string[(blob->length*2)] = '\0';
+       return hex_string;
+}
+
+
 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
 {
        int i, len;
        char *d, *n;
+       char *extra_prefix = NULL;
 
        if ( ! dn || ( dn->invalid)) return NULL;
 
        if (dn->linearized) return dn->linearized;
 
        if ( ! dn->components) {
-               dn->invalid = true;
+               ldb_dn_mark_invalid(dn);
                return NULL;
        }
 
+       if (dn->extra_type == 'B') {
+               char *hexstr = data_blob_hex_string_upper(dn, &dn->extra_val);
+               extra_prefix = talloc_asprintf(dn, "B:%u:%s:", (unsigned)(dn->extra_val.length*2), hexstr);
+               talloc_free(hexstr);
+       }
+
        if (dn->comp_num == 0) {
                dn->linearized = talloc_strdup(dn, "");
                if ( ! dn->linearized) return NULL;
@@ -737,13 +953,20 @@ const char *ldb_dn_get_linearized(struct ldb_dn *dn)
        dn->linearized = talloc_realloc(dn, dn->linearized,
                                        char, (d - dn->linearized + 1));
 
+       if (extra_prefix) {
+               char *old = dn->linearized;
+               dn->linearized = talloc_asprintf(dn, "%s%s", extra_prefix, old);
+               talloc_free(old);
+               talloc_free(extra_prefix);
+       }
+
        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;
+       char *p = NULL;
        int i;
 
        if (!linearized) {
@@ -758,6 +981,14 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
                return NULL;
        }
 
+       if (dn->extra_type == 'B') {
+               char *hexstr = data_blob_hex_string_upper(mem_ctx, &dn->extra_val);
+               p = talloc_asprintf(mem_ctx, "B:%u:%s:", (unsigned)(dn->extra_val.length*2), hexstr);
+               talloc_free(hexstr);
+       } else {
+               p = talloc_strdup(mem_ctx, "");
+       }
+
        for (i = 0; i < dn->ext_comp_num; i++) {
                const struct ldb_dn_extended_syntax *ext_syntax;
                const char *name = dn->ext_components[i].name;
@@ -782,11 +1013,9 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
                }
 
                if (i == 0) {
-                       p = talloc_asprintf(mem_ctx, "<%s=%s>",
-                                                       name, val.data);
+                       p = talloc_asprintf_append_buffer(p, "<%s=%s>", name, val.data);
                } else {
-                       p = talloc_asprintf_append(p, ";<%s=%s>",
-                                                       name, val.data);
+                       p = talloc_asprintf_append_buffer(p, ";<%s=%s>",name, val.data);
                }
 
                talloc_free(val.data);
@@ -797,7 +1026,13 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
        }
 
        if (dn->ext_comp_num && *linearized) {
-               p = talloc_asprintf_append(p, ";%s", linearized);
+               if (strncmp(linearized, "B:", 2) == 0) {
+                       linearized = strchr(linearized, ':');
+                       linearized = strchr(linearized+1, ':');
+                       linearized = strchr(linearized+1, ':');
+                       linearized++;
+               }
+               p = talloc_asprintf_append_buffer(p, ";%s", linearized);
        }
 
        if (!p) {
@@ -1287,7 +1522,7 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                                                struct ldb_dn_component,
                                                dn->comp_num + base->comp_num);
                if ( ! dn->components) {
-                       dn->invalid = true;
+                       ldb_dn_mark_invalid(dn);
                        return false;
                }
 
@@ -1296,7 +1531,7 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                                ldb_dn_copy_component(dn->components,
                                                        &base->components[i]);
                        if (dn->components[dn->comp_num].value.data == NULL) {
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                return false;
                        }
                }
@@ -1327,7 +1562,7 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
                        t = talloc_strdup(dn, s);
                }
                if ( ! t) {
-                       dn->invalid = true;
+                       ldb_dn_mark_invalid(dn);
                        return false;
                }
                LDB_FREE(dn->linearized);
@@ -1413,7 +1648,7 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
                                                struct ldb_dn_component,
                                                n);
                if ( ! dn->components) {
-                       dn->invalid = true;
+                       ldb_dn_mark_invalid(dn);
                        return false;
                }
 
@@ -1426,7 +1661,7 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
                                ldb_dn_copy_component(dn->components,
                                                        &child->components[i]);
                        if (dn->components[i].value.data == NULL) {
-                               dn->invalid = true;
+                               ldb_dn_mark_invalid(dn);
                                return false;
                        }
                }
@@ -1449,7 +1684,7 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
 
                t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
                if ( ! t) {
-                       dn->invalid = true;
+                       ldb_dn_mark_invalid(dn);
                        return false;
                }
                LDB_FREE(dn->linearized);
@@ -1818,7 +2053,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                        talloc_strdup(dn->ext_components, name);
                                if (!dn->ext_components[i].name ||
                                    !dn->ext_components[i].value.data) {
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        return LDB_ERR_OPERATIONS_ERROR;
                                }
 
@@ -1836,7 +2071,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                                   struct ldb_dn_ext_component,
                                                   dn->ext_comp_num);
                                if (!dn->ext_components) {
-                                       dn->invalid = true;
+                                       ldb_dn_mark_invalid(dn);
                                        return LDB_ERR_OPERATIONS_ERROR;
                                }
                                return LDB_SUCCESS;
@@ -1850,7 +2085,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
                                 struct ldb_dn_ext_component,
                                 dn->ext_comp_num + 1);
        if (!dn->ext_components) {
-               dn->invalid = true;
+               ldb_dn_mark_invalid(dn);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
@@ -1858,7 +2093,7 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn,
        p[dn->ext_comp_num].name = talloc_strdup(p, name);
 
        if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
-               dn->invalid = true;
+               ldb_dn_mark_invalid(dn);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        dn->ext_components = p;
@@ -1888,7 +2123,7 @@ bool ldb_dn_is_special(struct ldb_dn *dn)
 bool ldb_dn_has_extended(struct ldb_dn *dn)
 {
        if ( ! dn || dn->invalid) return false;
-       if (dn->ext_linearized && (dn->ext_linearized[0] == '<')) return true;
+       if (dn->ext_linearized && strchr(dn->ext_linearized,'<')) return true;
        return dn->ext_comp_num != 0;
 }
 
@@ -1905,3 +2140,26 @@ bool ldb_dn_is_null(struct ldb_dn *dn)
        if (dn->linearized && (dn->linearized[0] == '\0')) return true;
        return false;
 }
+
+int ldb_dn_get_binary(struct ldb_dn *dn, struct ldb_val *val)
+{
+       ZERO_STRUCTP(val);
+       if (dn->extra_type != 'B') {
+               return LDB_SUCCESS;
+       }
+       *val = dn->extra_val;
+       return LDB_SUCCESS;
+}
+
+int ldb_dn_set_binary(struct ldb_dn *dn, struct ldb_val *val)
+{
+       dn->extra_type = 'B';
+       dn->extra_val.data = talloc_memdup(dn, val->data, val->length);
+       dn->extra_val.length = val->length;
+
+       talloc_free(dn->linearized);
+       talloc_free(dn->ext_linearized);
+       dn->linearized = NULL;
+       dn->ext_linearized = NULL;
+       return LDB_SUCCESS;
+}
index a08369607397353b94bdeebb453d4ac587f0bdde..04f7ccb3f28474f6c3cbed7aa58315ec98364a4b 100644 (file)
@@ -1928,4 +1928,11 @@ unsigned int ldb_get_flags(struct ldb_context *ldb);
 void ldb_set_flags(struct ldb_context *ldb, unsigned flags);
 
 
+struct ldb_dn *ldb_dn_binary_from_ldb_val(void *mem_ctx,
+                                         struct ldb_context *ldb,
+                                         const struct ldb_val *strdn);
+
+int ldb_dn_get_binary(struct ldb_dn *dn, struct ldb_val *val);
+int ldb_dn_set_binary(struct ldb_dn *dn, struct ldb_val *val);
+
 #endif