From gfb@vtamail.vta.com  Wed May 11 19:41:45 2005
Return-Path: <gfb@vtamail.vta.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id B600716A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 11 May 2005 19:41:45 +0000 (GMT)
Received: from vtamail.vta.com (vta.com [208.199.187.6])
	by mx1.FreeBSD.org (Postfix) with ESMTP id EC1A643D70
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 11 May 2005 19:41:44 +0000 (GMT)
	(envelope-from gfb@vtamail.vta.com)
Received: from vtamail.vta.com (localhost.vta.com [127.0.0.1])
	by vtamail.vta.com (8.12.9/8.12.9) with ESMTP id j4BJfibs062091
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 11 May 2005 15:41:44 -0400 (EDT)
	(envelope-from gfb@vtamail.vta.com)
Received: (from root@localhost)
	by vtamail.vta.com (8.13.1/8.12.9/Submit) id j4BJfi7x062089;
	Wed, 11 May 2005 15:41:44 -0400 (EDT)
Message-Id: <200505111941.j4BJfi7x062089@vtamail.vta.com>
Date: Wed, 11 May 2005 15:41:44 -0400 (EDT)
From: "Guy F. Boyd" <gfb@vta.com>
Reply-To: "Guy F. Boyd" <gfb@vta.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: /sbin/ipfw2 silently discards MAC addr arg with improper 
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         80913
>Category:       bin
>Synopsis:       [patch] /sbin/ipfw2 silently discards MAC addr arg with improper characters
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ipfw
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 11 19:50:02 GMT 2005
>Closed-Date:    Sun Jun 10 14:00:44 GMT 2007
>Last-Modified:  Sun Jun 10 14:00:44 GMT 2007
>Originator:     Guy F. Boyd
>Release:        FreeBSD 4.11-STABLE i386
>Organization:
<VTA Technologies INC Atlanta Ga USA 30324>
>Environment:
System: FreeBSD nyc-end 4.11-STABLE FreeBSD 4.11-STABLE #4: Tue May 10 
17:27:02 EDT 2005 root@nyc-end:/usr/src/sys/compile/NYC_END i386

	Dell Optiplex GX200, FreeBSD 4-11 STABLE, i386
>Description:

	/sbin/ipfw2 silently discards improperly formatted 6-byte Media 
	Access Controller address strings that contain ascii characters which 
	are outside of the range of the set of characters that correctly 
	represent 4-bit hex values. ipfw2 then processes the remaining 
	arguments into a firewall rule that may have unintended effects on the 
	total ruleset.

>How-To-Repeat:

	# create a default deny rule
	ipfw add 1000 deny all from any to any 

	# allow 1 client -- oops finger slipped on last '0' should be '0' not 'O'
	ipfw add 999 allow all from any to any mac any 08:00:5b:00:aO:ac

	# result:
	nyc-end# ipfw show |grep 999

	999 	22739	2004155		allow ip from any to any MAC any any

	arguably pilot error but ipfw should generate a syntax error
	in this case instead. 

>Fix:

	$FreeBSD: src/sbin/ipfw/ipfw2.c,v 1.4.2.23 2004/11/08 18:47:11 pjd Exp $

	Add argument format checking to src/sbin/ipfw/ipfw2.c  at add_mac() for
	string arguments containing ':' delimiter. Return errx() as syntax error
	for improperly formatted arguments. First pass at patch attached.

>Release-Note:
>Audit-Trail:
Adding to audit trail from misfiled PR ports/81027 (although it is
badly formatted, so the patches probably will not apply):

Date: Sat, 14 May 2005 12:29:19 -0400
From: "Guy F. Boyd" <gfb@vta.com>
 
 
 *** ipfw2.c.orig	Tue May 10 18:29:23 2005
 --- ipfw2.c	Tue May 10 19:33:26 2005
 ***************
 *** 2630,2649 ****
 --- 2630,2683 ----
 
   /*
    * Fetch and add the MAC address and type, with masks.
 This generates one or
    * two microinstructions, and returns the pointer to the
 last one.
    */
   static ipfw_insn *
   add_mac(ipfw_insn *cmd, int ac, char *av[])
   {
   	ipfw_insn_mac *mac;
 
 + /*
 +  * Check for invalid characters if ':' delimiter is
 detected in av[].
 +  * The rule may otherwise produce unintended results if it
 silently
 +  * discards the improperly formatted supplied mac address.
 +  */
 +
 + #define CHECK_VALID_MACADDR_CHARS
 + #ifdef CHECK_VALID_MACADDR_CHARS
 + 	int i,j;
 + 	for (i = 0; i < ac; i++)
 + 	{
 + 		if (strnstr(av[i], ":", sizeof(av[i])))
 + 		{
 + 			for (j = 0; j < strlen(av[i]); j++)
 + 			{
 + 				if (av[i][j] < '0')
 + 					errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 				if (av[i][j] > ':')
 + 				{
 + 					if (av[i][j] < 'A')
 + 						errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 					if (av[i][j] > 'F')
 + 					{
 + 						if (av[i][j] < 'a')
 + 							errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 						if (av[i][j] > 'f')
 + 							errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 					}
 + 				}
 + 			}
 + 		}
 + 	}
 + #endif CHECK_VALID_MACADDR_CHARS
 +
   	if (ac < 2)
   		errx(EX_DATAERR, "MAC dst src");
 
   	cmd->opcode = O_MACADDR2;
   	cmd->len = (cmd->len & (F_NOT | F_OR)) |
 F_INSN_SIZE(ipfw_insn_mac);
 
   	mac = (ipfw_insn_mac *)cmd;
   	get_mac_addr_mask(av[0], mac->addr, mac->mask);	/* dst */
   	get_mac_addr_mask(av[1], &(mac->addr[6]),
 &(mac->mask[6])); /* src */
   	return cmd;
 
 ------=_NextPart_000_0001_01C55880.8E704DF0
 Content-Type: application/octet-stream;
 	name="ipfw2.diff"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
 	filename="ipfw2.diff"
 
 *** ipfw2.c.orig	Tue May 10 18:29:23 2005
 --- ipfw2.c	Tue May 10 19:33:26 2005
 ***************
 *** 2630,2649 ****
 --- 2630,2683 ----
  =20
   /*
    * Fetch and add the MAC address and type, with masks. This generates =
 one or
    * two microinstructions, and returns the pointer to the last one.
    */
   static ipfw_insn *
   add_mac(ipfw_insn *cmd, int ac, char *av[])
   {
   	ipfw_insn_mac *mac;
  =20
 + /*
 +  * Check for invalid characters if ':' delimiter is detected in av[].
 +  * The rule may otherwise produce unintended results if it silently
 +  * discards the improperly formatted supplied mac address.
 +  */
 +=20
 + #define CHECK_VALID_MACADDR_CHARS
 + #ifdef CHECK_VALID_MACADDR_CHARS
 + 	int i,j;
 + 	for (i =3D 0; i < ac; i++)=20
 + 	{
 + 		if (strnstr(av[i], ":", sizeof(av[i])))=20
 + 		{
 + 			for (j =3D 0; j < strlen(av[i]); j++)=20
 + 			{
 + 				if (av[i][j] < '0')=20
 + 					errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 				if (av[i][j] > ':') =20
 + 				{
 + 					if (av[i][j] < 'A')=20
 + 						errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 					if (av[i][j] > 'F') =20
 + 					{
 + 						if (av[i][j] < 'a') =20
 + 							errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 						if (av[i][j] > 'f') =20
 + 							errx(EX_DATAERR, "Invalid MAC addr %s", av[i] );
 + 					}=09
 + 				}
 + 			}
 + 		}
 + 	}
 + #endif CHECK_VALID_MACADDR_CHARS
 +=20
   	if (ac < 2)
   		errx(EX_DATAERR, "MAC dst src");
  =20
   	cmd->opcode =3D O_MACADDR2;
   	cmd->len =3D (cmd->len & (F_NOT | F_OR)) | =
 F_INSN_SIZE(ipfw_insn_mac);
  =20
   	mac =3D (ipfw_insn_mac *)cmd;
   	get_mac_addr_mask(av[0], mac->addr, mac->mask);	/* dst */
   	get_mac_addr_mask(av[1], &(mac->addr[6]), &(mac->mask[6])); /* src */
   	return cmd;
 
 ------=_NextPart_000_0001_01C55880.8E704DF0--
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: arved 
Responsible-Changed-When: Tue Jun 7 17:14:03 GMT 2005 
Responsible-Changed-Why:  
Assign to ipfw Mailinglist 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80913 

From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: bug-followup@FreeBSD.org, gfb@vta.com,
	Maxim Konovalov <maxim@FreeBSD.org>
Cc:  
Subject: Re: bin/80913: [patch] /sbin/ipfw2 silently discards MAC addr arg
 with improper characters
Date: Thu, 03 May 2007 08:38:01 +0400

 This is a multi-part message in MIME format.
 --------------080506050005050409040606
 Content-Type: text/plain; charset=KOI8-R; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Hi, can you test the following patch? (for CURRENT or RELENG_6)
 
 -- 
 WBR, Andrey V. Elsukov
 
 --------------080506050005050409040606
 Content-Type: text/plain;
  name="ipfw2.c.diff.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw2.c.diff.txt"
 
 --- src/sbin/ipfw/ipfw2.c	Wed Apr 18 18:03:08 2007
 +++ src/sbin/ipfw/ipfw2.c	Wed May  2 20:05:20 2007
 @@ -47,6 +47,7 @@
  #include <unistd.h>
  #include <fcntl.h>
  
 +#include <net/ethernet.h>
  #include <net/if.h>
  #include <net/if_dl.h>
  #include <net/pfvar.h>
 @@ -4374,36 +4375,51 @@
  }
  
  static void
 -get_mac_addr_mask(char *p, uint8_t *addr, uint8_t *mask)
 +get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask)
  {
  	int i, l;
 +	char *ap, *ptr, *optr;
 +	struct ether_addr *mac;
 +	const char *macset = "0123456789abcdefABCDEF:";
  
 -	for (i=0; i<6; i++)
 +	if (strcmp(p, "any") == 0) {
 +		for (i = 0; i < ETHER_ADDR_LEN; i++)
  		addr[i] = mask[i] = 0;
 -	if (strcmp(p, "any") == 0)
  		return;
 +	}
  
 -	for (i=0; *p && i<6;i++, p++) {
 -		addr[i] = strtol(p, &p, 16);
 -		if (*p != ':') /* we start with the mask */
 -			break;
 -	}
 -	if (*p == '/') { /* mask len */
 -		l = strtol(p+1, &p, 0);
 -		for (i=0; l>0; l -=8, i++)
 -			mask[i] = (l >=8) ? 0xff : (~0) << (8-l);
 -	} else if (*p == '&') { /* mask */
 -		for (i=0, p++; *p && i<6;i++, p++) {
 -			mask[i] = strtol(p, &p, 16);
 -			if (*p != ':')
 -				break;
 +	optr = ptr = strdup(p);
 +	if ((ap = strsep(&ptr, "&/")) != NULL && *ap != 0) {
 +		l = strlen(ap);
 +		if (strspn(ap, macset) != l || (mac = ether_aton(ap)) == NULL)
 +			errx(EX_DATAERR, "Incorrect MAC address");
 +		bcopy(mac, addr, ETHER_ADDR_LEN);
 +	} else
 +		errx(EX_DATAERR, "Incorrect MAC address");
 +
 +	if (ptr != NULL) { /* we have mask? */
 +		if (p[ptr - optr - 1] == '/') { /* mask len */
 +			l = strtol(ptr, &ap, 10);
 +			if (*ap != 0 || l > ETHER_ADDR_LEN * 8 || l < 0)
 +				errx(EX_DATAERR, "Incorrect mask length");
 +			for (i = 0; l > 0 && i < ETHER_ADDR_LEN; l -=8, i++)
 +				mask[i] = (l >= 8) ? 0xff: (~0) << (8 - l);
 +		} else { /* mask */
 +			l = strlen(ptr);
 +			if (strspn(ptr, macset) != l ||
 +			   (mac = ether_aton(ptr)) == NULL)
 +				errx(EX_DATAERR, "Incorrect mask");
 +			bcopy(mac, mask, ETHER_ADDR_LEN);
  		}
 -	} else if (*p == '\0') {
 -		for (i=0; i<6; i++)
 +	} else { /* default mask: ff:ff:ff:ff:ff:ff */
 +		for (i = 0; i < ETHER_ADDR_LEN; i++)
  			mask[i] = 0xff;
  	}
 -	for (i=0; i<6; i++)
 +
 +	for (i = 0; i < ETHER_ADDR_LEN; i++)
  		addr[i] &= mask[i];
 +
 +	free(optr);
  }
  
  /*
 
 --------------080506050005050409040606--

From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: bug-followup@FreeBSD.org, gfb@vta.com,
	Maxim Konovalov <maxim@FreeBSD.org>
Cc:  
Subject: Re: bin/80913: [patch] /sbin/ipfw2 silently discards MAC addr arg
 with improper characters
Date: Thu, 03 May 2007 08:36:27 +0400

 This is a multi-part message in MIME format.
 --------------030401010501060202090501
 Content-Type: text/plain; charset=KOI8-R; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Hi, can you test the following patch?
 
 -- 
 WBR, Andrey V. Elsukov
 
 --------------030401010501060202090501
 Content-Type: text/plain;
  name="ipfw2.c.diff.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="ipfw2.c.diff.txt"
 
 --- src/sbin/ipfw/ipfw2.c	Wed Apr 18 18:03:08 2007
 +++ src/sbin/ipfw/ipfw2.c	Wed May  2 20:05:20 2007
 @@ -47,6 +47,7 @@
  #include <unistd.h>
  #include <fcntl.h>
  
 +#include <net/ethernet.h>
  #include <net/if.h>
  #include <net/if_dl.h>
  #include <net/pfvar.h>
 @@ -4374,36 +4375,51 @@
  }
  
  static void
 -get_mac_addr_mask(char *p, uint8_t *addr, uint8_t *mask)
 +get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask)
  {
  	int i, l;
 +	char *ap, *ptr, *optr;
 +	struct ether_addr *mac;
 +	const char *macset = "0123456789abcdefABCDEF:";
  
 -	for (i=0; i<6; i++)
 +	if (strcmp(p, "any") == 0) {
 +		for (i = 0; i < ETHER_ADDR_LEN; i++)
  		addr[i] = mask[i] = 0;
 -	if (strcmp(p, "any") == 0)
  		return;
 +	}
  
 -	for (i=0; *p && i<6;i++, p++) {
 -		addr[i] = strtol(p, &p, 16);
 -		if (*p != ':') /* we start with the mask */
 -			break;
 -	}
 -	if (*p == '/') { /* mask len */
 -		l = strtol(p+1, &p, 0);
 -		for (i=0; l>0; l -=8, i++)
 -			mask[i] = (l >=8) ? 0xff : (~0) << (8-l);
 -	} else if (*p == '&') { /* mask */
 -		for (i=0, p++; *p && i<6;i++, p++) {
 -			mask[i] = strtol(p, &p, 16);
 -			if (*p != ':')
 -				break;
 +	optr = ptr = strdup(p);
 +	if ((ap = strsep(&ptr, "&/")) != NULL && *ap != 0) {
 +		l = strlen(ap);
 +		if (strspn(ap, macset) != l || (mac = ether_aton(ap)) == NULL)
 +			errx(EX_DATAERR, "Incorrect MAC address");
 +		bcopy(mac, addr, ETHER_ADDR_LEN);
 +	} else
 +		errx(EX_DATAERR, "Incorrect MAC address");
 +
 +	if (ptr != NULL) { /* we have mask? */
 +		if (p[ptr - optr - 1] == '/') { /* mask len */
 +			l = strtol(ptr, &ap, 10);
 +			if (*ap != 0 || l > ETHER_ADDR_LEN * 8 || l < 0)
 +				errx(EX_DATAERR, "Incorrect mask length");
 +			for (i = 0; l > 0 && i < ETHER_ADDR_LEN; l -=8, i++)
 +				mask[i] = (l >= 8) ? 0xff: (~0) << (8 - l);
 +		} else { /* mask */
 +			l = strlen(ptr);
 +			if (strspn(ptr, macset) != l ||
 +			   (mac = ether_aton(ptr)) == NULL)
 +				errx(EX_DATAERR, "Incorrect mask");
 +			bcopy(mac, mask, ETHER_ADDR_LEN);
  		}
 -	} else if (*p == '\0') {
 -		for (i=0; i<6; i++)
 +	} else { /* default mask: ff:ff:ff:ff:ff:ff */
 +		for (i = 0; i < ETHER_ADDR_LEN; i++)
  			mask[i] = 0xff;
  	}
 -	for (i=0; i<6; i++)
 +
 +	for (i = 0; i < ETHER_ADDR_LEN; i++)
  		addr[i] &= mask[i];
 +
 +	free(optr);
  }
  
  /*
 
 --------------030401010501060202090501--

From: "Guy F. Boyd" <gfb@vta.com>
To: "'Andrey V. Elsukov'" <bu7cher@yandex.ru>, <bug-followup@FreeBSD.org>,
        "'Maxim Konovalov'" <maxim@FreeBSD.org>
Cc:  
Subject: RE: bin/80913: [patch] /sbin/ipfw2 silently discards MAC addr arg with improper characters
Date: Thu, 3 May 2007 10:25:18 -0400

 Sure, thanks. May take a few days, ${real_job} and ${dead_car} are conspiring to
 make ${time} <=0 right now.
 
 Guy Boyd
 <gfb@vta.com>
 
 > -----Original Message-----
 > From: Andrey V. Elsukov [mailto:bu7cher@yandex.ru]
 > Sent: Thursday, May 03, 2007 12:38 AM
 > To: bug-followup@FreeBSD.org; gfb@vta.com; Maxim Konovalov
 > Subject: Re: bin/80913: [patch] /sbin/ipfw2 silently discards
 > MAC addr arg with improper characters
 >
 >
 > Hi, can you test the following patch? (for CURRENT or RELENG_6)
 >
 > --
 > WBR, Andrey V. Elsukov
 >
 
State-Changed-From-To: open->patched 
State-Changed-By: maxim 
State-Changed-When: Wed May 9 18:32:01 UTC 2007 
State-Changed-Why:  
Andrey's patch was committed to HEAD.  Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80913 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/80913: commit references a PR
Date: Wed,  9 May 2007 18:31:56 +0000 (UTC)

 maxim       2007-05-09 18:31:49 UTC
 
   FreeBSD src repository
 
   Modified files:
     sbin/ipfw            ipfw2.c 
   Log:
   o Teach get_mac_addr_mask() to not silently accept incorrect MAC
   addresses.
   o Swap a couple of magic 6s by ETHER_ADDR_LEN.
   
   PR:             bin/80913
   Submitted by:   Andrey V. Elsukov
   MFC after:      1 month
   
   Revision  Changes    Path
   1.105     +39 -23    src/sbin/ipfw/ipfw2.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: maxim 
State-Changed-When: Sun Jun 10 14:00:24 UTC 2007 
State-Changed-Why:  
Merged to RELENG_6. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80913 
>Unformatted:
