Commit message: CVE-2015-5330: ldb_dn_escape_value: use known string length, not strlen()

ldb_dn_escape_internal() reports the number of bytes it copied, so
lets use that number, rather than using strlen() and hoping a zero got
in the right place.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11599

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Pair-programmed-with: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
CVE: CVE-2015-5330
CWE: CWE-200
Vulnerability description: ldb before 1.1.24, as used in the AD LDAP server in Samba 4.x before 4.1.22, 4.2.x before 4.2.7, and 4.3.x before 4.3.3, mishandles string lengths, which allows remote attackers to obtain sensitive information from daemon heap memory by sending crafted packets and then reading (1) an error message or (2) a database value.

Project: samba
File: ldb_dn.c

char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn)
{
	return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
}

Project: samba
File: ldb_dn.c

char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) {
	return ldb_dn_canonical(mem_ctx, dn, 0);

}

Project: samba
File: ldb_dn.c

int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
{
	unsigned int i;
	int ret;

	if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
		return -1;
	}

	if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
		if (dn0->linearized && dn1->linearized) {
			/* try with a normal compare first, if we are lucky
			 * we will avoid exploding and casfolding */
			if (strcmp(dn0->linearized, dn1->linearized) == 0) {
				return 0;
			}
		}

		if ( ! ldb_dn_casefold_internal(dn0)) {
			return 1;
		}

		if ( ! ldb_dn_casefold_internal(dn1)) {
			return -1;
		}

	}

	if (dn0->comp_num != dn1->comp_num) {
		return (dn1->comp_num - dn0->comp_num);
	}

	if (dn0->comp_num == 0) {
		if (dn0->special && dn1->special) {
			return strcmp(dn0->linearized, dn1->linearized);
		} else if (dn0->special) {
			return 1;
		} else if (dn1->special) {
			return -1;
		} else {
			return 0;
		}
	}

	for (i = 0; i < dn0->comp_num; i++) {
		char *dn0_name = dn0->components[i].cf_name;
		char *dn1_name = dn1->components[i].cf_name;

		char *dn0_vdata = (char *)dn0->components[i].cf_value.data;
		char *dn1_vdata = (char *)dn1->components[i].cf_value.data;

		size_t dn0_vlen = dn0->components[i].cf_value.length;
		size_t dn1_vlen = dn1->components[i].cf_value.length;

		/* compare attr names */
		ret = strcmp(dn0_name, dn1_name);
		if (ret != 0) {
			return ret;
		}

		/* compare attr.cf_value. */
		if (dn0_vlen != dn1_vlen) {
			return dn0_vlen - dn1_vlen;
		}
		ret = strncmp(dn0_vdata, dn1_vdata, dn0_vlen);
		if (ret != 0) {
			return ret;
		}
	}

	return 0;
}

Project: samba
File: ldb_dn.c

const char *ldb_dn_get_casefold(struct ldb_dn *dn)
{
	unsigned int i;
	size_t len;
	char *d, *n;

	if (dn->casefold) return dn->casefold;

	if (dn->special) {
		dn->casefold = talloc_strdup(dn, dn->linearized);
		if (!dn->casefold) return NULL;
		dn->valid_case = true;
		return dn->casefold;
	}

	if ( ! ldb_dn_casefold_internal(dn)) {
		return NULL;
	}

	if (dn->comp_num == 0) {
		dn->casefold = talloc_strdup(dn, "");
		return dn->casefold;
	}

	/* calculate maximum possible length of DN */
	for (len = 0, i = 0; i < dn->comp_num; i++) {
		/* name len */
		len += strlen(dn->components[i].cf_name);
		/* max escaped data len */
		len += (dn->components[i].cf_value.length * 3);
		len += 2; /* '=' and ',' */
	}
	dn->casefold = talloc_array(dn, char, len);
	if ( ! dn->casefold) return NULL;

	d = dn->casefold;

	for (i = 0; i < dn->comp_num; i++) {

		/* copy the name */
		n = dn->components[i].cf_name;
		while (*n) *d++ = *n++;

		*d++ = '=';

		/* and the value */
		d += ldb_dn_escape_internal( d,
				(char *)dn->components[i].cf_value.data,
				dn->components[i].cf_value.length);
		*d++ = ',';
	}
	*(--d) = '\0';

	/* don't waste more memory than necessary */
	dn->casefold = talloc_realloc(dn, dn->casefold,
				      char, strlen(dn->casefold) + 1);

	return dn->casefold;
}