Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Dec 2003 00:23:11 +0700
From:      "Roman Y. Bogdanov" <brj@vzletka.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   http://www.freebsd.org/cgi/query-pr.cgi?pr=60293
Message-ID:  <52609734843.20031230002311@vzletka.net>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]

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

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
From:    Maxim Artemev <bert_raccoon@freemail.ru>
To:      brj@vzletka.net <brj@vzletka.net>
Date:    Monday, December 29, 2003, 11:40:25 PM
Subject: kern/60293: FreeBSD arp poison patch
Files:   if_ether.c.patch
--====----====----====----====----====----====----====----====----====----===--
Hello.

Here the updated patch (v1.2) for arp poison.

Feautures:
 * Mark as 'static' entry only via sysctl variable. Not default as it was in
old version.
 * Timeout of verifying.



P.S.
Can be forward to FreeBSD bugs team.

---
WBR, Max Artemev
úáï íã îôô, éÔÅÌ. íÏÓË×Á. http://www.ntt.ru/
[http://freecap.ru/] [http://theraccoons.ru/]

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

-- 
 Roman Y. Bogdanov
[-- Attachment #2 --]
--- if_ether.c.orig	Mon Dec  8 14:01:47 2003
+++ if_ether.c	Tue Dec  9 11:30:04 2003
@@ -40,6 +40,10 @@
  *	add "inuse/lock" bit (or ref. count) along with valid bit
  */
 
+/*
+ * ARP-posion Antidote code (c) 2003 by Bert <bert@furry.ru>
+ */
+
 #include "opt_inet.h"
 #include "opt_bdg.h"
 
@@ -82,6 +86,11 @@
 static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
 static int arpt_down = 20;	/* once declared down, don't send for 20 sec */
 
+static int arp_secure = 1;
+static int arpt_debug = 0;
+static int arpt_static = 0;
+
+
 SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW,
 	   &arpt_prune, 0, "");
 SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, 
@@ -96,6 +105,10 @@
 	struct	rtentry *la_rt;
 	struct	mbuf *la_hold;		/* last packet until resolved/timeout */
 	long	la_asked;		/* last time we QUERIED for this addr */
+	long	la_ack;			/* Arp reply acknowledgement flag */	
+        u_char  check_eth[ETHER_ADDR_LEN]; /* Original MAC address */
+	u_char  new_eth[ETHER_ADDR_LEN];   /* New MAC address */
+	struct in_addr	check_ip;
 #define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
 };
 
@@ -115,6 +128,19 @@
 SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
 	   &arp_proxyall, 0, "");
 
+/* sysctl arp antidote variable. Default is "on" */
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_antidote, CTLFLAG_RW,
+	   &arp_secure, 0, "Enable antidote for ARP poison");
+	   
+/* sysctl arp debug variable. Default is "off" */
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_debug, CTLFLAG_RW,
+	   &arpt_debug, 0, "Dump arp packets");
+
+/* sysctl arp static variable. Default is "off" */
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_static, CTLFLAG_RW,
+          &arpt_static, 0, "Make ARP entry static if poisoning detected");
+
+
 static void	arp_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
 static void	arprequest __P((struct ifnet *,
 			struct in_addr *, struct in_addr *, u_char *));
@@ -149,8 +175,14 @@
 	while ((ola = la) != 0) {
 		register struct rtentry *rt = la->la_rt;
 		la = la->la_le.le_next;
-		if (rt->rt_expire && rt->rt_expire <= time_second)
-			arptfree(ola); /* timer has expired, clear */
+		if ((rt->rt_expire && rt->rt_expire <= time_second) || ola->la_ack == 1)
+		{
+		    if (ola->la_ack && arpt_debug) {
+			log(LOG_INFO, "arp: Timeout of verifying for MAC address %*D.\n",
+			    sizeof(ola->new_eth), (u_char *)&ola->new_eth, ":");
+		    }
+		    arptfree(ola); /* timer has expired, clear */
+		}
 	}
 	splx(s);
 }
@@ -663,14 +695,77 @@
 			    ifp->if_name, ifp->if_unit);
 		    goto reply;
 		}
+		
+		/* Print announced packet if debug is enabled */
+		if (sdl->sdl_alen && arpt_debug) {
+                  log(LOG_INFO, "arp: Got MAC address %*D from %s via %s%d\n", 
+		      ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+		      inet_ntoa(isaddr),
+		      ifp->if_name, ifp->if_unit);
+		}
+		
+		
+		if (arp_secure && rt->rt_expire && 
+		   sdl->sdl_alen && la->la_ack) 
+		{
+		    int b_equals = (bcmp(ar_sha(ah), &la->check_eth, sdl->sdl_alen) == 0) &&
+        		(bcmp(ar_sha(ah), &la->new_eth, sdl->sdl_alen) == 0);
+	   		
+		  /* Check possible reply with old MAC-address*/
+		  if (b_equals) {
+		  /* Both addresses are equal. MAC address verified */
+		    if (arpt_debug)
+                      log(LOG_INFO, "arp: MAC address %*D from %s verified.\n",
+		          ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+		          inet_ntoa(isaddr));
+		    la->la_ack = 0;
+		  } else {
+		    /* Reply was with another MAC */
+                    log(LOG_ERR, "arp: ARP poison detected!, attacker from %*D trying to infect %*D (%s) in my ARP table!\n",
+		      sdl->sdl_alen, (u_char *)&la->new_eth, ":",
+		      sdl->sdl_alen, (u_char *)&la->check_eth, ":",
+		      inet_ntoa(la->check_ip));
+		     if (arpt_static)
+		       rt->rt_expire = 0;
+		      
+		     /* Clear cached MAC */
+		     bzero(&la->check_eth, sizeof(la->check_eth));
+		     la->la_ack = 0; 
+                     m_free(m);
+                     return;
+		  }
+		}
+		
 		if (sdl->sdl_alen &&
 		    bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
-			if (rt->rt_expire)
-			    log(LOG_INFO, "arp: %s moved from %*D to %*D on %s%d\n",
-				inet_ntoa(isaddr),
-				ifp->if_addrlen, (u_char *)LLADDR(sdl), ":",
-				ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
-				ifp->if_name, ifp->if_unit);
+			if (rt->rt_expire) {
+			    if (arp_secure) {
+                              if (la->la_ack == 0) {
+			        if (arpt_debug)
+                                  log(LOG_INFO, "arp: Got new MAC address %*D from %s (%s%d). Now verifying.\n",
+				      ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+				      inet_ntoa(isaddr),
+				      ifp->if_name, ifp->if_unit);
+				  /* Check old MAC address for alive */
+                                  arprequest(ifp, &myaddr, &isaddr, IF_LLADDR(ifp));
+				  (void)memcpy((u_char *)&la->check_eth, LLADDR(sdl), sdl->sdl_alen);
+				  (void)memcpy((u_char *)&la->new_eth, (u_char *)ar_sha(ah), sdl->sdl_alen);
+				
+				  la->check_ip.s_addr = isaddr.s_addr;
+				
+                                  la->la_ack++;
+				  la->la_asked++;
+                                  m_free(m);
+                                  return;
+			      }
+			    } else {
+			       log(LOG_INFO, "arp: %s moved from %*D to %*D on %s%d\n",
+			          inet_ntoa(isaddr),
+			  	  ifp->if_addrlen, (u_char *)LLADDR(sdl), ":",
+				  ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+				  ifp->if_name, ifp->if_unit);
+			    }
+			}
 			else {
 			    log(LOG_ERR,
 				"arp: %*D attempts to modify permanent entry for %s on %s%d\n",


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