Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Aug 2000 03:08:45 -0700 (PDT)
From:      Kris Kennaway <kris@hub.freebsd.org>
To:        audit@freebsd.org
Subject:   ether_line() patch
Message-ID:  <Pine.BSF.4.21.0008040306140.96614-100000@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
This patch fixes a minor overflow possibility in ether_line() (not really
a problem at all, it's basically academic) which uses sscanf and doesnt
specify a string length. I've replaced ether_line() with the version from
OpenBSD which doesn't use sscanf() at all.

Reviews, please!

Kris

Index: ether_addr.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/ether_addr.c,v
retrieving revision 1.11
diff -u -r1.11 ether_addr.c
--- ether_addr.c	2000/07/18 22:44:09	1.11
+++ ether_addr.c	2000/08/04 10:04:35
@@ -39,14 +39,15 @@
  */
 
 
-#include <stdio.h>
-#include <paths.h>
 #include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
+#include <net/ethernet.h>
 #include <sys/param.h>
 #include <sys/socket.h>
-#include <net/ethernet.h>
+#include <errno.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #ifdef YP
 #include <rpc/rpc.h>
 #include <rpcsvc/yp_prot.h>
@@ -57,6 +58,8 @@
 #define _PATH_ETHERS "/etc/ethers"
 #endif
 
+static char *_ether_aton __P((const char *, struct ether_addr *));
+
 /*
  * Parse a string of text containing an ethernet address and hostname
  * and separate it into its component parts.
@@ -66,28 +69,39 @@
 	struct ether_addr *e;
 	char *hostname;
 {
-        int i, o[6];
+	char *p;
+	size_t n;
 
-        i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2],
-                                              &o[3], &o[4], &o[5],
-					      hostname);
-	if (i != 7)
-                return (i);
-
-        for (i=0; i<6; i++)
-                e->octet[i] = o[i];
-        return (0);
+	/* Parse "xx:xx:xx:xx:xx:xx" */
+	if ((p = _ether_aton(l, e)) == NULL || (*p != ' ' && *p != '\t'))
+		goto bad;
+
+	/* Now get the hostname */
+	while (isspace(*p))
+		p++;
+	if (*p == '\0')
+		goto bad;
+	n = strcspn(p, " \t\n");
+	if (n >= MAXHOSTNAMELEN)
+		goto bad;
+	(void)strncpy(hostname, p, n);
+	hostname[n] = '\0';
+	return (0);
+
+bad:
+	errno = EINVAL;
+	return (-1);
 }
 
 /*
  * Convert an ASCII representation of an ethernet address to
  * binary form.
  */
-struct ether_addr *ether_aton(a)
+static char *_ether_aton(a, e)
 	const char *a;
+	struct ether_addr *e;
 {
         int i;
-	static struct ether_addr o;
 	unsigned int o0, o1, o2, o3, o4, o5;
 
         i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
@@ -95,14 +109,22 @@
         if (i != 6)
                 return (NULL);
 
-        o.octet[0]=o0;
-	o.octet[1]=o1;
-	o.octet[2]=o2;
-	o.octet[3]=o3;
-	o.octet[4]=o4;
-	o.octet[5]=o5;
+	e->octet[0]=o0;
+	e->octet[1]=o1;
+	e->octet[2]=o2;
+	e->octet[3]=o3;
+	e->octet[4]=o4;
+	e->octet[5]=o5;
+
+	return ((char *)e);
+}
+
+struct ether_addr *ether_aton(s)
+	const char *s;
+{
+	static struct ether_addr n;
 
-        return ((struct ether_addr *)&o);
+	return (_ether_aton(s, &n) ? &n : NULL);
 }
 
 /*
@@ -156,7 +178,7 @@
 				strlen(ether_a), &result, &resultlen)) {
 				continue;
 			}
-			strncpy(buf, result, resultlen);
+			strncpy(buf, result, resultlen - 1);
 			buf[resultlen] = '\0';
 			free(result);
 		}

--
In God we Trust -- all others must submit an X.509 certificate.
    -- Charles Forsythe <forsythe@alum.mit.edu>



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0008040306140.96614-100000>