summaryrefslogtreecommitdiffstats
path: root/sys/netinet/libalias
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1998-12-14 02:25:32 +0000
committerdillon <dillon@FreeBSD.org>1998-12-14 02:25:32 +0000
commit14901c04b79cb17c3c64e0f387e5bf232548c4f1 (patch)
tree944aea4f0c97efa78bd8751707f0852d6ebb930b /sys/netinet/libalias
parent95f78d45621446ffbafb1a53dc3294659c10152a (diff)
downloadFreeBSD-src-14901c04b79cb17c3c64e0f387e5bf232548c4f1.zip
FreeBSD-src-14901c04b79cb17c3c64e0f387e5bf232548c4f1.tar.gz
Reviewed by: freebsd-current
Add bounds checking to netbios NS packet resolving code. This should prevent natd from crashing on badly formed netbios packets (as might be heard when the machine is sitting on a cable modem or certain DSL networks), and also closes potential security holes that might have exploited the lack of bounds checking in the previous version of the code.
Diffstat (limited to 'sys/netinet/libalias')
-rw-r--r--sys/netinet/libalias/alias.c17
-rw-r--r--sys/netinet/libalias/alias_local.h4
-rw-r--r--sys/netinet/libalias/alias_nbt.c215
3 files changed, 192 insertions, 44 deletions
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index 48a852a..50e597f 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -73,6 +73,9 @@
- Eliminated PacketAliasIn2() and
PacketAliasOut2() as poorly conceived.
+ Version 2.3 Dec 1998 (dillon)
+ - Major bounds checking additions, see FreeBSD/CVS
+
See HISTORY file for additional revisions.
*/
@@ -603,6 +606,7 @@ UdpAliasIn(struct ip *pip)
u_short alias_port;
int accumulate;
u_short *sptr;
+ int r = 0;
alias_address = GetAliasAddress(link);
original_address = GetOriginalAddress(link);
@@ -613,11 +617,11 @@ UdpAliasIn(struct ip *pip)
if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER )
{
- AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
+ r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport);
} else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
|| ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER )
{
- AliasHandleUdpNbtNS(pip, link,
+ r = AliasHandleUdpNbtNS(pip, link,
&alias_address,
&alias_port,
&original_address,
@@ -648,7 +652,14 @@ UdpAliasIn(struct ip *pip)
(u_short *) &pip->ip_dst,
2);
pip->ip_dst = original_address;
- return(PKT_ALIAS_OK);
+
+ /*
+ * If we cannot figure out the packet, ignore it.
+ */
+ if (r < 0)
+ return(PKT_ALIAS_IGNORED);
+ else
+ return(PKT_ALIAS_OK);
}
return(PKT_ALIAS_IGNORED);
}
diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h
index 0e94a64..3846281 100644
--- a/sys/netinet/libalias/alias_local.h
+++ b/sys/netinet/libalias/alias_local.h
@@ -90,8 +90,8 @@ void HouseKeeping(void);
/*lint -save -library Suppress flexelint warnings */
void AliasHandleFtpOut(struct ip *, struct alias_link *, int);
void AliasHandleIrcOut(struct ip *pip, struct alias_link *link, int maxsize );
-void AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
-void AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
+int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short);
+int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *);
void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *);
void AliasHandleCUSeeMeIn(struct ip *, struct in_addr);
diff --git a/sys/netinet/libalias/alias_nbt.c b/sys/netinet/libalias/alias_nbt.c
index f3581a7..cd07431 100644
--- a/sys/netinet/libalias/alias_nbt.c
+++ b/sys/netinet/libalias/alias_nbt.c
@@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id:$
+ * $Id: alias_nbt.c,v 1.1 1998/05/24 03:03:10 amurai Exp $
*
* TODO:
* oClean up.
@@ -132,15 +132,21 @@ void PrintRcode( u_char rcode ) {
/* Handling Name field */
-u_char *AliasHandleName ( u_char *p ) {
+u_char *AliasHandleName ( u_char *p, char *pmax ) {
u_char *s;
u_char c;
int compress;
/* Following length field */
+
+ if (p == NULL || (char *)p >= pmax)
+ return(NULL);
+
if (*p & 0xc0 ) {
p = p + 2;
+ if ((char *)p > pmax)
+ return(NULL);
return ((u_char *)p);
}
while ( ( *p & 0x3f) != 0x00 ) {
@@ -152,6 +158,10 @@ u_char *AliasHandleName ( u_char *p ) {
/* Get next length field */
p = (u_char *)(p + (*p & 0x3f) + 1);
+ if ((char *)p > pmax) {
+ p = NULL;
+ break;
+ }
#ifdef DEBUG
printf(":");
#endif
@@ -179,7 +189,10 @@ u_char *AliasHandleName ( u_char *p ) {
}
/* Set up to out of Name field */
- p++;
+ if (p == NULL || (char *)p >= pmax)
+ p = NULL;
+ else
+ p++;
return ((u_char *)p);
}
@@ -194,19 +207,24 @@ u_char *AliasHandleName ( u_char *p ) {
#define DGM_POSITIVE_RES 0x15
#define DGM_NEGATIVE_RES 0x16
-void AliasHandleUdpNbt(
+int AliasHandleUdpNbt(
struct ip *pip, /* IP packet to examine/patch */
struct alias_link *link,
struct in_addr *alias_address,
- u_short alias_port )
-{
+ u_short alias_port
+) {
struct udphdr * uh;
NbtDataHeader *ndh;
- u_char *p;
+ u_char *p = NULL;
+ char *pmax;
/* Calculate data length of UDP packet */
uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+ pmax = (char *)uh + ntohs( uh->uh_ulen );
+
ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
+ if ((char *)(ndh + 1) > pmax)
+ return(-1);
#ifdef DEBUG
printf("\nType=%02x,", ndh->type );
#endif
@@ -215,8 +233,8 @@ void AliasHandleUdpNbt(
case DGM_DIRECT_GROUP:
case DGM_BROADCAST:
p = (u_char *)ndh + 14;
- p = AliasHandleName ( p ); /* Source Name */
- p = AliasHandleName ( p ); /* Destination Name */
+ p = AliasHandleName ( p, pmax ); /* Source Name */
+ p = AliasHandleName ( p, pmax ); /* Destination Name */
break;
case DGM_ERROR:
p = (u_char *)ndh + 11;
@@ -225,9 +243,11 @@ void AliasHandleUdpNbt(
case DGM_POSITIVE_RES:
case DGM_NEGATIVE_RES:
p = (u_char *)ndh + 10;
- p = AliasHandleName ( p ); /* Destination Name */
+ p = AliasHandleName ( p, pmax ); /* Destination Name */
break;
}
+ if (p == NULL || (char *)p > pmax)
+ p = NULL;
#ifdef DEBUG
printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
#endif
@@ -251,6 +271,7 @@ void AliasHandleUdpNbt(
printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
fflush(stdout);
#endif
+ return((p == NULL) ? -1 : 0);
}
/* Question Section */
#define QS_TYPE_NB 0x0020
@@ -261,14 +282,22 @@ typedef struct {
u_short class; /* The class of Request */
} NBTNsQuestion;
-u_char *AliasHandleQuestion(u_short count,
+u_char *
+AliasHandleQuestion(
+ u_short count,
NBTNsQuestion *q,
+ char *pmax,
NBTArguments *nbtarg)
{
while ( count != 0 ) {
/* Name Filed */
- q = (NBTNsQuestion *)AliasHandleName((u_char *)q );
+ q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
+
+ if (q == NULL || (char *)(q + 1) > pmax) {
+ q = NULL;
+ break;
+ }
/* Type and Class filed */
switch ( ntohs(q->type) ) {
@@ -308,12 +337,17 @@ typedef struct {
struct in_addr addr;
} NBTNsRNB;
-u_char *AliasHandleResourceNB( NBTNsResource *q,
+u_char *
+AliasHandleResourceNB(
+ NBTNsResource *q,
+ char *pmax,
NBTArguments *nbtarg)
{
NBTNsRNB *nb;
u_short bcount;
+ if (q == NULL || (char *)(q + 1) > pmax)
+ return(NULL);
/* Check out a length */
bcount = ntohs(q->rdlen);
@@ -325,7 +359,11 @@ u_char *AliasHandleResourceNB( NBTNsResource *q,
printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
#endif
- while ( bcount != 0 ) {
+ while ( nb != NULL && bcount != 0 ) {
+ if ((char *)(nb + 1) > pmax) {
+ nb = NULL;
+ break;
+ }
#ifdef DEBUG
printf("<%s>", inet_ntoa(nb->addr) );
#endif
@@ -356,6 +394,9 @@ u_char *AliasHandleResourceNB( NBTNsResource *q,
nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
bcount -= SizeOfNsRNB;
}
+ if (nb == NULL || (char *)(nb + 1) > pmax) {
+ nb = NULL;
+ }
return ((u_char *)nb);
}
@@ -365,12 +406,18 @@ typedef struct {
struct in_addr addr;
} NBTNsResourceA;
-u_char *AliasHandleResourceA( NBTNsResource *q,
+u_char *
+AliasHandleResourceA(
+ NBTNsResource *q,
+ char *pmax,
NBTArguments *nbtarg)
{
NBTNsResourceA *a;
u_short bcount;
+ if (q == NULL || (char *)(q + 1) > pmax)
+ return(NULL);
+
/* Forward to Resource A position */
a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
@@ -383,6 +430,8 @@ u_char *AliasHandleResourceA( NBTNsResource *q,
printf("->%s]",inet_ntoa(nbtarg->newaddr ));
#endif
while ( bcount != 0 ) {
+ if (a == NULL || (char *)(a + 1) > pmax)
+ return(NULL);
#ifdef DEBUG
printf("..%s", inet_ntoa(a->addr) );
#endif
@@ -405,6 +454,8 @@ u_char *AliasHandleResourceA( NBTNsResource *q,
a++; /*XXXX*/
bcount -= SizeOfResourceA;
}
+ if (a == NULL || (char *)(a + 1) > pmax)
+ a = NULL;
return ((u_char *)a);
}
@@ -412,12 +463,18 @@ typedef struct {
u_short opcode:4, flags:8, resv:4;
} NBTNsResourceNULL;
-u_char *AliasHandleResourceNULL( NBTNsResource *q,
+u_char *
+AliasHandleResourceNULL(
+ NBTNsResource *q,
+ char *pmax,
NBTArguments *nbtarg)
{
NBTNsResourceNULL *n;
u_short bcount;
+ if (q == NULL || (char *)(q + 1) > pmax)
+ return(NULL);
+
/* Forward to Resource NULL position */
n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
@@ -426,19 +483,31 @@ u_char *AliasHandleResourceNULL( NBTNsResource *q,
/* Processing all in_addr array */
while ( bcount != 0 ) {
+ if ((char *)(n + 1) > pmax) {
+ n = NULL;
+ break;
+ }
n++;
bcount -= sizeof(NBTNsResourceNULL);
}
+ if ((char *)(n + 1) > pmax)
+ n = NULL;
return ((u_char *)n);
}
-u_char *AliasHandleResourceNS( NBTNsResource *q,
+u_char *
+AliasHandleResourceNS(
+ NBTNsResource *q,
+ char *pmax,
NBTArguments *nbtarg)
{
NBTNsResourceNULL *n;
u_short bcount;
+ if (q == NULL || (char *)(q + 1) > pmax)
+ return(NULL);
+
/* Forward to Resource NULL position */
n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
@@ -446,8 +515,11 @@ u_char *AliasHandleResourceNS( NBTNsResource *q,
bcount = ntohs(q->rdlen);
/* Resource Record Name Filed */
- q = (NBTNsResource *)AliasHandleName( (u_char *)n ); /* XXX */
+ q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
+ if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
+ return(NULL);
+ else
return ((u_char *)n + bcount);
}
@@ -455,28 +527,44 @@ typedef struct {
u_short numnames;
} NBTNsResourceNBSTAT;
-u_char *AliasHandleResourceNBSTAT( NBTNsResource *q,
+u_char *
+AliasHandleResourceNBSTAT(
+ NBTNsResource *q,
+ char *pmax,
NBTArguments *nbtarg)
{
NBTNsResourceNBSTAT *n;
u_short bcount;
+ if (q == NULL || (char *)(q + 1) > pmax)
+ return(NULL);
+
/* Forward to Resource NBSTAT position */
n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
/* Check out of length */
bcount = ntohs(q->rdlen);
+ if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
+ return(NULL);
+ else
return ((u_char *)n + bcount);
}
-u_char *AliasHandleResource(u_short count,
+u_char *
+AliasHandleResource(
+ u_short count,
NBTNsResource *q,
- NBTArguments *nbtarg)
+ char *pmax,
+ NBTArguments
+ *nbtarg)
{
while ( count != 0 ) {
/* Resource Record Name Filed */
- q = (NBTNsResource *)AliasHandleName( (u_char *)q );
+ q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
+
+ if (q == NULL || (char *)(q + 1) > pmax)
+ break;
#ifdef DEBUG
printf("type=%02x, count=%d\n", ntohs(q->type), count );
#endif
@@ -484,22 +572,45 @@ u_char *AliasHandleResource(u_short count,
/* Type and Class filed */
switch ( ntohs(q->type) ) {
case RR_TYPE_NB:
- q = (NBTNsResource *)AliasHandleResourceNB( q, nbtarg );
+ q = (NBTNsResource *)AliasHandleResourceNB(
+ q,
+ pmax,
+ nbtarg
+ );
break;
case RR_TYPE_A:
- q = (NBTNsResource *)AliasHandleResourceA( q, nbtarg );
+ q = (NBTNsResource *)AliasHandleResourceA(
+ q,
+ pmax,
+ nbtarg
+ );
break;
case RR_TYPE_NS:
- q = (NBTNsResource *)AliasHandleResourceNS( q, nbtarg );
+ q = (NBTNsResource *)AliasHandleResourceNS(
+ q,
+ pmax,
+ nbtarg
+ );
break;
case RR_TYPE_NULL:
- q = (NBTNsResource *)AliasHandleResourceNULL( q, nbtarg );
+ q = (NBTNsResource *)AliasHandleResourceNULL(
+ q,
+ pmax,
+ nbtarg
+ );
break;
case RR_TYPE_NBSTAT:
- q = (NBTNsResource *)AliasHandleResourceNBSTAT( q, nbtarg );
+ q = (NBTNsResource *)AliasHandleResourceNBSTAT(
+ q,
+ pmax,
+ nbtarg
+ );
break;
- default: printf("\nUnknown Type of Resource %0x\n",
- ntohs(q->type) );
+ default:
+ printf(
+ "\nUnknown Type of Resource %0x\n",
+ ntohs(q->type)
+ );
break;
}
count--;
@@ -508,7 +619,7 @@ u_char *AliasHandleResource(u_short count,
return ((u_char *)q);
}
-void AliasHandleUdpNbtNS(
+int AliasHandleUdpNbtNS(
struct ip *pip, /* IP packet to examine/patch */
struct alias_link *link,
struct in_addr *alias_address,
@@ -518,8 +629,8 @@ void AliasHandleUdpNbtNS(
{
struct udphdr * uh;
NbtNSHeader * nsh;
- u_short dlen;
u_char * p;
+ char *pmax;
NBTArguments nbtarg;
/* Set up Common Parameter */
@@ -531,12 +642,16 @@ void AliasHandleUdpNbtNS(
/* Calculate data length of UDP packet */
uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
nbtarg.uh_sum = &(uh->uh_sum);
- dlen = ntohs( uh->uh_ulen );
nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
p = (u_char *)(nsh + 1);
+ pmax = (char *)uh + ntohs( uh->uh_ulen );
+
+ if ((char *)(nsh + 1) > pmax)
+ return(-1);
#ifdef DEBUG
- printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x, an=%04x, ns=%04x, ar=%04x, [%d]-->",
+ printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
+ ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
nsh->dir ? "Response": "Request",
nsh->nametrid,
nsh->opcode,
@@ -546,31 +661,53 @@ void AliasHandleUdpNbtNS(
ntohs(nsh->ancount),
ntohs(nsh->nscount),
ntohs(nsh->arcount),
- (u_char *)p -(u_char *)nsh);
+ (u_char *)p -(u_char *)nsh
+ );
#endif
/* Question Entries */
if (ntohs(nsh->qdcount) !=0 ) {
- p = AliasHandleQuestion(ntohs(nsh->qdcount), (NBTNsQuestion *)p, &nbtarg );
+ p = AliasHandleQuestion(
+ ntohs(nsh->qdcount),
+ (NBTNsQuestion *)p,
+ pmax,
+ &nbtarg
+ );
}
/* Answer Resource Records */
if (ntohs(nsh->ancount) !=0 ) {
- p = AliasHandleResource(ntohs(nsh->ancount), (NBTNsResource *)p, &nbtarg );
+ p = AliasHandleResource(
+ ntohs(nsh->ancount),
+ (NBTNsResource *)p,
+ pmax,
+ &nbtarg
+ );
}
/* Authority Resource Recodrs */
if (ntohs(nsh->nscount) !=0 ) {
- p = AliasHandleResource(ntohs(nsh->nscount), (NBTNsResource *)p, &nbtarg );
+ p = AliasHandleResource(
+ ntohs(nsh->nscount),
+ (NBTNsResource *)p,
+ pmax,
+ &nbtarg
+ );
}
/* Additional Resource Recodrs */
if (ntohs(nsh->arcount) !=0 ) {
- p = AliasHandleResource(ntohs(nsh->arcount), (NBTNsResource *)p, &nbtarg );
+ p = AliasHandleResource(
+ ntohs(nsh->arcount),
+ (NBTNsResource *)p,
+ pmax,
+ &nbtarg
+ );
}
#ifdef DEBUG
PrintRcode(nsh->rcode);
#endif
- return;
+ return ((p == NULL) ? -1 : 0);
}
+
OpenPOWER on IntegriCloud