Download | Plain Text | No Line Numbers


  1. diff -ruN netqmail-1.05-tls-new/Makefile netqmail-1.05/Makefile
  2. --- Makefile 2006-04-02 17:02:34.000000000 -0400
  3. +++ Makefile 2006-04-02 17:09:20.000000000 -0400
  4. @@ -1536,19 +1536,24 @@
  5. auto_split.h spf.h
  6. ./compile qmail-showctl.c
  7.  
  8. +qmail-spp.o: \
  9. +compile qmail-spp.c readwrite.h stralloc.h substdio.h control.h str.h \
  10. +byte.h env.h exit.h wait.h fork.h fd.h fmt.h getln.h
  11. + ./compile qmail-spp.c
  12. +
  13. qmail-smtpd: \
  14. load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
  15. timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o constmap.o \
  16. received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a fd.a wait.a \
  17. datetime.a getln.a open.a sig.a case.a env.a stralloc.a alloc.a substdio.a \
  18. -error.a str.a fs.a auto_qmail.o base64.o socket.lib dns.lib
  19. +error.a str.a fs.a auto_qmail.o base64.o qmail-spp.o socket.lib dns.lib
  20. ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
  21. timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o \
  22. tls.o ssl_timeoutio.o ndelay.a -L/usr/lib -lssl -lcrypto \
  23. constmap.o received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a \
  24. - fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
  25. + fd.a wait.a datetime.a getln.a open.a sig.a case.a qmail-spp.o env.a stralloc.a \
  26. alloc.a substdio.a error.a fs.a auto_qmail.o base64.o \
  27. str.a `cat socket.lib` `cat dns.lib`
  28.  
  29. qmail-smtpd.0: \
  30. qmail-smtpd.8
  31. @@ -1557,7 +1562,7 @@
  32. qmail-smtpd.o: \
  33. compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
  34. substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
  35. -error.h ipme.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ip.h qmail.h \
  36. +error.h ipme.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ip.h qmail.h qmail-spp.h \
  37. substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
  38. exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h spf.h
  39. ./compile qmail-smtpd.c
  40. diff -ruN netqmail-1.05-tls-new/qmail-smtpd.c netqmail-1.05/qmail-smtpd.c
  41. --- qmail-smtpd.c 2006-04-02 17:02:34.000000000 -0400
  42. +++ qmail-smtpd.c 2006-04-02 17:19:33.000000000 -0400
  43. @@ -24,6 +24,9 @@
  44. #include "commands.h"
  45. #include "wait.h"
  46. #include "spf.h"
  47. +#include "qmail-spp.h"
  48. +
  49. +int spp_val;
  50.  
  51. #define CRAM_MD5
  52. #define AUTHSLEEP 5
  53. @@ -151,6 +154,7 @@
  54. if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
  55. if (timeout <= 0) timeout = 1;
  56. if (rcpthosts_init() == -1) die_control();
  57. + if (spp_init() == -1) die_control();
  58.  
  59. bmfok = control_readfile(&bmf,"control/badmailfrom",0);
  60. if (bmfok == -1) die_control();
  61. @@ -268,6 +272,7 @@
  62. int seenmail = 0;
  63. int flagbarf; /* defined if seenmail */
  64. int flagbarfspf;
  65. +int allowed;
  66. int flagsize;
  67. stralloc spfbarfmsg = {0};
  68. stralloc mailfrom = {0};
  69. @@ -335,6 +340,7 @@
  70.  
  71. void smtp_helo(arg) char *arg;
  72. {
  73. + if(!spp_helo(arg)) return;
  74. smtp_greet("250 "); out("\r\n");
  75. seenmail = 0; dohelo(arg);
  76. }
  77. @@ -345,6 +351,7 @@
  78. #endif
  79. char size[FMT_ULONG];
  80. size[fmt_ulong(size,(unsigned int) databytes)] = 0;
  81. + if(!spp_helo(arg)) return;
  82. smtp_greet("250-");
  83. #ifdef TLS
  84. if (!ssl && (stat("control/servercert.pem",&st) == 0))
  85. @@ -362,6 +369,7 @@
  86. }
  87. void smtp_rset()
  88. {
  89. + spp_rset();
  90. seenmail = 0;
  91. out("250 flushed\r\n");
  92. }
  93. @@ -371,8 +379,10 @@
  94. flagsize = 0;
  95. mailfrom_parms(arg);
  96. if (flagsize) { err_size(); return; }
  97. + if (!(spp_val = spp_mail())) return;
  98. + flagbarfspf = 0;
  99. + if (spp_val == 1) {
  100. flagbarf = bmfcheck();
  101. - flagbarfspf = 0;
  102. if (spfbehavior && !relayclient)
  103. {
  104. switch(r = spfcheck()) {
  105. @@ -375,6 +384,7 @@
  106. }
  107. else
  108. env_unset("SPFRESULT");
  109. + }
  110. seenmail = 1;
  111. if (!stralloc_copys(&rcptto,"")) die_nomem();
  112. if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
  113. @@ -382,13 +392,18 @@
  114. if (!addrparse(arg)) { err_syntax(); return; }
  115. if (flagbarf) { err_bmf(); return; }
  116. if (flagbarfspf) { err_spf(); return; }
  117. + if (!relayclient) allowed = addrallowed();
  118. + else allowed = 1;
  119. + if (!(spp_val = spp_rcpt(allowed))) return;
  120. if (relayclient) {
  121. --addr.len;
  122. if (!stralloc_cats(&addr,relayclient)) die_nomem();
  123. if (!stralloc_0(&addr)) die_nomem();
  124. }
  125. - else
  126. - if (!addrallowed()) { err_nogateway(); return; }
  127. + else if (spp_val == 1) {
  128. + if (!allowed) { err_nogateway(); return; }
  129. + }
  130. + spp_rcpt_accepted();
  131. if (!stralloc_cats(&rcptto,"T")) die_nomem();
  132. if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
  133. if (!stralloc_0(&rcptto)) die_nomem();
  134. @@ -508,6 +523,7 @@
  135.  
  136. if (!seenmail) { err_wantmail(); return; }
  137. if (!rcptto.len) { err_wantrcpt(); return; }
  138. + if (!spp_data()) return;
  139. seenmail = 0;
  140. if (databytes) bytestooverflow = databytes + 1;
  141. if (qmail_open(&qqt) == -1) { err_qqt(); return; }
  142. @@ -515,6 +531,8 @@
  143.  
  144. received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
  145. spfreceived();
  146. + qmail_put(&qqt,sppheaders.s,sppheaders.len); /* set in qmail-spp.c */
  147. + spp_rset();
  148. blast(&hops);
  149. hops = (hops >= MAXHOPS);
  150. if (hops) qmail_fail(&qqt);
  151. @@ -738,6 +756,7 @@
  152.  
  153. switch (authcmds[i].fun(arg)) {
  154. case 0:
  155. + if (!spp_auth(authcmds[i].text, user.s)) return;
  156. flagauth = 1;
  157. protocol = "ESMTPA";
  158. relayclient = "";
  159. @@ -1016,8 +1035,10 @@
  160. if (chdir(auto_qmail) == -1) die_control();
  161. setup();
  162. if (ipme_init() != 1) die_ipme();
  163. + if (spp_connect()) {
  164. smtp_greet("220 ");
  165. out(" ESMTP\r\n");
  166. + }
  167. if (commands(&ssin,&smtpcommands) == 0) die_read();
  168. die_nomem();
  169. }
  170. diff -ruN netqmail-1.05-tls-new/qmail-spp.c netqmail-1.05/qmail-spp.c
  171. --- qmail-spp.c 1969-12-31 19:00:00.000000000 -0500
  172. +++ qmail-spp.c 2006-04-02 17:22:52.000000000 -0400
  173. @@ -0,0 +1,259 @@
  174. +/*
  175. + * Copyright (C) 2004-2005 Pawel Foremski <pjf@asn.pl>
  176. + *
  177. + * This program is free software; you can redistribute it and/or
  178. + * modify it under the terms of the GNU General Public License
  179. + * as published by the Free Software Foundation; either
  180. + * version 2 of the License, or (at your option) any later
  181. + * version.
  182. + *
  183. + * This program is distributed in the hope that it will be useful,
  184. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  185. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  186. + * GNU General Public License for more details.
  187. + *
  188. + * You should have received a copy of the GNU General Public License
  189. + * along with this program; if not, write to the Free Software Foundation,
  190. + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  191. + *
  192. + *** Note
  193. + *
  194. + * This is the core of qmail-spp patch for qmail
  195. + *
  196. + * Why I made it a separate file? Because I wanted qmail-spp to apply more
  197. + * cleanly on heavily patched qmail sources and to make it bit simpler to
  198. + * maintain, so don't treat it as a library.
  199. + *
  200. + * "..." comments marks places where code for other SMTP commands should be
  201. + * added, if needed.
  202. + *
  203. + */
  204. +
  205. +#include "readwrite.h"
  206. +#include "stralloc.h"
  207. +#include "substdio.h"
  208. +#include "control.h"
  209. +#include "str.h"
  210. +#include "byte.h"
  211. +#include "env.h"
  212. +#include "exit.h"
  213. +#include "wait.h"
  214. +#include "fork.h"
  215. +#include "fd.h"
  216. +#include "fmt.h"
  217. +#include "getln.h"
  218. +
  219. +/* stuff needed from qmail-smtpd */
  220. +extern void flush();
  221. +extern void out();
  222. +extern void die_nomem();
  223. +extern stralloc addr;
  224. +/* *** */
  225. +
  226. +stralloc sppheaders = {0};
  227. +static int spprun = 0;
  228. +static int sppfok = 0;
  229. +static int sppret;
  230. +static stralloc sppf = {0};
  231. +static stralloc plugins_dummy = {0}, plugins_connect = {0}, plugins_helo = {0}, plugins_mail = {0},
  232. + plugins_rcpt = {0}, plugins_data = {0}, plugins_auth = {0}; /* ... */
  233. +static stralloc error_mail = {0}, error_rcpt = {0}, error_data = {0}; /* ... */
  234. +static stralloc sppmsg = {0};
  235. +static char rcptcountstr[FMT_ULONG];
  236. +static unsigned long rcptcount;
  237. +static unsigned long rcptcountall;
  238. +static substdio ssdown;
  239. +static char downbuf[128];
  240. +
  241. +static void err_spp(s1, s2) char *s1, *s2; { out("451 qmail-spp failure: "); out(s1); out(": "); out(s2); out(" (#4.3.0)\r\n"); }
  242. +
  243. +int spp_init()
  244. +{
  245. + int i, len = 0;
  246. + stralloc *plugins_to;
  247. + char *x, *conffile = "control/smtpplugins";
  248. +
  249. + if (!env_get("NOSPP")) {
  250. + spprun = 1;
  251. + plugins_to = &plugins_dummy;
  252. + x = env_get("SPPCONFFILE");
  253. + if (x && *x) conffile = x;
  254. + sppfok = control_readfile(&sppf, conffile, 0);
  255. + if (sppfok != 1) return -1;
  256. + for (i = 0; i < sppf.len; i += len) {
  257. + len = str_len(sppf.s + i) + 1;
  258. + if (sppf.s[i] == '[')
  259. + switch (sppf.s[i + 1]) {
  260. + case 'c': plugins_to = &plugins_connect; break;
  261. + case 'h': plugins_to = &plugins_helo; break;
  262. + case 'm': plugins_to = &plugins_mail; break;
  263. + case 'r': plugins_to = &plugins_rcpt; break;
  264. + case 'd': plugins_to = &plugins_data; break;
  265. + case 'a': plugins_to = &plugins_auth; break;
  266. + /* ... */
  267. + default: plugins_to = &plugins_dummy;
  268. + }
  269. + else
  270. + if (!stralloc_catb(plugins_to, sppf.s + i, len)) die_nomem();
  271. + }
  272. + }
  273. +
  274. + return 0;
  275. +}
  276. +
  277. +void sppout() { if (sppmsg.len) out(sppmsg.s); out("\r\n"); }
  278. +
  279. +int spp(plugins, addrenv) stralloc *plugins; char *addrenv;
  280. +{
  281. + static int pipes[2];
  282. + static int i, pid, wstat, match, last;
  283. + static stralloc data = {0};
  284. + static char *(args[4]);
  285. + static stralloc *errors_to;
  286. +
  287. + if (!spprun) return 1;
  288. + if (addrenv) if (!env_put2(addrenv, addr.s)) die_nomem();
  289. + last = 0;
  290. +
  291. + for (i = 0; i < plugins->len; i += str_len(plugins->s + i) + 1) {
  292. + if (plugins->s[i] == ':')
  293. + { args[0] = "/bin/sh"; args[1] = "-c"; args[2] = plugins->s + i + 1; args[3] = 0; }
  294. + else
  295. + { args[0] = plugins->s + i; args[1] = 0; }
  296. +
  297. + if (pipe(pipes) == -1)
  298. + { err_spp(plugins->s + i, "can't pipe()"); return 0; }
  299. +
  300. + switch (pid = vfork()) {
  301. + case -1:
  302. + err_spp(plugins->s + i, "vfork() failed");
  303. + return 0;
  304. + case 0:
  305. + close(0); close(pipes[0]); fd_move(1, pipes[1]);
  306. + execv(*args, args);
  307. + _exit(120);
  308. + }
  309. +
  310. + close(pipes[1]);
  311. + substdio_fdbuf(&ssdown, read, pipes[0], downbuf, sizeof(downbuf));
  312. + do {
  313. + if (getln(&ssdown, &data, &match, '\n') == -1) die_nomem();
  314. + if (data.len > 1) {
  315. + data.s[data.len - 1] = 0;
  316. + switch (data.s[0]) {
  317. + case 'H':
  318. + if (!stralloc_catb(&sppheaders, data.s + 1, data.len - 2)) die_nomem();
  319. + if (!stralloc_append(&sppheaders, "\n")) die_nomem();
  320. + break;
  321. + case 'C':
  322. + if (addrenv) {
  323. + if (!stralloc_copyb(&addr, data.s + 1, data.len - 1)) die_nomem();
  324. + if (!env_put2(addrenv, addr.s)) die_nomem();
  325. + }
  326. + break;
  327. + case 'S': if (!env_put(data.s + 1)) die_nomem(); break;
  328. + case 'U': if (!env_unset(data.s + 1)) die_nomem(); break;
  329. + case 'A': spprun = 0;
  330. + case 'O':
  331. + case 'N':
  332. + case 'D': last = 1; match = 0; break;
  333. + case 'E':
  334. + case 'R': last = 1; match = 0;
  335. + case 'P': out(data.s + 1); out("\r\n"); break;
  336. + case 'L':
  337. + switch (data.s[1]) {
  338. + case 'M': errors_to = &error_mail; break;
  339. + case 'R': errors_to = &error_rcpt; break;
  340. + case 'D': errors_to = &error_data; break;
  341. + /* ... */
  342. + default: errors_to = 0;
  343. + }
  344. + if (errors_to) {
  345. + if (!stralloc_catb(errors_to, data.s + 2, data.len - 3)) die_nomem();
  346. + if (!stralloc_catb(errors_to, "\r\n", 2)) die_nomem();
  347. + }
  348. + break;
  349. + }
  350. + }
  351. + } while (match);
  352. +
  353. + close(pipes[0]);
  354. + if (wait_pid(&wstat,pid) == -1) { err_spp(plugins->s + i, "wait_pid() failed"); return 0; }
  355. + if (wait_crashed(wstat)) { err_spp(plugins->s + i, "child crashed"); return 0; }
  356. + if (wait_exitcode(wstat) == 120) { err_spp(plugins->s + i, "can't execute"); return 0; }
  357. +
  358. + if (last)
  359. + switch (*data.s) {
  360. + case 'E': return 0;
  361. + case 'A':
  362. + case 'N': return 1;
  363. + case 'O': return 2;
  364. + case 'R':
  365. + case 'D': flush(); _exit(0);
  366. + }
  367. + }
  368. +
  369. + return 1;
  370. +}
  371. +
  372. +int spp_errors(errors) stralloc *errors;
  373. +{
  374. + if (!errors->len) return 1;
  375. + if (!stralloc_0(errors)) die_nomem();
  376. + out(errors->s);
  377. + return 0;
  378. +}
  379. +
  380. +int spp_connect() { return spp(&plugins_connect, 0); }
  381. +
  382. +int spp_helo(arg) char *arg;
  383. +{
  384. + if (!env_put2("SMTPHELOHOST", arg)) die_nomem();
  385. + return spp(&plugins_helo, 0);
  386. +}
  387. +
  388. +void spp_rset()
  389. +{
  390. + if (!stralloc_copys(&sppheaders, "")) die_nomem();
  391. + if (!stralloc_copys(&error_mail, "")) die_nomem();
  392. + if (!stralloc_copys(&error_rcpt, "")) die_nomem();
  393. + if (!stralloc_copys(&error_data, "")) die_nomem();
  394. + /* ... */
  395. + rcptcount = rcptcountall = 0;
  396. +}
  397. +
  398. +int spp_mail()
  399. +{
  400. + if (!spp_errors(&error_mail)) return 0;
  401. + rcptcount = rcptcountall = 0;
  402. + return spp(&plugins_mail, "SMTPMAILFROM");
  403. +}
  404. +
  405. +int spp_rcpt(allowed) int allowed;
  406. +{
  407. + if (!spp_errors(&error_rcpt)) return 0;
  408. + rcptcountstr[fmt_ulong(rcptcountstr, rcptcount)] = 0;
  409. + if (!env_put2("SMTPRCPTCOUNT", rcptcountstr)) die_nomem();
  410. + rcptcountstr[fmt_ulong(rcptcountstr, ++rcptcountall)] = 0;
  411. + if (!env_put2("SMTPRCPTCOUNTALL", rcptcountstr)) die_nomem();
  412. + if (!env_put2("SMTPRCPTHOSTSOK", allowed ? "1" : "0")) die_nomem();
  413. + sppret = spp(&plugins_rcpt, "SMTPRCPTTO");
  414. + return sppret;
  415. +}
  416. +
  417. +void spp_rcpt_accepted() { rcptcount++; }
  418. +
  419. +int spp_data()
  420. +{
  421. + if (!spp_errors(&error_data)) return 0;
  422. + return spp(&plugins_data, 0);
  423. +}
  424. +
  425. +int spp_auth(method, user) char *method, *user;
  426. +{
  427. + if (!env_put2("SMTPAUTHMETHOD", method)) die_nomem();
  428. + if (!env_put2("SMTPAUTHUSER", user)) die_nomem();
  429. + return spp(&plugins_auth, 0);
  430. +}
  431. +
  432. +/* ... */
  433. diff -ruN netqmail-1.05-tls-new/qmail-spp.h netqmail-1.05/qmail-spp.h
  434. --- qmail-spp.h 1969-12-31 19:00:00.000000000 -0500
  435. +++ qmail-spp.h 2006-04-02 17:23:10.000000000 -0400
  436. @@ -0,0 +1,14 @@
  437. +#ifndef QMAIL_SPP_H
  438. +#define QMAIL_SPP_H
  439. +
  440. +extern stralloc sppheaders;
  441. +extern int spp_init();
  442. +extern int spp_connect();
  443. +extern int spp_helo();
  444. +extern void spp_rset();
  445. +extern int spp_mail();
  446. +extern int spp_rcpt();
  447. +extern int spp_data();
  448. +extern int spp_auth();
  449. +
  450. +#endif
  451.