0a1,10
> 
> /* NEWER VERSION 2.0 HAS BEEN RELEASED.
>  * SEE HTTP://www.interazioni.it/opensource
>  * Patch 'qmail-smtpd-chkusr' v.1.0
>  * for qmail 1.03 and vpopmail 5.3.3
>  * 
>  * Antonio Nati tonix@interazioni.it
>  * 
>  */
> 
26a37,47
> #include <pwd.h>
> #include <sys/types.h>
> #include <unistd.h>
> #include <dirent.h>
> #include <stdio.h>
> 
> #include "open.h"
> #include "/vpopmail/include/vpopmail.h"
> #include "/vpopmail/include/vauth.h"
> #include "/vpopmail/include/vpopmail_config.h"
> 
62d82
< 
119c139
<  
---
> 
210a231,434
> void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); }
> 
> int realrcpt_check()
> {
>   stralloc user = {0};
>   stralloc domain = {0};
>   stralloc domain_path = {0};
>   stralloc bounce_path = {0};
>   stralloc alias_name = {0};
>   stralloc alias_path = {0};
>   stralloc mailing_path = {0};
>   int count;
>   int retstat = 0;
>   struct vqpasswd *user_passwd = NULL;
>   int fd_file = -1;
>   int read_char;
>   DIR *dir_file = NULL;
>   uid_t eff_uid;
>   gid_t eff_gid;
>   int offset;
>   char read_buf[1024];
> 
> /* if not local rcpthost we cannot control mailbox */
> 
>   if (!addrallowed()) { return 1; }
> 
> /* Set up our variables */
> 
> /* qmail-smtpd is running now as (effective) qmaild:qnofiles */
> /* Save the effective UID & GID (qmaild:qnofiles) */
>   eff_uid = geteuid ();
>   eff_gid = getegid ();
> 
> /* Search the '@' character */
>   count = byte_rchr(addr.s,addr.len,'@');
> 
> /* The following lines could interest people using # instead of @ in e-mail address */
> /* If '@' not found search the '%' character */
> /*
>   if (count >= addr.len) {
>     count = byte_rchr(addr.s,addr.len,'%');
>   }
> */
> 
> /*
>  * Give extra room to variables used often or used outside stralloc_x calls
>  * This should make all safer and even faster
>  * (when these fields are used by stralloc_x routines)
> */
>   if (!stralloc_ready (&domain, 200)) die_nomem();
>   if (!stralloc_ready (&domain_path, 200)) die_nomem();
> 
>   if (count < addr.len) {
>     if (!stralloc_copyb (&user, addr.s, count)) die_nomem();
>     if (!stralloc_0 (&user)) die_nomem();
>     if (!stralloc_copys (&domain, addr.s + count + 1)) die_nomem();
>     if (!stralloc_0 (&domain)) die_nomem();
>   }
>   else {
>     if (!stralloc_copys (&user, addr.s)) die_nomem();
>     if (!stralloc_0 (&user)) die_nomem();
>     if (!stralloc_copys (&domain, DEFAULT_DOMAIN)) die_nomem();
>     if (!stralloc_0 (&domain)) die_nomem();
>   }
> 
> /* My personal control: continue only if a domain (default or not) is specified */
> 
>   if (domain.len == 1)
>     return 0;
> 
> /* Now set new effective UID & GID, getting it from real UID & GID (vpopmail:vchkpw) */
> 
>   setegid (getgid());
>   seteuid (getuid());
> 
> /* qmail-smtpd is running now as effective vpopmail:vchkpw */
> 
>   case_lowers (user.s);
>   case_lowers (domain.s);
> 
> /* Check if domain is a real domain */
> 
>   if (!stralloc_0 (&domain)) die_nomem();
>   vget_real_domain(domain.s, domain.a);
> 
>   domain.len = strlen (domain.s);
>   if (domain.len > (domain.a - 1)) die_nomem();
> 
> /* Let's get domain's real path */
>   vget_assign(domain.s, domain_path.s, 156, NULL, NULL);
> 
>   domain_path.len = strlen (domain_path.s);
> 
> /* Now Let's start the test suite */
> 
> 	switch (0) {
> 
> 	case 0:
> /* Check if domain has bouncing enabled */
> 
> 		/* Allocate room for bounce_path */
>   		if (!stralloc_ready (&bounce_path, 200)) die_nomem();
> 		if (!stralloc_copy (&bounce_path, &domain_path)) die_nomem();
>   		if (!stralloc_cats (&bounce_path, "/.qmail-default")) die_nomem();
> 		if (!stralloc_0 (&bounce_path)) die_nomem();
> 
>   		read_char = 0;
>   		fd_file = open_read (bounce_path.s);	
>   		if (fd_file != -1) {
>       			read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
>       			close (fd_file);
>       			if (read_char < 0) read_char = 0;
>   			}
>   		read_buf[read_char] = 0;
> 
>   		if ( strstr(read_buf, "bounce-no-mailbox") == NULL ) {
> 			retstat = 1;
> 			break;
>   		}
>   
> 	case 1:
> /* User control: check the existance of a real user */
> 
> 	  	user_passwd = vauth_getpw (user.s, domain.s);
> 	  	if (user_passwd != NULL) {
> 
> 		/* If user exists check if he has BOUNCE_MAIL flag set */
> 
> 			if (user_passwd->pw_gid & BOUNCE_MAIL)
> 		    		retstat = 0;
> 	    		else
> 		    		retstat = 1;
> 			break;
> 	  	}
> 
> 	case 2:
> /* Check for aliases/forwards - valias*/
> 
> 		if (valias_select (user.s, domain.s) != NULL) {
> 			retstat = 1;
> 			break;
> 		}
> 
> 	case 3:
> /* Check for aliases/forwards - .qmail-x files */
> 
> 		/* Allocate room for alias_path */
>   		if (!stralloc_ready (&alias_path, 200)) die_nomem();
> 	    	if (!stralloc_copy (&alias_name, &user)) die_nomem();
> 
> 		/* Change all '.' in ':' before continuing on aliases */
> 	    	for (count = 0; count < alias_name.len; ++count)
> 	      	if (*(alias_name.s + count) == '.') *(alias_name.s + count) = ':';
> 
> 	    	if (!stralloc_copy (&alias_path, &domain_path)) die_nomem();
> 	    	if (!stralloc_cats (&alias_path, "/.qmail-")) die_nomem();
> 	    	if (!stralloc_cats (&alias_path, alias_name.s)) die_nomem();
> 	    	if (!stralloc_0 (&alias_path)) die_nomem();
> 
> 		/* access executes anyway as real (vpopmail:vchkpw), that's ok */
> 	    	if (access (alias_path.s, F_OK) == 0) {
> 	      		retstat = 1;
> 			break;
> 	    	}
> 
> 	case 4:
> /* Let's check for mailing lists */
> 
> 		/* Allocate room for mailing_path */
>   		if (!stralloc_ready (&mailing_path, 300)) die_nomem();
> 
> 		/* Search for the outer '-' character */
> 	      	for (offset = user.len - 1; offset > 0; --offset)
> 			if (*(user.s + offset) == '-')  {
> 				if (!stralloc_copy (&mailing_path, &domain_path)) die_nomem();
> 	      			if (!stralloc_cats (&mailing_path, "/")) die_nomem();
> 	      			if (!stralloc_catb (&mailing_path, user.s, offset)) die_nomem();
> 	      			if (!stralloc_cats (&mailing_path, "/mailinglist")) die_nomem();
> 	      			if (!stralloc_0 (&mailing_path)) die_nomem();
> 				/* access executes anyway as real (vpopmail:vchkpw), that's ok */
> 			    	if (access (mailing_path.s, F_OK) == 0) {
>                 			retstat = 1;
>                 			break;
> 	            		}
> 	        	}
> 
> /*
>  * Add this code if another case is following
> 		if (retstat == 1)
> 			break;
> */
> 	    
> 	} /* end switch */
> 
> /* Now switch back effective to saved UID & GID (qmaild:qnofiles) */
> 
>   setegid (eff_gid);
>   seteuid (eff_uid);
> 
> /* qmail-smtpd is running again as (effective) qmaild:qnofiles */
> 
>   return retstat;
> }
> 
260a485
>   if (!realrcpt_check()) { err_realrcpt(); return; }
