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;