summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-10-02 12:03:05 +1000
committerAndrew Tridgell <tridge@samba.org>2009-10-02 12:03:05 +1000
commitfd22e0304782e20b9bbb29464b6c745d409ff4c6 (patch)
treed6fe91cfa850696de5a2b8849124fd1f60e28ce4
parent634d9d64766dd125d202f47c2d0cefc9da3c87b6 (diff)
downloadsamba-fd22e0304782e20b9bbb29464b6c745d409ff4c6.tar.gz
samba-fd22e0304782e20b9bbb29464b6c745d409ff4c6.tar.bz2
samba-fd22e0304782e20b9bbb29464b6c745d409ff4c6.zip
s4-ldb: Add support for binary blobs in DNs
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.
-rw-r--r--source4/dsdb/schema/schema_syntax.c136
-rw-r--r--source4/lib/ldb/common/ldb_dn.c318
-rw-r--r--source4/lib/ldb/include/ldb.h7
3 files changed, 408 insertions, 53 deletions
diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c
index c564471d4b..cbbd4a8636 100644
--- a/source4/dsdb/schema/schema_syntax.c
+++ b/source4/dsdb/schema/schema_syntax.c
@@ -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,
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
index 12a513fc42..798b85dc85 100644
--- a/source4/lib/ldb/common/ldb_dn.c
+++ b/source4/lib/ldb/common/ldb_dn.c
@@ -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;
+}
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index a083696073..04f7ccb3f2 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -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