smtpd.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208
  1. #include "common.h"
  2. #include "smtpd.h"
  3. #include "smtp.h"
  4. #include "ip.h"
  5. #include <mp.h>
  6. #include <libsec.h>
  7. #include <auth.h>
  8. #include "../smtp/y.tab.h"
  9. char *me;
  10. char *him="";
  11. char *dom;
  12. process *pp;
  13. String *mailer;
  14. NetConnInfo *nci;
  15. int filterstate = ACCEPT;
  16. int trusted;
  17. int logged;
  18. int rejectcount;
  19. int hardreject;
  20. ulong peerip;
  21. Biobuf bin;
  22. int debug;
  23. int fflag;
  24. int rflag;
  25. int sflag;
  26. int authenticate;
  27. int authenticated;
  28. int passwordinclear;
  29. char *tlscert;
  30. List senders;
  31. List rcvers;
  32. List ourdoms;
  33. List badguys;
  34. int pipemsg(int*);
  35. String* startcmd(void);
  36. int rejectcheck(void);
  37. String* mailerpath(char*);
  38. static int
  39. catchalarm(void *a, char *msg)
  40. {
  41. USED(a);
  42. if(strstr(msg, "alarm")){
  43. if(senders.first && rcvers.first)
  44. syslog(0, "smtpd", "note: %s->%s: %s\n", s_to_c(senders.first->p),
  45. s_to_c(rcvers.first->p), msg);
  46. else
  47. syslog(0, "smtpd", "note: %s\n", msg);
  48. }
  49. if(pp){
  50. syskillpg(pp->pid); /* perhaps should wait also?? */
  51. proc_free(pp);
  52. pp = 0;
  53. }
  54. return 0;
  55. }
  56. /* override string error functions to do something reasonable */
  57. void
  58. s_error(char *f, char *status)
  59. {
  60. char errbuf[Errlen];
  61. errbuf[0] = 0;
  62. rerrstr(errbuf, sizeof(errbuf));
  63. if(f && *f)
  64. reply("452 out of memory %s: %s\r\n", f, errbuf);
  65. else
  66. reply("452 out of memory %s\r\n", errbuf);
  67. syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys);
  68. exits(status);
  69. }
  70. void
  71. main(int argc, char **argv)
  72. {
  73. char *p, buf[1024];
  74. String *s;
  75. Link *l;
  76. uchar addr[IPv4addrlen];
  77. char *netdir;
  78. netdir = nil;
  79. ARGBEGIN{
  80. case 'd':
  81. debug++;
  82. break;
  83. case 'n': /* log peer ip address */
  84. netdir = ARGF();
  85. break;
  86. case 'f': /* disallow relaying */
  87. fflag = 1;
  88. break;
  89. case 'h': /* default domain name */
  90. dom = ARGF();
  91. break;
  92. case 'k': /* prohibited ip address */
  93. p = ARGF();
  94. if (p){
  95. s = s_new();
  96. s_append(s, p);
  97. listadd(&badguys, s);
  98. }
  99. break;
  100. case 'm': /* set mail command */
  101. p = ARGF();
  102. if(p)
  103. mailer = mailerpath(p);
  104. break;
  105. case 'r':
  106. rflag = 1; /* verify sender's domain */
  107. break;
  108. case 's': /* save blocked messages */
  109. sflag = 1;
  110. break;
  111. case 'a':
  112. authenticate = 1;
  113. break;
  114. case 'p':
  115. passwordinclear = 1;
  116. break;
  117. case 'c':
  118. tlscert = ARGF();
  119. break;
  120. case 't':
  121. fprint(2, "%s: the -t option is no longer supported, see -c\n", argv0);
  122. tlscert = "/sys/lib/ssl/smtpd-cert.pem";
  123. break;
  124. default:
  125. fprint(2, "usage: smtpd [-dfhrs] [-n net] [-c cert]\n");
  126. exits("usage");
  127. }ARGEND;
  128. nci = getnetconninfo(netdir, 0);
  129. if(nci == nil)
  130. sysfatal("can't get remote system's address");
  131. if(mailer == nil)
  132. mailer = mailerpath("send");
  133. v4parseip(addr, nci->rsys);
  134. peerip = nhgetl(addr);
  135. /* check if this IP address is banned */
  136. for(l = badguys.first; l; l = l->next)
  137. if(cidrcheck(s_to_c(l->p)))
  138. exits("banned");
  139. if(debug){
  140. close(2);
  141. snprint(buf, sizeof(buf), "%s/smtpd", UPASLOG);
  142. if (open(buf, OWRITE) >= 0) {
  143. seek(2, 0, 2);
  144. fprint(2, "%d smtpd %s\n", getpid(), thedate());
  145. } else
  146. debug = 0;
  147. }
  148. getconf();
  149. Binit(&bin, 0, OREAD);
  150. chdir(UPASLOG);
  151. me = sysname_read();
  152. if(dom == 0 || dom[0] == 0)
  153. dom = domainname_read();
  154. if(dom == 0 || dom[0] == 0)
  155. dom = me;
  156. sayhi();
  157. parseinit();
  158. /* allow 45 minutes to parse the header */
  159. atnotify(catchalarm, 1);
  160. alarm(45*60*1000);
  161. zzparse();
  162. exits(0);
  163. }
  164. void
  165. listfree(List *l)
  166. {
  167. Link *lp;
  168. Link *next;
  169. for(lp = l->first; lp; lp = next){
  170. next = lp->next;
  171. s_free(lp->p);
  172. free(lp);
  173. }
  174. l->first = l->last = 0;
  175. }
  176. void
  177. listadd(List *l, String *path)
  178. {
  179. Link *lp;
  180. lp = (Link *)malloc(sizeof(Link));
  181. lp->p = path;
  182. lp->next = 0;
  183. if(l->last)
  184. l->last->next = lp;
  185. else
  186. l->first = lp;
  187. l->last = lp;
  188. }
  189. #define SIZE 4096
  190. int
  191. reply(char *fmt, ...)
  192. {
  193. char buf[SIZE], *out;
  194. va_list arg;
  195. int n;
  196. va_start(arg, fmt);
  197. out = vseprint(buf, buf+SIZE, fmt, arg);
  198. va_end(arg);
  199. n = (long)(out-buf);
  200. if(debug) {
  201. seek(2, 0, 2);
  202. write(2, buf, n);
  203. }
  204. write(1, buf, n);
  205. return n;
  206. }
  207. void
  208. reset(void)
  209. {
  210. if(rejectcheck())
  211. return;
  212. listfree(&rcvers);
  213. listfree(&senders);
  214. if(filterstate != DIALUP){
  215. logged = 0;
  216. filterstate = ACCEPT;
  217. }
  218. reply("250 ok\r\n");
  219. }
  220. void
  221. sayhi(void)
  222. {
  223. reply("220 %s SMTP\r\n", dom);
  224. }
  225. void
  226. hello(String *himp, int extended)
  227. {
  228. if(rejectcheck())
  229. return;
  230. him = s_to_c(himp);
  231. if(strchr(him, '.') == 0 && nci != nil && strchr(nci->rsys, '.') != nil)
  232. him = nci->rsys;
  233. reply("250%c%s you are %s\r\n", extended ? '-' : ' ', dom, him);
  234. if (extended) {
  235. if(tlscert != nil)
  236. reply("250-STARTTLS\r\n");
  237. if (passwordinclear)
  238. reply("250 AUTH CRAM-MD5 PLAIN LOGIN\r\n");
  239. else
  240. reply("250 AUTH CRAM-MD5\r\n");
  241. }
  242. }
  243. void
  244. sender(String *path)
  245. {
  246. String *s;
  247. char *cp;
  248. static char *lastsender;
  249. if(rejectcheck())
  250. return;
  251. if (authenticate && !authenticated) {
  252. rejectcount++;
  253. reply("530 Authentication required\r\n");
  254. return;
  255. }
  256. if(him == 0 || *him == 0){
  257. rejectcount++;
  258. reply("503 Start by saying HELO, please.\r\n", s_to_c(path));
  259. return;
  260. }
  261. /* don't add the domain onto black holes or we will loop */
  262. if(strchr(s_to_c(path), '!') == 0 && strcmp(s_to_c(path), "/dev/null") != 0){
  263. s = s_new();
  264. s_append(s, him);
  265. s_append(s, "!");
  266. s_append(s, s_to_c(path));
  267. s_terminate(s);
  268. s_free(path);
  269. path = s;
  270. }
  271. if(shellchars(s_to_c(path))){
  272. rejectcount++;
  273. reply("503 Bad character in sender address %s.\r\n", s_to_c(path));
  274. return;
  275. }
  276. /*
  277. * if the last sender address resulted in a rejection because the sending
  278. * domain didn't exist and this sender has the same domain, reject immediately.
  279. */
  280. if(lastsender){
  281. if (strncmp(lastsender, s_to_c(path), strlen(lastsender)) == 0){
  282. filterstate = REFUSED;
  283. rejectcount++;
  284. reply("554 Sender domain must exist: %s\r\n", s_to_c(path));
  285. return;
  286. }
  287. free(lastsender); /* different sender domain */
  288. lastsender = 0;
  289. }
  290. /*
  291. * see if this ip address, domain name, user name or account is blocked
  292. */
  293. filterstate = blocked(path);
  294. /*
  295. * perform DNS lookup to see if sending domain exists
  296. */
  297. if(filterstate == ACCEPT && rflag && returnable(s_to_c(path))){
  298. if(rmtdns(nci->root, s_to_c(path)) < 0){
  299. filterstate = REFUSED;
  300. lastsender = strdup(s_to_c(path));
  301. cp = strrchr(lastsender, '!');
  302. if(cp)
  303. *cp = 0;
  304. }
  305. }
  306. logged = 0;
  307. listadd(&senders, path);
  308. reply("250 sender is %s\r\n", s_to_c(path));
  309. }
  310. void
  311. receiver(String *path)
  312. {
  313. char *sender;
  314. if(rejectcheck())
  315. return;
  316. if(him == 0 || *him == 0){
  317. rejectcount++;
  318. reply("503 Start by saying HELO, please\r\n");
  319. return;
  320. }
  321. if(senders.last)
  322. sender = s_to_c(senders.last->p);
  323. else
  324. sender = "<unknown>";
  325. if(!recipok(s_to_c(path))){
  326. rejectcount++;
  327. syslog(0, "smtpd", "Disallowed %s (%s/%s) to %s",
  328. sender, him, nci->rsys, s_to_c(path));
  329. reply("550 %s ... user unknown\r\n", s_to_c(path));
  330. return;
  331. }
  332. logged = 0;
  333. /* forwarding() can modify 'path' on loopback request */
  334. if(filterstate == ACCEPT && (fflag && !authenticated) && forwarding(path)) {
  335. syslog(0, "smtpd", "Bad Forward %s (%s/%s) (%s)",
  336. s_to_c(senders.last->p), him, nci->rsys, s_to_c(path));
  337. rejectcount++;
  338. reply("550 we don't relay. send to your-path@[] for loopback.\r\n");
  339. return;
  340. }
  341. listadd(&rcvers, path);
  342. reply("250 receiver is %s\r\n", s_to_c(path));
  343. }
  344. void
  345. quit(void)
  346. {
  347. reply("221 Successful termination\r\n");
  348. close(0);
  349. exits(0);
  350. }
  351. void
  352. turn(void)
  353. {
  354. if(rejectcheck())
  355. return;
  356. reply("502 TURN unimplemented\r\n");
  357. }
  358. void
  359. noop(void)
  360. {
  361. if(rejectcheck())
  362. return;
  363. reply("250 Stop wasting my time!\r\n");
  364. }
  365. void
  366. help(String *cmd)
  367. {
  368. if(rejectcheck())
  369. return;
  370. if(cmd)
  371. s_free(cmd);
  372. reply("250 Read rfc821 and stop wasting my time\r\n");
  373. }
  374. void
  375. verify(String *path)
  376. {
  377. char *p, *q;
  378. char *av[4];
  379. if(rejectcheck())
  380. return;
  381. if(shellchars(s_to_c(path))){
  382. reply("503 Bad character in address %s.\r\n", s_to_c(path));
  383. return;
  384. }
  385. av[0] = s_to_c(mailer);
  386. av[1] = "-x";
  387. av[2] = s_to_c(path);
  388. av[3] = 0;
  389. pp = noshell_proc_start(av, (stream *)0, outstream(), (stream *)0, 1, 0);
  390. if (pp == 0) {
  391. reply("450 We're busy right now, try later\r\n");
  392. return;
  393. }
  394. p = Brdline(pp->std[1]->fp, '\n');
  395. if(p == 0){
  396. reply("550 String does not match anything.\r\n");
  397. } else {
  398. p[Blinelen(pp->std[1]->fp)-1] = 0;
  399. if(strchr(p, ':'))
  400. reply("550 String does not match anything.\r\n");
  401. else{
  402. q = strrchr(p, '!');
  403. if(q)
  404. p = q+1;
  405. reply("250 %s <%s@%s>\r\n", s_to_c(path), p, dom);
  406. }
  407. }
  408. proc_wait(pp);
  409. proc_free(pp);
  410. pp = 0;
  411. }
  412. /*
  413. * get a line that ends in crnl or cr, turn terminating crnl into a nl
  414. *
  415. * return 0 on EOF
  416. */
  417. static int
  418. getcrnl(String *s, Biobuf *fp)
  419. {
  420. int c;
  421. for(;;){
  422. c = Bgetc(fp);
  423. if(debug) {
  424. seek(2, 0, 2);
  425. fprint(2, "%c", c);
  426. }
  427. switch(c){
  428. case -1:
  429. goto out;
  430. case '\r':
  431. c = Bgetc(fp);
  432. if(c == '\n'){
  433. if(debug) {
  434. seek(2, 0, 2);
  435. fprint(2, "%c", c);
  436. }
  437. s_putc(s, '\n');
  438. goto out;
  439. }
  440. Bungetc(fp);
  441. s_putc(s, '\r');
  442. break;
  443. case '\n':
  444. s_putc(s, c);
  445. goto out;
  446. default:
  447. s_putc(s, c);
  448. break;
  449. }
  450. }
  451. out:
  452. s_terminate(s);
  453. return s_len(s);
  454. }
  455. void
  456. logcall(int nbytes)
  457. {
  458. Link *l;
  459. String *to, *from;
  460. to = s_new();
  461. from = s_new();
  462. for(l = senders.first; l; l = l->next){
  463. if(l != senders.first)
  464. s_append(from, ", ");
  465. s_append(from, s_to_c(l->p));
  466. }
  467. for(l = rcvers.first; l; l = l->next){
  468. if(l != rcvers.first)
  469. s_append(to, ", ");
  470. s_append(to, s_to_c(l->p));
  471. }
  472. syslog(0, "smtpd", "[%s/%s] %s sent %d bytes to %s", him, nci->rsys,
  473. s_to_c(from), nbytes, s_to_c(to));
  474. s_free(to);
  475. s_free(from);
  476. }
  477. static void
  478. logmsg(char *action)
  479. {
  480. Link *l;
  481. if(logged)
  482. return;
  483. logged = 1;
  484. for(l = rcvers.first; l; l = l->next)
  485. syslog(0, "smtpd", "%s %s (%s/%s) (%s)", action,
  486. s_to_c(senders.last->p), him, nci->rsys, s_to_c(l->p));
  487. }
  488. static int
  489. optoutall(int filterstate)
  490. {
  491. Link *l;
  492. switch(filterstate){
  493. case ACCEPT:
  494. case TRUSTED:
  495. return filterstate;
  496. }
  497. for(l = rcvers.first; l; l = l->next)
  498. if(!optoutofspamfilter(s_to_c(l->p)))
  499. return filterstate;
  500. return ACCEPT;
  501. }
  502. String*
  503. startcmd(void)
  504. {
  505. int n;
  506. Link *l;
  507. char **av;
  508. String *cmd;
  509. char *filename;
  510. /*
  511. * ignore the filterstate if the all the receivers prefer it.
  512. */
  513. filterstate = optoutall(filterstate);
  514. switch (filterstate){
  515. case BLOCKED:
  516. case DELAY:
  517. rejectcount++;
  518. logmsg("Blocked");
  519. filename = dumpfile(s_to_c(senders.last->p));
  520. cmd = s_new();
  521. s_append(cmd, "cat > ");
  522. s_append(cmd, filename);
  523. pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 0, 0);
  524. break;
  525. case DIALUP:
  526. logmsg("Dialup");
  527. rejectcount++;
  528. reply("554 We don't accept mail from dial-up ports.\r\n");
  529. /*
  530. * we could exit here, because we're never going to accept mail from this
  531. * ip address, but it's unclear that RFC821 allows that. Instead we set
  532. * the hardreject flag and go stupid.
  533. */
  534. hardreject = 1;
  535. return 0;
  536. case DENIED:
  537. logmsg("Denied");
  538. rejectcount++;
  539. reply("554-We don't accept mail from %s.\r\n", s_to_c(senders.last->p));
  540. reply("554 Contact postmaster@%s for more information.\r\n", dom);
  541. return 0;
  542. case REFUSED:
  543. logmsg("Refused");
  544. rejectcount++;
  545. reply("554 Sender domain must exist: %s\r\n", s_to_c(senders.last->p));
  546. return 0;
  547. default:
  548. case NONE:
  549. logmsg("Confused");
  550. rejectcount++;
  551. reply("554-We have had an internal mailer error classifying your message.\r\n");
  552. reply("554-Filterstate is %d\r\n", filterstate);
  553. reply("554 Contact postmaster@%s for more information.\r\n", dom);
  554. return 0;
  555. case ACCEPT:
  556. case TRUSTED:
  557. /*
  558. * set up mail command
  559. */
  560. cmd = s_clone(mailer);
  561. n = 3;
  562. for(l = rcvers.first; l; l = l->next)
  563. n++;
  564. av = malloc(n*sizeof(char*));
  565. if(av == nil){
  566. reply("450 We're busy right now, try later\n");
  567. s_free(cmd);
  568. return 0;
  569. }
  570. n = 0;
  571. av[n++] = s_to_c(cmd);
  572. av[n++] = "-r";
  573. for(l = rcvers.first; l; l = l->next)
  574. av[n++] = s_to_c(l->p);
  575. av[n] = 0;
  576. /*
  577. * start mail process
  578. */
  579. pp = noshell_proc_start(av, instream(), outstream(), outstream(), 0, 0);
  580. free(av);
  581. break;
  582. }
  583. if(pp == 0) {
  584. reply("450 We're busy right now, try later\n");
  585. s_free(cmd);
  586. return 0;
  587. }
  588. return cmd;
  589. }
  590. /*
  591. * print out a header line, expanding any domainless addresses into
  592. * address@him
  593. */
  594. char*
  595. bprintnode(Biobuf *b, Node *p)
  596. {
  597. if(p->s){
  598. if(p->addr && strchr(s_to_c(p->s), '@') == nil){
  599. if(Bprint(b, "%s@%s", s_to_c(p->s), him) < 0)
  600. return nil;
  601. } else {
  602. if(Bwrite(b, s_to_c(p->s), s_len(p->s)) < 0)
  603. return nil;
  604. }
  605. }else{
  606. if(Bputc(b, p->c) < 0)
  607. return nil;
  608. }
  609. if(p->white)
  610. if(Bwrite(b, s_to_c(p->white), s_len(p->white)) < 0)
  611. return nil;
  612. return p->end+1;
  613. }
  614. static String*
  615. getaddr(Node *p)
  616. {
  617. for(; p; p = p->next)
  618. if(p->s && p->addr)
  619. return p->s;
  620. return nil;
  621. }
  622. /*
  623. * add waring headers of the form
  624. * X-warning: <reason>
  625. * for any headers that looked like they might be forged.
  626. *
  627. * return byte count of new headers
  628. */
  629. static int
  630. forgedheaderwarnings(void)
  631. {
  632. int nbytes;
  633. Field *f;
  634. nbytes = 0;
  635. /* warn about envelope sender */
  636. if(strcmp(s_to_c(senders.last->p), "/dev/null") != 0 && masquerade(senders.last->p, nil))
  637. nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect envelope domain\n");
  638. /*
  639. * check Sender: field. If it's OK, ignore the others because this is an
  640. * exploded mailing list.
  641. */
  642. for(f = firstfield; f; f = f->next){
  643. if(f->node->c == SENDER){
  644. if(masquerade(getaddr(f->node), him))
  645. nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect Sender: domain\n");
  646. else
  647. return nbytes;
  648. }
  649. }
  650. /* check From: */
  651. for(f = firstfield; f; f = f->next){
  652. if(f->node->c == FROM && masquerade(getaddr(f->node), him))
  653. nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect From: domain\n");
  654. }
  655. return nbytes;
  656. }
  657. /*
  658. * pipe message to mailer with the following transformations:
  659. * - change \r\n into \n.
  660. * - add sender's domain to any addrs with no domain
  661. * - add a From: if none of From:, Sender:, or Replyto: exists
  662. * - add a Received: line
  663. */
  664. int
  665. pipemsg(int *byteswritten)
  666. {
  667. int status;
  668. char *cp;
  669. String *line;
  670. String *hdr;
  671. int n, nbytes;
  672. int sawdot;
  673. Field *f;
  674. Node *p;
  675. Link *l;
  676. pipesig(&status); /* set status to 1 on write to closed pipe */
  677. sawdot = 0;
  678. status = 0;
  679. /*
  680. * add a 'From ' line as envelope
  681. */
  682. nbytes = 0;
  683. nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
  684. s_to_c(senders.first->p), thedate());
  685. /*
  686. * add our own Received: stamp
  687. */
  688. nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
  689. if(nci->rsys)
  690. nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
  691. nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());
  692. /*
  693. * read first 16k obeying '.' escape. we're assuming
  694. * the header will all be there.
  695. */
  696. line = s_new();
  697. hdr = s_new();
  698. while(sawdot == 0 && s_len(hdr) < 16*1024){
  699. n = getcrnl(s_reset(line), &bin);
  700. /* eof or error ends the message */
  701. if(n <= 0)
  702. break;
  703. /* a line with only a '.' ends the message */
  704. cp = s_to_c(line);
  705. if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
  706. sawdot = 1;
  707. break;
  708. }
  709. s_append(hdr, *cp == '.' ? cp+1 : cp);
  710. }
  711. /*
  712. * parse header
  713. */
  714. yyinit(s_to_c(hdr), s_len(hdr));
  715. yyparse();
  716. /*
  717. * Llook for masquerades. Let Sender: trump From: to allow mailing list
  718. * forwarded messages.
  719. */
  720. if(fflag)
  721. nbytes += forgedheaderwarnings();
  722. /*
  723. * add an orginator and/or destination if either is missing
  724. */
  725. if(originator == 0){
  726. if(senders.last == nil)
  727. Bprint(pp->std[0]->fp, "From: /dev/null@%s\n", him);
  728. else
  729. Bprint(pp->std[0]->fp, "From: %s\n", s_to_c(senders.last->p));
  730. }
  731. if(destination == 0){
  732. Bprint(pp->std[0]->fp, "To: ");
  733. for(l = rcvers.first; l; l = l->next){
  734. if(l != rcvers.first)
  735. Bprint(pp->std[0]->fp, ", ");
  736. Bprint(pp->std[0]->fp, "%s", s_to_c(l->p));
  737. }
  738. Bprint(pp->std[0]->fp, "\n");
  739. }
  740. /*
  741. * add sender's domain to any domainless addresses
  742. * (to avoid forging local addresses)
  743. */
  744. cp = s_to_c(hdr);
  745. for(f = firstfield; cp != nil && f; f = f->next){
  746. for(p = f->node; cp != 0 && p; p = p->next)
  747. cp = bprintnode(pp->std[0]->fp, p);
  748. Bprint(pp->std[0]->fp, "\n");
  749. }
  750. if(cp == nil)
  751. status = 1;
  752. /* write anything we read following the header */
  753. if(status == 0)
  754. if(Bwrite(pp->std[0]->fp, cp, s_to_c(hdr) + s_len(hdr) - cp) < 0)
  755. status = 1;
  756. s_free(hdr);
  757. /*
  758. * pass rest of message to mailer. take care of '.'
  759. * escapes.
  760. */
  761. while(status == 0 && sawdot == 0){
  762. n = getcrnl(s_reset(line), &bin);
  763. /* eof or error ends the message */
  764. if(n <= 0)
  765. break;
  766. /* a line with only a '.' ends the message */
  767. cp = s_to_c(line);
  768. if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
  769. sawdot = 1;
  770. break;
  771. }
  772. nbytes += n;
  773. if(Bwrite(pp->std[0]->fp, *cp == '.' ? cp+1 : cp, n) < 0){
  774. status = 1;
  775. break;
  776. }
  777. }
  778. s_free(line);
  779. pipesigoff();
  780. if(sawdot == 0){
  781. /* message did not terminate normally */
  782. syskillpg(pp->pid);
  783. status = 1;
  784. }
  785. if(Bflush(pp->std[0]->fp) < 0)
  786. status = 1;
  787. stream_free(pp->std[0]);
  788. pp->std[0] = 0;
  789. *byteswritten = nbytes;
  790. return status;
  791. }
  792. void
  793. data(void)
  794. {
  795. String *cmd;
  796. String *err;
  797. int status, nbytes;
  798. char *cp, *ep;
  799. if(rejectcheck())
  800. return;
  801. if(senders.last == 0){
  802. reply("503 Data without MAIL FROM:\r\n");
  803. rejectcount++;
  804. return;
  805. }
  806. if(rcvers.last == 0){
  807. reply("503 Data without RCPT TO:\r\n");
  808. rejectcount++;
  809. return;
  810. }
  811. cmd = startcmd();
  812. if(cmd == 0)
  813. return;
  814. reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
  815. /*
  816. * allow 145 more minutes to move the data
  817. */
  818. alarm(145*60*1000);
  819. status = pipemsg(&nbytes);
  820. /*
  821. * read any error messages
  822. */
  823. err = s_new();
  824. while(s_read_line(pp->std[2]->fp, err))
  825. ;
  826. alarm(0);
  827. atnotify(catchalarm, 0);
  828. status |= proc_wait(pp);
  829. if(debug){
  830. seek(2, 0, 2);
  831. fprint(2, "%d status %ux\n", getpid(), status);
  832. if(*s_to_c(err))
  833. fprint(2, "%d error %s\n", getpid(), s_to_c(err));
  834. }
  835. proc_free(pp);
  836. pp = 0;
  837. /*
  838. * if process terminated abnormally, send back error message
  839. */
  840. if(status){
  841. syslog(0, "smtpd", "++[%s/%s] %s returned %d", him, nci->rsys, s_to_c(cmd), status);
  842. for(cp = s_to_c(err); ep = strchr(cp, '\n'); cp = ep){
  843. *ep++ = 0;
  844. reply("450-%s\r\n", cp);
  845. syslog(0, "smtpd", "450-%s", cp);
  846. }
  847. reply("450 mail process terminated abnormally\r\n");
  848. } else {
  849. if(filterstate == BLOCKED)
  850. reply("554 we believe this is spam. we don't accept it.\r\n");
  851. else
  852. if(filterstate == DELAY)
  853. reply("554 There will be a delay in delivery of this message.\r\n");
  854. else {
  855. reply("250 sent\r\n");
  856. logcall(nbytes);
  857. }
  858. }
  859. s_free(cmd);
  860. s_free(err);
  861. listfree(&senders);
  862. listfree(&rcvers);
  863. }
  864. /*
  865. * when we have blocked a transaction based on IP address, there is nothing
  866. * that the sender can do to convince us to take the message. after the
  867. * first rejection, some spammers continually RSET and give a new MAIL FROM:
  868. * filling our logs with rejections. rejectcheck() limits the retries and
  869. * swiftly rejects all further commands after the first 500-series message
  870. * is issued.
  871. */
  872. int
  873. rejectcheck(void)
  874. {
  875. if(rejectcount > MAXREJECTS){
  876. syslog(0, "smtpd", "Rejected (%s/%s)", him, nci->rsys);
  877. reply("554 too many errors. transaction failed.\r\n");
  878. exits("errcount");
  879. }
  880. if(hardreject){
  881. rejectcount++;
  882. reply("554 We don't accept mail from dial-up ports.\r\n");
  883. }
  884. return hardreject;
  885. }
  886. /*
  887. * create abs path of the mailer
  888. */
  889. String*
  890. mailerpath(char *p)
  891. {
  892. String *s;
  893. if(p == nil)
  894. return nil;
  895. if(*p == '/')
  896. return s_copy(p);
  897. s = s_new();
  898. s_append(s, UPASBIN);
  899. s_append(s, "/");
  900. s_append(s, p);
  901. return s;
  902. }
  903. String *
  904. s_dec64(String *sin)
  905. {
  906. String *sout;
  907. int lin, lout;
  908. lin = s_len(sin);
  909. /*
  910. * if the string is coming from smtpd.y, it will have no nl.
  911. * if it is coming from getcrnl below, it will have an nl.
  912. */
  913. if (*(s_to_c(sin)+lin-1) == '\n')
  914. lin--;
  915. sout = s_newalloc(lin+1);
  916. lout = dec64((uchar *)s_to_c(sout), lin, s_to_c(sin), lin);
  917. if (lout < 0) {
  918. s_free(sout);
  919. return nil;
  920. }
  921. sout->ptr = sout->base + lout;
  922. s_terminate(sout);
  923. return sout;
  924. }
  925. void
  926. starttls(void)
  927. {
  928. uchar *cert;
  929. int certlen, fd;
  930. TLSconn *conn;
  931. conn = mallocz(sizeof *conn, 1);
  932. cert = readcert(tlscert, &certlen);
  933. if (conn == nil || cert == nil) {
  934. if (conn != nil)
  935. free(conn);
  936. reply("454 TLS not available\r\n");
  937. return;
  938. }
  939. reply("220 Go ahead make my day\r\n");
  940. conn->cert = cert;
  941. conn->certlen = certlen;
  942. fd = tlsServer(Bfildes(&bin), conn);
  943. if (fd < 0) {
  944. free(cert);
  945. free(conn);
  946. if(debug)fprint(2, "tlsServer failed: %r\n");
  947. return; /* XXX We should really force the client to hang up here. */
  948. }
  949. Bterm(&bin);
  950. Binit(&bin, fd, OREAD);
  951. dup(fd, 1);
  952. passwordinclear = 1;
  953. if(debug)fprint(2, "tlsServer suceeded\n");
  954. }
  955. void
  956. auth(String *mech, String *resp)
  957. {
  958. Chalstate *chs = nil;
  959. AuthInfo *ai = nil;
  960. String *s_resp1_64 = nil;
  961. String *s_resp2_64 = nil;
  962. String *s_resp1 = nil;
  963. String *s_resp2 = nil;
  964. char *scratch = nil;
  965. char *user, *pass;
  966. if (rejectcheck())
  967. goto bomb_out;
  968. syslog(0, "smtpd", "auth(%s, %s) from %s\n", s_to_c(mech), s_to_c(resp), him);
  969. if (authenticated) {
  970. bad_sequence:
  971. rejectcount++;
  972. reply("503 Bad sequence of commands\r\n");
  973. goto bomb_out;
  974. }
  975. if (cistrcmp(s_to_c(mech), "plain") == 0) {
  976. if (!passwordinclear) {
  977. rejectcount++;
  978. reply("538 Encryption required for requested authentication mechanism\r\n");
  979. goto bomb_out;
  980. }
  981. s_resp1_64 = resp;
  982. if (s_resp1_64 == nil) {
  983. reply("334 \r\n");
  984. s_resp1_64 = s_new();
  985. if (getcrnl(s_resp1_64, &bin) <= 0) {
  986. goto bad_sequence;
  987. }
  988. }
  989. s_resp1 = s_dec64(s_resp1_64);
  990. if (s_resp1 == nil) {
  991. rejectcount++;
  992. reply("501 Cannot decode base64\r\n");
  993. goto bomb_out;
  994. }
  995. memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
  996. user = (s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1);
  997. pass = user + (strlen(user) + 1);
  998. ai = auth_userpasswd(user, pass);
  999. authenticated = ai != nil;
  1000. memset(pass, 'X', strlen(pass));
  1001. goto windup;
  1002. }
  1003. else if (cistrcmp(s_to_c(mech), "login") == 0) {
  1004. if (!passwordinclear) {
  1005. rejectcount++;
  1006. reply("538 Encryption required for requested authentication mechanism\r\n");
  1007. goto bomb_out;
  1008. }
  1009. if (resp == nil) {
  1010. reply("334 VXNlcm5hbWU6\r\n");
  1011. s_resp1_64 = s_new();
  1012. if (getcrnl(s_resp1_64, &bin) <= 0)
  1013. goto bad_sequence;
  1014. }
  1015. reply("334 UGFzc3dvcmQ6\r\n");
  1016. s_resp2_64 = s_new();
  1017. if (getcrnl(s_resp2_64, &bin) <= 0)
  1018. goto bad_sequence;
  1019. s_resp1 = s_dec64(s_resp1_64);
  1020. s_resp2 = s_dec64(s_resp2_64);
  1021. memset(s_to_c(s_resp2_64), 'X', s_len(s_resp2_64));
  1022. if (s_resp1 == nil || s_resp2 == nil) {
  1023. rejectcount++;
  1024. reply("501 Cannot decode base64\r\n");
  1025. goto bomb_out;
  1026. }
  1027. ai = auth_userpasswd(s_to_c(s_resp1), s_to_c(s_resp2));
  1028. authenticated = ai != nil;
  1029. memset(s_to_c(s_resp2), 'X', s_len(s_resp2));
  1030. windup:
  1031. if (authenticated)
  1032. reply("235 Authentication successful\r\n");
  1033. else {
  1034. rejectcount++;
  1035. reply("535 Authentication failed\r\n");
  1036. }
  1037. goto bomb_out;
  1038. }
  1039. else if (cistrcmp(s_to_c(mech), "cram-md5") == 0) {
  1040. char *resp;
  1041. int chal64n;
  1042. char *t;
  1043. chs = auth_challenge("proto=cram role=server");
  1044. if (chs == nil) {
  1045. rejectcount++;
  1046. reply("501 Couldn't get CRAM-MD5 challenge\r\n");
  1047. goto bomb_out;
  1048. }
  1049. scratch = malloc(chs->nchal * 2 + 1);
  1050. chal64n = enc64(scratch, chs->nchal * 2, (uchar *)chs->chal, chs->nchal);
  1051. scratch[chal64n] = 0;
  1052. reply("334 %s\r\n", scratch);
  1053. s_resp1_64 = s_new();
  1054. if (getcrnl(s_resp1_64, &bin) <= 0)
  1055. goto bad_sequence;
  1056. s_resp1 = s_dec64(s_resp1_64);
  1057. if (s_resp1 == nil) {
  1058. rejectcount++;
  1059. reply("501 Cannot decode base64\r\n");
  1060. goto bomb_out;
  1061. }
  1062. /* should be of form <user><space><response> */
  1063. resp = s_to_c(s_resp1);
  1064. t = strchr(resp, ' ');
  1065. if (t == nil) {
  1066. rejectcount++;
  1067. reply("501 Poorly formed CRAM-MD5 response\r\n");
  1068. goto bomb_out;
  1069. }
  1070. *t++ = 0;
  1071. chs->user = resp;
  1072. chs->resp = t;
  1073. chs->nresp = strlen(t);
  1074. ai = auth_response(chs);
  1075. authenticated = ai != nil;
  1076. goto windup;
  1077. }
  1078. rejectcount++;
  1079. reply("501 Unrecognised authentication type %s\r\n", s_to_c(mech));
  1080. bomb_out:
  1081. if (ai)
  1082. auth_freeAI(ai);
  1083. if (chs)
  1084. auth_freechal(chs);
  1085. if (scratch)
  1086. free(scratch);
  1087. if (s_resp1)
  1088. s_free(s_resp1);
  1089. if (s_resp2)
  1090. s_free(s_resp2);
  1091. if (s_resp1_64)
  1092. s_free(s_resp1_64);
  1093. if (s_resp2_64)
  1094. s_free(s_resp2_64);
  1095. }