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 > #include > #include > #include > #include > > #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; }