Download | Plain Text | No Line Numbers


  1. diff -Naur qmail-1.03.orig/Makefile qmail-1.03/Makefile
  2. --- qmail-1.03.orig/Makefile Sun Dec 24 15:24:55 2006
  3. +++ qmail-1.03/Makefile Mon Dec 25 23:42:18 2006
  4. @@ -1,5 +1,9 @@
  5. # Don't edit Makefile! Use conf-* for configuration.
  6.  
  7. +VPOPMAIL_HOME=/usr/local/vpopmail
  8. +SMTPD_CHKUSER_OBJ=chkuser.o
  9. +VPOPMAIL_LIBS=`head -1 $(VPOPMAIL_HOME)/etc/lib_deps`
  10. +
  11. SHELL=/bin/sh
  12.  
  13. default: it
  14. @@ -312,6 +316,10 @@
  15. exit.h auto_spawn.h
  16. ./compile chkspawn.c
  17.  
  18. +chkuser.o: \
  19. +compile chkuser.c chkuser.h chkuser_settings.h
  20. + ./compile chkuser.c
  21. +
  22. clean: \
  23. TARGETS
  24. rm -f `cat TARGETS`
  25. @@ -1598,21 +1606,21 @@
  26. timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o constmap.o \
  27. received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a fd.a wait.a \
  28. datetime.a getln.a open.a sig.a case.a env.a stralloc.a alloc.a substdio.a \
  29. -error.a str.a fs.a auto_qmail.o base64.o qmail-spp.o socket.lib dns.lib
  30. - ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
  31. +error.a str.a fs.a auto_qmail.o base64.o qmail-spp.o socket.lib dns.lib $(SMTPD_CHKUSER_OBJ)
  32. + ./load qmail-smtpd $(SMTPD_CHKUSER_OBJ) rcpthosts.o commands.o timeoutread.o \
  33. timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o \
  34. tls.o ssl_timeoutio.o ndelay.a -L/usr/lib -lssl -lcrypto \
  35. constmap.o received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a \
  36. fd.a wait.a datetime.a getln.a open.a sig.a case.a qmail-spp.o env.a stralloc.a \
  37. alloc.a substdio.a error.a fs.a auto_qmail.o base64.o \
  38. - str.a `cat socket.lib` `cat dns.lib`
  39. + str.a `cat socket.lib` $(VPOPMAIL_LIBS) `cat dns.lib`
  40.  
  41. qmail-smtpd.0: \
  42. qmail-smtpd.8
  43. nroff -man qmail-smtpd.8 > qmail-smtpd.0
  44.  
  45. qmail-smtpd.o: \
  46. -compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
  47. +compile qmail-smtpd.c chkuser.h sig.h readwrite.h stralloc.h gen_alloc.h \
  48. substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
  49. error.h ipme.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \
  50. substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
  51. diff -Naur qmail-1.03.orig/TARGETS qmail-1.03/TARGETS
  52. --- qmail-1.03.orig/TARGETS Sun Dec 24 15:24:55 2006
  53. +++ qmail-1.03/TARGETS Mon Dec 25 23:42:42 2006
  54. @@ -407,3 +407,4 @@
  55. man
  56. setup
  57. check
  58. +chkuser.o
  59. diff -Naur qmail-1.03.orig/chkuser.c qmail-1.03/chkuser.c
  60. --- qmail-1.03.orig/chkuser.c Thu Jan 1 01:00:00 1970
  61. +++ qmail-1.03/chkuser.c Mon Dec 25 23:42:27 2006
  62. @@ -0,0 +1,1156 @@
  63. +
  64. +/*
  65. + *
  66. + * 'chkuser.c' v.2.0.8
  67. + * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
  68. + *
  69. + * Author: Antonio Nati tonix@interazioni.it
  70. + * All rights on this software and
  71. + * the identifying words chkusr and chkuser kept by the author
  72. + *
  73. + * This software may be freely used, modified and distributed,
  74. + * but this lines must be kept in every original or derived version.
  75. + * Original author "Antonio Nati" and the web URL
  76. + * "http://www.interazioni.it/opensource"
  77. + * must be indicated in every related work or web page
  78. + *
  79. + */
  80. +
  81. +#include <pwd.h>
  82. +
  83. +/* required by vpopmail */
  84. +#include <stdio.h>
  85. +
  86. +#include <stdlib.h>
  87. +#include <string.h>
  88. +#include <unistd.h>
  89. +
  90. +#include "dns.h"
  91. +#include "env.h"
  92. +#include "ipme.h"
  93. +#include "now.h"
  94. +#include "open.h"
  95. +#include "subfd.h"
  96. +#include "substdio.h"
  97. +#include "stralloc.h"
  98. +
  99. +#include "vpopmail.h"
  100. +#include "vauth.h"
  101. +#include "vpopmail_config.h"
  102. +
  103. +#include "chkuser.h"
  104. +#include "chkuser_settings.h"
  105. +
  106. +#if defined _exit
  107. +#undef _exit
  108. +#endif
  109. +
  110. +extern void flush();
  111. +extern void out (char *s);
  112. +
  113. +extern char *remotehost;
  114. +extern char *remoteip;
  115. +extern char *remoteinfo;
  116. +extern char *relayclient;
  117. +extern char *fakehelo;
  118. +
  119. +extern void die_nomem();
  120. +
  121. +#define DIE_NOMEM() die_nomem()
  122. +
  123. +#if defined CHKUSER_DEBUG
  124. +
  125. +#if defined CHKUSER_DEBUG_STDERR
  126. +
  127. +#define CHKUSER_DBG(a) write (STDERR_FILENO, a, strlen (a))
  128. +#define CHKUSER_DBG_INT(a) { int x; char str[30]; sprintf (str, "%d", a); write (STDERR_FILENO, str, strlen (str));}
  129. +
  130. +#else
  131. +
  132. +#define CHKUSER_DBG(a) write (STDOUT_FILENO, a, strlen (a))
  133. +#define CHKUSER_DBG_INT(a) { int x; char str[30]; sprintf (str, "%d", a); write (STDOUT_FILENO, str, strlen (str));}
  134. +
  135. +#endif
  136. +#else
  137. +
  138. +#define CHKUSER_DBG(a) /* DBG dummy */
  139. +#define CHKUSER_DBG_INT(a) /* DBG dummy */
  140. +
  141. +#endif
  142. +
  143. +static int INTRUSION_threshold_reached = 0;
  144. +static int first_time_init_flag = 1;
  145. +
  146. +static int recipients = 0;
  147. +static int wrong_recipients = 0;
  148. +
  149. +static stralloc user = {0};
  150. +static stralloc domain = {0};
  151. +static stralloc domain_path = {0};
  152. +static stralloc tmp_path = {0};
  153. +static stralloc alias_path = {0};
  154. +
  155. +#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
  156. + static char *identify_remote;
  157. +#endif
  158. +
  159. +#if defined CHKUSER_ENABLE_EXTENSIONS
  160. +#define CHKUSER_ENABLE_USERS_EXTENSIONS
  161. +#endif
  162. +
  163. +#if defined CHKUSER_ENABLE_LISTS
  164. +#define CHKUSER_ENABLE_EZMLM_LISTS
  165. +#endif
  166. +
  167. +#if defined CHKUSER_EXTENSION_DASH
  168. +#define CHKUSER_USERS_DASH CHKUSER_EXTENSION_DASH
  169. +#endif
  170. +
  171. +
  172. +#if defined CHKUSER_ENABLE_VAUTH_OPEN
  173. + static int db_already_open = 0;
  174. +#endif
  175. +
  176. +#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
  177. + static char *starting_string = 0;
  178. + static int starting_value = -1;
  179. +#endif
  180. +
  181. +#if defined CHKUSER_RCPT_LIMIT_VARIABLE
  182. + static char *maxrcpt_string = 0;
  183. + static int maxrcpt_limit = 0;
  184. + static int maxrcpt_limit_reached = 0;
  185. +#endif
  186. +
  187. +#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
  188. + static char *maxwrongrcpt_string = 0;
  189. + static int maxwrongrcpt_limit = 0;
  190. + static int maxwrongrcpt_limit_reached = 0;
  191. +#endif
  192. +
  193. +#if defined CHKUSER_MBXQUOTA_VARIABLE
  194. + static char *maxmbxquota_string = 0;
  195. + static int maxmbxquota_limit = 0;
  196. +#endif
  197. +
  198. +#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
  199. +
  200. + static unsigned int sender_nocheck = 0;
  201. +
  202. +#endif
  203. +
  204. +#if defined CHKUSER_SENDER_FORMAT || defined CHKUSER_SENDER_MX
  205. +static stralloc sender_user = {0};
  206. +static stralloc sender_domain = {0};
  207. +#endif
  208. +
  209. +
  210. +#if defined CHKUSER_ERROR_DELAY
  211. +
  212. + static int chkuser_delay_interval = CHKUSER_ERROR_DELAY * 1000;
  213. +
  214. +#define CHKUSER_DELAY() chkuser_delay()
  215. +
  216. +void chkuser_delay (void) {
  217. +
  218. + usleep (chkuser_delay_interval);
  219. +
  220. +#if defined CHKUSER_ERROR_DELAY_INCREASE
  221. + chkuser_delay_interval += CHKUSER_ERROR_DELAY_INCREASE * 1000;
  222. +#endif
  223. +}
  224. +
  225. +#if defined CHKUSER_RCPT_DELAY_ANYERROR
  226. +#define CHKUSER_RCPT_DELAY_ANY() chkuser_delay()
  227. +#else
  228. +#define CHKUSER_RCPT_DELAY_ANY() /* no delay for any error */
  229. +#endif
  230. +
  231. +#if defined CHKUSER_SENDER_DELAY_ANYERROR
  232. +#define CHKUSER_SENDER_DELAY_ANY() chkuser_delay()
  233. +#else
  234. +#define CHKUSER_SENDER_DELAY_ANY() /* no delay for any error */
  235. +#endif
  236. +
  237. +
  238. +#else
  239. +#define CHKUSER_DELAY() /* no delay */
  240. +#define CHKUSER_RCPT_DELAY_ANY() /* no delay */
  241. +#define CHKUSER_SENDER_DELAY_ANY() /* no delay */
  242. +#endif
  243. +
  244. +#if defined CHKUSER_ENABLE_LOGGING
  245. +
  246. +static stralloc logstr = { 0 };
  247. +
  248. +static void chkuser_commonlog (char *sender, char *rcpt, char *title, char *description) {
  249. +
  250. + substdio_puts (subfderr, "CHKUSER ");
  251. + substdio_puts (subfderr, title);
  252. + substdio_puts (subfderr, ": from <");
  253. + substdio_puts (subfderr, sender);
  254. + substdio_puts (subfderr, ":" );
  255. + if (remoteinfo) {
  256. + substdio_puts (subfderr, remoteinfo);
  257. + }
  258. + substdio_puts (subfderr, ":" );
  259. +#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
  260. + if (identify_remote) substdio_puts (subfderr, identify_remote);
  261. +#endif
  262. + substdio_puts (subfderr, "> remote <");
  263. + if (fakehelo) substdio_puts (subfderr, fakehelo);
  264. + substdio_puts (subfderr, ":" );
  265. + if (remotehost) substdio_puts (subfderr, remotehost);
  266. + substdio_puts (subfderr, ":" );
  267. + if (remoteip) substdio_puts (subfderr, remoteip);
  268. + substdio_puts (subfderr, "> rcpt <");
  269. + substdio_puts (subfderr, rcpt);
  270. + substdio_puts (subfderr, "> : ");
  271. + substdio_puts (subfderr, description);
  272. + substdio_puts (subfderr, "\n");
  273. + substdio_flush (subfderr);
  274. +}
  275. +
  276. +#else
  277. +#define chkuser_commonlog(a,b,c,d) /* no log */
  278. +#endif
  279. +
  280. +#if defined CHKUSER_SENDER_FORMAT
  281. +
  282. +static int check_sender_address_format (stralloc *user, stralloc *domain) {
  283. +
  284. + int x;
  285. +
  286. + for (x = 0; x < (user->len -1); ++x) {
  287. + if ((!isalnum (user->s[x]))
  288. +
  289. +#if defined CHKUSER_ALLOW_SENDER_SRS
  290. + && (user->s[x] != '#')
  291. + && (user->s[x] != '+')
  292. +#endif
  293. +#if defined CHKUSER_ALLOW_SENDER_CHAR_1
  294. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_1)
  295. +#endif
  296. +#if defined CHKUSER_ALLOW_SENDER_CHAR_2
  297. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_2)
  298. +#endif
  299. +#if defined CHKUSER_ALLOW_SENDER_CHAR_3
  300. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_3)
  301. +#endif
  302. +#if defined CHKUSER_ALLOW_SENDER_CHAR_4
  303. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_4)
  304. +#endif
  305. +#if defined CHKUSER_ALLOW_SENDER_CHAR_5
  306. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_5)
  307. +#endif
  308. + && (user->s[x] != '_') && (user->s[x] != '-') && (user->s[x] != '.') && (user->s[x] != '=')) {
  309. + return 0;
  310. + }
  311. + }
  312. +
  313. +/*
  314. + * Be careful, this is a base check
  315. + * Minimum is x.xx + ending \0
  316. + * Minimum characters needed are 5
  317. + */
  318. +#if defined CHKUSER_MIN_DOMAIN_LEN
  319. + if (domain->len < (CHKUSER_MIN_DOMAIN_LEN +1)) {
  320. + return 0;
  321. + }
  322. +#endif
  323. +
  324. +/*
  325. + * This is a safety check
  326. + */
  327. +#if defined CHKUSER_MIN_DOMAIN_LEN
  328. + if (domain->len < 2) {
  329. + return 0;
  330. + }
  331. +#endif
  332. +
  333. + for (x = 0; x < (domain->len -1); ++x) {
  334. + if ((!isalnum (domain->s[x])) && (domain->s[x] != '-') && (domain->s[x] != '.')) {
  335. + return 0;
  336. + }
  337. + }
  338. +
  339. + if ((domain->s[0] == '-') || (domain->s[domain->len -2] == '-') || (domain->s[0] == '.') || (domain->s[domain->len -2] == '.')) {
  340. + return 0;
  341. + }
  342. + if (strstr (domain->s, "..") != NULL) {
  343. + return 0;
  344. + }
  345. + if (strncmp (domain->s, "xn--", 4) == 0) {
  346. + if (strstr (&domain->s[4], "--") != NULL)
  347. + return 0;
  348. + } else {
  349. + if (strstr (domain->s, "--") != NULL)
  350. + return 0;
  351. + }
  352. + if (strstr (domain->s, ".-") != NULL) {
  353. + return 0;
  354. + }
  355. + if (strstr (domain->s, "-.") != NULL) {
  356. + return 0;
  357. + }
  358. + if (strchr (domain->s, '.') == NULL) {
  359. + return 0;
  360. + }
  361. +
  362. + return 1;
  363. +}
  364. +
  365. +#endif
  366. +
  367. +#if defined CHKUSER_RCPT_FORMAT
  368. +
  369. +static int check_rcpt_address_format (stralloc *user, stralloc *domain) {
  370. +
  371. + int x;
  372. +
  373. + for (x = 0; x < (user->len -1); ++x) {
  374. + if ((!isalnum (user->s[x]))
  375. +#if defined CHKUSER_ALLOW_RCPT_SRS
  376. + && (user->s[x] != '#')
  377. + && (user->s[x] != '+')
  378. +#endif
  379. +#if defined CHKUSER_ALLOW_RCPT_CHAR_1
  380. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_1)
  381. +#endif
  382. +#if defined CHKUSER_ALLOW_RCPT_CHAR_2
  383. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_2)
  384. +#endif
  385. +#if defined CHKUSER_ALLOW_RCPT_CHAR_3
  386. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_3)
  387. +#endif
  388. +#if defined CHKUSER_ALLOW_RCPT_CHAR_4
  389. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_4)
  390. +#endif
  391. +#if defined CHKUSER_ALLOW_RCPT_CHAR_5
  392. + && (user->s[x] != CHKUSER_ALLOW_SENDER_CHAR_5)
  393. +#endif
  394. +
  395. + && (user->s[x] != '_') && (user->s[x] != '-') && (user->s[x] != '.') && (user->s[x] != '=')) {
  396. + return 0;
  397. + }
  398. + }
  399. +
  400. +/*
  401. + * Be careful, this is a base check
  402. + * Minimum is x.xx + ending \0
  403. + * Minimum characters needed are 5
  404. + */
  405. +#if defined CHKUSER_MIN_DOMAIN_LEN
  406. + if (domain->len < (CHKUSER_MIN_DOMAIN_LEN +1)) {
  407. + return 0;
  408. + }
  409. +#endif
  410. +
  411. +/*
  412. + * This is a safety check
  413. + */
  414. +#if defined CHKUSER_MIN_DOMAIN_LEN
  415. + if (domain->len < 2) {
  416. + return 0;
  417. + }
  418. +#endif
  419. + for (x = 0; x < (domain->len -1); ++x) {
  420. + if ((!isalnum (domain->s[x])) && (domain->s[x] != '-') && (domain->s[x] != '.')) {
  421. + return 0;
  422. + }
  423. + }
  424. +
  425. + if ((domain->s[0] == '-') || (domain->s[domain->len -2] == '-') || (domain->s[0] == '.') || (domain->s[domain->len -2] == '.')) {
  426. + return 0;
  427. + }
  428. + if (strstr (domain->s, "..") != NULL) {
  429. + return 0;
  430. + }
  431. + if (strncmp (domain->s, "xn--", 4) == 0) {
  432. + if (strstr (&domain->s[4], "--") != NULL)
  433. + return 0;
  434. + } else {
  435. + if (strstr (domain->s, "--") != NULL)
  436. + return 0;
  437. + }
  438. + if (strstr (domain->s, ".-") != NULL) {
  439. + return 0;
  440. + }
  441. + if (strstr (domain->s, "-.") != NULL) {
  442. + return 0;
  443. + }
  444. + if (strchr (domain->s, '.') == NULL) {
  445. + return 0;
  446. + }
  447. +
  448. + return 1;
  449. +}
  450. +
  451. +#endif
  452. +
  453. +#if defined CHKUSER_SENDER_MX || defined CHKUSER_RCPT_MX
  454. +
  455. +static unsigned long mx_random;
  456. +static ipalloc mx_ip = {0};
  457. +
  458. +static int chkuser_mx_lookup (stralloc *domain) {
  459. +
  460. + int status;
  461. +
  462. + mx_random = now() + getpid();
  463. + dns_init(0);
  464. + status = dns_mxip (&mx_ip, domain, mx_random);
  465. +
  466. + if (status == DNS_MEM) DIE_NOMEM();
  467. +
  468. + return status;
  469. +}
  470. +
  471. +#endif
  472. +
  473. +
  474. +void chkuser_cleanup (int exit_value) {
  475. +
  476. +#if defined CHKUSER_DB_CLEANUP
  477. + vclose ();
  478. +#endif
  479. + _exit (exit_value);
  480. +}
  481. +
  482. +static void first_time_init (void) {
  483. +
  484. + char * temp_string;
  485. +
  486. +#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
  487. + starting_string = env_get (CHKUSER_STARTING_VARIABLE);
  488. + if (starting_string) {
  489. + if (strcasecmp(starting_string, "ALWAYS") == 0) {
  490. + starting_value = 1;
  491. + } else if (strcasecmp(starting_string, "DOMAIN") == 0) {
  492. + starting_value = 0;
  493. + }
  494. + } else {
  495. + starting_string = "";
  496. + }
  497. +#endif
  498. +
  499. +#if defined CHKUSER_RCPT_LIMIT_VARIABLE
  500. + maxrcpt_string = env_get (CHKUSER_RCPT_LIMIT_VARIABLE);
  501. + if (maxrcpt_string) {
  502. + maxrcpt_limit = atoi (maxrcpt_string);
  503. + if (maxrcpt_limit < 1) {
  504. + maxrcpt_limit = 0;
  505. + }
  506. + } else {
  507. + maxrcpt_string = "";;
  508. + }
  509. +#endif
  510. +
  511. +#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
  512. + maxwrongrcpt_string = env_get (CHKUSER_WRONGRCPT_LIMIT_VARIABLE);
  513. + if (maxwrongrcpt_string) {
  514. + maxwrongrcpt_limit = atoi (maxwrongrcpt_string);
  515. + if (maxwrongrcpt_limit < 1) {
  516. + maxwrongrcpt_limit = 0;
  517. + }
  518. + } else {
  519. + maxwrongrcpt_string = "";
  520. + }
  521. +#endif
  522. +
  523. +#if defined CHKUSER_MBXQUOTA_VARIABLE
  524. + maxmbxquota_string = env_get (CHKUSER_MBXQUOTA_VARIABLE);
  525. + if (maxmbxquota_string) {
  526. + maxmbxquota_limit = atoi (maxmbxquota_string);
  527. + if (maxmbxquota_limit < 1) {
  528. + maxmbxquota_limit = 0;
  529. + }
  530. + } else {
  531. + maxmbxquota_string = "";
  532. + }
  533. +#endif
  534. +
  535. +#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
  536. +
  537. + temp_string = env_get (CHKUSER_SENDER_NOCHECK_VARIABLE);
  538. + if (temp_string) {
  539. + sender_nocheck = 1;
  540. + } else {
  541. + sender_nocheck = 0;
  542. + }
  543. +
  544. +#endif
  545. +
  546. +#if defined CHKUSER_IDENTIFY_REMOTE_VARIABLE
  547. +
  548. + identify_remote = env_get (CHKUSER_IDENTIFY_REMOTE_VARIABLE);
  549. + if (identify_remote) {
  550. + }
  551. +
  552. +#endif
  553. +
  554. + if (!stralloc_ready (&user, 300)) DIE_NOMEM();
  555. + if (!stralloc_ready (&domain, 500)) DIE_NOMEM();
  556. + if (!stralloc_ready (&domain_path, 1000)) DIE_NOMEM();
  557. + if (!stralloc_ready (&tmp_path, 1000)) DIE_NOMEM();
  558. + if (!stralloc_ready (&alias_path, 1000)) DIE_NOMEM();
  559. +
  560. + first_time_init_flag = 0;
  561. +
  562. +}
  563. +
  564. +/*
  565. + * realrcpt ()
  566. + *
  567. + * Returns:
  568. + *
  569. + * CHKUSER_OK = 1 = Ok, recipients does exists
  570. + *
  571. + * 0 = Not in rcpthosts
  572. + *
  573. + * < 0 various errors
  574. + *
  575. + *
  576. + * Parameters:
  577. + * stralloc *sender = sender address
  578. + * stralloc *rcpt = rcpt address to check
  579. + *
  580. + *
  581. +*/
  582. +
  583. +static int realrcpt (stralloc *sender, stralloc *rcpt)
  584. +{
  585. + int count;
  586. + int retstat = CHKUSER_KO;
  587. + struct vqpasswd *user_passwd = NULL;
  588. + int fd_file = -1;
  589. + int read_char;
  590. + int offset;
  591. + char read_buf[1024];
  592. +
  593. +#if defined CHKUSER_ENABLE_UIDGID
  594. + uid_t eff_uid;
  595. + gid_t eff_gid;
  596. +#endif
  597. +
  598. +#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
  599. + if (starting_value == -1) {
  600. + if (addrallowed()) {
  601. + return CHKUSER_OK;
  602. + } else {
  603. + if (relayclient) {
  604. + return CHKUSER_RELAYING;
  605. + }
  606. +
  607. + return CHKUSER_NORCPTHOSTS;
  608. + }
  609. + }
  610. +#endif
  611. +
  612. + if (INTRUSION_threshold_reached == 1) {
  613. + return CHKUSER_ERR_INTRUSION_THRESHOLD;
  614. + }
  615. +
  616. +#if defined CHKUSER_RCPT_LIMIT_VARIABLE
  617. +
  618. + ++recipients;
  619. + if ((maxrcpt_limit > 0) && (recipients >= maxrcpt_limit)) {
  620. + chkuser_commonlog (sender->s, rcpt->s, "intrusion threshold", "max number of allowed rcpt");
  621. + INTRUSION_threshold_reached = 1;
  622. + return CHKUSER_ERR_MAXRCPT;
  623. + }
  624. +#endif
  625. +
  626. +/* Search the '@' character */
  627. + count = byte_rchr(rcpt->s,rcpt->len,'@');
  628. +
  629. + if (count < rcpt->len) {
  630. + if (!stralloc_copyb (&user, rcpt->s, count)) DIE_NOMEM();
  631. + if (!stralloc_copys (&domain, rcpt->s + count + 1)) DIE_NOMEM();
  632. + }
  633. + else {
  634. + if (!stralloc_copys (&user, rcpt->s)) DIE_NOMEM();
  635. + domain.len = 0;
  636. + }
  637. + if (!stralloc_0 (&user)) DIE_NOMEM();
  638. + if (!stralloc_0 (&domain)) DIE_NOMEM();
  639. +
  640. +#if defined CHKUSER_ENABLE_UIDGID
  641. +
  642. +/* qmail-smtpd is running now as (effective) qmaild:nofiles */
  643. +/* Save the effective UID & GID (qmaild:nofiles) */
  644. + eff_uid = geteuid ();
  645. + eff_gid = getegid ();
  646. +
  647. +/* Now set new effective UID & GID, getting it from real UID & GID (vpopmail:vchkpw) */
  648. + setegid (getgid());
  649. + seteuid (getuid());
  650. +
  651. +/* qmail-smtpd is running now as effective vpopmail:vchkpw */
  652. +#endif
  653. +
  654. +
  655. +/*
  656. + *
  657. + * Now let's start the test/setting suite
  658. + *
  659. + **/
  660. +
  661. + switch (0) {
  662. +
  663. + case 0:
  664. +/* These are some preliminary settings */
  665. + case_lowers (user.s);
  666. + case_lowers (domain.s);
  667. +
  668. + case 1:
  669. +
  670. + if (domain.len == 1) {
  671. +#if defined CHKUSER_DOMAIN_WANTED
  672. + retstat = CHKUSER_ERR_DOMAIN_MISSING;
  673. + break;
  674. +#else
  675. + if (!stralloc_copys (&domain, DEFAULT_DOMAIN)) DIE_NOMEM();
  676. + if (!stralloc_0 (&domain)) DIE_NOMEM();
  677. +#endif
  678. + }
  679. +
  680. + case 2:
  681. +
  682. +#if defined CHKUSER_RCPT_FORMAT
  683. +
  684. + if (check_rcpt_address_format (&user, &domain) == 0) {
  685. + retstat = CHKUSER_ERR_RCPT_FORMAT;
  686. + break;
  687. + }
  688. +#endif
  689. +
  690. + case 3:
  691. +
  692. + if (!addrallowed()) {
  693. +
  694. +#if defined CHKUSER_RCPT_MX
  695. + switch (chkuser_mx_lookup(&domain)) {
  696. +
  697. + case DNS_HARD:
  698. + retstat = CHKUSER_ERR_RCPT_MX;
  699. + break;
  700. +
  701. + case DNS_SOFT:
  702. + retstat = CHKUSER_ERR_RCPT_MX_TMP;
  703. + break;
  704. + }
  705. +
  706. + if (retstat != CHKUSER_KO) {
  707. + break;
  708. + }
  709. +#endif
  710. +
  711. + if (relayclient) {
  712. + retstat = CHKUSER_RELAYING;
  713. + break;
  714. + }
  715. +
  716. + retstat = CHKUSER_NORCPTHOSTS;
  717. + break;
  718. + }
  719. +
  720. + case 4:
  721. +
  722. +#if defined CHKUSER_ENABLE_VAUTH_OPEN
  723. + if (db_already_open != 1) {
  724. + if (vauth_open () == 0) {
  725. + db_already_open == 1;
  726. + } else {
  727. + retstat = CHKUSER_ERR_AUTH_RESOURCE;
  728. + }
  729. + };
  730. +#endif
  731. +
  732. + case 5:
  733. +
  734. +#if defined CHKUSER_ENABLE_VGET_REAL_DOMAIN
  735. +/* Check if domain is a real domain */
  736. +
  737. + vget_real_domain(domain.s, domain.a);
  738. +
  739. + domain.len = strlen (domain.s) +1;
  740. + if (domain.len > (domain.a - 1)) DIE_NOMEM();
  741. +#endif
  742. +
  743. +/* Let's get domain's real path */
  744. + if (vget_assign(domain.s, domain_path.s, domain_path.a -1, NULL, NULL) == NULL) {
  745. + retstat = CHKUSER_OK;
  746. + break;
  747. + }
  748. +
  749. + domain_path.len = strlen (domain_path.s);
  750. +
  751. + case 6:
  752. +
  753. +/* Check if domain has bouncing enabled */
  754. +
  755. +#if !defined CHKUSER_ALWAYS_ON
  756. +
  757. +#if defined CHKUSER_STARTING_VARIABLE
  758. + if (starting_value == 0) {
  759. +#endif
  760. +
  761. + if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
  762. +
  763. +#if defined CHKUSER_SPECIFIC_BOUNCING
  764. + if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
  765. + if (!stralloc_cats (&tmp_path, CHKUSER_SPECIFIC_BOUNCING)) DIE_NOMEM();
  766. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  767. + fd_file = open_read (tmp_path.s);
  768. + if (fd_file != -1) {
  769. + close (fd_file);
  770. + } else {
  771. + retstat = CHKUSER_OK;
  772. + break;
  773. + }
  774. +#else
  775. + if (!stralloc_cats (&tmp_path, "/.qmail-default")) DIE_NOMEM();
  776. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  777. +
  778. + read_char = 0;
  779. + fd_file = open_read (tmp_path.s);
  780. + if (fd_file != -1) {
  781. + read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
  782. + close (fd_file);
  783. + if (read_char < 0) read_char = 0;
  784. + }
  785. + read_buf[read_char] = 0;
  786. +
  787. + if ( strstr(read_buf, CHKUSER_BOUNCE_STRING) == NULL ) {
  788. + retstat = CHKUSER_OK;
  789. + break;
  790. + }
  791. +#endif
  792. +#if defined CHKUSER_STARTING_VARIABLE
  793. + }
  794. +#endif
  795. +#endif
  796. +
  797. + case 7:
  798. +#if defined VALIAS
  799. +/* Check for aliases/forwards - valias*/
  800. +
  801. + if (valias_select (user.s, domain.s) != NULL) {
  802. + retstat = CHKUSER_OK;
  803. + break;
  804. + }
  805. +#endif
  806. +
  807. + case 8:
  808. +#if defined CHKUSER_ENABLE_ALIAS
  809. +/* Check for aliases/forwards - .qmail.x files */
  810. +
  811. + if (!stralloc_copy (&tmp_path, &user)) DIE_NOMEM();
  812. + /* Change all '.' in ':' before continuing on aliases */
  813. + for (count = 0; count < tmp_path.len; ++count)
  814. + if (*(tmp_path.s + count) == '.') *(tmp_path.s + count) = ':';
  815. +
  816. + if (!stralloc_copy (&alias_path, &domain_path)) DIE_NOMEM();
  817. + if (!stralloc_cats (&alias_path, "/.qmail-")) DIE_NOMEM();
  818. + if (!stralloc_cats (&alias_path, tmp_path.s)) DIE_NOMEM();
  819. + if (!stralloc_0 (&alias_path)) DIE_NOMEM();
  820. +
  821. + fd_file = open_read (alias_path.s);
  822. + if (fd_file != -1) {
  823. + close (fd_file);
  824. + retstat = CHKUSER_OK;
  825. + break;
  826. + }
  827. +#endif
  828. +
  829. + case 9:
  830. +
  831. +#if defined CHKUSER_ENABLE_ALIAS_DEFAULT
  832. +
  833. + if (!stralloc_copy (&tmp_path, &user)) DIE_NOMEM();
  834. + /* Change all '.' in ':' before continuing on aliases */
  835. + for (count = 0; count < tmp_path.len; ++count)
  836. + if (*(tmp_path.s + count) == '.') *(tmp_path.s + count) = ':';
  837. +
  838. + /* Search for the outer '-' character */
  839. + for (offset = user.len - 1; offset > 0; --offset)
  840. + if (*(user.s + offset) == CHKUSER_USERS_DASH) {
  841. + if (!stralloc_copy (&alias_path, &domain_path)) die_nomem();
  842. + if (!stralloc_cats (&alias_path, "/.qmail-")) die_nomem();
  843. + if (!stralloc_catb (&alias_path, user.s, offset)) die_nomem();
  844. + if (!stralloc_cats (&alias_path, "-default")) die_nomem();
  845. + if (!stralloc_0 (&alias_path)) die_nomem();
  846. +
  847. + fd_file = open_read (alias_path.s);
  848. + if (fd_file != -1) {
  849. + close (fd_file);
  850. + retstat = CHKUSER_OK;
  851. + break;
  852. + }
  853. + }
  854. +
  855. + if (retstat != CHKUSER_KO) {
  856. + break;
  857. + }
  858. +
  859. +#endif
  860. +
  861. + case 10:
  862. +#if defined CHKUSER_ENABLE_USERS
  863. +/* User control: check the existance of a real user */
  864. +
  865. + user_passwd = vauth_getpw (user.s, domain.s);
  866. +
  867. +#if defined CHKUSER_ENABLE_USERS_EXTENSIONS
  868. + if (user_passwd == NULL) {
  869. + count = 0;
  870. + while ((count < (user.len -1)) && (user_passwd == NULL)) {
  871. + count += byte_chr(&user.s[count], user.len - count, CHKUSER_USERS_DASH);
  872. + if (count < user.len) {
  873. + if (!stralloc_copyb (&tmp_path, user.s, count)) DIE_NOMEM();
  874. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  875. + user_passwd = vauth_getpw (tmp_path.s, domain.s);
  876. + ++count;
  877. + }
  878. + }
  879. + }
  880. +
  881. +#endif
  882. + if (user_passwd != NULL) {
  883. +
  884. + /* If user exists check if he has BOUNCE_MAIL flag set */
  885. +
  886. + if (user_passwd->pw_gid & BOUNCE_MAIL)
  887. + retstat = CHKUSER_KO;
  888. + else {
  889. + retstat = CHKUSER_OK;
  890. +#if defined CHKUSER_MBXQUOTA_VARIABLE
  891. + if ((maxmbxquota_limit > 0) && (strcasecmp(user_passwd->pw_shell, "NOQUOTA") != 0)) {
  892. + if (!stralloc_copys (&tmp_path, user_passwd->pw_dir)) DIE_NOMEM();
  893. + if (!stralloc_cats (&tmp_path, "/Maildir")) DIE_NOMEM();
  894. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  895. +
  896. + if (vmaildir_readquota(tmp_path.s,format_maildirquota(user_passwd->pw_shell))
  897. + >= maxmbxquota_limit) {
  898. + retstat = CHKUSER_ERR_MBXFULL;
  899. + }
  900. + }
  901. +#endif
  902. + }
  903. + break;
  904. + }
  905. +#endif
  906. +
  907. + case 11:
  908. +#if defined CHKUSER_ENABLE_EZMLM_LISTS
  909. +/* Let's check for mailing lists */
  910. +
  911. + /* Search for the outer CHKUSER_EZMLM_DASH character */
  912. + for (offset = user.len - 2; offset > 0; --offset) {
  913. + if (*(user.s + offset) == CHKUSER_EZMLM_DASH) {
  914. + if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
  915. + if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
  916. + if (!stralloc_catb (&tmp_path, user.s, offset)) DIE_NOMEM();
  917. + if (!stralloc_cats (&tmp_path, "/mailinglist")) DIE_NOMEM();
  918. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  919. + fd_file = open_read (tmp_path.s);
  920. + if (fd_file != -1) {
  921. + close (fd_file);
  922. + retstat = CHKUSER_OK;
  923. + break;
  924. + }
  925. + }
  926. + }
  927. + if (retstat != CHKUSER_KO) {
  928. + break;
  929. + }
  930. +#endif
  931. +
  932. + case 12:
  933. +#if defined CHKUSER_ENABLE_MAILMAN_LISTS
  934. +/* Let's check for mailing lists */
  935. +
  936. + /* Search for the outer CHKUSER_MAILMAN_DASH character */
  937. + for (offset = user.len - 2; offset > 0; --offset) {
  938. + if (*(user.s + offset) == CHKUSER_MAILMAN_DASH) {
  939. + if (!stralloc_copy (&tmp_path, &domain_path)) DIE_NOMEM();
  940. + if (!stralloc_cats (&tmp_path, "/")) DIE_NOMEM();
  941. + if (!stralloc_cats (&alias_path, "/.qmail-")) DIE_NOMEM();
  942. + if (!stralloc_catb (&tmp_path, user.s, offset)) DIE_NOMEM();
  943. + if (!stralloc_0 (&tmp_path)) DIE_NOMEM();
  944. + fd_file = open_read (tmp_path.s);
  945. + read_char = 0;
  946. + if (fd_file != -1) {
  947. + read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
  948. + close (fd_file);
  949. + if (read_char < 0) read_char = 0;
  950. + }
  951. + read_buf[read_char] = 0;
  952. +
  953. + if ( strstr(read_buf, CHKUSER_MAILMAN_STRING) == NULL ) {
  954. + retstat = CHKUSER_OK;
  955. + break;
  956. + }
  957. +
  958. + }
  959. + }
  960. + if (retstat != CHKUSER_KO) {
  961. + break;
  962. + }
  963. +#endif
  964. +
  965. +/*
  966. + * Add this code if another case is following
  967. + case xx:
  968. + code ....
  969. + code ....
  970. + code ....
  971. + code ....
  972. +
  973. + if (xxxxxxxx) {
  974. + retstat != CHKUSER_KO)
  975. + break;
  976. + }
  977. +*/
  978. +
  979. + default:
  980. + retstat = CHKUSER_KO;
  981. +
  982. + } /* end switch */
  983. +
  984. +#if defined CHKUSER_ENABLE_UIDGID
  985. +/* Now switch back effective to saved UID & GID (qmaild:nofiles) */
  986. +
  987. + setegid (eff_gid);
  988. + seteuid (eff_uid);
  989. +
  990. +/* qmail-smtpd is running again as (effective) qmaild:nofiles */
  991. +#endif
  992. +
  993. + return retstat;
  994. +
  995. +}
  996. +
  997. +
  998. +
  999. +/*
  1000. + * chkuser_realrcpt ()
  1001. + *
  1002. + * Returns a simple status:
  1003. + *
  1004. + * CHKUSER_OK = 1 = Ok, recipients does exists
  1005. + *
  1006. + * CHKUSER_NORCPTHOSTS = Not in rcpthosts
  1007. + *
  1008. + * CHKUSER_KO = ERROR
  1009. + *
  1010. + *
  1011. + * Parameters:
  1012. + * stralloc *sender = sender address
  1013. + * stralloc *rcpt = rcpt address to check
  1014. + *
  1015. + *
  1016. +*/
  1017. +
  1018. +int chkuser_realrcpt (stralloc *sender, stralloc *rcpt) {
  1019. +
  1020. +int retstat;
  1021. +
  1022. + if (first_time_init_flag) {
  1023. + first_time_init ();
  1024. + }
  1025. +
  1026. + retstat = realrcpt (sender, rcpt);
  1027. +
  1028. + switch (retstat) {
  1029. +
  1030. + case CHKUSER_OK:
  1031. +#if defined CHKUSER_LOG_VALID_RCPT
  1032. + chkuser_commonlog (sender->s, rcpt->s, "accepted rcpt", "found existing recipient");
  1033. +#endif
  1034. + return CHKUSER_OK;
  1035. + break;
  1036. +
  1037. + case CHKUSER_RELAYING:
  1038. +#if defined CHKUSER_LOG_VALID_RCPT
  1039. + chkuser_commonlog (sender->s, rcpt->s, "relaying rcpt", "client allowed to relay");
  1040. +#endif
  1041. + return CHKUSER_RELAYING;
  1042. + break;
  1043. +
  1044. + case CHKUSER_NORCPTHOSTS:
  1045. + chkuser_commonlog (sender->s, rcpt->s, "rejected relaying", "client not allowed to relay");
  1046. + CHKUSER_RCPT_DELAY_ANY();
  1047. + out(CHKUSER_NORELAY_STRING);
  1048. + break;
  1049. +
  1050. + case CHKUSER_KO:
  1051. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "not existing recipient");
  1052. + CHKUSER_DELAY();
  1053. + out(CHKUSER_NORCPT_STRING);
  1054. + break;
  1055. +
  1056. + case CHKUSER_ERR_AUTH_RESOURCE:
  1057. + chkuser_commonlog (sender->s, rcpt->s, "no auth resource", "no auth resource available");
  1058. + CHKUSER_RCPT_DELAY_ANY();
  1059. + out(CHKUSER_RESOURCE_STRING);
  1060. + break;
  1061. +
  1062. + case CHKUSER_ERR_MBXFULL:
  1063. + chkuser_commonlog (sender->s, rcpt->s, "mbx overquota", "rcpt mailbox is overquota");
  1064. + CHKUSER_RCPT_DELAY_ANY();
  1065. + out(CHKUSER_MBXFULL_STRING);
  1066. + break;
  1067. +
  1068. + case CHKUSER_ERR_MAXRCPT:
  1069. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "max number of recipients");
  1070. + CHKUSER_DELAY ();
  1071. + out(CHKUSER_MAXRCPT_STRING);
  1072. + break;
  1073. +
  1074. + case CHKUSER_ERR_MAXWRONGRCPT:
  1075. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "max number of invalid recipients");
  1076. + CHKUSER_DELAY ();
  1077. + out(CHKUSER_MAXWRONGRCPT_STRING);
  1078. + break;
  1079. +
  1080. + case CHKUSER_ERR_INTRUSION_THRESHOLD:
  1081. + chkuser_commonlog (sender->s, rcpt->s, "rejected intrusion", "rcpt ignored, session over INTRUSION threshold");
  1082. + CHKUSER_DELAY ();
  1083. + out(CHKUSER_INTRUSIONTHRESHOLD_STRING);
  1084. + break;
  1085. +
  1086. + case CHKUSER_ERR_DOMAIN_MISSING:
  1087. + CHKUSER_DELAY ();
  1088. + out(CHKUSER_DOMAINMISSING_STRING);
  1089. + break;
  1090. +
  1091. + case CHKUSER_ERR_RCPT_FORMAT:
  1092. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "invalid rcpt address format");
  1093. + CHKUSER_RCPT_DELAY_ANY();
  1094. + out(CHKUSER_RCPTFORMAT_STRING);
  1095. + break;
  1096. +
  1097. + case CHKUSER_ERR_RCPT_MX:
  1098. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "invalid rcpt MX domain");
  1099. + CHKUSER_RCPT_DELAY_ANY();
  1100. + out(CHKUSER_RCPTMX_STRING);
  1101. + break;
  1102. +
  1103. + case CHKUSER_ERR_RCPT_MX_TMP:
  1104. + chkuser_commonlog (sender->s, rcpt->s, "rejected rcpt", "temporary DNS problem");
  1105. + CHKUSER_RCPT_DELAY_ANY();
  1106. + out(CHKUSER_RCPTMX_TMP_STRING);
  1107. + break;
  1108. + }
  1109. +
  1110. +
  1111. +
  1112. +#if defined CHKUSER_WRONGRCPT_LIMIT_VARIABLE
  1113. + if ((retstat == CHKUSER_KO) || (retstat == CHKUSER_ERR_DOMAIN_MISSING)) {
  1114. + ++wrong_recipients;
  1115. + if ((INTRUSION_threshold_reached == 0) && (maxwrongrcpt_limit > 0) && (wrong_recipients >= maxwrongrcpt_limit)) {
  1116. + chkuser_commonlog (sender->s, rcpt->s, "intrusion threshold", "max number of allowed invalid rcpt");
  1117. + INTRUSION_threshold_reached = 1;
  1118. + }
  1119. + }
  1120. +#endif
  1121. +
  1122. + return CHKUSER_KO;
  1123. +}
  1124. +
  1125. +
  1126. +/*
  1127. + *
  1128. + * This routine checks for sender format and MX
  1129. + *
  1130. + */
  1131. +
  1132. +
  1133. +int chkuser_sender (stralloc *sender) {
  1134. +
  1135. +int count;
  1136. +
  1137. + if (first_time_init_flag) {
  1138. + first_time_init ();
  1139. + }
  1140. +
  1141. +#if !defined CHKUSER_ALWAYS_ON && defined CHKUSER_STARTING_VARIABLE
  1142. + if (starting_value == -1) {
  1143. + return CHKUSER_OK;
  1144. + }
  1145. +#endif
  1146. +
  1147. +#if defined CHKUSER_SENDER_FORMAT || defined CHKUSER_SENDER_MX
  1148. +
  1149. +#if defined CHKUSER_SENDER_NOCHECK_VARIABLE
  1150. +
  1151. + if (sender_nocheck == 1) {
  1152. + return CHKUSER_OK;
  1153. + }
  1154. +#endif
  1155. +
  1156. + if (sender->len <= 1) {
  1157. +#if defined CHKUSER_LOG_VALID_SENDER
  1158. + chkuser_commonlog (sender->s, "", "accepted null sender", "accepted null sender always");
  1159. +#endif
  1160. + return CHKUSER_OK;
  1161. + }
  1162. +
  1163. + count = byte_rchr(sender->s,sender->len,'@');
  1164. + if (count < sender->len) {
  1165. + if (!stralloc_copyb (&sender_user, sender->s, count)) DIE_NOMEM();
  1166. + if (!stralloc_copys (&sender_domain, sender->s + count + 1)) DIE_NOMEM();
  1167. + } else {
  1168. + if (!stralloc_copys (&sender_user, sender->s)) DIE_NOMEM();
  1169. + sender_domain.len = 0;
  1170. + }
  1171. + if (!stralloc_0 (&sender_user)) DIE_NOMEM();
  1172. + if (!stralloc_0 (&sender_domain)) DIE_NOMEM();
  1173. +
  1174. +#if defined CHKUSER_SENDER_FORMAT
  1175. + if (check_sender_address_format (&sender_user, &sender_domain) == 0) {
  1176. + chkuser_commonlog (sender->s, "", "rejected sender", "invalid sender address format");
  1177. + CHKUSER_SENDER_DELAY_ANY();
  1178. + out(CHKUSER_SENDERFORMAT_STRING);
  1179. + return CHKUSER_ERR_SENDER_FORMAT;
  1180. + }
  1181. +
  1182. +#endif
  1183. +
  1184. +#if defined CHKUSER_SENDER_MX
  1185. +
  1186. + switch (chkuser_mx_lookup(&sender_domain)) {
  1187. +
  1188. + case DNS_HARD:
  1189. + CHKUSER_SENDER_DELAY_ANY();
  1190. + out(CHKUSER_SENDERMX_STRING);
  1191. + chkuser_commonlog (sender->s, "", "rejected sender", "invalid sender MX domain");
  1192. + return CHKUSER_ERR_SENDER_MX;
  1193. + break;
  1194. +
  1195. + case DNS_SOFT:
  1196. + CHKUSER_SENDER_DELAY_ANY();
  1197. + out(CHKUSER_SENDERMX_TMP_STRING);
  1198. + chkuser_commonlog (sender->s, "", "rejected sender", "temporary DNS problem");
  1199. + return CHKUSER_ERR_SENDER_MX_TMP;
  1200. + break;
  1201. + }
  1202. +
  1203. +#if defined CHKUSER_LOG_VALID_SENDER
  1204. + chkuser_commonlog (sender->s, "", "accepted sender", "sender accepted");
  1205. +#endif
  1206. +
  1207. + return CHKUSER_OK;
  1208. +#endif
  1209. +
  1210. +#else
  1211. +
  1212. + return CHKUSER_OK;
  1213. +
  1214. +#endif
  1215. +
  1216. +}
  1217. +
  1218. +
  1219. diff -Naur qmail-1.03.orig/chkuser.h qmail-1.03/chkuser.h
  1220. --- qmail-1.03.orig/chkuser.h Thu Jan 1 01:00:00 1970
  1221. +++ qmail-1.03/chkuser.h Mon Dec 25 23:42:27 2006
  1222. @@ -0,0 +1,51 @@
  1223. +
  1224. +/*
  1225. + *
  1226. + * 'chkuser.h' v.2.0.8
  1227. + * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
  1228. + *
  1229. + * Author: Antonio Nati tonix@interazioni.it
  1230. + * All rights on this software and
  1231. + * the identifying words chkusr and chkuser kept by the author
  1232. + *
  1233. + * This software may be freely used, modified and distributed,
  1234. + * but this lines must be kept in every original or derived version.
  1235. + * Original author "Antonio Nati" and the web URL
  1236. + * "http://www.interazioni.it/opensource"
  1237. + * must be indicated in every related work or web page
  1238. + *
  1239. + */
  1240. +
  1241. +#define CHKUSER
  1242. +#define CHKUSER_VERSION "2.0.8"
  1243. +#define CHKUSER_VERSION_RL 2
  1244. +#define CHKUSER_VERSION_MJ 0
  1245. +#define CHKUSER_VERSION_MN 8
  1246. +
  1247. +#define CHKUSER_OK 1
  1248. +#define CHKUSER_RELAYING 0
  1249. +#define CHKUSER_KO -1
  1250. +#define CHKUSER_NORCPTHOSTS -10
  1251. +#define CHKUSER_ERR_AUTH_RESOURCE -20
  1252. +#define CHKUSER_ERR_MBXFULL -30
  1253. +#define CHKUSER_ERR_MAXRCPT -40
  1254. +#define CHKUSER_ERR_MAXWRONGRCPT -50
  1255. +#define CHKUSER_ERR_DOMAIN_MISSING -60
  1256. +#define CHKUSER_ERR_RCPT_FORMAT -70
  1257. +#define CHKUSER_ERR_RCPT_MX -75
  1258. +#define CHKUSER_ERR_RCPT_MX_TMP -76
  1259. +#define CHKUSER_ERR_SENDER_FORMAT -80
  1260. +#define CHKUSER_ERR_SENDER_MX -85
  1261. +#define CHKUSER_ERR_SENDER_MX_TMP -86
  1262. +#define CHKUSER_ERR_INTRUSION_THRESHOLD -90
  1263. +
  1264. +void chkuser_cleanup (int exit_value);
  1265. +int chkuser_realrcpt (stralloc *sender, stralloc *rcpt);
  1266. +int chkuser_sender (stralloc *sender);
  1267. +
  1268. +#ifdef TLS_H
  1269. +#undef _exit
  1270. +#define _exit(value) { if (ssl) ssl_free(ssl); chkuser_cleanup(value); }
  1271. +#else
  1272. +#define _exit(value) chkuser_cleanup(value);
  1273. +#endif
  1274. diff -Naur qmail-1.03.orig/chkuser_settings.h qmail-1.03/chkuser_settings.h
  1275. --- qmail-1.03.orig/chkuser_settings.h Thu Jan 1 01:00:00 1970
  1276. +++ qmail-1.03/chkuser_settings.h Mon Dec 25 23:42:27 2006
  1277. @@ -0,0 +1,373 @@
  1278. +
  1279. +/*
  1280. + *
  1281. + * 'chkuser_settings.h' v.2.0.8
  1282. + * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
  1283. + *
  1284. + * Author: Antonio Nati tonix@interazioni.it
  1285. + * All rights on this software and
  1286. + * the identifying words chkusr and chkuser kept by the author
  1287. + *
  1288. + * This software may be freely used, modified and distributed,
  1289. + * but this lines must be kept in every original or derived version.
  1290. + * Original author "Antonio Nati" and the web URL
  1291. + * "http://www.interazioni.it/opensource"
  1292. + * must be indicated in every related work or web page
  1293. + *
  1294. + */
  1295. +
  1296. +/*
  1297. + * the following line enables debugging of chkuser
  1298. + */
  1299. +/* #define CHKUSER_DEBUG */
  1300. +
  1301. +/*
  1302. + * The following line moves DEBUG output from STDOUT (default) to STDERR
  1303. + * Example of usage within sh: ./qmail-smtpd 2> /var/log/smtpd-debug.log
  1304. + */
  1305. +/* #define CHKUSER_DEBUG_STDERR */
  1306. +
  1307. +/*
  1308. + * Uncomment the following define if you want chkuser ALWAYS enabled.
  1309. + * If uncommented, it will check for rcpt existance despite any .qmail-default
  1310. + * setting.
  1311. + * So, unsomments this if you are aware that ALL rcpt in all domains will be
  1312. + * ALWAYS checked.
  1313. + */
  1314. +/* #define CHKUSER_ALWAYS_ON */
  1315. +
  1316. +/*
  1317. + * The following defines which virtual manager is used.
  1318. + * Up to know, only vpopmail, but versions with pure qmail are in the mind.
  1319. + */
  1320. +#define CHKUSER_VPOPMAIL
  1321. +
  1322. +/*
  1323. + * Uncomment the following line if you want chkuser to work depending on a VARIABLE setting
  1324. + * VALUE HERE DEFINED is the name of the variable
  1325. + * Values admitted inside the variable: NONE | ALWAYS | DOMAIN
  1326. + * NONE = chkuser will not work
  1327. + * ALWAYS = chkuser will work always
  1328. + * DOMAIN = chkuser will work depending by single domain settings
  1329. + * if CHKUSER_ALWAYS_ON is defined, this define is useless
  1330. + * if CHKUSER_STARTING_VARIABLE is defined, and no variable or no value is set, then chkuser is disabled
  1331. + */
  1332. +/* #define CHKUSER_STARTING_VARIABLE "CHKUSER_START" */
  1333. +
  1334. +/*
  1335. + * Uncomment this to enable uid/gid changing
  1336. + * (switching UID/GID is NOT compatible with TLS; you may keep this commented if you have TLS)
  1337. + */
  1338. +/* EDIT #define CHKUSER_ENABLE_UIDGID */
  1339. +
  1340. +/*
  1341. + * Uncomment this to check if a domain is ALWAYS specified in rcpt addresses
  1342. + */
  1343. +/* EDIT #define CHKUSER_DOMAIN_WANTED */
  1344. +
  1345. +/*
  1346. + * Uncomment this to check for vpopmail users
  1347. + */
  1348. +#define CHKUSER_ENABLE_USERS
  1349. +
  1350. +/*
  1351. + * Uncomment this to check for alias
  1352. + */
  1353. +#define CHKUSER_ENABLE_ALIAS
  1354. +
  1355. +/*
  1356. + * The following #define set the character used for lists extensions
  1357. + * be careful: this is a single char '-' definition, not a "string"
  1358. + */
  1359. +#define CHKUSER_EZMLM_DASH '-'
  1360. +
  1361. +/*
  1362. + * Uncomment this to set an alternative way to check for bouncing enabling;
  1363. + * with this option enabled, the file here defined
  1364. + * will be searched, inside the domain dir, in order to check if bouncing is enabled
  1365. + * The content of this file is not important, just it's existence is enough
  1366. + */
  1367. +/* #define CHKUSER_SPECIFIC_BOUNCING ".qmailchkuser-bouncing" */
  1368. +
  1369. +/*
  1370. + * This is the string to look for inside .qmail-default
  1371. + * Be careful, chkuser looks within the first 1023 characters of .qmail-default for
  1372. + * this string (despite the line containing the string is working or commented).
  1373. + */
  1374. +#define CHKUSER_BOUNCE_STRING "bounce-no-mailbox"
  1375. +
  1376. +/*
  1377. + * This is to enable auth open checking
  1378. + * it is useful to avoid bouncing if MySQL/LDAP/PostGRES/etc are down or not reachable
  1379. + */
  1380. +/* #define CHKUSER_ENABLE_VAUTH_OPEN */
  1381. +
  1382. +/*
  1383. + * Uncomment to enable logging of rejected recipients and variuos limits reached
  1384. + */
  1385. +#define CHKUSER_ENABLE_LOGGING
  1386. +
  1387. +/*
  1388. + * Uncomment to enable logging of "good" rcpts
  1389. + * valid only if CHKUSER_ENABLE_LOGGING is defined
  1390. + */
  1391. +#define CHKUSER_LOG_VALID_RCPT
  1392. +
  1393. +/*
  1394. + * Uncomment to enable usage of a variable escluding any check on the sender.
  1395. + * The variable should be set in tcp.smtp for clients, with static IP, whose mailer
  1396. + * is composing bad sender addresses
  1397. + */
  1398. +/* #define CHKUSER_SENDER_NOCHECK_VARIABLE "SENDER_NOCHECK" */
  1399. +
  1400. +/*
  1401. + * Uncomment to enable usage of "#" and "+" characters within sender address
  1402. + * This is used by SRS (Sender Rewriting Scheme) products
  1403. + */
  1404. +#define CHKUSER_ALLOW_SENDER_SRS
  1405. +
  1406. +/*
  1407. + * If you need more additional characters to be accepted within sender address
  1408. + * uncomment one of the following #define and edit the character value.
  1409. + * Be careful to use '*' (single hiphen) and NOT "*" (double hiphen) around the
  1410. + * wanted char.
  1411. + */
  1412. +/* #define CHKUSER_ALLOW_SENDER_CHAR_1 '$' */
  1413. +/* #define CHKUSER_ALLOW_SENDER_CHAR_2 '%' */
  1414. +/* #define CHKUSER_ALLOW_SENDER_CHAR_3 '£' */
  1415. +/* #define CHKUSER_ALLOW_SENDER_CHAR_4 '?' */
  1416. +/* #define CHKUSER_ALLOW_SENDER_CHAR_5 '*' */
  1417. +
  1418. +/*
  1419. + * The following #define sets the minimum length of a domain:
  1420. + * as far as I know, "k.st" is the shortest domain, so 4 characters is the
  1421. + * minimum length.
  1422. + * This value is used to check formally a domain name validity.
  1423. + * if CHKUSER_SENDER_FORMAT is undefined, no check on length is done.
  1424. + * If you comment this define, no check on length is done.
  1425. + */
  1426. +#define CHKUSER_MIN_DOMAIN_LEN 4
  1427. +
  1428. +/*
  1429. + * Uncomment to enable logging of "good" senders
  1430. + * valid only if CHKUSER_ENABLE_LOGGING is defined
  1431. + */
  1432. +#define CHKUSER_LOG_VALID_SENDER
  1433. +
  1434. +/*
  1435. + * Uncomment to define a variable which contains the max recipients number
  1436. + * this will return always error if total recipients exceed this limit.
  1437. + * The first reached, between CHKUSER_RCPT_LIMIT_VARIABLE and CHKUSER_WRONGRCPT_LIMIT_VARIABLE,
  1438. + * makes chkuser rejecting everything else
  1439. + */
  1440. +#define CHKUSER_RCPT_LIMIT_VARIABLE "CHKUSER_RCPTLIMIT"
  1441. +
  1442. +/*
  1443. + * Uncomment to define a variable which contains the max unknown recipients number
  1444. + * this will return always error if not existing recipients exceed this limit.
  1445. + * The first reached, between CHKUSER_RCPT_LIMIT_VARIABLE and CHKUSER_WRONGRCPT_LIMIT_VARIABLE,
  1446. + * makes chkuser rejecting everything else
  1447. + */
  1448. +#define CHKUSER_WRONGRCPT_LIMIT_VARIABLE "CHKUSER_WRONGRCPTLIMIT"
  1449. +
  1450. +/*
  1451. + * Uncomment to define the variable containing the percent to check for.
  1452. + * Remember to define externally (i.e. in tcp.smtp) the environment variable containing
  1453. + * the limit percent.
  1454. + * If the variable is not defined, or it is <= 0, quota checking is not performed.
  1455. + */
  1456. +#define CHKUSER_MBXQUOTA_VARIABLE "CHKUSER_MBXQUOTA"
  1457. +
  1458. +/*
  1459. + * Delay to wait for each not existing recipient
  1460. + * value is expressed in milliseconds
  1461. + */
  1462. +#define CHKUSER_ERROR_DELAY 1000
  1463. +
  1464. +/*
  1465. + * Uncomment to consider rcpt errors on address format and MX as intrusive
  1466. + *
  1467. + */
  1468. +#define CHKUSER_RCPT_DELAY_ANYERROR
  1469. +
  1470. +/*
  1471. + * Uncomment to consider sender errors on address format and MX as intrusive
  1472. + *
  1473. + */
  1474. +#define CHKUSER_SENDER_DELAY_ANYERROR
  1475. +
  1476. +#define CHKUSER_NORCPT_STRING "511 sorry, no mailbox here by that name (#5.1.1 - chkuser)\r\n"
  1477. +#define CHKUSER_RESOURCE_STRING "430 system temporary unavailable, try again later (#4.3.0 - chkuser)\r\n"
  1478. +#define CHKUSER_MBXFULL_STRING "522 sorry, recipient mailbox is full (#5.2.2 - chkuser)\r\n"
  1479. +#define CHKUSER_MAXRCPT_STRING "571 sorry, reached maximum number of recipients for one session (#5.7.1 - chkuser)\r\n"
  1480. +#define CHKUSER_MAXWRONGRCPT_STRING "571 sorry, you are violating our security policies (#5.1.1 - chkuser)\r\n"
  1481. +#define CHKUSER_DOMAINMISSING_STRING "511 sorry, you must specify a domain (#5.1.1 - chkuser)\r\n"
  1482. +#define CHKUSER_RCPTFORMAT_STRING "511 sorry, recipient address has invalid format (#5.1.1 - chkuser)\r\n"
  1483. +#define CHKUSER_RCPTMX_STRING "511 sorry, can't find a valid MX for rcpt domain (#5.1.1 - chkuser)\r\n"
  1484. +#define CHKUSER_SENDERFORMAT_STRING "571 sorry, sender address has invalid format (#5.7.1 - chkuser)\r\n"
  1485. +#define CHKUSER_SENDERMX_STRING "511 sorry, can't find a valid MX for sender domain (#5.1.1 - chkuser)\r\n"
  1486. +#define CHKUSER_INTRUSIONTHRESHOLD_STRING "571 sorry, you are violating our security policies (#5.7.1 - chkuser)\r\n"
  1487. +#define CHKUSER_NORELAY_STRING "553 sorry, that domain isn't in my list of allowed rcpthosts (#5.5.3 - chkuser)\r\n"
  1488. +
  1489. +/***************************************************
  1490. + *
  1491. + * new/modified defines in/from 2.0.6
  1492. + *
  1493. + **************************************************/
  1494. +
  1495. +/*
  1496. + * Before version 5.3.25, vpopmail used the function vget_real_domain()
  1497. + * to get the real name of a domain (useful if rcpt domain is aliasing
  1498. + * another domain).
  1499. + * From version 5.3.25, this call is not available and has been
  1500. + * substituted by other calls.
  1501. + *
  1502. + * must be enabled if vpopmail version< 5.3.5
  1503. + * must be disabled if vpopmail version => 5.3.5 *
  1504. + */
  1505. +/* #define CHKUSER_ENABLE_VGET_REAL_DOMAIN */
  1506. +
  1507. +/***************************************************
  1508. + *
  1509. + * new/modified defines in/from 2.0.7
  1510. + *
  1511. + **************************************************/
  1512. +
  1513. +/*
  1514. + * Uncomment next define to accept recipients for
  1515. + * aliases that have a -default extension
  1516. + */
  1517. +#define CHKUSER_ENABLE_ALIAS_DEFAULT
  1518. +
  1519. +
  1520. +/*
  1521. + * Uncomment to enable usage of "#" and "+" characters within rcpt address
  1522. + * This is used by SRS (Sender Rewriting Scheme) products
  1523. + */
  1524. +#define CHKUSER_ALLOW_RCPT_SRS
  1525. +
  1526. +/*
  1527. + * If you need more additional characters to be accepted within rcpt address
  1528. + * uncomment one of the following #define and edit the character value.
  1529. + * Be careful to use '*' (single hiphen) and NOT "*" (double hiphen) around the
  1530. + * wanted char.
  1531. + */
  1532. +/* #define CHKUSER_ALLOW_RCPT_CHAR_1 '$' */
  1533. +/* #define CHKUSER_ALLOW_RCPT_CHAR_2 '%' */
  1534. +/* #define CHKUSER_ALLOW_RCPT_CHAR_3 '£' */
  1535. +/* #define CHKUSER_ALLOW_RCPT_CHAR_4 '?' */
  1536. +/* #define CHKUSER_ALLOW_RCPT_CHAR_5 '*' */
  1537. +
  1538. +/*
  1539. + * This define has been eliminated.
  1540. + * Turning it ON or OFF has no effect, as we consider the existence
  1541. + * of #define VALIAS inside ~vpopmail/include/vpopmail_config.h
  1542. + */
  1543. +/* #define CHKUSER_ENABLE_VALIAS */
  1544. +
  1545. +/*
  1546. + * Uncomment this to enable user extension on names (i.e. TMDA)
  1547. + * (for mailing lists this is done without checking this define)
  1548. + * This define substitutes #define CHKUSER_ENABLE_EXTENSIONS
  1549. + */
  1550. +/* #define CHKUSER_ENABLE_USERS_EXTENSIONS */
  1551. +
  1552. +/*
  1553. + * Enables checking for EZMLM lists
  1554. + * this define substitutes #define CHKUSER_ENABLE_LISTS
  1555. + *
  1556. + */
  1557. +#define CHKUSER_ENABLE_EZMLM_LISTS
  1558. +
  1559. +/*
  1560. + * Help identifying remote authorized IPs giving them a descriptive name
  1561. + * Can be put in tcp.smtp, and will be displayed inside chkuser log
  1562. + * Substitutes RELAYCLIENT in chkuser logging
  1563. + */
  1564. +#define CHKUSER_IDENTIFY_REMOTE_VARIABLE "CHKUSER_IDENTIFY"
  1565. +
  1566. +/*
  1567. + * The following #define set the character used for users extensions
  1568. + * be careful: this is a single char '-' definition, not a "string"
  1569. + * this define substitutes #define CHKUSER_EXTENSION_DASH
  1570. + * MUST be defined if CHKUSER_ENABLE_USERS_EXTENSIONS is defined
  1571. + */
  1572. +#define CHKUSER_USERS_DASH '-'
  1573. +
  1574. +/*
  1575. + * New error strings for SOFT DNS problems
  1576. + */
  1577. +#define CHKUSER_RCPTMX_TMP_STRING "451 DNS temporary failure (#4.5.1 - chkuser)\r\n"
  1578. +#define CHKUSER_SENDERMX_TMP_STRING "451 DNS temporary failure (#4.5.1 - chkuser)\r\n"
  1579. +
  1580. +/*
  1581. + * Enables checking for mailman lists
  1582. + *
  1583. + */
  1584. +/* #define CHKUSER_ENABLE_MAILMAN_LISTS */
  1585. +
  1586. +/*
  1587. + * Identifies the pattern string to be searched within mailman aliases
  1588. + *
  1589. + */
  1590. +#define CHKUSER_MAILMAN_STRING "mailman"
  1591. +
  1592. +/*
  1593. + * The following #define set the character used for mailman lists extensions
  1594. + * be careful: this is a single char '-' definition, not a "string"
  1595. + */
  1596. +#define CHKUSER_MAILMAN_DASH '-'
  1597. +
  1598. +
  1599. +/*
  1600. + * Enables final clean-up routine of chkuser
  1601. + * This routine cleans open DB connections used for checking users and valiases
  1602. + */
  1603. +#define CHKUSER_DB_CLEANUP
  1604. +
  1605. +/***************************************************
  1606. + *
  1607. + * new/modified defines in/from 2.0.8
  1608. + *
  1609. + **************************************************/
  1610. +
  1611. +/*
  1612. + * The following defines are NO MORE used. NULL SENDER rejecting breaks RFC
  1613. + * compatibility, and makes harder to handle e-mail receipts.
  1614. + * Please comment or delete them from your chkuser_settings.h.
  1615. + */
  1616. +/* #define CHKUSER_ACCEPT_NULL_SENDER */
  1617. +/* #define CHKUSER_ENABLE_NULL_SENDER_WITH_TCPREMOTEHOST */
  1618. +
  1619. +/*
  1620. + * Uncomment to enable checking of user and domain format for rcpt addresses
  1621. + * user = [a-z0-9_-]
  1622. + * domain = [a-z0-9-.] with not consecutive "-.", not leading or ending "-."
  1623. + */
  1624. +/* #define CHKUSER_RCPT_FORMAT */
  1625. +
  1626. +/*
  1627. + * Uncomment to enable checking of domain MX for rcpt addresses
  1628. + * It works on any rcpt address domain that is not inside rcpthosts
  1629. + */
  1630. +/* #define CHKUSER_RCPT_MX */
  1631. +
  1632. +/*
  1633. + * Uncomment to enable checking of user and domain format for sender address
  1634. + * user = [a-z0-9_-]
  1635. + * domain = [a-z0-9-.] with not consecutive "-.", not leading or ending "-."
  1636. + */
  1637. +/* #define CHKUSER_SENDER_FORMAT */
  1638. +
  1639. +/*
  1640. + * Uncomment to enable checking of domain MX for sender address
  1641. + * it works on the first rcpt address, despite of any domain setting on chkuser
  1642. + */
  1643. +/* #define CHKUSER_SENDER_MX */
  1644. +
  1645. +/*
  1646. + * Delay to add, for each not existing recipient, to the initial CHKUSER_ERROR_DELAY value
  1647. + * value is expressed in milliseconds
  1648. + */
  1649. +#define CHKUSER_ERROR_DELAY_INCREASE 300
  1650. +
  1651. diff -Naur qmail-1.03.orig/conf-cc qmail-1.03/conf-cc
  1652. --- qmail-1.03.orig/conf-cc Sun Dec 24 15:24:55 2006
  1653. +++ qmail-1.03/conf-cc Mon Dec 25 23:42:57 2006
  1654. @@ -1 +1 @@
  1655. -cc -O -pipe -funroll-loops -march=pentiumpro -I/usr/include -L/usr/lib -DTLS
  1656. +cc -O -pipe -funroll-loops -march=pentiumpro -I/usr/include -L/usr/lib -DTLS -I/usr/local/vpopmail/include
  1657. diff -Naur qmail-1.03.orig/qmail-smtpd.c qmail-1.03/qmail-smtpd.c
  1658. --- qmail-1.03.orig/qmail-smtpd.c Mon Dec 25 23:39:28 2006
  1659. +++ qmail-1.03/qmail-smtpd.c Mon Dec 25 23:41:17 2006
  1660. @@ -45,6 +45,10 @@
  1661. int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
  1662. #endif
  1663.  
  1664. +/* start chkuser code */
  1665. +#include "chkuser.h"
  1666. +/* end chkuser code */
  1667. +
  1668. int safewrite(fd,buf,len) int fd; char *buf; int len;
  1669. {
  1670. int r;
  1671. @@ -330,6 +334,9 @@
  1672. flagsize = 0;
  1673. mailfrom_parms(arg);
  1674. if (flagsize) { err_size(); return; }
  1675. +/* start chkuser code */
  1676. + if (chkuser_sender (&addr) != CHKUSER_OK) { return; }
  1677. +/* end chkuser code */
  1678. if (!(spp_val = spp_mail())) return;
  1679. flagbarfspf = 0;
  1680. if (spp_val == 1) {
  1681. @@ -397,9 +404,8 @@
  1682. if (!addrparse(arg)) { err_syntax(); return; }
  1683. if (flagbarf) { err_bmf(); return; }
  1684. if (flagbarfspf) { err_spf(); return; }
  1685. - if (!relayclient) allowed = addrallowed();
  1686. - else allowed = 1;
  1687. - if (!(spp_val = spp_rcpt(allowed))) return;
  1688. +/*
  1689. + * Original code substituted by chkuser code
  1690. if (relayclient) {
  1691. --addr.len;
  1692. if (!stralloc_cats(&addr,relayclient)) die_nomem();
  1693. @@ -404,6 +413,23 @@
  1694. else if (spp_val == 1) {
  1695. if (!allowed) { err_nogateway(); return; }
  1696. }
  1697. + * end of substituted code
  1698. + */
  1699. +
  1700. +/* start chkuser code */
  1701. + switch (chkuser_realrcpt (&mailfrom, &addr)) {
  1702. + case CHKUSER_KO:
  1703. + return;
  1704. + break;
  1705. +
  1706. + case CHKUSER_RELAYING:
  1707. + --addr.len;
  1708. + if (!stralloc_cats(&addr,relayclient)) die_nomem();
  1709. + if (!stralloc_0(&addr)) die_nomem();
  1710. + break;
  1711. + }
  1712. +/* end chkuser code */
  1713. + if (!(spp_val = spp_rcpt(1))) return;
  1714. spp_rcpt_accepted();
  1715. if (!stralloc_cats(&rcptto,"T")) die_nomem();
  1716. if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
  1717.