summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/sm_resolve.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/sm_resolve.c')
-rw-r--r--contrib/sendmail/src/sm_resolve.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/contrib/sendmail/src/sm_resolve.c b/contrib/sendmail/src/sm_resolve.c
index e3eb77f..a6f5862 100644
--- a/contrib/sendmail/src/sm_resolve.c
+++ b/contrib/sendmail/src/sm_resolve.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -46,7 +46,7 @@
# if NAMED_BIND
# include "sm_resolve.h"
-SM_RCSID("$Id: sm_resolve.c,v 8.24 2001/09/11 04:05:16 gshapiro Exp $")
+SM_RCSID("$Id: sm_resolve.c,v 8.24.4.6 2002/06/25 04:22:41 ca Exp $")
static struct stot
{
@@ -180,8 +180,8 @@ parse_dns_reply(data, len)
p = data;
/* doesn't work on Crays? */
- memcpy(&r->dns_r_h, p, sizeof(HEADER));
- p += sizeof(HEADER);
+ memcpy(&r->dns_r_h, p, sizeof(r->dns_r_h));
+ p += sizeof(r->dns_r_h);
status = dn_expand(data, data + len, p, host, sizeof host);
if (status < 0)
{
@@ -200,7 +200,7 @@ parse_dns_reply(data, len)
rr = &r->dns_r_head;
while (p < data + len)
{
- int type, class, ttl, size;
+ int type, class, ttl, size, txtlen;
status = dn_expand(data, data + len, p, host, sizeof host);
if (status < 0)
@@ -213,7 +213,21 @@ parse_dns_reply(data, len)
GETSHORT(class, p);
GETLONG(ttl, p);
GETSHORT(size, p);
- *rr = (RESOURCE_RECORD_T *) xalloc(sizeof(RESOURCE_RECORD_T));
+ if (p + size > data + len)
+ {
+ /*
+ ** announced size of data exceeds length of
+ ** data paket: someone is cheating.
+ */
+
+ if (LogLevel > 5)
+ sm_syslog(LOG_WARNING, NOQID,
+ "ERROR: DNS RDLENGTH=%d > data len=%d",
+ size, len - (p - data));
+ dns_free_data(r);
+ return NULL;
+ }
+ *rr = (RESOURCE_RECORD_T *) xalloc(sizeof(**rr));
if (*rr == NULL)
{
dns_free_data(r);
@@ -260,7 +274,7 @@ parse_dns_reply(data, len)
}
l = strlen(host) + 1;
(*rr)->rr_u.rr_mx = (MX_RECORD_T *)
- xalloc(sizeof(MX_RECORD_T) + l);
+ xalloc(sizeof(*((*rr)->rr_u.rr_mx)) + l);
if ((*rr)->rr_u.rr_mx == NULL)
{
dns_free_data(r);
@@ -281,7 +295,7 @@ parse_dns_reply(data, len)
}
l = strlen(host) + 1;
(*rr)->rr_u.rr_srv = (SRV_RECORDT_T*)
- xalloc(sizeof(SRV_RECORDT_T) + l);
+ xalloc(sizeof(*((*rr)->rr_u.rr_srv)) + l);
if ((*rr)->rr_u.rr_srv == NULL)
{
dns_free_data(r);
@@ -295,14 +309,35 @@ parse_dns_reply(data, len)
break;
case T_TXT:
- (*rr)->rr_u.rr_txt = (char *) xalloc(size + 1);
+
+ /*
+ ** The TXT record contains the length as
+ ** leading byte, hence the value is restricted
+ ** to 255, which is less than the maximum value
+ ** of RDLENGTH (size). Nevertheless, txtlen
+ ** must be less than size because the latter
+ ** specifies the length of the entire TXT
+ ** record.
+ */
+
+ txtlen = *p;
+ if (txtlen >= size)
+ {
+ if (LogLevel > 5)
+ sm_syslog(LOG_WARNING, NOQID,
+ "ERROR: DNS TXT record size=%d <= text len=%d",
+ size, txtlen);
+ dns_free_data(r);
+ return NULL;
+ }
+ (*rr)->rr_u.rr_txt = (char *) xalloc(txtlen + 1);
if ((*rr)->rr_u.rr_txt == NULL)
{
dns_free_data(r);
return NULL;
}
- (void) strncpy((*rr)->rr_u.rr_txt, (char*) p + 1, *p);
- (*rr)->rr_u.rr_txt[*p] = 0;
+ (void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1,
+ txtlen + 1);
break;
default:
@@ -313,6 +348,7 @@ parse_dns_reply(data, len)
return NULL;
}
(void) memcpy((*rr)->rr_u.rr_data, p, size);
+ break;
}
p += size;
rr = &(*rr)->rr_next;
OpenPOWER on IntegriCloud