#
# validrcptto-iztaci.patch
#
# Aplica el parche validrcptto.cdb.patch de jms
# (https://qmail.jms1.net/patches/validrcptto.cdb.shtml)
# sobre el parche combinado de iztaci-qmail:
#
# auth_tls_force-tls_ext-todo_dnsmas512_queue-extra-log.patch
# (SHA256: 2bb7214a63340415e6982b31d6ce7815b9a3651c106441e3567f1fae7f336c45)
#

diff -Naur s/netqmail-1.06/Makefile work/netqmail-1.06/Makefile
--- s/netqmail-1.06/Makefile	2017-08-11 15:23:22.000000000 -0500
+++ work/netqmail-1.06/Makefile	2017-08-11 15:29:04.000000000 -0500
@@ -1561,14 +1561,14 @@
 load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
-open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
+open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
 fs.a auto_qmail.o base64.o socket.lib
 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
 	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
 	tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o  `cat \
+	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o  `cat \
 	socket.lib`
 
 qmail-smtpd.0: \
@@ -1580,7 +1580,7 @@
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
-exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h cdb.h uint32.h
 	./compile qmail-smtpd.c
 
 qmail-start: \
diff -Naur s/netqmail-1.06/qmail-smtpd.c work/netqmail-1.06/qmail-smtpd.c
--- s/netqmail-1.06/qmail-smtpd.c	2017-08-11 15:23:22.000000000 -0500
+++ work/netqmail-1.06/qmail-smtpd.c	2017-08-11 15:28:36.000000000 -0500
@@ -24,6 +24,8 @@
 #include "timeoutwrite.h"
 #include "commands.h"
 #include "wait.h"
+#include "strerr.h"
+#include "cdb.h"
 
 #define AUTHSLEEP 5
 
@@ -143,6 +145,11 @@
 stralloc bmf = {0};
 struct constmap mapbmf;
 
+int vrtfd = -1;
+int vrtcount = 0;
+int vrtlimit = 10;
+int vrtlog_do = 0;
+
 void setup()
 {
   char *x;
@@ -161,6 +168,9 @@
   if (bmfok == -1) die_control();
   if (bmfok)
     if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+
+    vrtfd = open_read("control/validrcptto.cdb");
+    if (-1 == vrtfd) if (errno != error_noent) die_control();
  
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
@@ -270,6 +280,72 @@
   return 0;
 }
 
+void vrtlog(a,b)
+const char *a;
+const char *b;
+{
+  if (vrtlog_do) strerr_warn2(a,b,0);
+}
+
+int vrtcheck()
+{
+  static char *rcptto = "qmail-smtpd: validrcptto RCPT TO: ";
+  static char *found = "qmail-smtpd: validrcptto found: ";
+  int j,k,r;
+  uint32 dlen;
+  stralloc laddr = {0};
+
+  stralloc user = {0};
+  stralloc adom = {0};
+  stralloc utry = {0};
+
+  if (-1 == vrtfd) return 1;
+
+  /* lowercase whatever we were sent */
+  if (!stralloc_copy(&laddr,&addr)) die_nomem() ;
+  case_lowerb(laddr.s,laddr.len);
+
+  vrtlog(rcptto,laddr.s,0);
+
+  /* exact match? */
+  r = cdb_seek(vrtfd,laddr.s,laddr.len-1,&dlen) ;
+  if (r>0) { vrtlog(found,laddr.s,0); return r; }
+
+  j = byte_rchr(laddr.s,laddr.len,'@');
+  if (j < laddr.len)
+  {
+    /* start "-default" search loop */
+    stralloc_copyb(&user,laddr.s,j) ;
+    stralloc_copyb(&adom,laddr.s+j,laddr.len-j-1);
+
+    while(1)
+    {
+      k = byte_rchr(user.s,user.len,'-');
+      if (k >= user.len) break ;
+
+      user.len = k+1;
+      stralloc_cats(&user,"default");
+
+      stralloc_copy(&utry,&user);
+      stralloc_cat (&utry,&adom);
+      stralloc_0(&utry);
+
+      r = cdb_seek(vrtfd,utry.s,utry.len-1,&dlen);
+      if (r>0) { vrtlog(found,utry.s,0); return r; }
+
+      user.len = k ;
+    }
+
+    /* try "@domain" */
+
+    r = cdb_seek(vrtfd,laddr.s+j,laddr.len-j-1,&dlen) ;
+    if (r>0) { vrtlog(found,laddr.s+j,0); return r; }
+  }
+
+  return 0;
+}
+
+
 int addrallowed()
 {
   int r;
@@ -405,12 +481,25 @@
   }
   else
     if (!addrallowed()) { err_nogateway(); return; }
+  if (!env_get("RELAYCLIENT") && !vrtcheck()) {
+    strerr_warn4("qmail-smtpd: not in validrcptto: ",addr.s,
+      " at ",remoteip,0);
+    if(vrtlimit && (++vrtcount >= vrtlimit)) {
+      strerr_warn2("qmail-smtpd: excessive validrcptto violations,"
+        " hanging up on ",remoteip,0);
+      die_vrt();
+    }
+    err_vrt();
+    return;
+  }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
   out("250 ok\r\n");
 }
 
+void err_vrt() { out("553 sorry, this recipient is not in my validrcptto list (#5.7.1)\r\n"); }
+void die_vrt() { out("421 too many invalid addresses, goodbye (#4.3.0)\r\n"); flush(); _exit(1); }
 
 int saferead(fd,buf,len) int fd; char *buf; int len;
 {
@@ -1033,9 +1122,17 @@
 int argc;
 char **argv;
 {
+  char *x ;
+  uint32 u;
   childargs = argv + 1;
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
+
+  x = env_get("VALIDRCPTTO_LIMIT");
+  if(x) { scan_ulong(x,&u); vrtlimit = (int) u; }
+  x = env_get("VALIDRCPTTO_LOG");
+  if(x) { scan_ulong(x,&u); vrtlog_do = (int) u; }
+
   setup();
   if (ipme_init() != 1) die_ipme();
   smtp_greet("220 ");
