1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-18 06:04:06 +03:00

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>
This commit is contained in:
Stefan Metzmacher 2015-08-07 11:36:47 +02:00 committed by Karolin Seeger
parent 7693d683b5
commit df431a39e4
5 changed files with 43 additions and 39 deletions

View File

@ -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 {

View File

@ -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,

View File

@ -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',

View File

@ -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));

View File

@ -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;