summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/common/ldb_dn.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/common/ldb_dn.c')
-rw-r--r--source4/lib/ldb/common/ldb_dn.c319
1 files changed, 286 insertions, 33 deletions
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
index 12a513fc42..fa3865e77f 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,9 +456,12 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
return false;
}
- /* The RDN size must be less than 255 characters */
- if (strlen(parse_dn) > 255) {
- 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++;
}
/* Empty DNs */
@@ -383,7 +569,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 +584,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 +604,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 +614,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 +633,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 +662,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 +774,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 +803,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 +833,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 +869,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 +948,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 +976,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 +1008,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 +1021,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 +1517,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 +1526,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 +1557,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 +1643,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 +1656,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 +1679,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 +2048,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 +2066,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 +2080,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 +2088,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 +2118,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 +2135,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;
+}