summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-08-07 11:36:47 +0200
committerKarolin Seeger <kseeger@samba.org>2016-02-24 11:43:58 +0100
commit79f2cf166f1eb5c001c2c3124c0cbd2e4fbcba22 (patch)
tree5fc7210816efbd85383c0dd07985d8daabdc5629
parent4c40108da8ea319e566e324ac7ea10f61b263d69 (diff)
downloadsamba-79f2cf166f1eb5c001c2c3124c0cbd2e4fbcba22.tar.gz
CVE-2016-0771: s4:dns_server: fix idl for dns_txt_record
From RFC 1035: 3.3.14. TXT RDATA format +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TXT-DATA / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ where: TXT-DATA One or more <character-string>s. TXT RRs are used to hold descriptive text. The semantics of the text depends on the domain where it is found. Each record contains an array of strings instead of just one string. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11128 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11686 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--librpc/idl/dns.idl7
-rw-r--r--librpc/ndr/ndr_dns.c27
-rw-r--r--librpc/wscript_build2
-rw-r--r--source4/dns_server/dns_query.c15
-rw-r--r--source4/dns_server/dns_update.c31
5 files changed, 43 insertions, 39 deletions
diff --git a/librpc/idl/dns.idl b/librpc/idl/dns.idl
index 1183bd12299..918073ca9a8 100644
--- a/librpc/idl/dns.idl
+++ b/librpc/idl/dns.idl
@@ -8,7 +8,7 @@
encoding if it doesn't work out
*/
-import "misc.idl";
+import "misc.idl", "dnsp.idl";
[
helper("librpc/ndr/ndr_dns.h"),
helpstring("DNS records"),
@@ -163,9 +163,8 @@ interface dns
dns_string exchange;
} dns_mx_record;
- typedef [public] struct {
- [value(strlen(txt))] uint8 length;
- [charset(DOS)] uint8 txt[length];
+ typedef [public,nopull] struct {
+ dnsp_string_list txt;
} dns_txt_record;
typedef [public] struct {
diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c
index 0b9e3b05071..065d992684c 100644
--- a/librpc/ndr/ndr_dns.c
+++ b/librpc/ndr/ndr_dns.c
@@ -30,6 +30,7 @@
#include "includes.h"
#include "librpc/gen_ndr/ndr_dns.h"
#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
#include "system/locale.h"
#include "lib/util/util_net.h"
@@ -230,6 +231,29 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr,
return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
}
+_PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r)
+{
+ NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
+ if (ndr_flags & NDR_SCALARS) {
+ enum ndr_err_code ndr_err;
+ uint32_t data_size = ndr->data_size;
+ uint32_t record_size = 0;
+ ndr_err = ndr_token_retrieve(&ndr->array_size_list, r,
+ &record_size);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PULL_NEED_BYTES(ndr, record_size);
+ ndr->data_size = ndr->offset + record_size;
+ }
+ NDR_CHECK(ndr_pull_align(ndr, 1));
+ NDR_CHECK(ndr_pull_dnsp_string_list(ndr, NDR_SCALARS, &r->txt));
+ NDR_CHECK(ndr_pull_trailer_align(ndr, 1));
+ ndr->data_size = data_size;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ }
+ return NDR_ERR_SUCCESS;
+}
+
_PUBLIC_ enum ndr_err_code ndr_push_dns_res_rec(struct ndr_push *ndr,
int ndr_flags,
const struct dns_res_rec *r)
@@ -302,6 +326,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_dns_res_rec(struct ndr_pull *ndr,
NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->length));
_saved_offset1 = ndr->offset;
if (r->length > 0) {
+ NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list,
+ &r->rdata,
+ r->length));
NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->rdata,
r->rr_type));
NDR_CHECK(ndr_pull_dns_rdata(ndr, NDR_SCALARS,
diff --git a/librpc/wscript_build b/librpc/wscript_build
index a8a90047909..30820d2c034 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -32,7 +32,7 @@ bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
bld.SAMBA_SUBSYSTEM('NDR_DNS',
source='gen_ndr/ndr_dns.c ndr/ndr_dns.c',
- public_deps='ndr'
+ public_deps='ndr NDR_DNSP'
)
bld.SAMBA_SUBSYSTEM('NDR_DSBACKUP',
diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index 77f797bf5b2..f246958a94b 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -46,8 +46,7 @@ static WERROR create_response_rr(const struct dns_name_question *question,
{
struct dns_res_rec *ans = *answers;
uint16_t ai = *ancount;
- char *tmp;
- uint32_t i;
+ enum ndr_err_code ndr_err;
ZERO_STRUCT(ans[ai]);
@@ -101,14 +100,12 @@ static WERROR create_response_rr(const struct dns_name_question *question,
}
break;
case DNS_QTYPE_TXT:
- tmp = talloc_asprintf(ans, "\"%s\"", rec->data.txt.str[0]);
- W_ERROR_HAVE_NO_MEMORY(tmp);
- for (i=1; i<rec->data.txt.count; i++) {
- tmp = talloc_asprintf_append_buffer(
- tmp, " \"%s\"", rec->data.txt.str[i]);
- W_ERROR_HAVE_NO_MEMORY(tmp);
+ ndr_err = ndr_dnsp_string_list_copy(ans,
+ &rec->data.txt,
+ &ans[ai].rdata.txt_record.txt);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_NOMEM;
}
- ans[ai].rdata.txt_record.txt = tmp;
break;
default:
DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
index 04e7d9adff7..fb02ba074d4 100644
--- a/source4/dns_server/dns_update.c
+++ b/source4/dns_server/dns_update.c
@@ -299,9 +299,7 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
const struct dns_res_rec *rrec,
struct dnsp_DnssrvRpcRecord *r)
{
- char *tmp;
- char *txt_record_txt;
- char *saveptr = NULL;
+ enum ndr_err_code ndr_err;
if (rrec->rr_type == DNS_QTYPE_ALL) {
return DNS_ERR(FORMAT_ERROR);
@@ -354,28 +352,11 @@ static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
break;
case DNS_QTYPE_TXT:
- r->data.txt.count = 0;
- r->data.txt.str = talloc_array(mem_ctx, const char *,
- r->data.txt.count);
- W_ERROR_HAVE_NO_MEMORY(r->data.txt.str);
-
- txt_record_txt = talloc_strdup(r->data.txt.str,
- rrec->rdata.txt_record.txt);
- W_ERROR_HAVE_NO_MEMORY(txt_record_txt);
-
- tmp = strtok_r(txt_record_txt, "\"", &saveptr);
- while (tmp) {
- if (strcmp(tmp, " ") == 0) {
- tmp = strtok_r(NULL, "\"", &saveptr);
- continue;
- }
- r->data.txt.str = talloc_realloc(mem_ctx, r->data.txt.str, const char *,
- r->data.txt.count+1);
- r->data.txt.str[r->data.txt.count] = talloc_strdup(r->data.txt.str, tmp);
- W_ERROR_HAVE_NO_MEMORY(r->data.txt.str[r->data.txt.count]);
-
- r->data.txt.count++;
- tmp = strtok_r(NULL, "\"", &saveptr);
+ ndr_err = ndr_dnsp_string_list_copy(mem_ctx,
+ &rrec->rdata.txt_record.txt,
+ &r->data.txt);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_NOMEM;
}
break;