smtpd.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. #include "common.h"
  2. #include "smtpd.h"
  3. #include "smtp.h"
  4. #include <ctype.h>
  5. #include <ip.h>
  6. #include <ndb.h>
  7. #include <mp.h>
  8. #include <libsec.h>
  9. #include <auth.h>
  10. #include "../smtp/y.tab.h"
  11. #define DBGMX 1
  12. char *me;
  13. char *him="";
  14. char *dom;
  15. process *pp;
  16. String *mailer;
  17. NetConnInfo *nci;
  18. int filterstate = ACCEPT;
  19. int trusted;
  20. int logged;
  21. int rejectcount;
  22. int hardreject;
  23. Biobuf bin;
  24. int debug;
  25. int Dflag;
  26. int fflag;
  27. int gflag;
  28. int rflag;
  29. int sflag;
  30. int authenticate;
  31. int authenticated;
  32. int passwordinclear;
  33. char *tlscert;
  34. uchar rsysip[IPaddrlen];
  35. List senders;
  36. List rcvers;
  37. char pipbuf[ERRMAX];
  38. char *piperror;
  39. String* mailerpath(char*);
  40. int pipemsg(int*);
  41. int rejectcheck(void);
  42. String* startcmd(void);
  43. static int
  44. catchalarm(void *a, char *msg)
  45. {
  46. int rv;
  47. USED(a);
  48. /* log alarms but continue */
  49. if(strstr(msg, "alarm") != nil){
  50. if(senders.first && senders.first->p &&
  51. rcvers.first && rcvers.first->p)
  52. syslog(0, "smtpd", "note: %s->%s: %s",
  53. s_to_c(senders.first->p),
  54. s_to_c(rcvers.first->p), msg);
  55. else
  56. syslog(0, "smtpd", "note: %s", msg);
  57. rv = Atnoterecog;
  58. } else
  59. rv = Atnoteunknown;
  60. /* kill the children if there are any */
  61. if(pp)
  62. syskillpg(pp->pid);
  63. return rv;
  64. }
  65. /* override string error functions to do something reasonable */
  66. void
  67. s_error(char *f, char *status)
  68. {
  69. char errbuf[Errlen];
  70. errbuf[0] = 0;
  71. rerrstr(errbuf, sizeof(errbuf));
  72. if(f && *f)
  73. reply("452 4.3.0 out of memory %s: %s\r\n", f, errbuf);
  74. else
  75. reply("452 4.3.0 out of memory %s\r\n", errbuf);
  76. syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys);
  77. exits(status);
  78. }
  79. static void
  80. usage(void)
  81. {
  82. fprint(2,
  83. "usage: smtpd [-adDfghprs] [-c cert] [-k ip] [-m mailer] [-n net]\n");
  84. exits("usage");
  85. }
  86. void
  87. main(int argc, char **argv)
  88. {
  89. char *netdir;
  90. char buf[1024];
  91. netdir = nil;
  92. quotefmtinstall();
  93. fmtinstall('I', eipfmt);
  94. ARGBEGIN{
  95. case 'a':
  96. authenticate = 1;
  97. break;
  98. case 'c':
  99. tlscert = EARGF(usage());
  100. break;
  101. case 'D':
  102. Dflag++;
  103. break;
  104. case 'd':
  105. debug++;
  106. break;
  107. case 'f': /* disallow relaying */
  108. fflag = 1;
  109. break;
  110. case 'g':
  111. gflag = 1;
  112. break;
  113. case 'h': /* default domain name */
  114. dom = EARGF(usage());
  115. break;
  116. case 'k': /* prohibited ip address */
  117. addbadguy(EARGF(usage()));
  118. break;
  119. case 'm': /* set mail command */
  120. mailer = mailerpath(EARGF(usage()));
  121. break;
  122. case 'n': /* log peer ip address */
  123. netdir = EARGF(usage());
  124. break;
  125. case 'p':
  126. passwordinclear = 1;
  127. break;
  128. case 'r':
  129. rflag = 1; /* verify sender's domain */
  130. break;
  131. case 's': /* save blocked messages */
  132. sflag = 1;
  133. break;
  134. case 't':
  135. fprint(2, "%s: the -t option is no longer supported, see -c\n",
  136. argv0);
  137. tlscert = "/sys/lib/ssl/smtpd-cert.pem";
  138. break;
  139. default:
  140. usage();
  141. }ARGEND;
  142. nci = getnetconninfo(netdir, 0);
  143. if(nci == nil)
  144. sysfatal("can't get remote system's address");
  145. parseip(rsysip, nci->rsys);
  146. if(mailer == nil)
  147. mailer = mailerpath("send");
  148. if(debug){
  149. close(2);
  150. snprint(buf, sizeof(buf), "%s/smtpd.db", UPASLOG);
  151. if (open(buf, OWRITE) >= 0) {
  152. seek(2, 0, 2);
  153. fprint(2, "%d smtpd %s\n", getpid(), thedate());
  154. } else
  155. debug = 0;
  156. }
  157. getconf();
  158. Binit(&bin, 0, OREAD);
  159. if (chdir(UPASLOG) < 0)
  160. syslog(0, "smtpd", "no %s: %r", UPASLOG);
  161. me = sysname_read();
  162. if(dom == 0 || dom[0] == 0)
  163. dom = domainname_read();
  164. if(dom == 0 || dom[0] == 0)
  165. dom = me;
  166. sayhi();
  167. parseinit();
  168. /* allow 45 minutes to parse the header */
  169. atnotify(catchalarm, 1);
  170. alarm(45*60*1000);
  171. zzparse();
  172. exits(0);
  173. }
  174. void
  175. listfree(List *l)
  176. {
  177. Link *lp, *next;
  178. for(lp = l->first; lp; lp = next){
  179. next = lp->next;
  180. s_free(lp->p);
  181. free(lp);
  182. }
  183. l->first = l->last = 0;
  184. }
  185. void
  186. listadd(List *l, String *path)
  187. {
  188. Link *lp;
  189. lp = (Link *)malloc(sizeof *lp);
  190. lp->p = path;
  191. lp->next = 0;
  192. if(l->last)
  193. l->last->next = lp;
  194. else
  195. l->first = lp;
  196. l->last = lp;
  197. }
  198. #define SIZE 4096
  199. int
  200. reply(char *fmt, ...)
  201. {
  202. int n;
  203. char buf[SIZE], *out;
  204. va_list arg;
  205. va_start(arg, fmt);
  206. out = vseprint(buf, buf+SIZE, fmt, arg);
  207. va_end(arg);
  208. n = (long)(out - buf);
  209. if(debug) {
  210. seek(2, 0, 2);
  211. write(2, buf, n);
  212. }
  213. write(1, buf, n);
  214. return n;
  215. }
  216. void
  217. reset(void)
  218. {
  219. if(rejectcheck())
  220. return;
  221. listfree(&rcvers);
  222. listfree(&senders);
  223. if(filterstate != DIALUP){
  224. logged = 0;
  225. filterstate = ACCEPT;
  226. }
  227. reply("250 2.0.0 ok\r\n");
  228. }
  229. void
  230. sayhi(void)
  231. {
  232. reply("220 %s ESMTP\r\n", dom);
  233. }
  234. /*
  235. * make callers from class A networks infested by spammers
  236. * wait longer.
  237. */
  238. static char netaspam[256] = {
  239. [58] 1,
  240. [66] 1,
  241. [71] 1,
  242. [76] 1,
  243. [77] 1,
  244. [78] 1,
  245. [79] 1,
  246. [80] 1,
  247. [81] 1,
  248. [82] 1,
  249. [83] 1,
  250. [84] 1,
  251. [85] 1,
  252. [86] 1,
  253. [87] 1,
  254. [88] 1,
  255. [89] 1,
  256. [190] 1,
  257. [201] 1,
  258. [217] 1,
  259. };
  260. static int
  261. delaysecs(void)
  262. {
  263. if (netaspam[rsysip[0]])
  264. return 60;
  265. return 15;
  266. }
  267. void
  268. hello(String *himp, int extended)
  269. {
  270. char **mynames;
  271. char *ldot, *rdot;
  272. him = s_to_c(himp);
  273. syslog(0, "smtpd", "%s from %s as %s", extended? "ehlo": "helo",
  274. nci->rsys, him);
  275. if(rejectcheck())
  276. return;
  277. if (strchr(him, '.') && nci && !trusted && fflag &&
  278. strcmp(nci->rsys, nci->lsys) != 0){
  279. /*
  280. * We don't care if he lies about who he is, but it is
  281. * not okay to pretend to be us. Many viruses do this,
  282. * just parroting back what we say in the greeting.
  283. */
  284. if(strcmp(him, dom) == 0)
  285. goto Liarliar;
  286. for(mynames = sysnames_read(); mynames && *mynames; mynames++){
  287. if(cistrcmp(*mynames, him) == 0){
  288. Liarliar:
  289. syslog(0, "smtpd",
  290. "Hung up on %s; claimed to be %s",
  291. nci->rsys, him);
  292. if(Dflag)
  293. sleep(delaysecs()*1000);
  294. reply("554 5.7.0 Liar!\r\n");
  295. exits("client pretended to be us");
  296. return;
  297. }
  298. }
  299. }
  300. /*
  301. * it is unacceptable to claim any string that doesn't look like
  302. * a domain name (e.g., has at least one dot in it), but
  303. * Microsoft mail client software gets this wrong, so let trusted
  304. * (local) clients omit the dot.
  305. */
  306. rdot = strrchr(him, '.');
  307. if (rdot && rdot[1] == '\0') {
  308. *rdot = '\0'; /* clobber trailing dot */
  309. rdot = strrchr(him, '.'); /* try again */
  310. }
  311. if (!trusted && rdot == nil)
  312. goto Liarliar;
  313. /*
  314. * Reject obviously bogus domains and those reserved by RFC 2606.
  315. */
  316. if (rdot == nil)
  317. rdot = him;
  318. else
  319. rdot++;
  320. if (cistrcmp(rdot, "localdomain") == 0 ||
  321. cistrcmp(rdot, "localhost") == 0 ||
  322. cistrcmp(rdot, "example") == 0 ||
  323. cistrcmp(rdot, "invalid") == 0 ||
  324. cistrcmp(rdot, "test") == 0)
  325. goto Liarliar; /* bad top-level domain */
  326. /* check second-level RFC 2606 domains: example\.(com|net|org) */
  327. if (rdot != him)
  328. *--rdot = '\0';
  329. ldot = strrchr(him, '.');
  330. if (rdot != him)
  331. *rdot = '.';
  332. if (ldot == nil)
  333. ldot = him;
  334. else
  335. ldot++;
  336. if (cistrcmp(ldot, "example.com") == 0 ||
  337. cistrcmp(ldot, "example.net") == 0 ||
  338. cistrcmp(ldot, "example.org") == 0)
  339. goto Liarliar;
  340. /*
  341. * similarly, if the claimed domain is not an address-literal,
  342. * require at least one letter, which there will be in
  343. * at least the last component (e.g., .com, .net) if it's real.
  344. * this rejects non-address-literal IP addresses,
  345. * among other bogosities.
  346. */
  347. if (!trusted && him[0] != '[') {
  348. char *p;
  349. for (p = him; *p != '\0'; p++)
  350. if (isascii(*p) && isalpha(*p))
  351. break;
  352. if (*p == '\0')
  353. goto Liarliar;
  354. }
  355. if(strchr(him, '.') == 0 && nci != nil && strchr(nci->rsys, '.') != nil)
  356. him = nci->rsys;
  357. if(Dflag)
  358. sleep(delaysecs()*1000);
  359. reply("250%c%s you are %s\r\n", extended ? '-' : ' ', dom, him);
  360. if (extended) {
  361. reply("250-ENHANCEDSTATUSCODES\r\n"); /* RFCs 2034 and 3463 */
  362. if(tlscert != nil)
  363. reply("250-STARTTLS\r\n");
  364. if (passwordinclear)
  365. reply("250 AUTH CRAM-MD5 PLAIN LOGIN\r\n");
  366. else
  367. reply("250 AUTH CRAM-MD5\r\n");
  368. }
  369. }
  370. void
  371. sender(String *path)
  372. {
  373. String *s;
  374. static char *lastsender;
  375. if(rejectcheck())
  376. return;
  377. if (authenticate && !authenticated) {
  378. rejectcount++;
  379. reply("530 5.7.0 Authentication required\r\n");
  380. return;
  381. }
  382. if(him == 0 || *him == 0){
  383. rejectcount++;
  384. reply("503 Start by saying HELO, please.\r\n", s_to_c(path));
  385. return;
  386. }
  387. /* don't add the domain onto black holes or we will loop */
  388. if(strchr(s_to_c(path), '!') == 0 && strcmp(s_to_c(path), "/dev/null") != 0){
  389. s = s_new();
  390. s_append(s, him);
  391. s_append(s, "!");
  392. s_append(s, s_to_c(path));
  393. s_terminate(s);
  394. s_free(path);
  395. path = s;
  396. }
  397. if(shellchars(s_to_c(path))){
  398. rejectcount++;
  399. reply("501 5.1.3 Bad character in sender address %s.\r\n",
  400. s_to_c(path));
  401. return;
  402. }
  403. /*
  404. * if the last sender address resulted in a rejection because the sending
  405. * domain didn't exist and this sender has the same domain, reject
  406. * immediately.
  407. */
  408. if(lastsender){
  409. if (strncmp(lastsender, s_to_c(path), strlen(lastsender)) == 0){
  410. filterstate = REFUSED;
  411. rejectcount++;
  412. reply("554 5.1.8 Sender domain must exist: %s\r\n",
  413. s_to_c(path));
  414. return;
  415. }
  416. free(lastsender); /* different sender domain */
  417. lastsender = 0;
  418. }
  419. /*
  420. * see if this ip address, domain name, user name or account is blocked
  421. */
  422. filterstate = blocked(path);
  423. logged = 0;
  424. listadd(&senders, path);
  425. reply("250 2.0.0 sender is %s\r\n", s_to_c(path));
  426. }
  427. enum { Rcpt, Domain, Ntoks };
  428. typedef struct Sender Sender;
  429. struct Sender {
  430. Sender *next;
  431. char *rcpt;
  432. char *domain;
  433. };
  434. static Sender *sendlist, *sendlast;
  435. static int
  436. rdsenders(void)
  437. {
  438. int lnlen, nf, ok = 1;
  439. char *line, *senderfile;
  440. char *toks[Ntoks];
  441. Biobuf *sf;
  442. Sender *snd;
  443. static int beenhere = 0;
  444. if (beenhere)
  445. return 1;
  446. beenhere = 1;
  447. /*
  448. * we're sticking with a system-wide sender list because
  449. * per-user lists would require fully resolving recipient
  450. * addresses to determine which users they correspond to
  451. * (barring exploiting syntactic conventions).
  452. */
  453. senderfile = smprint("%s/senders", UPASLIB);
  454. sf = Bopen(senderfile, OREAD);
  455. free(senderfile);
  456. if (sf == nil)
  457. return 1;
  458. while ((line = Brdline(sf, '\n')) != nil) {
  459. if (line[0] == '#' || line[0] == '\n')
  460. continue;
  461. lnlen = Blinelen(sf);
  462. line[lnlen-1] = '\0'; /* clobber newline */
  463. nf = tokenize(line, toks, nelem(toks));
  464. if (nf != nelem(toks))
  465. continue; /* malformed line */
  466. snd = malloc(sizeof *snd);
  467. if (snd == nil)
  468. sysfatal("out of memory: %r");
  469. memset(snd, 0, sizeof *snd);
  470. snd->next = nil;
  471. if (sendlast == nil)
  472. sendlist = snd;
  473. else
  474. sendlast->next = snd;
  475. sendlast = snd;
  476. snd->rcpt = strdup(toks[Rcpt]);
  477. snd->domain = strdup(toks[Domain]);
  478. }
  479. Bterm(sf);
  480. return ok;
  481. }
  482. /*
  483. * read (recipient, sender's DNS) pairs from /mail/lib/senders.
  484. * Only allow mail to recipient from any of sender's IPs.
  485. * A recipient not mentioned in the file is always permitted.
  486. */
  487. static int
  488. senderok(char *rcpt)
  489. {
  490. int mentioned = 0, matched = 0;
  491. uchar dnsip[IPaddrlen];
  492. Sender *snd;
  493. Ndbtuple *nt, *next, *first;
  494. rdsenders();
  495. for (snd = sendlist; snd != nil; snd = snd->next) {
  496. if (strcmp(rcpt, snd->rcpt) != 0)
  497. continue;
  498. /*
  499. * see if this domain's ips match nci->rsys.
  500. * if not, perhaps a later entry's domain will.
  501. */
  502. mentioned = 1;
  503. if (parseip(dnsip, snd->domain) != -1 &&
  504. memcmp(rsysip, dnsip, IPaddrlen) == 0)
  505. return 1;
  506. /*
  507. * NB: nt->line links form a circular list(!).
  508. * we need to make one complete pass over it to free it all.
  509. */
  510. first = nt = dnsquery(nci->root, snd->domain, "ip");
  511. if (first == nil)
  512. continue;
  513. do {
  514. if (strcmp(nt->attr, "ip") == 0 &&
  515. parseip(dnsip, nt->val) != -1 &&
  516. memcmp(rsysip, dnsip, IPaddrlen) == 0)
  517. matched = 1;
  518. next = nt->line;
  519. free(nt);
  520. nt = next;
  521. } while (nt != first);
  522. }
  523. if (matched)
  524. return 1;
  525. else
  526. return !mentioned;
  527. }
  528. void
  529. receiver(String *path)
  530. {
  531. char *sender, *rcpt;
  532. if(rejectcheck())
  533. return;
  534. if(him == 0 || *him == 0){
  535. rejectcount++;
  536. reply("503 Start by saying HELO, please\r\n");
  537. return;
  538. }
  539. if(senders.last)
  540. sender = s_to_c(senders.last->p);
  541. else
  542. sender = "<unknown>";
  543. if(!recipok(s_to_c(path))){
  544. rejectcount++;
  545. syslog(0, "smtpd",
  546. "Disallowed %s (%s/%s) to blocked, unknown or invalid name %s",
  547. sender, him, nci->rsys, s_to_c(path));
  548. reply("550 5.1.1 %s ... user unknown\r\n", s_to_c(path));
  549. return;
  550. }
  551. rcpt = s_to_c(path);
  552. if (!senderok(rcpt)) {
  553. rejectcount++;
  554. syslog(0, "smtpd", "Disallowed sending IP of %s (%s/%s) to %s",
  555. sender, him, nci->rsys, rcpt);
  556. reply("550 5.7.1 %s ... sending system not allowed\r\n", rcpt);
  557. return;
  558. }
  559. logged = 0;
  560. /* forwarding() can modify 'path' on loopback request */
  561. if(filterstate == ACCEPT && fflag && !authenticated && forwarding(path)) {
  562. syslog(0, "smtpd", "Bad Forward %s (%s/%s) (%s)",
  563. senders.last->p? s_to_c(senders.last->p): sender,
  564. him, nci->rsys, path? s_to_c(path): rcpt);
  565. rejectcount++;
  566. reply("550 5.7.1 we don't relay. send to your-path@[] for "
  567. "loopback.\r\n");
  568. return;
  569. }
  570. listadd(&rcvers, path);
  571. reply("250 2.0.0 receiver is %s\r\n", s_to_c(path));
  572. }
  573. void
  574. quit(void)
  575. {
  576. reply("221 2.0.0 Successful termination\r\n");
  577. close(0);
  578. exits(0);
  579. }
  580. void
  581. noop(void)
  582. {
  583. if(rejectcheck())
  584. return;
  585. reply("250 2.0.0 Nothing to see here. Move along ...\r\n");
  586. }
  587. void
  588. help(String *cmd)
  589. {
  590. if(rejectcheck())
  591. return;
  592. if(cmd)
  593. s_free(cmd);
  594. reply("250 2.0.0 See http://www.ietf.org/rfc/rfc2821\r\n");
  595. }
  596. void
  597. verify(String *path)
  598. {
  599. char *p, *q;
  600. char *av[4];
  601. if(rejectcheck())
  602. return;
  603. if(shellchars(s_to_c(path))){
  604. reply("503 5.1.3 Bad character in address %s.\r\n", s_to_c(path));
  605. return;
  606. }
  607. av[0] = s_to_c(mailer);
  608. av[1] = "-x";
  609. av[2] = s_to_c(path);
  610. av[3] = 0;
  611. pp = noshell_proc_start(av, (stream *)0, outstream(), (stream *)0, 1, 0);
  612. if (pp == 0) {
  613. reply("450 4.3.2 We're busy right now, try later\r\n");
  614. return;
  615. }
  616. p = Brdline(pp->std[1]->fp, '\n');
  617. if(p == 0){
  618. reply("550 5.1.0 String does not match anything.\r\n");
  619. } else {
  620. p[Blinelen(pp->std[1]->fp)-1] = 0;
  621. if(strchr(p, ':'))
  622. reply("550 5.1.0 String does not match anything.\r\n");
  623. else{
  624. q = strrchr(p, '!');
  625. if(q)
  626. p = q+1;
  627. reply("250 2.0.0 %s <%s@%s>\r\n", s_to_c(path), p, dom);
  628. }
  629. }
  630. proc_wait(pp);
  631. proc_free(pp);
  632. pp = 0;
  633. }
  634. /*
  635. * get a line that ends in crnl or cr, turn terminating crnl into a nl
  636. *
  637. * return 0 on EOF
  638. */
  639. static int
  640. getcrnl(String *s, Biobuf *fp)
  641. {
  642. int c;
  643. for(;;){
  644. c = Bgetc(fp);
  645. if(debug) {
  646. seek(2, 0, 2);
  647. fprint(2, "%c", c);
  648. }
  649. switch(c){
  650. case 0:
  651. break;
  652. case -1:
  653. goto out;
  654. case '\r':
  655. c = Bgetc(fp);
  656. if(c == '\n'){
  657. if(debug) {
  658. seek(2, 0, 2);
  659. fprint(2, "%c", c);
  660. }
  661. s_putc(s, '\n');
  662. goto out;
  663. }
  664. Bungetc(fp);
  665. s_putc(s, '\r');
  666. break;
  667. case '\n':
  668. s_putc(s, c);
  669. goto out;
  670. default:
  671. s_putc(s, c);
  672. break;
  673. }
  674. }
  675. out:
  676. s_terminate(s);
  677. return s_len(s);
  678. }
  679. void
  680. logcall(int nbytes)
  681. {
  682. Link *l;
  683. String *to, *from;
  684. to = s_new();
  685. from = s_new();
  686. for(l = senders.first; l; l = l->next){
  687. if(l != senders.first)
  688. s_append(from, ", ");
  689. s_append(from, s_to_c(l->p));
  690. }
  691. for(l = rcvers.first; l; l = l->next){
  692. if(l != rcvers.first)
  693. s_append(to, ", ");
  694. s_append(to, s_to_c(l->p));
  695. }
  696. syslog(0, "smtpd", "[%s/%s] %s sent %d bytes to %s", him, nci->rsys,
  697. s_to_c(from), nbytes, s_to_c(to));
  698. s_free(to);
  699. s_free(from);
  700. }
  701. static void
  702. logmsg(char *action)
  703. {
  704. Link *l;
  705. if(logged)
  706. return;
  707. logged = 1;
  708. for(l = rcvers.first; l; l = l->next)
  709. syslog(0, "smtpd", "%s %s (%s/%s) (%s)", action,
  710. s_to_c(senders.last->p), him, nci->rsys, s_to_c(l->p));
  711. }
  712. static int
  713. optoutall(int filterstate)
  714. {
  715. Link *l;
  716. switch(filterstate){
  717. case ACCEPT:
  718. case TRUSTED:
  719. return filterstate;
  720. }
  721. for(l = rcvers.first; l; l = l->next)
  722. if(!optoutofspamfilter(s_to_c(l->p)))
  723. return filterstate;
  724. return ACCEPT;
  725. }
  726. String*
  727. startcmd(void)
  728. {
  729. int n;
  730. char *filename;
  731. char **av;
  732. Link *l;
  733. String *cmd;
  734. /*
  735. * ignore the filterstate if the all the receivers prefer it.
  736. */
  737. filterstate = optoutall(filterstate);
  738. switch (filterstate){
  739. case BLOCKED:
  740. case DELAY:
  741. rejectcount++;
  742. logmsg("Blocked");
  743. filename = dumpfile(s_to_c(senders.last->p));
  744. cmd = s_new();
  745. s_append(cmd, "cat > ");
  746. s_append(cmd, filename);
  747. pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 0, 0);
  748. break;
  749. case DIALUP:
  750. logmsg("Dialup");
  751. rejectcount++;
  752. reply("554 5.7.1 We don't accept mail from dial-up ports.\r\n");
  753. /*
  754. * we could exit here, because we're never going to accept mail
  755. * from this ip address, but it's unclear that RFC821 allows
  756. * that. Instead we set the hardreject flag and go stupid.
  757. */
  758. hardreject = 1;
  759. return 0;
  760. case DENIED:
  761. logmsg("Denied");
  762. rejectcount++;
  763. reply("554-5.7.1 We don't accept mail from %s.\r\n",
  764. s_to_c(senders.last->p));
  765. reply("554 5.7.1 Contact postmaster@%s for more information.\r\n",
  766. dom);
  767. return 0;
  768. case REFUSED:
  769. logmsg("Refused");
  770. rejectcount++;
  771. reply("554 5.7.1 Sender domain must exist: %s\r\n",
  772. s_to_c(senders.last->p));
  773. return 0;
  774. default:
  775. case NONE:
  776. logmsg("Confused");
  777. rejectcount++;
  778. reply("554-5.7.0 We have had an internal mailer error "
  779. "classifying your message.\r\n");
  780. reply("554-5.7.0 Filterstate is %d\r\n", filterstate);
  781. reply("554 5.7.0 Contact postmaster@%s for more information.\r\n",
  782. dom);
  783. return 0;
  784. case ACCEPT:
  785. case TRUSTED:
  786. /*
  787. * now that all other filters have been passed,
  788. * do grey-list processing.
  789. */
  790. if(gflag)
  791. vfysenderhostok();
  792. /*
  793. * set up mail command
  794. */
  795. cmd = s_clone(mailer);
  796. n = 3;
  797. for(l = rcvers.first; l; l = l->next)
  798. n++;
  799. av = malloc(n * sizeof(char*));
  800. if(av == nil){
  801. reply("450 4.3.2 We're busy right now, try later\r\n");
  802. s_free(cmd);
  803. return 0;
  804. }
  805. n = 0;
  806. av[n++] = s_to_c(cmd);
  807. av[n++] = "-r";
  808. for(l = rcvers.first; l; l = l->next)
  809. av[n++] = s_to_c(l->p);
  810. av[n] = 0;
  811. /*
  812. * start mail process
  813. */
  814. pp = noshell_proc_start(av, instream(), outstream(),
  815. outstream(), 0, 0);
  816. free(av);
  817. break;
  818. }
  819. if(pp == 0) {
  820. reply("450 4.3.2 We're busy right now, try later\r\n");
  821. s_free(cmd);
  822. return 0;
  823. }
  824. return cmd;
  825. }
  826. /*
  827. * print out a header line, expanding any domainless addresses into
  828. * address@him
  829. */
  830. char*
  831. bprintnode(Biobuf *b, Node *p)
  832. {
  833. if(p->s){
  834. if(p->addr && strchr(s_to_c(p->s), '@') == nil){
  835. if(Bprint(b, "%s@%s", s_to_c(p->s), him) < 0)
  836. return nil;
  837. } else {
  838. if(Bwrite(b, s_to_c(p->s), s_len(p->s)) < 0)
  839. return nil;
  840. }
  841. }else{
  842. if(Bputc(b, p->c) < 0)
  843. return nil;
  844. }
  845. if(p->white)
  846. if(Bwrite(b, s_to_c(p->white), s_len(p->white)) < 0)
  847. return nil;
  848. return p->end+1;
  849. }
  850. static String*
  851. getaddr(Node *p)
  852. {
  853. for(; p; p = p->next)
  854. if(p->s && p->addr)
  855. return p->s;
  856. return nil;
  857. }
  858. /*
  859. * add warning headers of the form
  860. * X-warning: <reason>
  861. * for any headers that looked like they might be forged.
  862. *
  863. * return byte count of new headers
  864. */
  865. static int
  866. forgedheaderwarnings(void)
  867. {
  868. int nbytes;
  869. Field *f;
  870. nbytes = 0;
  871. /* warn about envelope sender */
  872. if(strcmp(s_to_c(senders.last->p), "/dev/null") != 0 &&
  873. masquerade(senders.last->p, nil))
  874. nbytes += Bprint(pp->std[0]->fp,
  875. "X-warning: suspect envelope domain\n");
  876. /*
  877. * check Sender: field. If it's OK, ignore the others because this
  878. * is an exploded mailing list.
  879. */
  880. for(f = firstfield; f; f = f->next)
  881. if(f->node->c == SENDER)
  882. if(masquerade(getaddr(f->node), him))
  883. nbytes += Bprint(pp->std[0]->fp,
  884. "X-warning: suspect Sender: domain\n");
  885. else
  886. return nbytes;
  887. /* check From: */
  888. for(f = firstfield; f; f = f->next){
  889. if(f->node->c == FROM && masquerade(getaddr(f->node), him))
  890. nbytes += Bprint(pp->std[0]->fp,
  891. "X-warning: suspect From: domain\n");
  892. }
  893. return nbytes;
  894. }
  895. /*
  896. * pipe message to mailer with the following transformations:
  897. * - change \r\n into \n.
  898. * - add sender's domain to any addrs with no domain
  899. * - add a From: if none of From:, Sender:, or Replyto: exists
  900. * - add a Received: line
  901. */
  902. int
  903. pipemsg(int *byteswritten)
  904. {
  905. int n, nbytes, sawdot, status;
  906. char *cp;
  907. Field *f;
  908. Link *l;
  909. Node *p;
  910. String *hdr, *line;
  911. pipesig(&status); /* set status to 1 on write to closed pipe */
  912. sawdot = 0;
  913. status = 0;
  914. /*
  915. * add a 'From ' line as envelope
  916. */
  917. nbytes = 0;
  918. nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
  919. s_to_c(senders.first->p), thedate());
  920. /*
  921. * add our own Received: stamp
  922. */
  923. nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
  924. if(nci->rsys)
  925. nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
  926. nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());
  927. /*
  928. * read first 16k obeying '.' escape. we're assuming
  929. * the header will all be there.
  930. */
  931. line = s_new();
  932. hdr = s_new();
  933. while(sawdot == 0 && s_len(hdr) < 16*1024){
  934. n = getcrnl(s_reset(line), &bin);
  935. /* eof or error ends the message */
  936. if(n <= 0)
  937. break;
  938. /* a line with only a '.' ends the message */
  939. cp = s_to_c(line);
  940. if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
  941. sawdot = 1;
  942. break;
  943. }
  944. s_append(hdr, *cp == '.' ? cp+1 : cp);
  945. }
  946. /*
  947. * parse header
  948. */
  949. yyinit(s_to_c(hdr), s_len(hdr));
  950. yyparse();
  951. /*
  952. * Look for masquerades. Let Sender: trump From: to allow mailing list
  953. * forwarded messages.
  954. */
  955. if(fflag)
  956. nbytes += forgedheaderwarnings();
  957. /*
  958. * add an orginator and/or destination if either is missing
  959. */
  960. if(originator == 0){
  961. if(senders.last == nil)
  962. Bprint(pp->std[0]->fp, "From: /dev/null@%s\n", him);
  963. else
  964. Bprint(pp->std[0]->fp, "From: %s\n",
  965. s_to_c(senders.last->p));
  966. }
  967. if(destination == 0){
  968. Bprint(pp->std[0]->fp, "To: ");
  969. for(l = rcvers.first; l; l = l->next){
  970. if(l != rcvers.first)
  971. Bprint(pp->std[0]->fp, ", ");
  972. Bprint(pp->std[0]->fp, "%s", s_to_c(l->p));
  973. }
  974. Bprint(pp->std[0]->fp, "\n");
  975. }
  976. /*
  977. * add sender's domain to any domainless addresses
  978. * (to avoid forging local addresses)
  979. */
  980. cp = s_to_c(hdr);
  981. for(f = firstfield; cp != nil && f; f = f->next){
  982. for(p = f->node; cp != 0 && p; p = p->next)
  983. cp = bprintnode(pp->std[0]->fp, p);
  984. if(status == 0 && Bprint(pp->std[0]->fp, "\n") < 0){
  985. piperror = "write error";
  986. status = 1;
  987. }
  988. }
  989. if(cp == nil){
  990. piperror = "sender domain";
  991. status = 1;
  992. }
  993. /* write anything we read following the header */
  994. if(status == 0 &&
  995. Bwrite(pp->std[0]->fp, cp, s_to_c(hdr) + s_len(hdr) - cp) < 0){
  996. piperror = "write error 2";
  997. status = 1;
  998. }
  999. s_free(hdr);
  1000. /*
  1001. * pass rest of message to mailer. take care of '.'
  1002. * escapes.
  1003. */
  1004. while(sawdot == 0){
  1005. n = getcrnl(s_reset(line), &bin);
  1006. /* eof or error ends the message */
  1007. if(n <= 0)
  1008. break;
  1009. /* a line with only a '.' ends the message */
  1010. cp = s_to_c(line);
  1011. if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
  1012. sawdot = 1;
  1013. break;
  1014. }
  1015. if(cp[0] == '.'){
  1016. cp++;
  1017. n--;
  1018. }
  1019. nbytes += n;
  1020. if(status == 0 && Bwrite(pp->std[0]->fp, cp, n) < 0){
  1021. piperror = "write error 3";
  1022. status = 1;
  1023. }
  1024. }
  1025. s_free(line);
  1026. if(sawdot == 0){
  1027. /* message did not terminate normally */
  1028. snprint(pipbuf, sizeof pipbuf, "network eof: %r");
  1029. piperror = pipbuf;
  1030. syskillpg(pp->pid);
  1031. status = 1;
  1032. }
  1033. if(status == 0 && Bflush(pp->std[0]->fp) < 0){
  1034. piperror = "write error 4";
  1035. status = 1;
  1036. }
  1037. stream_free(pp->std[0]);
  1038. pp->std[0] = 0;
  1039. *byteswritten = nbytes;
  1040. pipesigoff();
  1041. if(status && !piperror)
  1042. piperror = "write on closed pipe";
  1043. return status;
  1044. }
  1045. char*
  1046. firstline(char *x)
  1047. {
  1048. char *p;
  1049. static char buf[128];
  1050. strncpy(buf, x, sizeof(buf));
  1051. buf[sizeof(buf)-1] = 0;
  1052. p = strchr(buf, '\n');
  1053. if(p)
  1054. *p = 0;
  1055. return buf;
  1056. }
  1057. int
  1058. sendermxcheck(void)
  1059. {
  1060. int pid;
  1061. char *cp, *senddom, *user, *who;
  1062. Waitmsg *w;
  1063. who = s_to_c(senders.first->p);
  1064. if(strcmp(who, "/dev/null") == 0){
  1065. /* /dev/null can only send to one rcpt at a time */
  1066. if(rcvers.first != rcvers.last){
  1067. werrstr("rejected: /dev/null sending to multiple "
  1068. "recipients");
  1069. return -1;
  1070. }
  1071. return 0;
  1072. }
  1073. if(access("/mail/lib/validatesender", AEXEC) < 0)
  1074. return 0;
  1075. senddom = strdup(who);
  1076. if((cp = strchr(senddom, '!')) == nil){
  1077. werrstr("rejected: domainless sender %s", who);
  1078. free(senddom);
  1079. return -1;
  1080. }
  1081. *cp++ = 0;
  1082. user = cp;
  1083. switch(pid = fork()){
  1084. case -1:
  1085. werrstr("deferred: fork: %r");
  1086. return -1;
  1087. case 0:
  1088. /*
  1089. * Could add an option with the remote IP address
  1090. * to allow validatesender to implement SPF eventually.
  1091. */
  1092. execl("/mail/lib/validatesender", "validatesender",
  1093. "-n", nci->root, senddom, user, nil);
  1094. _exits("exec validatesender: %r");
  1095. default:
  1096. break;
  1097. }
  1098. free(senddom);
  1099. w = wait();
  1100. if(w == nil){
  1101. werrstr("deferred: wait failed: %r");
  1102. return -1;
  1103. }
  1104. if(w->pid != pid){
  1105. werrstr("deferred: wait returned wrong pid %d != %d",
  1106. w->pid, pid);
  1107. free(w);
  1108. return -1;
  1109. }
  1110. if(w->msg[0] == 0){
  1111. free(w);
  1112. return 0;
  1113. }
  1114. /*
  1115. * skip over validatesender 143123132: prefix from rc.
  1116. */
  1117. cp = strchr(w->msg, ':');
  1118. if(cp && *(cp+1) == ' ')
  1119. werrstr("%s", cp+2);
  1120. else
  1121. werrstr("%s", w->msg);
  1122. free(w);
  1123. return -1;
  1124. }
  1125. void
  1126. data(void)
  1127. {
  1128. int status, nbytes;
  1129. char *cp, *ep;
  1130. char errx[ERRMAX];
  1131. Link *l;
  1132. String *cmd, *err;
  1133. if(rejectcheck())
  1134. return;
  1135. if(senders.last == 0){
  1136. reply("503 2.5.2 Data without MAIL FROM:\r\n");
  1137. rejectcount++;
  1138. return;
  1139. }
  1140. if(rcvers.last == 0){
  1141. reply("503 2.5.2 Data without RCPT TO:\r\n");
  1142. rejectcount++;
  1143. return;
  1144. }
  1145. if(!trusted && sendermxcheck()){
  1146. rerrstr(errx, sizeof errx);
  1147. if(strncmp(errx, "rejected:", 9) == 0)
  1148. reply("554 5.7.1 %s\r\n", errx);
  1149. else
  1150. reply("450 4.7.0 %s\r\n", errx);
  1151. for(l=rcvers.first; l; l=l->next)
  1152. syslog(0, "smtpd", "[%s/%s] %s -> %s sendercheck: %s",
  1153. him, nci->rsys, s_to_c(senders.first->p),
  1154. s_to_c(l->p), errx);
  1155. rejectcount++;
  1156. return;
  1157. }
  1158. cmd = startcmd();
  1159. if(cmd == 0)
  1160. return;
  1161. reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
  1162. /*
  1163. * allow 145 more minutes to move the data
  1164. */
  1165. alarm(145*60*1000);
  1166. status = pipemsg(&nbytes);
  1167. /*
  1168. * read any error messages
  1169. */
  1170. err = s_new();
  1171. while(s_read_line(pp->std[2]->fp, err))
  1172. ;
  1173. alarm(0);
  1174. atnotify(catchalarm, 0);
  1175. status |= proc_wait(pp);
  1176. if(debug){
  1177. seek(2, 0, 2);
  1178. fprint(2, "%d status %ux\n", getpid(), status);
  1179. if(*s_to_c(err))
  1180. fprint(2, "%d error %s\n", getpid(), s_to_c(err));
  1181. }
  1182. /*
  1183. * if process terminated abnormally, send back error message
  1184. */
  1185. if(status){
  1186. int code;
  1187. char *ecode;
  1188. if(strstr(s_to_c(err), "mail refused")){
  1189. syslog(0, "smtpd", "++[%s/%s] %s %s refused: %s",
  1190. him, nci->rsys, s_to_c(senders.first->p),
  1191. s_to_c(cmd), firstline(s_to_c(err)));
  1192. code = 554;
  1193. ecode = "5.0.0";
  1194. } else {
  1195. syslog(0, "smtpd", "++[%s/%s] %s %s %s%s%sreturned %#q %s",
  1196. him, nci->rsys,
  1197. s_to_c(senders.first->p), s_to_c(cmd),
  1198. piperror? "error during pipemsg: ": "",
  1199. piperror? piperror: "",
  1200. piperror? "; ": "",
  1201. pp->waitmsg->msg, firstline(s_to_c(err)));
  1202. code = 450;
  1203. ecode = "4.0.0";
  1204. }
  1205. for(cp = s_to_c(err); ep = strchr(cp, '\n'); cp = ep){
  1206. *ep++ = 0;
  1207. reply("%d-%s %s\r\n", code, ecode, cp);
  1208. }
  1209. reply("%d %s mail process terminated abnormally\r\n",
  1210. code, ecode);
  1211. } else {
  1212. /*
  1213. * if a message appeared on stderr, despite good status,
  1214. * log it. this can happen if rewrite.in contains a bad
  1215. * r.e., for example.
  1216. */
  1217. if(*s_to_c(err))
  1218. syslog(0, "smtpd",
  1219. "%s returned good status, but said: %s",
  1220. s_to_c(mailer), s_to_c(err));
  1221. if(filterstate == BLOCKED)
  1222. reply("554 5.7.1 we believe this is spam. "
  1223. "we don't accept it.\r\n");
  1224. else if(filterstate == DELAY)
  1225. reply("450 4.3.0 There will be a delay in delivery "
  1226. "of this message.\r\n");
  1227. else {
  1228. reply("250 2.5.0 sent\r\n");
  1229. logcall(nbytes);
  1230. }
  1231. }
  1232. proc_free(pp);
  1233. pp = 0;
  1234. s_free(cmd);
  1235. s_free(err);
  1236. listfree(&senders);
  1237. listfree(&rcvers);
  1238. }
  1239. /*
  1240. * when we have blocked a transaction based on IP address, there is nothing
  1241. * that the sender can do to convince us to take the message. after the
  1242. * first rejection, some spammers continually RSET and give a new MAIL FROM:
  1243. * filling our logs with rejections. rejectcheck() limits the retries and
  1244. * swiftly rejects all further commands after the first 500-series message
  1245. * is issued.
  1246. */
  1247. int
  1248. rejectcheck(void)
  1249. {
  1250. if(rejectcount > MAXREJECTS){
  1251. syslog(0, "smtpd", "Rejected (%s/%s)", him, nci->rsys);
  1252. reply("554 5.5.0 too many errors. transaction failed.\r\n");
  1253. exits("errcount");
  1254. }
  1255. if(hardreject){
  1256. rejectcount++;
  1257. reply("554 5.7.1 We don't accept mail from dial-up ports.\r\n");
  1258. }
  1259. return hardreject;
  1260. }
  1261. /*
  1262. * create abs path of the mailer
  1263. */
  1264. String*
  1265. mailerpath(char *p)
  1266. {
  1267. String *s;
  1268. if(p == nil)
  1269. return nil;
  1270. if(*p == '/')
  1271. return s_copy(p);
  1272. s = s_new();
  1273. s_append(s, UPASBIN);
  1274. s_append(s, "/");
  1275. s_append(s, p);
  1276. return s;
  1277. }
  1278. String *
  1279. s_dec64(String *sin)
  1280. {
  1281. int lin, lout;
  1282. String *sout;
  1283. lin = s_len(sin);
  1284. /*
  1285. * if the string is coming from smtpd.y, it will have no nl.
  1286. * if it is coming from getcrnl below, it will have an nl.
  1287. */
  1288. if (*(s_to_c(sin)+lin-1) == '\n')
  1289. lin--;
  1290. sout = s_newalloc(lin+1);
  1291. lout = dec64((uchar *)s_to_c(sout), lin, s_to_c(sin), lin);
  1292. if (lout < 0) {
  1293. s_free(sout);
  1294. return nil;
  1295. }
  1296. sout->ptr = sout->base + lout;
  1297. s_terminate(sout);
  1298. return sout;
  1299. }
  1300. void
  1301. starttls(void)
  1302. {
  1303. int certlen, fd;
  1304. uchar *cert;
  1305. TLSconn *conn;
  1306. if (tlscert == nil) {
  1307. reply("500 5.5.1 illegal command or bad syntax\r\n");
  1308. return;
  1309. }
  1310. conn = mallocz(sizeof *conn, 1);
  1311. cert = readcert(tlscert, &certlen);
  1312. if (conn == nil || cert == nil) {
  1313. if (conn != nil)
  1314. free(conn);
  1315. reply("454 4.7.5 TLS not available\r\n");
  1316. return;
  1317. }
  1318. reply("220 2.0.0 Go ahead make my day\r\n");
  1319. conn->cert = cert;
  1320. conn->certlen = certlen;
  1321. fd = tlsServer(Bfildes(&bin), conn);
  1322. if (fd < 0) {
  1323. free(cert);
  1324. free(conn);
  1325. syslog(0, "smtpd", "TLS start-up failed with %s", him);
  1326. /* force the client to hang up */
  1327. close(Bfildes(&bin)); /* probably fd 0 */
  1328. close(1);
  1329. exits("tls failed");
  1330. }
  1331. Bterm(&bin);
  1332. Binit(&bin, fd, OREAD);
  1333. if (dup(fd, 1) < 0)
  1334. fprint(2, "dup of %d failed: %r\n", fd);
  1335. passwordinclear = 1;
  1336. syslog(0, "smtpd", "started TLS with %s", him);
  1337. }
  1338. void
  1339. auth(String *mech, String *resp)
  1340. {
  1341. char *user, *pass, *scratch = nil;
  1342. AuthInfo *ai = nil;
  1343. Chalstate *chs = nil;
  1344. String *s_resp1_64 = nil, *s_resp2_64 = nil, *s_resp1 = nil;
  1345. String *s_resp2 = nil;
  1346. if (rejectcheck())
  1347. goto bomb_out;
  1348. syslog(0, "smtpd", "auth(%s, %s) from %s", s_to_c(mech),
  1349. "(protected)", him);
  1350. if (authenticated) {
  1351. bad_sequence:
  1352. rejectcount++;
  1353. reply("503 5.5.2 Bad sequence of commands\r\n");
  1354. goto bomb_out;
  1355. }
  1356. if (cistrcmp(s_to_c(mech), "plain") == 0) {
  1357. if (!passwordinclear) {
  1358. rejectcount++;
  1359. reply("538 5.7.1 Encryption required for requested "
  1360. "authentication mechanism\r\n");
  1361. goto bomb_out;
  1362. }
  1363. s_resp1_64 = resp;
  1364. if (s_resp1_64 == nil) {
  1365. reply("334 \r\n");
  1366. s_resp1_64 = s_new();
  1367. if (getcrnl(s_resp1_64, &bin) <= 0)
  1368. goto bad_sequence;
  1369. }
  1370. s_resp1 = s_dec64(s_resp1_64);
  1371. if (s_resp1 == nil) {
  1372. rejectcount++;
  1373. reply("501 5.5.4 Cannot decode base64\r\n");
  1374. goto bomb_out;
  1375. }
  1376. memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
  1377. user = (s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1);
  1378. pass = user + (strlen(user) + 1);
  1379. ai = auth_userpasswd(user, pass);
  1380. authenticated = ai != nil;
  1381. memset(pass, 'X', strlen(pass));
  1382. goto windup;
  1383. }
  1384. else if (cistrcmp(s_to_c(mech), "login") == 0) {
  1385. if (!passwordinclear) {
  1386. rejectcount++;
  1387. reply("538 5.7.1 Encryption required for requested "
  1388. "authentication mechanism\r\n");
  1389. goto bomb_out;
  1390. }
  1391. if (resp == nil) {
  1392. reply("334 VXNlcm5hbWU6\r\n");
  1393. s_resp1_64 = s_new();
  1394. if (getcrnl(s_resp1_64, &bin) <= 0)
  1395. goto bad_sequence;
  1396. }
  1397. reply("334 UGFzc3dvcmQ6\r\n");
  1398. s_resp2_64 = s_new();
  1399. if (getcrnl(s_resp2_64, &bin) <= 0)
  1400. goto bad_sequence;
  1401. s_resp1 = s_dec64(s_resp1_64);
  1402. s_resp2 = s_dec64(s_resp2_64);
  1403. memset(s_to_c(s_resp2_64), 'X', s_len(s_resp2_64));
  1404. if (s_resp1 == nil || s_resp2 == nil) {
  1405. rejectcount++;
  1406. reply("501 5.5.4 Cannot decode base64\r\n");
  1407. goto bomb_out;
  1408. }
  1409. ai = auth_userpasswd(s_to_c(s_resp1), s_to_c(s_resp2));
  1410. authenticated = ai != nil;
  1411. memset(s_to_c(s_resp2), 'X', s_len(s_resp2));
  1412. windup:
  1413. if (authenticated) {
  1414. /* if you authenticated, we trust you despite your IP */
  1415. trusted = 1;
  1416. reply("235 2.0.0 Authentication successful\r\n");
  1417. } else {
  1418. rejectcount++;
  1419. reply("535 5.7.1 Authentication failed\r\n");
  1420. syslog(0, "smtpd", "authentication failed: %r");
  1421. }
  1422. goto bomb_out;
  1423. }
  1424. else if (cistrcmp(s_to_c(mech), "cram-md5") == 0) {
  1425. int chal64n;
  1426. char *resp, *t;
  1427. chs = auth_challenge("proto=cram role=server");
  1428. if (chs == nil) {
  1429. rejectcount++;
  1430. reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n");
  1431. goto bomb_out;
  1432. }
  1433. scratch = malloc(chs->nchal * 2 + 1);
  1434. chal64n = enc64(scratch, chs->nchal * 2, (uchar *)chs->chal,
  1435. chs->nchal);
  1436. scratch[chal64n] = 0;
  1437. reply("334 %s\r\n", scratch);
  1438. s_resp1_64 = s_new();
  1439. if (getcrnl(s_resp1_64, &bin) <= 0)
  1440. goto bad_sequence;
  1441. s_resp1 = s_dec64(s_resp1_64);
  1442. if (s_resp1 == nil) {
  1443. rejectcount++;
  1444. reply("501 5.5.4 Cannot decode base64\r\n");
  1445. goto bomb_out;
  1446. }
  1447. /* should be of form <user><space><response> */
  1448. resp = s_to_c(s_resp1);
  1449. t = strchr(resp, ' ');
  1450. if (t == nil) {
  1451. rejectcount++;
  1452. reply("501 5.5.4 Poorly formed CRAM-MD5 response\r\n");
  1453. goto bomb_out;
  1454. }
  1455. *t++ = 0;
  1456. chs->user = resp;
  1457. chs->resp = t;
  1458. chs->nresp = strlen(t);
  1459. ai = auth_response(chs);
  1460. authenticated = ai != nil;
  1461. goto windup;
  1462. }
  1463. rejectcount++;
  1464. reply("501 5.5.1 Unrecognised authentication type %s\r\n", s_to_c(mech));
  1465. bomb_out:
  1466. if (ai)
  1467. auth_freeAI(ai);
  1468. if (chs)
  1469. auth_freechal(chs);
  1470. if (scratch)
  1471. free(scratch);
  1472. if (s_resp1)
  1473. s_free(s_resp1);
  1474. if (s_resp2)
  1475. s_free(s_resp2);
  1476. if (s_resp1_64)
  1477. s_free(s_resp1_64);
  1478. if (s_resp2_64)
  1479. s_free(s_resp2_64);
  1480. }