Herrm, forgot the attachment (tm).

----- Forwarded message from Jose Celestino <[EMAIL PROTECTED]> -----

Date: Mon, 21 Oct 2002 12:00:37 +0100
From: Jose Celestino <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
Subject: verifyrcpt
Message-ID: <[EMAIL PROTECTED]>
Mail-Followup-To: [EMAIL PROTECTED]
User-Agent: Mutt/1.5.1i

Hi, I altered John Morrissey's patch to reduce the ldap connections to a
sustainable level.

It is not hammering on the ldap server anymore for every connection, the
constmap (is domain in locals?) is previous to anything else and if any
local check is ok then it returns 1 just there.

That is fine if I imagine the number of bounces we receive (mailer-daemon@local,
postmaster@local, etc...).

I also added a sleep :))

This may be of use to someone....

-- 
Jose Celestino <[EMAIL PROTECTED]> SysAdmin::SAPO.pt http://www.sapo.pt
-----------------------------------------------------
"Lately, the only thing keeping me from becoming a serial killer is my distaste
for manual labor."        -- Dilbert

----- End forwarded message -----

-- 
Jose Celestino <[EMAIL PROTECTED]> SysAdmin::SAPO.pt http://www.sapo.pt
-----------------------------------------------------
"Lately, the only thing keeping me from becoming a serial killer is my distaste
for manual labor."        -- Dilbert
diff -N -c -r qmail-1.03/qmail-smtpd.c qmail-1.03.japc/qmail-smtpd.c
*** qmail-1.03/qmail-smtpd.c    2002-10-19 17:27:20.000000000 +0100
--- qmail-1.03.japc/qmail-smtpd.c       2002-10-19 17:57:41.000000000 +0100
***************
*** 33,38 ****
--- 33,52 ----
  SSL *ssl = NULL;
  stralloc clientcert = {0};
  #endif
+ #ifdef VERIFY_RCPT
+ # include <pwd.h>
+ # include <sys/types.h>
+ # include <sys/stat.h>
+ # include <unistd.h>
+ # include "auto_usera.h"
+ # include "auto_break.h"
+ # include "constmap.h"
+ # include "qlx.h"
+ # include "qmail-ldap.h"
+ # include "qldap-errno.h"
+ # include "qldap-ldaplib.h"
+ # include "qldap-debug.h"
+ #endif
  
  #define MAXHOPS 100
  unsigned int databytes = 0;
***************
*** 157,163 ****
  void err_deny() { out("553 sorry, mail from your location is administratively denied 
(#5.7.1)\r\n"); }
  void err_badrcptto() { out("553 sorry, mail to that recipient is not accepted 
(#5.7.1)\r\n"); }
  void err_554msg(arg) char *arg; { out("554 sorry, "); out(arg); out("\r\n"); 
/*logstring(3,"message denied because");*/ logstring(3,arg); logflush(3); }
! 
  
  stralloc greeting = {0};
  
--- 171,180 ----
  void err_deny() { out("553 sorry, mail from your location is administratively denied 
(#5.7.1)\r\n"); }
  void err_badrcptto() { out("553 sorry, mail to that recipient is not accepted 
(#5.7.1)\r\n"); }
  void err_554msg(arg) char *arg; { out("554 sorry, "); out(arg); out("\r\n"); 
/*logstring(3,"message denied because");*/ logstring(3,arg); logflush(3); }
! #ifdef VERIFY_RCPT
! void err_ldaplookup() { out("451 Temporary directory failure, try again later 
(#4.3.0)\r\n"); logline(3,"temporary failure on LDAP lookup for SMTP RCPT command"); }
! void err_nosuchuser() { out("550-That e-mail address does not exist (#5.7.1)\r\n"); }
! #endif
  
  stralloc greeting = {0};
  
***************
*** 701,707 ****
--- 718,950 ----
    out("250 ok\r\n");
  }
  
+ #ifdef VERIFY_RCPT
+ int valid_rcpt()
+ {
+   int at,i;
+   struct passwd *pw = {0};
+   struct stat st;
+   stralloc filter = {0}, username = {0}, alias_path = {0}, locals = {0};
+   struct constmap maplocals;
+   searchinfo search = {0};
+   int ret = -1, dash = 0;
+   char *r;
+   char *s;
+   int len;
+   stralloc dash_mailaddr = {0};
+   extern stralloc qldap_objectclass;
+   int qldap_localdelivery=1; /* a universal truth -- japc */
+ 
+   /* We only want to verify addresses that we're sure are going to be
+    * locally delivered; if we can't verify (for sure) that it's local,
+    * then assume it's good so we don't unduly reject mail.
+    */
+ 
+   /* read locals */
+   if (control_readfile(&locals, "control/locals", 0) != 1)
+     return 1;
+   if (! constmap_init(&maplocals, locals.s, locals.len, 0))
+     return 1;
+ 
+   /* if the e-mail address @domain is not in locals then let it pass */
+   at = str_rchr(addr.s, '@');
+   if (! constmap(&maplocals, addr.s + at + 1, addr.len - at - 2)) {
+     constmap_free(&maplocals);
+     return 1;
+   }
+   /* clean */
+   constmap_free(&maplocals);
+ 
+   at = 0;
+   s = addr.s;
+   len = addr.len;
+   for (at = len - 1; s[at] != '@' && at >= 0 ; at--) ;
+   /* handels also mail with 2 @ */
+     /* at = index to last @ sign in mail address */
+     /* s = mailaddress, len = lenght of address */
+     /* i = position of current '-' */
+   i = at;
+   do {
+     r = addr.s;
+     dash = i;
+     if (qldap_localdelivery) {
+       if (! stralloc_copyb(&username, r, dash)) die_nomem();
+       if (! stralloc_0(&username)) die_nomem();
+       if (getpwnam(username.s) != 0)
+         return 1;
+     }
+ 
+     if (pw = getpwnam(auto_usera)) {
+       if (! stralloc_copys(&alias_path, pw->pw_dir)) die_nomem();
+       if (! stralloc_cats(&alias_path, "/.qmail-"))  die_nomem();
+       if (! stralloc_catb(&alias_path, r, dash)) die_nomem();
+       if (! stralloc_0(&alias_path))                 die_nomem();
+ 
+       if (stat(alias_path.s, &st) != -1)
+         return 1;
+     }
+     if (pw = getpwnam(auto_usera)) {
+       if (! stralloc_copys(&alias_path, pw->pw_dir)) die_nomem();
+       if (! stralloc_cats(&alias_path, "/.qmail-"))  die_nomem();
+       if (! stralloc_catb(&alias_path, r, dash)) die_nomem();
+       if (! stralloc_cats(&alias_path, "-default"))  die_nomem();
+       if (! stralloc_0(&alias_path))                 die_nomem();
+ 
+       if (stat(alias_path.s, &st) != -1)
+         return  1;
+     }
+ 
+     /* Nothing else found it, check .qmail-default. */
+     if (pw || (pw = getpwnam(auto_usera))) {
+       if (! stralloc_copys(&alias_path, pw->pw_dir))       die_nomem();
+       if (! stralloc_cats(&alias_path, "/.qmail-default")) die_nomem();
+       if (! stralloc_0(&alias_path))                       die_nomem();
+ 
+       if (stat(alias_path.s, &st) != -1)
+         return 1;
+       }
+       while ( i != 0 ) {
+         --i;
+         if ( s[i] == *auto_break ) break;
+       }
+ 
+   } while ( i != 0 );
+ 
+   /* init_ldap only after the domain check to prevent
+      unneeded ldap conns -- japc */
+   if (init_ldap(&qldap_localdelivery, 0, 0, 0, 0, 0, 0) == -1) {
+     err_ldaplookup();
+     qldap_close();
+     return -1;
+   }
+ 
+   if (qldap_open() != 0) {
+     err_ldaplookup();
+     qldap_close();
+     return -1;
+   }
+ 
+   /* escape any weird characters in address */
+   if (!escape_forldap(&addr) ) { qldap_close(); _exit(QLX_NOMEM); };
+ 
+   /* build an ldap search filter for this address */
+   build_mail_filter(&filter, &addr, die_nomem);
+   log(16, "ldapfilter: '%s'\n", filter.s);
+   search.filter = filter.s;
+ 
+   /* do the lookup with search.filter */
+   if (qldap_lookup_orig(&search, 0, 0, 0) == 0) {
+     qldap_close();
+     return 1; /* it found something */
+   }
+ 
+   if (qldap_errno != LDAP_NOSUCH) {
+     qldap_close();
+     return -1;
+   }
+ 
+   /* a little bit more detailed ldap queries */
+   at = 0;
+   s = addr.s;
+   len = addr.len;
+   ret = -1;
+   for (at = len - 1; s[at] != '@' && at >= 0 ; at--) ;
+   /* handels also mail with 2 @ */
+     /* at = index to last @ sign in mail address */
+     /* s = mailaddress, len = lenght of address */
+     /* i = position of current '-' */
+   i = at;
+   do {
+     /* this handles the "catch all" and "-default" extension */
+         /* but also the normal eMail address */
+ 
+     /* build the search string for the email address */
+     if (!stralloc_copys(&filter,"(" ) ) _exit(QLX_NOMEM);
+     /* optional objectclass */
+     if ( qldap_objectclass.len ) {
+       if (!stralloc_cats(&filter,"&(")) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&filter,LDAP_OBJECTCLASS)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM);
+       if (!stralloc_cat(&filter,&qldap_objectclass)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM);
+     } /* end */
+ 
+     /* mail address */
+     if (!stralloc_cats(&filter,"|(")) _exit(QLX_NOMEM);
+     if (!stralloc_cats(&filter,LDAP_MAIL)) _exit(QLX_NOMEM);
+     if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM);
+     /* username till current '-' */
+     if (!stralloc_catb(&filter,s, i)) _exit(QLX_NOMEM);
+     if ( i != at ) { /* do not append catchall in the first round */
+       /* catchall or default */
+       if ( i != 0 ) /* add '-' */
+         if (!stralloc_cats(&filter,auto_break)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM);
+     }
+     /* @damin.com */
+     if (!stralloc_catb(&filter,s+at, len-at)) _exit(QLX_NOMEM);
+ 
+     /* mailalternate address */
+     if (!stralloc_cats(&filter,")(")) _exit(QLX_NOMEM);
+     if (!stralloc_cats(&filter,LDAP_MAILALTERNATE)) _exit(QLX_NOMEM);
+     if (!stralloc_cats(&filter,"=")) _exit(QLX_NOMEM);
+     /* username till current '-' */
+     if (!stralloc_catb(&filter,s, i)) _exit(QLX_NOMEM);
+     if ( i != at ) { /* do not append catchall in the first round */
+       /* catchall or default */
+       if ( i != 0 ) /* add '-' */
+         if (!stralloc_cats(&filter,auto_break)) _exit(QLX_NOMEM);
+       if (!stralloc_cats(&filter,LDAP_CATCH_ALL)) _exit(QLX_NOMEM);
+     }
+     /* @domain.com */
+     if (!stralloc_catb(&filter,s+at, len-at)) _exit(QLX_NOMEM);
+     if (!stralloc_cats(&filter,"))")) _exit(QLX_NOMEM);
+ 
+     /* optional objectclass */
+     if ( qldap_objectclass.len ) {
+       if (!stralloc_cats(&filter,")")) _exit(QLX_NOMEM);
+     } /* end */
+     if (!stralloc_0(&filter)) _exit(QLX_NOMEM);
+ 
+     log(16, "ldapfilter: '%s'\n", filter.s);
+     search.filter = filter.s;
+     search.bindpw = 0;    /* rebind off */
+ 
+     /* do the search for the email address */
+     /* do the search */
+     if ((ret = qldap_lookup_orig(&search, 0, 0, 0)) == 0) {
+       qldap_close();
+       return 1;
+     }
+ 
+     if ( ret == 0 || i == 0 ) break; /* something found or nothing found */
+ #ifdef DASH_EXT
+     /* XXX if mail starts with a - it will probably not work as expected */
+     while ( i != 0 ) {
+       i--;
+       if ( s[i] == *auto_break ) break;
+     }
+ #else
+     /* normal qmail-ldap behavior test for [EMAIL PROTECTED] and
+        [EMAIL PROTECTED] */
+     i = 0;
+ #endif
+ 
+   } while ( ret != 0 && qldap_errno == LDAP_NOSUCH );
+ 
+   alloc_free(filter.s); filter.s = 0;
+ 
+   /* If we've fallen through to here, then we didn't find the user. */
+   qldap_close();
+   return 0;
+ }
+ #endif /* VERIFY_RCPT */
+ 
  void smtp_rcpt(arg) char *arg; {
+ #ifdef VERIFY_RCPT
+   int verifyrcpt_toggle = 0;
+ #endif
+ 
    if (!seenmail) { err_wantmail(); return; }
    logpid(3); logstring(3,"remote sent 'rcpt to' ="); logstring(3,arg); logflush(3);
    if (!addrparse(arg))
***************
*** 803,808 ****
--- 1041,1063 ----
  #endif
  
    } /* else from if relayclient */
+ 
+ #ifdef VERIFY_RCPT
+   control_readint(&verifyrcpt_toggle, "control/verifyrcptto");
+ 
+   if (verifyrcpt_toggle && !relayclient) {
+     switch (valid_rcpt()) {
+       case -1:
+         err_ldaplookup();
+         return;
+       case 0:
+         sleep(3);
+         err_nosuchuser();
+         return;
+     }
+   }
+ #endif
+ 
    ++rcptcount;
    if (maxrcptcount && rcptcount > maxrcptcount)
    {

Reply via email to