shithub: riscv

Download patch

ref: fd277c053d8cbc1b9bbd930670e032c1427ea0a8
parent: 50e617f8b60b61e98538cb8ccb09958740defb9a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Feb 11 18:40:34 EST 2019

upas/smtpd: implement ipv6 support for ip blacklist, replace v4parsecidr() with parseipandmask()

--- a/sys/src/cmd/upas/smtp/greylist.c
+++ b/sys/src/cmd/upas/smtp/greylist.c
@@ -42,13 +42,7 @@
 static int
 onwhitelist(void)
 {
-	int lnlen;
-	char *line, *parse, *p;
-	char input[128];
-	uchar *mask;
-	uchar mask4[IPaddrlen], addr4[IPaddrlen];
-	uchar rmask[IPaddrlen], addr[IPaddrlen];
-	uchar ipmasked[IPaddrlen], addrmasked[IPaddrlen];
+	char *line, *p;
 	Biobuf *wl;
 
 	wl = Bopen(whitelist, OREAD);
@@ -55,41 +49,13 @@
 	if (wl == nil)
 		return 0;
 	while ((line = Brdline(wl, '\n')) != nil) {
-		lnlen = Blinelen(wl);
-		line[lnlen-1] = '\0';		/* clobber newline */
-
+		line[Blinelen(wl)-1] = '\0';		/* clobber newline */
 		p = strpbrk(line, " \t");
 		if (p)
 			*p = 0;
 		if (line[0] == '#' || line[0] == 0)
 			continue;
-
-		/* default mask is /24 (v4) or /128 (v6) for bare IP */
-		parse = line;
-		if (strchr(line, '/') == nil) {
-			strecpy(input, input + sizeof input - 5, line);
-			if (strchr(line, ':') != nil)	/* v6? */
-				strcat(input, "/128");
-			else if (strchr(line, '.') != nil)
-				strcat(input, "/24");	/* was /32 */
-			parse = input;
-		}
-		mask = rmask;
-		if (strchr(line, ':') != nil) {		/* v6? */
-			parseip(addr, parse);
-			p = strchr(parse, '/');
-			if (p != nil)
-				parseipmask(mask, p);
-			else
-				mask = IPallbits;
-		} else {
-			v4parsecidr(addr4, mask4, parse);
-			v4tov6(addr, addr4);
-			v4tov6(mask, mask4);
-		}
-		maskip(addr, mask, addrmasked);
-		maskip(rsysip, mask, ipmasked);
-		if (equivip6(ipmasked, addrmasked))
+		if(ipcheck(line))
 			break;
 	}
 	Bterm(wl);
--- a/sys/src/cmd/upas/smtp/mkfile
+++ b/sys/src/cmd/upas/smtp/mkfile
@@ -1,5 +1,4 @@
 </$objtype/mkfile
-<../mkupas
 
 TARG = smtpd\
 	smtp\
@@ -55,3 +54,5 @@
 
 ../common/libcommon.a$O:
 	cd ../common && mk
+
+<../mkupas
--- a/sys/src/cmd/upas/smtp/smtpd.c
+++ b/sys/src/cmd/upas/smtp/smtpd.c
@@ -238,6 +238,19 @@
 	return n;
 }
 
+int
+ipcheck(char *s)
+{
+	uchar ip[IPaddrlen], mask[IPaddrlen];
+	uchar net[IPaddrlen], rnet[IPaddrlen];
+
+	if(parseipandmask(ip, mask, s, strchr(s, '/')) == -1)
+		return 0;
+	maskip(ip, mask, net);
+	maskip(rsysip, mask, rnet);
+	return ipcmp(net, rnet) == 0;
+}
+
 void
 reset(void)
 {
@@ -611,8 +624,7 @@
 		 * if not, perhaps a later entry's domain will.
 		 */
 		mentioned = 1;
-		if (parseip(dnsip, snd->domain) != -1 &&
-		    memcmp(rsysip, dnsip, IPaddrlen) == 0)
+		if (parseip(dnsip, snd->domain) != -1 && ipcmp(rsysip, dnsip) == 0)
 			return 1;
 		/*
 		 * NB: nt->line links form a circular list(!).
@@ -622,9 +634,8 @@
 		if (first == nil)
 			continue;
 		do {
-			if (strcmp(nt->attr, "ip") == 0 &&
-			    parseip(dnsip, nt->val) != -1 &&
-			    memcmp(rsysip, dnsip, IPaddrlen) == 0)
+			if (strcmp(nt->attr, "ip") == 0
+			&&  parseip(dnsip, nt->val) != -1 && ipcmp(rsysip, dnsip) == 0)
 				matched = 1;
 			next = nt->line;
 			free(nt);
--- a/sys/src/cmd/upas/smtp/smtpd.h
+++ b/sys/src/cmd/upas/smtp/smtpd.h
@@ -38,6 +38,8 @@
 extern	List	rcvers;
 extern	uchar	rsysip[];
 
+int	ipcheck(char*);
+
 void	addbadguy(char*);
 void	auth(String *, String *);
 int	blocked(String*);
--- a/sys/src/cmd/upas/smtp/spam.c
+++ b/sys/src/cmd/upas/smtp/spam.c
@@ -44,10 +44,8 @@
 static	int	hisaction;
 static	List	ourdoms;
 static	List 	badguys;
-static	ulong	v4peerip;
 
 static	char*	getline(Biobuf*);
-static	int	cidrcheck(char*);
 
 static int
 findkey(char *val, Keyword *p)
@@ -110,11 +108,7 @@
 	char *cp, *p;
 	String *s;
 	char buf[512];
-	uchar addr[4];
 
-	v4parseip(addr, nci->rsys);
-	v4peerip = nhgetl(addr);
-
 	trusted = istrusted(nci->rsys);
 	hisaction = getaction(nci->rsys, "ip");
 	if(debug){
@@ -149,8 +143,10 @@
 				dom = strdup(p);
 			break;
 		case OURNETS:
-			if (trusted == 0)
-				trusted = cidrcheck(p);
+			while(trusted == 0 && *p){
+				trusted = ipcheck(p);
+				p += strlen(p) + 1;
+			}
 			break;
 		case OURDOMS:
 			while(*p){
@@ -398,44 +394,6 @@
 	return rv;
 }
 
-/* this is a v4 only check */
-static int
-cidrcheck(char *cp)
-{
-	char *p;
-	ulong a, m;
-	uchar addr[IPv4addrlen];
-	uchar mask[IPv4addrlen];
-
-	if(v4peerip == 0)
-		return 0;
-
-	/* parse a list of CIDR addresses comparing each to the peer IP addr */
-	while(cp && *cp){
-		v4parsecidr(addr, mask, cp);
-		a = nhgetl(addr);
-		m = nhgetl(mask);
-		/*
-		 * if a mask isn't specified, we build a minimal mask
-		 * instead of using the default mask for that net.  in this
-		 * case we never allow a class A mask (0xff000000).
-		 */
-		if(strchr(cp, '/') == 0){
-			m = 0xff000000;
-			p = cp;
-			for(p = strchr(p, '.'); p && p[1]; p = strchr(p + 1, '.'))
-				m = (m>>8)|0xff000000;
-
-			/* force at least a class B */
-			m |= 0xffff0000;
-		}
-		if((v4peerip & m) == a)
-			return 1;
-		cp += strlen(cp) + 1;
-	}		
-	return 0;
-}
-
 int
 isbadguy(void)
 {
@@ -443,7 +401,7 @@
 
 	/* check if this IP address is banned */
 	for(l = badguys.first; l; l = l->next)
-		if(cidrcheck(s_to_c(l->p)))
+		if(ipcheck(s_to_c(l->p)))
 			return 1;
 
 	return 0;