From 6e800bfba708124077defab3c9379db201f4c43c Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Mon, 24 Oct 2011 17:20:46 +1100 Subject: s4-dnsserver: Build a dns name tree for correct enumeration The result of EnumRecords/EnumRecords2 RPC calls, is a list of dns records that are one level below in the name hierarchy starting from the search name. This patch builds a tree of names to get the list of records one level below the search names and correctly count the number of child records for each of those. Signed-off-by: Andrew Tridgell --- source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 110 +++++++++++------------- 1 file changed, 51 insertions(+), 59 deletions(-) (limited to 'source4/rpc_server/dnsserver/dcerpc_dnsserver.c') diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 93f315b857..fd0c97795a 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1429,7 +1429,7 @@ static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate, for (i=0; icount; i++) { status = dns_fill_records_array(tmp_ctx, NULL, record_type, select_flag, NULL, - res->msgs[i], recs, + res->msgs[i], 0, recs, &add_names, &add_count); if (!W_ERROR_IS_OK(status)) { talloc_free(tmp_ctx); @@ -1457,7 +1457,7 @@ static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate, } status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A, select_flag, rname, - res->msgs[0], recs, + res->msgs[0], 0, recs, NULL, NULL); talloc_free(rname); talloc_free(res); @@ -1487,16 +1487,16 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, struct DNS_RPC_RECORDS_ARRAY **buffer) { TALLOC_CTX *tmp_ctx; - char *name, *branch_name; + char *name; const char * const attrs[] = { "name", "dnsRecord", NULL }; struct ldb_result *res; struct DNS_RPC_RECORDS_ARRAY *recs; char **add_names = NULL; - const char *ptr; char *rname; int add_count = 0; int i, ret, len; WERROR status; + struct dns_tree *tree, *base, *node; tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); @@ -1530,81 +1530,73 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name, (ldb_qsort_cmp_fn_t)dns_name_compare); - /* Add the parent record with blank name */ - ptr = ldb_msg_find_attr_as_string(res->msgs[0], "name", NULL); - if (strcmp(ptr, name) == 0 || strcmp(ptr, "@") == 0) { - /* parent record found */ - if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) { - status = WERR_OK; - } else { - status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, NULL, - res->msgs[0], recs, - &add_names, &add_count); - } - i = 1; + /* Build a tree of name components from dns name */ + if (strcmp(name, z->name) == 0) { + tree = dns_build_tree(tmp_ctx, "@", res); } else { - /* parent record not in the search */ - if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) { - status = WERR_OK; - } else { - status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, NULL, - NULL, recs, - &add_names, &add_count); - } - i = 0; + tree = dns_build_tree(tmp_ctx, name, res); } + W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx); - if (!W_ERROR_IS_OK(status)) { - talloc_free(tmp_ctx); - return status; + /* Find the parent record in the tree */ + base = tree; + while (base->level != -1) { + base = base->children[0]; + } + + /* Add the parent record with blank name */ + if (!(select_flag & DNS_RPC_VIEW_ONLY_CHILDREN)) { + status = dns_fill_records_array(tmp_ctx, z, record_type, + select_flag, NULL, + base->data, 0, + recs, &add_names, &add_count); + if (!W_ERROR_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } } /* Add all the children records */ if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) { - for ( ; icount; i++) { - char *name2; - const char *tmp_str; - - ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL); - name2 = dns_split_node_name(tmp_ctx, ptr, name); - tmp_str = strrchr(name2, '.'); - if (tmp_str == NULL) { - branch_name = talloc_strdup(tmp_ctx, name2); - } else { - /* Skip '.' */ - branch_name = talloc_strdup(tmp_ctx, &tmp_str[1]); - } - talloc_free(name2); + for (i=0; inum_children; i++) { + node = base->children[i]; status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, branch_name, - res->msgs[i], recs, - &add_names, &add_count); + select_flag, node->name, + node->data, node->num_children, + recs, &add_names, &add_count); if (!W_ERROR_IS_OK(status)) { talloc_free(tmp_ctx); return status; } - - talloc_free(branch_name); } } - talloc_free(res); + talloc_free(res); + talloc_free(tree); talloc_free(name); /* Add any additional records */ if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) { for (i=0; iname); - ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, - LDB_SCOPE_ONELEVEL, attrs, - "(&(objectClass=dnsNode)(name=%s))", name); - talloc_free(name); - if (ret != LDB_SUCCESS || res->count == 0) { - talloc_free(res); - continue; + struct dnsserver_zone *z2; + + /* Search all the available zones for additional name */ + for (z2 = dsstate->zones; z2; z2 = z2->next) { + name = dns_split_node_name(tmp_ctx, add_names[i], z2->name); + ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn, + LDB_SCOPE_ONELEVEL, attrs, + "(&(objectClass=dnsNode)(name=%s))", name); + talloc_free(name); + if (ret != LDB_SUCCESS) { + continue; + } + if (res->count == 1) { + break; + } else { + talloc_free(res); + continue; + } } len = strlen(add_names[i]); @@ -1615,7 +1607,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, } status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A, select_flag, rname, - res->msgs[0], recs, + res->msgs[0], 0, recs, NULL, NULL); talloc_free(rname); talloc_free(res); -- cgit