Download | Plain Text | No Line Numbers


  1. http://code.dogmap.org./qmail/#realrcptto
  2.  
  3. Changes in version 2009.01.31 (manuel mausz):
  4. - userlookup + set DTUSER environment variable for quotacheck plugin
  5.  
  6. Changes in version 2006.12.10:
  7. - For QMAILRRTENYALL, use error code 554 after DATA, not 550. Thanks to
  8. ... sorry, I lost track of who found this.
  9. - Log stat() errors for .qmail files. Thanks to Chris Bensend for suggesting
  10. this.
  11.  
  12. Changes in version 2006.10.26:
  13. - Logging uses substdio_puts() and substdio_flush() instead of
  14. substdio_putsflush(). This makes log entries less likely to be
  15. interleaved. Thanks to Matthew Dempsky for finding this.
  16.  
  17. Changes in version 2004.09.14:
  18. - Strict syntax fix: a variable declaration was accidentally put among
  19. statements instead of at the beginning of the block.
  20.  
  21. Changes in version 2004.08.30:
  22. - Added QMAILRRTDENYALL.
  23. - Cleanup: missing "break" for some switch statements (no visible behavior
  24. changes AFAICT). Thanks to Markus Stumpf for finding these.
  25.  
  26. Changes in version 2004.02.05:
  27. - Short-circuit speedup when "dash" is empty.
  28. - Move duplicated code into realrcptto.c.
  29. - Add logging of rejected addresses.
  30. - Verified inter-patchability with netqmail-1.05 and Russell Nelson's
  31. qmail-smtpd-viruscan patch.
  32.  
  33. diff -Naur Makefile.orig Makefile
  34. --- Makefile.orig 1998-06-15 06:52:55.000000000 -0400
  35. +++ Makefile 2006-12-08 03:21:25.000000000 -0500
  36. @@ -1447,15 +1447,15 @@
  37. ./compile qmail-qmqpd.c
  38.  
  39. qmail-qmtpd: \
  40. -load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
  41. +load qmail-qmtpd.o realrcptto.o slurpclose.o rcpthosts.o control.o constmap.o received.o \
  42. date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \
  43. getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
  44. -str.a fs.a auto_qmail.o dns.o ip.o ipalloc.o ipme.o byte_diff.o
  45. - ./load qmail-qmtpd rcpthosts.o control.o constmap.o \
  46. +str.a fs.a auto_qmail.o dns.o ip.o ipalloc.o ipme.o byte_diff.o auto_break.o auto_usera.o
  47. + ./load qmail-qmtpd realrcptto.o slurpclose.o rcpthosts.o control.o constmap.o \
  48. received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
  49. datetime.a open.a getln.a sig.a case.a env.a stralloc.a \
  50. - alloc.a substdio.a error.a fs.a auto_qmail.o dns.o \
  51. + alloc.a substdio.a error.a fs.a auto_qmail.o dns.o auto_break.o auto_usera.o \
  52. `cat dns.lib` ip.o ipalloc.o ipme.o byte_diff.o str.a
  53.  
  54. qmail-qmtpd.0: \
  55. qmail-qmtpd.8
  56. @@ -1614,18 +1614,18 @@
  57. ./compile qmail-showctl.c
  58.  
  59. qmail-smtpd: \
  60. -load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
  61. +load qmail-smtpd.o realrcptto.o slurpclose.o rcpthosts.o qregex.o commands.o timeoutread.o \
  62. timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
  63. date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
  64. open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
  65. -fs.a auto_qmail.o base64.o qmail-spp.o socket.lib dns.o ip.o ipalloc.o
  66. - ./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
  67. +fs.a auto_qmail.o base64.o qmail-spp.o auto_break.o auto_usera.o socket.lib dns.o ip.o ipalloc.o
  68. + ./load qmail-smtpd realrcptto.o slurpclose.o qregex.o rcpthosts.o commands.o timeoutread.o \
  69. timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
  70. tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
  71. received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
  72. datetime.a getln.a open.a sig.a case.a qmail-spp.o env.a stralloc.a \
  73. - alloc.a strerr.a substdio.a error.a fs.a auto_qmail.o base64.o `cat \
  74. - socket.lib` dns.o str.a `cat dns.lib`
  75. + alloc.a strerr.a substdio.a error.a fs.a auto_qmail.o base64.o auto_break.o \
  76. + auto_usera.o `cat socket.lib` dns.o str.a `cat dns.lib`
  77.  
  78. qmail-smtpd.0: \
  79. qmail-smtpd.8
  80. @@ -1774,6 +1774,11 @@
  81. auto_split.h
  82. ./compile readsubdir.c
  83.  
  84. +realrcptto.o: \
  85. +compile realrcptto.c auto_break.h auto_usera.h byte.h case.h cdb.h \
  86. +constmap.h error.h fmt.h open.h str.h stralloc.h uint32.h
  87. + ./compile realrcptto.c
  88. +
  89. received.o: \
  90. compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
  91. datetime.h date822fmt.h received.h
  92. diff -Naur qmail-qmtpd.c.orig qmail-qmtpd.c
  93. --- qmail-qmtpd.c.orig 1998-06-15 06:52:55.000000000 -0400
  94. +++ qmail-qmtpd.c 2006-12-08 03:21:25.000000000 -0500
  95. @@ -14,6 +14,15 @@
  96.  
  97. void badproto() { _exit(100); }
  98. void resources() { _exit(111); }
  99. +void die_nomem() { resources(); }
  100. +void die_control() { resources(); }
  101. +void die_cdb() { resources(); }
  102. +void die_sys() { resources(); }
  103. +
  104. +extern void realrcptto_init();
  105. +extern void realrcptto_start();
  106. +extern int realrcptto();
  107. +extern int realrcptto_deny();
  108.  
  109. int safewrite(fd,buf,len) int fd; char *buf; int len;
  110. {
  111. @@ -98,6 +107,8 @@
  112. if (rcpthosts_init() == -1) resources();
  113. relayclient = env_get("RELAYCLIENT");
  114. relayclientlen = relayclient ? str_len(relayclient) : 0;
  115. +
  116. + realrcptto_init();
  117.  
  118. if (control_readint(&databytes,"control/databytes") == -1) resources();
  119. x = env_get("DATABYTES");
  120. @@ -114,6 +125,7 @@
  121. if (!local) local = "unknown";
  122.  
  123. for (;;) {
  124. + realrcptto_start();
  125. if (!stralloc_copys(&failure,"")) resources();
  126. flagsenderok = 1;
  127.  
  128. @@ -216,6 +228,10 @@
  129. case -1: resources();
  130. case 0: failure.s[failure.len - 1] = 'D';
  131. }
  132. +
  133. + if (!failure.s[failure.len - 1])
  134. + if (!realrcptto(buf,1))
  135. + failure.s[failure.len - 1] = 'D';
  136.  
  137. if (!failure.s[failure.len - 1]) {
  138. qmail_to(&qq,buf);
  139. @@ -231,6 +247,7 @@
  140. result = qmail_close(&qq);
  141. if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)";
  142. if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
  143. + if (!relayclient && realrcptto_deny()) result = "Dsorry, no mailbox here by that name. (#5.1.1)\r\n";
  144.  
  145. if (*result)
  146. len = str_len(result);
  147. diff -Naur qmail-smtpd.c.orig qmail-smtpd.c
  148. --- qmail-smtpd.c.orig 1998-06-15 06:52:55.000000000 -0400
  149. +++ qmail-smtpd.c 2006-12-09 04:02:00.000000000 -0500
  150. @@ -111,12 +111,24 @@
  151. void die_ipme()
  152. {
  153. enew(); eout("Unable to figure out my IP addresses!\n");
  154. out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush();
  155. eflush(); _exit(1);
  156. }
  157. +void die_cdb()
  158. +{
  159. + enew(); eout("Unable to read cdb user database!\n");
  160. + out("421 unable to read cdb user database (#4.3.0)\r\n"); flush();
  161. + eflush(); _exit(1);
  162. +}
  163. +void die_sys()
  164. +{
  165. + enew(); eout("Unable to read system user database!\n");
  166. + out("421 unable to read system user database (#4.3.0)\r\n"); flush();
  167. + eflush(); _exit(1);
  168. +}
  169. void straynewline()
  170. {
  171. enew(); eout("Stray newline from "); eout(remoteip); eout(".\n");
  172. out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush();
  173. eflush(); _exit(1);
  174. }
  175. @@ -161,6 +173,13 @@
  176. int err_wantstarttls() { out("530 Must issue a STARTTLS command first (#5.7.0)\r\n"); return -1; };
  177. void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
  178.  
  179. +extern void realrcptto_init();
  180. +extern void realrcptto_start();
  181. +extern int realrcptto();
  182. +extern int realrcptto_deny();
  183. +
  184. +int flagauth = 0;
  185. +
  186. stralloc greeting = {0};
  187.  
  188. void smtp_greet(code) char *code;
  189. @@ -259,7 +259,8 @@
  190. fdmbrt = open_read("control/morebadrcptto.cdb");
  191. if (fdmbrt == -1) if (errno != error_noent) die_control();
  192.  
  193.  
  194. + realrcptto_init();
  195.  
  196. if (control_readint(&databytes,"control/databytes") == -1) die_control();
  197. x = env_get("DATABYTES");
  198. @@ -635,7 +635,8 @@
  199. if (!stralloc_copys(&rcptto,"")) die_nomem();
  200. if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
  201. if (!stralloc_0(&mailfrom)) die_nomem();
  202. + realrcptto_start();
  203. recipcount = 0;
  204. out("250 ok\r\n");
  205. }
  206. void smtp_rcpt(arg) char *arg; {
  207. @@ -680,5 +701,9 @@
  208. flagbrt = 1;
  209. log_deny("BAD RCPT TO", mailfrom.s,addr.s);
  210. }
  211. + if (!flagauth && !relayclient && !realrcptto(addr.s,1)) {
  212. + out("554 sorry, no mailbox here by that name. (#5.1.1)\r\n");
  213. + return;
  214. + }
  215. if (!(spp_val = spp_rcpt(allowed))) return;
  216. if (!relayclient && spp_val == 1) {
  217. @@ -899,6 +899,7 @@
  218. if (mailfrom.len == 1 && recipcount > 1) { err_badbounce(); return; }
  219. if (flagbrt) { err_brt(); return; }
  220. if (!spp_data()) return;
  221. + if (!relayclient && realrcptto_deny()) { out("550 sorry, no mailbox here by that name. (#5.1.1)\r\n"); return; }
  222. seenmail = 0;
  223. if (databytes) bytestooverflow = databytes + 1;
  224. if (qmail_open(&qqt) == -1) { err_qqt(); return; }
  225. @@ -961,6 +961,5 @@
  226. static stralloc slop = {0}; /* b64 challenge */
  227. #endif
  228.  
  229. -int flagauth = 0;
  230. char **childargs;
  231. char ssauthbuf[512];
  232. diff -Naur /dev/null realrcptto.c
  233. --- /dev/null 2006-09-14 17:39:14.000000000 +0200
  234. +++ realrcptto.c 2009-01-31 01:01:21.000000000 +0100
  235. @@ -0,0 +1,421 @@
  236. +#include <sys/types.h>
  237. +#include <sys/stat.h>
  238. +#include <unistd.h>
  239. +#include <pwd.h>
  240. +#include "auto_break.h"
  241. +#include "auto_usera.h"
  242. +#include "byte.h"
  243. +#include "case.h"
  244. +#include "cdb.h"
  245. +#include "constmap.h"
  246. +#include "error.h"
  247. +#include "fmt.h"
  248. +#include "open.h"
  249. +#include "str.h"
  250. +#include "stralloc.h"
  251. +#include "uint32.h"
  252. +#include "substdio.h"
  253. +#include "env.h"
  254. +#include "slurpclose.h"
  255. +
  256. +extern void die_nomem();
  257. +extern void die_control();
  258. +extern void die_cdb();
  259. +extern void die_sys();
  260. +
  261. +static stralloc envnoathost = {0};
  262. +static stralloc percenthack = {0};
  263. +static stralloc locals = {0};
  264. +static stralloc vdoms = {0};
  265. +static struct constmap mappercenthack;
  266. +static struct constmap maplocals;
  267. +static struct constmap mapvdoms;
  268. +
  269. +static char *dash;
  270. +static char *extension;
  271. +static char *local;
  272. +static struct passwd *pw;
  273. +
  274. +static char errbuf[128];
  275. +static struct substdio sserr = SUBSTDIO_FDBUF(write,2,errbuf,sizeof errbuf);
  276. +
  277. +static char pidbuf[64];
  278. +static char remoteipbuf[64]=" ";
  279. +
  280. +static int flagdenyall;
  281. +static int flagdenyany;
  282. +
  283. +void realrcptto_init()
  284. +{
  285. + char *x;
  286. +
  287. + if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1)
  288. + die_control();
  289. +
  290. + if (control_readfile(&locals,"control/locals",1) != 1) die_control();
  291. + if (!constmap_init(&maplocals,locals.s,locals.len,0)) die_nomem();
  292. + switch(control_readfile(&percenthack,"control/percenthack",0)) {
  293. + case -1: die_control();
  294. + case 0: if (!constmap_init(&mappercenthack,"",0,0)) die_nomem();
  295. + case 1:
  296. + if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0))
  297. + die_nomem();
  298. + }
  299. + switch(control_readfile(&vdoms,"control/virtualdomains",0)) {
  300. + case -1: die_control();
  301. + case 0: if (!constmap_init(&mapvdoms,"",0,1)) die_nomem();
  302. + case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) die_nomem();
  303. + }
  304. +
  305. + str_copy(pidbuf + fmt_ulong(pidbuf,getpid())," ");
  306. + x=env_get("PROTO");
  307. + if (x) {
  308. + static char const remoteip[]="REMOTEIP";
  309. + unsigned int len = str_len(x);
  310. + if (len <= sizeof remoteipbuf - sizeof remoteip) {
  311. + byte_copy(remoteipbuf,len,x);
  312. + byte_copy(remoteipbuf + len,sizeof remoteip,remoteip);
  313. + x = env_get(remoteipbuf);
  314. + len = str_len(x);
  315. + if (len + 1 < sizeof remoteipbuf) {
  316. + byte_copy(remoteipbuf,len,x);
  317. + remoteipbuf[len]=' ';
  318. + remoteipbuf[len + 1]='\0';
  319. + }
  320. + }
  321. + }
  322. +
  323. + x = env_get("QMAILRRTDENYALL");
  324. + flagdenyall = (x && x[0]=='1' && x[1]=='\0');
  325. +}
  326. +
  327. +void realrcptto_start()
  328. +{
  329. + flagdenyany = 0;
  330. +}
  331. +
  332. +static int denyaddr(addr, depth)
  333. +char *addr;
  334. +int depth;
  335. +{
  336. + if (depth == 1)
  337. + {
  338. + substdio_puts(&sserr,"realrcptto ");
  339. + substdio_puts(&sserr,pidbuf);
  340. + substdio_puts(&sserr,remoteipbuf);
  341. + substdio_puts(&sserr,addr);
  342. + substdio_puts(&sserr,"\n");
  343. + substdio_flush(&sserr);
  344. + flagdenyany = 1;
  345. + }
  346. + return flagdenyall;
  347. +}
  348. +
  349. +static void stat_error(path,error)
  350. +char* path;
  351. +int error;
  352. +{
  353. + substdio_puts(&sserr,"unable to stat ");
  354. + substdio_puts(&sserr,path);
  355. + substdio_puts(&sserr,": ");
  356. + substdio_puts(&sserr,error_str(error));
  357. + substdio_puts(&sserr,"\n");
  358. + substdio_flush(&sserr);
  359. +}
  360. +
  361. +#define GETPW_USERLEN 32
  362. +
  363. +static int userext()
  364. +{
  365. + char username[GETPW_USERLEN];
  366. + struct stat st;
  367. +
  368. + extension = local + str_len(local);
  369. + for (;;) {
  370. + if (extension - local < sizeof(username))
  371. + if (!*extension || (*extension == *auto_break)) {
  372. + byte_copy(username,extension - local,local);
  373. + username[extension - local] = 0;
  374. + case_lowers(username);
  375. + errno = 0;
  376. + pw = getpwnam(username);
  377. + if (errno == error_txtbsy) die_sys();
  378. + if (pw)
  379. + if (pw->pw_uid)
  380. + if (stat(pw->pw_dir,&st) == 0) {
  381. + if (st.st_uid == pw->pw_uid) {
  382. + dash = "";
  383. + if (*extension) { ++extension; dash = "-"; }
  384. + return 1;
  385. + }
  386. + }
  387. + else
  388. + if (error_temp(errno)) die_sys();
  389. + }
  390. + if (extension == local) return 0;
  391. + --extension;
  392. + }
  393. +}
  394. +
  395. +// max lookups
  396. +#define MAXRECURSION 5
  397. +
  398. +static int handleqme(qme, depth)
  399. +stralloc *qme;
  400. +int depth;
  401. +{
  402. + stralloc cmds = {0};
  403. + char *username = NULL;
  404. + int fd, i, j, k, count;
  405. +
  406. + if (depth >= MAXRECURSION) return 0;
  407. + if (!stralloc_ready(&cmds,0)) die_nomem();
  408. + cmds.len = 0;
  409. +
  410. + fd = open_read(qme->s);
  411. + if (fd == -1) return 0;
  412. + if (slurpclose(fd,&cmds,256) == -1) die_nomem();
  413. + if (!cmds.len || (cmds.s[cmds.len - 1] != '\n'))
  414. + if (!stralloc_cats(&cmds,"\n")) die_nomem();
  415. +
  416. + i = count = 0;
  417. + for (j = 0;j < cmds.len;++j)
  418. + {
  419. + if (cmds.s[j] == '\n')
  420. + {
  421. + cmds.s[j] = 0;
  422. + k = j;
  423. + while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
  424. + cmds.s[--k] = 0;
  425. + switch(cmds.s[i])
  426. + {
  427. + case 0:
  428. + case '#':
  429. + case '.':
  430. + case '/':
  431. + case '|':
  432. + case '+':
  433. + break;
  434. + case '&':
  435. + ++i;
  436. + default:
  437. + count++;
  438. + username = cmds.s + i;
  439. + break;
  440. + }
  441. + i = j + 1;
  442. + }
  443. + }
  444. +
  445. + if (count == 1 && username)
  446. + realrcptto(username, ++depth);
  447. +
  448. + return 1;
  449. +}
  450. +
  451. +int realrcptto(addr, depth)
  452. +char *addr;
  453. +int depth;
  454. +{
  455. + env_unset("DTUSER");
  456. + return realrcptto_ex(addr, depth);
  457. +}
  458. +
  459. +int realrcptto_ex(addr, depth)
  460. +char *addr;
  461. +int depth;
  462. +{
  463. + char *homedir, *username;
  464. + static stralloc localpart = {0};
  465. + static stralloc lower = {0};
  466. + static stralloc nughde = {0};
  467. + static stralloc wildchars = {0};
  468. + static stralloc safeext = {0};
  469. + static stralloc qme = {0};
  470. + unsigned int i,at;
  471. +
  472. + /* Short circuit, or full logging? Short circuit. */
  473. + if (flagdenyall && flagdenyany) return 1;
  474. +
  475. + /* qmail-send:rewrite */
  476. + if (!stralloc_copys(&localpart,addr)) die_nomem();
  477. + i = byte_rchr(localpart.s,localpart.len,'@');
  478. + if (i == localpart.len) {
  479. + if (!stralloc_cats(&localpart,"@")) die_nomem();
  480. + if (!stralloc_cat(&localpart,&envnoathost)) die_nomem();
  481. + }
  482. + while (constmap(&mappercenthack,localpart.s + i + 1,localpart.len - i - 1)) {
  483. + unsigned int j = byte_rchr(localpart.s,i,'%');
  484. + if (j == i) break;
  485. + localpart.len = i;
  486. + i = j;
  487. + localpart.s[i] = '@';
  488. + }
  489. + at = byte_rchr(localpart.s,localpart.len,'@');
  490. + if (constmap(&maplocals,localpart.s + at + 1,localpart.len - at - 1)) {
  491. + localpart.len = at;
  492. + localpart.s[at] = '\0';
  493. + } else {
  494. + unsigned int xlen,newlen;
  495. + char *x;
  496. + for (i = 0;;++i) {
  497. + if (i > localpart.len) return denyaddr(addr, depth);
  498. + if (!i || (i == at + 1) || (i == localpart.len) ||
  499. + ((i > at) && (localpart.s[i] == '.'))) {
  500. + x = constmap(&mapvdoms,localpart.s + i,localpart.len - i);
  501. + if (x && i == at + 1) {
  502. + // set QMAILQUEUE if catch-all
  503. + char *qmailqueue;
  504. + qmailqueue = env_get("QMAILQUEUE");
  505. + if (qmailqueue) {
  506. + if (!env_put("QMAILQUEUE=bin/qmail-queue")) die_nomem();
  507. + }
  508. + }
  509. + if (x) break;
  510. + }
  511. + }
  512. + if (!*x) return 1;
  513. + xlen = str_len(x) + 1; /* +1 for '-' */
  514. + newlen = xlen + at + 1; /* +1 for \0 */
  515. + if (xlen < 1 || newlen - 1 < xlen || newlen < 1 ||
  516. + !stralloc_ready(&localpart,newlen))
  517. + die_nomem();
  518. + localpart.s[newlen - 1] = '\0';
  519. + byte_copyr(localpart.s + xlen,at,localpart.s);
  520. + localpart.s[xlen - 1] = '-';
  521. + byte_copy(localpart.s,xlen - 1,x);
  522. + localpart.len = newlen;
  523. + }
  524. +
  525. + /* qmail-lspawn:nughde_get */
  526. + {
  527. + int r,fd,flagwild;
  528. + if (!stralloc_copys(&lower,"!")) die_nomem();
  529. + if (!stralloc_cats(&lower,localpart.s)) die_nomem();
  530. + if (!stralloc_0(&lower)) die_nomem();
  531. + case_lowerb(lower.s,lower.len);
  532. + if (!stralloc_copys(&nughde,"")) die_nomem();
  533. + fd = open_read("users/cdb");
  534. + if (fd == -1) {
  535. + if (errno != error_noent) die_cdb();
  536. + } else {
  537. + uint32 dlen;
  538. + r = cdb_seek(fd,"",0,&dlen);
  539. + if (r != 1) die_cdb();
  540. + if (!stralloc_ready(&wildchars,(unsigned int) dlen)) die_nomem();
  541. + wildchars.len = dlen;
  542. + if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) die_cdb();
  543. + i = lower.len;
  544. + flagwild = 0;
  545. + do { /* i > 0 */
  546. + if (!flagwild || (i == 1) ||
  547. + (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1])
  548. + < wildchars.len)) {
  549. + r = cdb_seek(fd,lower.s,i,&dlen);
  550. + if (r == -1) die_cdb();
  551. + if (r == 1) {
  552. + char *x;
  553. + if (!stralloc_ready(&nughde,(unsigned int) dlen)) die_nomem();
  554. + nughde.len = dlen;
  555. + if (cdb_bread(fd,nughde.s,nughde.len) == -1) die_cdb();
  556. + if (flagwild)
  557. + if (!stralloc_cats(&nughde,localpart.s + i - 1)) die_nomem();
  558. + if (!stralloc_0(&nughde)) die_nomem();
  559. + close(fd);
  560. + x=nughde.s;
  561. + /* skip username */
  562. + username=x;
  563. + x += byte_chr(x,nughde.s + nughde.len - x,'\0');
  564. + if (x == nughde.s + nughde.len) return 1;
  565. + ++x;
  566. + /* skip uid */
  567. + x += byte_chr(x,nughde.s + nughde.len - x,'\0');
  568. + if (x == nughde.s + nughde.len) return 1;
  569. + ++x;
  570. + /* skip gid */
  571. + x += byte_chr(x,nughde.s + nughde.len - x,'\0');
  572. + if (x == nughde.s + nughde.len) return 1;
  573. + ++x;
  574. + /* skip homedir */
  575. + homedir=x;
  576. + x += byte_chr(x,nughde.s + nughde.len - x,'\0');
  577. + if (x == nughde.s + nughde.len) return 1;
  578. + ++x;
  579. + /* skip dash */
  580. + dash=x;
  581. + x += byte_chr(x,nughde.s + nughde.len - x,'\0');
  582. + if (x == nughde.s + nughde.len) return 1;
  583. + ++x;
  584. + extension=x;
  585. + goto got_nughde;
  586. + }
  587. + }
  588. + --i;
  589. + flagwild = 1;
  590. + } while (i);
  591. + close(fd);
  592. + }
  593. + }
  594. +
  595. + /* qmail-getpw */
  596. + local = localpart.s;
  597. + if (!userext()) {
  598. + extension = local;
  599. + dash = "-";
  600. + pw = getpwnam(auto_usera);
  601. + }
  602. + if (!pw) return denyaddr(addr, depth);
  603. + if (!stralloc_copys(&nughde,pw->pw_dir)) die_nomem();
  604. + if (!stralloc_0(&nughde)) die_nomem();
  605. + homedir=nughde.s;
  606. + username=pw->pw_name;
  607. +
  608. + got_nughde:
  609. +
  610. + /* qmail-local:qmesearch */
  611. + //if (!*dash) return 1;
  612. + if (!*dash) { env_put2("DTUSER", username); return 1; }
  613. + if (!stralloc_copys(&safeext,extension)) die_nomem();
  614. + case_lowerb(safeext.s,safeext.len);
  615. + for (i = 0;i < safeext.len;++i)
  616. + {
  617. + if (safeext.s[i] == '.')
  618. + safeext.s[i] = ':';
  619. + }
  620. + {
  621. + struct stat st;
  622. + int i;
  623. + if (!stralloc_copys(&qme,homedir)) die_nomem();
  624. + if (!stralloc_cats(&qme,"/.qmail")) die_nomem();
  625. + if (!stralloc_cats(&qme,dash)) die_nomem();
  626. + if (!stralloc_cat(&qme,&safeext)) die_nomem();
  627. + if (!stralloc_0(&qme)) die_nomem();
  628. + //if (stat(qme.s,&st) == 0) return 1;
  629. + if (stat(qme.s,&st) == 0) { handleqme(&qme, depth); return 1; }
  630. + if (errno != error_noent) {
  631. + stat_error(qme.s,errno);
  632. + return 1;
  633. + }
  634. + for (i = safeext.len;i >= 0;--i)
  635. + if (!i || (safeext.s[i - 1] == '-')) {
  636. + if (!stralloc_copys(&qme,homedir)) die_nomem();
  637. + if (!stralloc_cats(&qme,"/.qmail")) die_nomem();
  638. + if (!stralloc_cats(&qme,dash)) die_nomem();
  639. + if (!stralloc_catb(&qme,safeext.s,i)) die_nomem();
  640. + if (!stralloc_cats(&qme,"default")) die_nomem();
  641. + if (!stralloc_0(&qme)) die_nomem();
  642. + //if (stat(qme.s,&st) == 0) return 1;
  643. + if (stat(qme.s,&st) == 0) { handleqme(&qme, depth); return 1; }
  644. + if (errno != error_noent) {
  645. + stat_error(qme.s,errno);
  646. + return 1;
  647. + }
  648. + }
  649. + return denyaddr(addr, depth);
  650. + }
  651. +}
  652. +
  653. +int realrcptto_deny()
  654. +{
  655. + return flagdenyall && flagdenyany;
  656. +}
  657.