srvrsmtp.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:55k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #include <sendmail.h>
  14. #ifndef lint
  15. # if SMTP
  16. static char id[] = "@(#)$Id: srvrsmtp.c,v 8.403 1999/12/08 18:38:23 ca Exp $ (with SMTP)";
  17. # else /* SMTP */
  18. static char id[] = "@(#)$Id: srvrsmtp.c,v 8.403 1999/12/08 18:38:23 ca Exp $ (without SMTP)";
  19. # endif /* SMTP */
  20. #endif /* ! lint */
  21. #if SMTP
  22. # if SASL
  23. #  define ENC64LEN(l) (((l) + 2) * 4 / 3 + 1)
  24. # endif /* SASL */
  25. static time_t checksmtpattack __P((volatile int *, int, bool,
  26.      char *, ENVELOPE *));
  27. static void mail_esmtp_args __P((char *, char *, ENVELOPE *));
  28. static void printvrfyaddr __P((ADDRESS *, bool, bool));
  29. static void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
  30. static int runinchild __P((char *, ENVELOPE *));
  31. static char *skipword __P((char *volatile, char *));
  32. extern ENVELOPE BlankEnvelope;
  33. /*
  34. **  SMTP -- run the SMTP protocol.
  35. **
  36. ** Parameters:
  37. ** nullserver -- if non-NULL, rejection message for
  38. ** all SMTP commands.
  39. ** e -- the envelope.
  40. **
  41. ** Returns:
  42. ** never.
  43. **
  44. ** Side Effects:
  45. ** Reads commands from the input channel and processes
  46. ** them.
  47. */
  48. struct cmd
  49. {
  50. char *cmd_name; /* command name */
  51. int cmd_code; /* internal code, see below */
  52. };
  53. /* values for cmd_code */
  54. # define CMDERROR 0 /* bad command */
  55. # define CMDMAIL 1 /* mail -- designate sender */
  56. # define CMDRCPT 2 /* rcpt -- designate recipient */
  57. # define CMDDATA 3 /* data -- send message text */
  58. # define CMDRSET 4 /* rset -- reset state */
  59. # define CMDVRFY 5 /* vrfy -- verify address */
  60. # define CMDEXPN 6 /* expn -- expand address */
  61. # define CMDNOOP 7 /* noop -- do nothing */
  62. # define CMDQUIT 8 /* quit -- close connection and die */
  63. # define CMDHELO 9 /* helo -- be polite */
  64. # define CMDHELP 10 /* help -- give usage info */
  65. # define CMDEHLO 11 /* ehlo -- extended helo (RFC 1425) */
  66. # define CMDETRN 12 /* etrn -- flush queue */
  67. # if SASL
  68. #  define CMDAUTH 13 /* auth -- SASL authenticate */
  69. # endif /* SASL */
  70. /* non-standard commands */
  71. # define CMDONEX 16 /* onex -- sending one transaction only */
  72. # define CMDVERB 17 /* verb -- go into verbose mode */
  73. # define CMDXUSR 18 /* xusr -- initial (user) submission */
  74. /* unimplemented commands from RFC 821 */
  75. # define CMDUNIMPL 19 /* unimplemented rfc821 commands */
  76. /* use this to catch and log "door handle" attempts on your system */
  77. # define CMDLOGBOGUS 23 /* bogus command that should be logged */
  78. /* debugging-only commands, only enabled if SMTPDEBUG is defined */
  79. # define CMDDBGQSHOW 24 /* showq -- show send queue */
  80. # define CMDDBGDEBUG 25 /* debug -- set debug mode */
  81. static struct cmd CmdTab[] =
  82. {
  83. { "mail", CMDMAIL },
  84. { "rcpt", CMDRCPT },
  85. { "data", CMDDATA },
  86. { "rset", CMDRSET },
  87. { "vrfy", CMDVRFY },
  88. { "expn", CMDEXPN },
  89. { "help", CMDHELP },
  90. { "noop", CMDNOOP },
  91. { "quit", CMDQUIT },
  92. { "helo", CMDHELO },
  93. { "ehlo", CMDEHLO },
  94. { "etrn", CMDETRN },
  95. { "verb", CMDVERB },
  96. { "onex", CMDONEX },
  97. { "xusr", CMDXUSR },
  98. { "send", CMDUNIMPL },
  99. { "saml", CMDUNIMPL },
  100. { "soml", CMDUNIMPL },
  101. { "turn", CMDUNIMPL },
  102. # if SASL
  103. { "auth", CMDAUTH, },
  104. # endif /* SASL */
  105.     /* remaining commands are here only to trap and log attempts to use them */
  106. { "showq", CMDDBGQSHOW },
  107. { "debug", CMDDBGDEBUG },
  108. { "wiz", CMDLOGBOGUS },
  109. { NULL, CMDERROR }
  110. };
  111. static bool OneXact = FALSE; /* one xaction only this run */
  112. static char *CurSmtpClient; /* who's at the other end of channel */
  113. # define MAXBADCOMMANDS 25 /* maximum number of bad commands */
  114. # define MAXNOOPCOMMANDS 20 /* max "noise" commands before slowdown */
  115. # define MAXHELOCOMMANDS 3 /* max HELO/EHLO commands before slowdown */
  116. # define MAXVRFYCOMMANDS 6 /* max VRFY/EXPN commands before slowdown */
  117. # define MAXETRNCOMMANDS 8 /* max ETRN commands before slowdown */
  118. # define MAXTIMEOUT (4 * 60) /* max timeout for bad commands */
  119. void
  120. smtp(nullserver, d_flags, e)
  121. char *nullserver;
  122. BITMAP256 d_flags;
  123. register ENVELOPE *volatile e;
  124. {
  125. register char *volatile p;
  126. register struct cmd *volatile c = NULL;
  127. char *cmd;
  128. auto ADDRESS *vrfyqueue;
  129. ADDRESS *a;
  130. volatile bool gotmail; /* mail command received */
  131. volatile bool gothello; /* helo command received */
  132. bool vrfy; /* set if this is a vrfy command */
  133. char *volatile protocol; /* sending protocol */
  134. char *volatile sendinghost; /* sending hostname */
  135. char *volatile peerhostname; /* name of SMTP peer or "localhost" */
  136. auto char *delimptr;
  137. char *id;
  138. volatile int nrcpts = 0; /* number of RCPT commands */
  139. bool doublequeue;
  140. volatile bool discard;
  141. volatile int badcommands = 0; /* count of bad commands */
  142. volatile int nverifies = 0; /* count of VRFY/EXPN commands */
  143. volatile int n_etrn = 0; /* count of ETRN commands */
  144. volatile int n_noop = 0; /* count of NOOP/VERB/ONEX etc cmds */
  145. volatile int n_helo = 0; /* count of HELO/EHLO commands */
  146. volatile int delay = 1; /* timeout for bad commands */
  147. bool ok;
  148. bool tempfail = FALSE;
  149. volatile time_t wt; /* timeout after too many commands */
  150. volatile time_t previous; /* time after checksmtpattack() */
  151. volatile int lognullconnection = TRUE;
  152. register char *q;
  153. char *addr;
  154. char *greetcode = "220";
  155. QUEUE_CHAR *new;
  156. int argno;
  157. char *args[MAXSMTPARGS];
  158. char inp[MAXLINE];
  159. char cmdbuf[MAXLINE];
  160. # if SASL
  161. sasl_conn_t *conn;
  162. volatile bool sasl_ok;
  163. bool ismore;
  164. int result;
  165. volatile int authenticating;
  166. char *hostname;
  167. char *user;
  168. char *in, *out, *out2;
  169. const char *errstr;
  170. int inlen, out2len;
  171. unsigned int outlen;
  172. char *volatile auth_type;
  173. char *mechlist;
  174. int len, num;
  175. # endif /* SASL */
  176. if (fileno(OutChannel) != fileno(stdout))
  177. {
  178. /* arrange for debugging output to go to remote host */
  179. (void) dup2(fileno(OutChannel), fileno(stdout));
  180. }
  181. settime(e);
  182. (void)sm_getla(e);
  183. peerhostname = RealHostName;
  184. if (peerhostname == NULL)
  185. peerhostname = "localhost";
  186. CurHostName = peerhostname;
  187. CurSmtpClient = macvalue('_', e);
  188. if (CurSmtpClient == NULL)
  189. CurSmtpClient = CurHostName;
  190. /* check_relay may have set discard bit, save for later */
  191. discard = bitset(EF_DISCARD, e->e_flags);
  192. sm_setproctitle(TRUE, e, "server %s startup", CurSmtpClient);
  193. # if SASL
  194. sasl_ok = FALSE; /* SASL can't be used (yet) */
  195. /* SASL server new connection */
  196. hostname = macvalue('j', e);
  197. /* XXX input parameter for realm? */
  198. #  if SASL > 10505
  199. /* use empty realm: doesn't work in SASL <= 1.5.5 */
  200. result = sasl_server_new("smtp", hostname, "", NULL, 0, &conn);
  201. #  else /* SASL > 10505 */
  202. /* use no realm -> realm is set to hostname by SASL lib */
  203. result = sasl_server_new("smtp", hostname, NULL, NULL, 0, &conn);
  204. #  endif /* SASL > 10505 */
  205. if (result == SASL_OK)
  206. {
  207. sasl_ok = TRUE;
  208. /*
  209. **  SASL set properties for sasl
  210. **  set local/remote IP
  211. **  XXX only IPv4: Cyrus SASL doesn't support anything else
  212. **
  213. **  XXX where exactly are these used/required?
  214. **  Kerberos_v4
  215. */
  216. # if NETINET
  217. in = macvalue(macid("{daemon_family}", NULL), e);
  218. if (in != NULL && strcmp(in, "inet") == 0)
  219. {
  220. SOCKADDR_LEN_T addrsize;
  221. struct sockaddr_in saddr_l;
  222. struct sockaddr_in saddr_r;
  223. addrsize = sizeof(struct sockaddr_in);
  224. if (getpeername(fileno(InChannel),
  225. (struct sockaddr *)&saddr_r,
  226. &addrsize) == 0)
  227. {
  228. sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
  229. addrsize = sizeof(struct sockaddr_in);
  230. if (getsockname(fileno(InChannel),
  231. (struct sockaddr *)&saddr_l,
  232. &addrsize) == 0)
  233. sasl_setprop(conn, SASL_IP_LOCAL,
  234.      &saddr_l);
  235. }
  236. }
  237. # endif /* NETINET */
  238. /* end setting properties */
  239. authenticating = SASL_NOT_AUTH;
  240. auth_type = NULL;
  241. mechlist = NULL;
  242. user = NULL;
  243. #  if 0
  244. define(macid("{auth_author}", NULL), NULL, &BlankEnvelope);
  245. #  endif /* 0 */
  246. if (sasl_ok)
  247. {
  248. /* "user" is currently (cyrus-sasl 1.4.1) unused */
  249. result = sasl_listmech(conn, "user", /* XXX */
  250.        "", " ", "", &mechlist,
  251.        (u_int *)&len, (u_int *)&num);
  252. if (result == SASL_OK && num > 0)
  253. {
  254. if (LogLevel > 11)
  255. sm_syslog(LOG_INFO, NOQID,
  256.   "SASL: available mech=%s, allowed mech=%s",
  257.   mechlist, AuthMechanisms);
  258. mechlist = intersect(AuthMechanisms, mechlist);
  259. }
  260. else
  261. {
  262. sasl_ok = FALSE;
  263. if (LogLevel > 9)
  264. sm_syslog(LOG_WARNING, NOQID,
  265.   "SASL error: listmech=%d, num=%d",
  266.   result, num);
  267. }
  268. }
  269. else if (LogLevel > 9)
  270. sm_syslog(LOG_WARNING, NOQID,
  271.   "SASL error: get*name()");
  272. }
  273. else
  274. {
  275. sasl_ok = FALSE; /* SASL can't be used */
  276. if (LogLevel > 9)
  277. sm_syslog(LOG_WARNING, NOQID,
  278.   "SASL error: sasl_server_new=%d", result);
  279. }
  280. # endif /* SASL */
  281. /* output the first line, inserting "ESMTP" as second word */
  282. expand(SmtpGreeting, inp, sizeof inp, e);
  283. p = strchr(inp, 'n');
  284. if (p != NULL)
  285. *p++ = '';
  286. id = strchr(inp, ' ');
  287. if (id == NULL)
  288. id = &inp[strlen(inp)];
  289. if (p == NULL)
  290. snprintf(cmdbuf, sizeof cmdbuf,
  291.  "%s %%.*s ESMTP%%s", greetcode);
  292. else
  293. snprintf(cmdbuf, sizeof cmdbuf,
  294.  "%s-%%.*s ESMTP%%s", greetcode);
  295. message(cmdbuf, id - inp, inp, id);
  296. /* output remaining lines */
  297. while ((id = p) != NULL && (p = strchr(id, 'n')) != NULL)
  298. {
  299. *p++ = '';
  300. if (isascii(*id) && isspace(*id))
  301. id++;
  302. (void) snprintf(cmdbuf, sizeof cmdbuf, "%s-%%s", greetcode);
  303. message(cmdbuf, id);
  304. }
  305. if (id != NULL)
  306. {
  307. if (isascii(*id) && isspace(*id))
  308. id++;
  309. (void) snprintf(cmdbuf, sizeof cmdbuf, "%s %%s", greetcode);
  310. message(cmdbuf, id);
  311. }
  312. protocol = NULL;
  313. sendinghost = macvalue('s', e);
  314. gothello = FALSE;
  315. gotmail = FALSE;
  316. for (;;)
  317. {
  318. /* arrange for backout */
  319. (void) setjmp(TopFrame);
  320. QuickAbort = FALSE;
  321. HoldErrs = FALSE;
  322. SuprErrs = FALSE;
  323. LogUsrErrs = FALSE;
  324. OnlyOneError = TRUE;
  325. e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
  326. /* setup for the read */
  327. e->e_to = NULL;
  328. Errors = 0;
  329. FileName = NULL;
  330. (void) fflush(stdout);
  331. /* read the input line */
  332. SmtpPhase = "server cmd read";
  333. sm_setproctitle(TRUE, e, "server %s cmd read", CurSmtpClient);
  334. # if SASL
  335. /*
  336. **  SMTP AUTH requires accepting any length,
  337. **  at least for challenge/response
  338. **  XXX
  339. */
  340. # endif /* SASL */
  341. p = sfgets(inp, sizeof inp, InChannel, TimeOuts.to_nextcommand,
  342. SmtpPhase);
  343. /* handle errors */
  344. if (p == NULL)
  345. {
  346. char *d;
  347. d = macvalue(macid("{daemon_name}", NULL), e);
  348. if (d == NULL)
  349. d = "stdin";
  350. /* end of file, just die */
  351. disconnect(1, e);
  352. message("421 4.4.1 %s Lost input channel from %s",
  353. MyHostName, CurSmtpClient);
  354. if (LogLevel > (gotmail ? 1 : 19))
  355. sm_syslog(LOG_NOTICE, e->e_id,
  356.   "lost input channel from %.100s to %s after %s",
  357.   CurSmtpClient, d,
  358.   (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
  359. /*
  360. **  If have not accepted mail (DATA), do not bounce
  361. **  bad addresses back to sender.
  362. */
  363. if (bitset(EF_CLRQUEUE, e->e_flags))
  364. e->e_sendqueue = NULL;
  365. goto doquit;
  366. }
  367. /* clean up end of line */
  368. fixcrlf(inp, TRUE);
  369. # if SASL
  370. if (authenticating == SASL_PROC_AUTH)
  371. {
  372. if (tTd(95, 2))
  373. dprintf("AUTH: got "%s"n", inp);
  374. #  if 0
  375. if (*inp == '')
  376. {
  377. authenticating = SASL_NOT_AUTH;
  378. message("501 5.5.2 missing input");
  379. continue;
  380. }
  381. #  endif /* 0 */
  382. if (*inp == '*' && *(inp + 1) == '')
  383. {
  384. authenticating = SASL_NOT_AUTH;
  385. /* rfc 2254 4. */
  386. message("501 5.0.0 AUTH aborted");
  387. continue;
  388. }
  389. /* could this be shorter? XXX */
  390. out = xalloc(strlen(inp));
  391. result = sasl_decode64(inp, strlen(inp), out, &outlen);
  392. if (result != SASL_OK)
  393. {
  394. authenticating = SASL_NOT_AUTH;
  395. /* rfc 2254 4. */
  396. message("501 5.5.4 cannot decode AUTH parameter %s",
  397. inp);
  398. continue;
  399. }
  400. result = sasl_server_step(conn, out, outlen,
  401.   &out, &outlen, &errstr);
  402. /* get an OK if we're done */
  403. if (result == SASL_OK)
  404. {
  405.   authenticated:
  406. message("235 2.0.0 OK Authenticated");
  407. authenticating = SASL_IS_AUTH;
  408. define(macid("{auth_type}", NULL),
  409.        newstr(auth_type), &BlankEnvelope);
  410. if (tTd(95, 8))
  411. dprintf("SASL auth_type: '%s'n",
  412. auth_type);
  413. result = sasl_getprop(conn, SASL_USERNAME,
  414.       (void **)&user);
  415. if (result != SASL_OK)
  416. {
  417. user = NULL;
  418. define(macid("{auth_authen}", NULL),
  419.        NULL, &BlankEnvelope);
  420. }
  421. else
  422. {
  423. define(macid("{auth_authen}", NULL),
  424.        newstr(user), &BlankEnvelope);
  425. if (tTd(95, 8))
  426. dprintf("SASL auth_authen: '%s'n",
  427. user);
  428. }
  429. #  if 0
  430. /* get realm? */
  431. sasl_getprop(conn, SASL_REALM, (void **) &data);
  432. #  endif /* 0 */
  433. }
  434. else if (result == SASL_CONTINUE)
  435. {
  436. len = ENC64LEN(outlen);
  437. out2 = xalloc(len);
  438. result = sasl_encode64(out, outlen, out2, len,
  439.        (u_int *)&out2len);
  440. if (result != SASL_OK)
  441. {
  442. /* correct code? XXX */
  443. /* 454 Temp. authentication failure */
  444. message("454 4.5.4 Internal error: unable to encode64");
  445. if (LogLevel > 5)
  446. sm_syslog(LOG_WARNING, e->e_id,
  447.   "SASL encode64 error [%d for "%s"]",
  448.   result, out);
  449. /* start over? */
  450. authenticating = SASL_NOT_AUTH;
  451. }
  452. else
  453. {
  454. message("334 %s", out2);
  455. if (tTd(95, 2))
  456. dprintf("SASL continue: msg='%s' len=%dn",
  457. out2, out2len);
  458. }
  459. }
  460. else
  461. {
  462. /* not SASL_OK or SASL_CONT */
  463. message("500 5.7.0 authentication failed");
  464. if (LogLevel > 5)
  465. sm_syslog(LOG_WARNING, e->e_id,
  466.   "authentication failed: %s (%d)",
  467.   sasl_errstring(result, NULL,
  468.  NULL),
  469.   result);
  470. authenticating = SASL_NOT_AUTH;
  471. }
  472. }
  473. else
  474. {
  475. /* don't want to do any of this if authenticating */
  476. # endif /* SASL */
  477. /* echo command to transcript */
  478. if (e->e_xfp != NULL)
  479. fprintf(e->e_xfp, "<<< %sn", inp);
  480. if (LogLevel >= 15)
  481. sm_syslog(LOG_INFO, e->e_id,
  482.   "<-- %s",
  483.   inp);
  484. if (e->e_id == NULL)
  485. sm_setproctitle(TRUE, e, "%s: %.80s",
  486. CurSmtpClient, inp);
  487. else
  488. sm_setproctitle(TRUE, e, "%s %s: %.80s",
  489. qid_printname(e),
  490. CurSmtpClient, inp);
  491. /* break off command */
  492. for (p = inp; isascii(*p) && isspace(*p); p++)
  493. continue;
  494. cmd = cmdbuf;
  495. while (*p != '' &&
  496.        !(isascii(*p) && isspace(*p)) &&
  497.        cmd < &cmdbuf[sizeof cmdbuf - 2])
  498. *cmd++ = *p++;
  499. *cmd = '';
  500. /* throw away leading whitespace */
  501. while (isascii(*p) && isspace(*p))
  502. p++;
  503. /* decode command */
  504. for (c = CmdTab; c->cmd_name != NULL; c++)
  505. {
  506. if (!strcasecmp(c->cmd_name, cmdbuf))
  507. break;
  508. }
  509. /* reset errors */
  510. errno = 0;
  511. /*
  512. **  Process command.
  513. **
  514. ** If we are running as a null server, return 550
  515. ** to everything.
  516. */
  517. if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
  518. {
  519. switch (c->cmd_code)
  520. {
  521.   case CMDQUIT:
  522.   case CMDHELO:
  523.   case CMDEHLO:
  524.   case CMDNOOP:
  525.   case CMDRSET:
  526. /* process normally */
  527. break;
  528.   case CMDETRN:
  529. if (bitnset(D_ETRNONLY, d_flags) &&
  530.     nullserver == NULL)
  531. break;
  532. continue;
  533.   default:
  534. if (++badcommands > MAXBADCOMMANDS)
  535. {
  536. delay *= 2;
  537. if (delay >= MAXTIMEOUT)
  538. delay = MAXTIMEOUT;
  539. (void) sleep(delay);
  540. }
  541. if (nullserver != NULL)
  542. {
  543. if (ISSMTPREPLY(nullserver))
  544. usrerr(nullserver);
  545. else
  546. usrerr("550 5.0.0 %s", nullserver);
  547. }
  548. else
  549. usrerr("452 4.4.5 Insufficient disk space; try again later");
  550. continue;
  551. }
  552. }
  553. /* non-null server */
  554. switch (c->cmd_code)
  555. {
  556.   case CMDMAIL:
  557.   case CMDEXPN:
  558.   case CMDVRFY:
  559.   case CMDETRN:
  560. lognullconnection = FALSE;
  561. }
  562. switch (c->cmd_code)
  563. {
  564. # if SASL
  565.   case CMDAUTH: /* sasl */
  566. if (!sasl_ok)
  567. {
  568. message("503 5.3.3 AUTH not available");
  569. break;
  570. }
  571. if (authenticating == SASL_IS_AUTH)
  572. {
  573. message("503 5.5.0 Already Authenticated");
  574. break;
  575. }
  576. if (gotmail)
  577. {
  578. message("503 5.5.0 AUTH not permitted during a mail transaction");
  579. break;
  580. }
  581. ismore = FALSE;
  582. /* make sure it's a valid string */
  583. for (q = p; *q != '' && isascii(*q); q++)
  584. {
  585. if (isspace(*q))
  586. {
  587. *q = '';
  588. while (*++q != '' &&
  589.        isascii(*q) && isspace(*q))
  590. continue;
  591. *(q - 1) = '';
  592. ismore = (*q != '');
  593. break;
  594. }
  595. }
  596. /* check whether mechanism is available */
  597. if (iteminlist(p, mechlist, " ") == NULL)
  598. {
  599. message("503 5.3.3 AUTH mechanism %s not available",
  600. p);
  601. break;
  602. }
  603. if (ismore)
  604. {
  605. /* could this be shorter? XXX */
  606. in = xalloc(strlen(q));
  607. result = sasl_decode64(q, strlen(q), in,
  608.        (u_int *)&inlen);
  609. if (result != SASL_OK)
  610. {
  611. message("501 5.5.4 cannot BASE64 decode '%s'",
  612. q);
  613. if (LogLevel > 5)
  614. sm_syslog(LOG_WARNING, e->e_id,
  615.   "SASL decode64 error [%d for "%s"]",
  616.   result, q);
  617. /* start over? */
  618. authenticating = SASL_NOT_AUTH;
  619. in = NULL;
  620. inlen = 0;
  621. break;
  622. }
  623. if (tTd(95, 99))
  624. {
  625. int i;
  626. dprintf("AUTH: more "");
  627. for (i = 0; i < inlen; i++)
  628. {
  629. if (isascii(in[i]) &&
  630.     isprint(in[i]))
  631. dprintf("%c", in[i]);
  632. else
  633. dprintf("_");
  634. }
  635. dprintf(""n");
  636. }
  637. q = in;
  638. }
  639. else
  640. {
  641. in = NULL;
  642. inlen = 0;
  643. }
  644. /* see if that auth type exists */
  645. result = sasl_server_start(conn, p, in, inlen,
  646.    &out, &outlen, &errstr);
  647. /* XXX other errors */
  648. ismore = FALSE;
  649. switch (result)
  650. {
  651.   case SASL_OK:
  652.   case SASL_CONTINUE:
  653. ismore = TRUE;
  654. break;
  655.   case SASL_NOMECH:
  656. message("504 5.7.0 Unrecognized authentication type [%s]", p);
  657. break;
  658.   case SASL_NOUSER:
  659. message("504 5.7.0 Unrecognized user");
  660. break;
  661.   case SASL_BADAUTH:
  662. message("504 5.7.0 Authentication failure");
  663. break;
  664.   case SASL_BADPROT:
  665. message("504 5.7.0 Bad protocol");
  666. break;
  667.   case SASL_NOAUTHZ:
  668. message("504 5.7.0 Authorization failure");
  669. break;
  670.   case SASL_TOOWEAK:
  671. message("504 5.7.0 Mechanism too weak for this user");
  672. break;
  673.   case SASL_ENCRYPT:
  674. message("504 5.7.0 Encryption needed to use mechanism");
  675. break;
  676.   case SASL_TRANS:
  677. message("504 5.7.1 One time use of a plaintext password will enable requested mechanism for user");
  678. break;
  679.   case SASL_EXPIRED:
  680. message("504 5.7.1 Passphrase expired, has to be reset");
  681. break;
  682.   case SASL_DISABLED:
  683. message("504 5.7.1 Account disabled");
  684. break;
  685.   case SASL_PWLOCK:
  686. message("504 5.7.0 Password locked");
  687. break;
  688.   case SASL_NOCHANGE:
  689. message("504 5.7.0 Requested change was not needed");
  690. break;
  691.   case SASL_BADVERS:
  692. message("504 5.3.5 Version mismatch with plug-in");
  693. break;
  694.   default:
  695. message("500 5.3.5 Internal SASL error: %s (%d)",
  696. sasl_errstring(result, NULL, NULL),
  697. result);
  698. if (LogLevel > 0)
  699. sm_syslog(LOG_ERR, e->e_id,
  700.   "Internal SASL error: %s (%d)",
  701.   sasl_errstring(result, NULL,
  702.  NULL),
  703.   result);
  704. break;
  705. }
  706. if (!ismore)
  707. break; /* we had an error: break out */
  708. auth_type = newstr(p);
  709. if (result == SASL_OK)
  710. {
  711. /* ugly, but same code */
  712. goto authenticated;
  713. /* authenticated by the initial response */
  714. }
  715. /* len is at least 2 */
  716. len = ENC64LEN(outlen);
  717. out2 = xalloc(len);
  718. result = sasl_encode64(out, outlen, out2, len,
  719. (u_int *)&out2len);
  720. if (result != SASL_OK)
  721. {
  722. /* correct code? XXX */
  723. /* 454 Temporary authentication failure */
  724. message("454 4.5.4 Internal error: unable to encode64");
  725. if (LogLevel > 5)
  726. sm_syslog(LOG_WARNING, e->e_id,
  727.   "SASL encode64 error [%d for "%s"]",
  728.   result, out);
  729. /* start over? */
  730. authenticating = SASL_NOT_AUTH;
  731. }
  732. else
  733. {
  734. message("334 %s", out2);
  735. authenticating = SASL_PROC_AUTH;
  736. }
  737. break;
  738. # endif /* SASL */
  739.   case CMDHELO: /* hello -- introduce yourself */
  740.   case CMDEHLO: /* extended hello */
  741. if (c->cmd_code == CMDEHLO)
  742. {
  743. protocol = "ESMTP";
  744. SmtpPhase = "server EHLO";
  745. }
  746. else
  747. {
  748. protocol = "SMTP";
  749. SmtpPhase = "server HELO";
  750. }
  751. /* avoid denial-of-service */
  752. (void) checksmtpattack(&n_helo, MAXHELOCOMMANDS, TRUE,
  753.        "HELO/EHLO", e);
  754. /* check for duplicate HELO/EHLO per RFC 1651 4.2 */
  755. if (gothello)
  756. {
  757. usrerr("503 %s Duplicate HELO/EHLO",
  758. MyHostName);
  759. break;
  760. }
  761. /* check for valid domain name (re 1123 5.2.5) */
  762. if (*p == '' && !AllowBogusHELO)
  763. {
  764. usrerr("501 %s requires domain address",
  765. cmdbuf);
  766. break;
  767. }
  768. /* check for long domain name (hides Received: info) */
  769. if (strlen(p) > MAXNAME)
  770. {
  771. usrerr("501 Invalid domain name");
  772. if (LogLevel > 9)
  773. sm_syslog(LOG_INFO, CurEnv->e_id,
  774.   "invalid domain name (too long) from %.100s",
  775.   CurSmtpClient);
  776. break;
  777. }
  778. for (q = p; *q != ''; q++)
  779. {
  780. if (!isascii(*q))
  781. break;
  782. if (isalnum(*q))
  783. continue;
  784. if (isspace(*q))
  785. {
  786. *q = '';
  787. break;
  788. }
  789. if (strchr("[].-_#", *q) == NULL)
  790. break;
  791. }
  792. if (*q == '')
  793. {
  794. q = "pleased to meet you";
  795. sendinghost = newstr(p);
  796. }
  797. else if (!AllowBogusHELO)
  798. {
  799. usrerr("501 Invalid domain name");
  800. if (LogLevel > 9)
  801. sm_syslog(LOG_INFO, CurEnv->e_id,
  802.   "invalid domain name (%.100s) from %.100s",
  803.   p, CurSmtpClient);
  804. break;
  805. }
  806. else
  807. {
  808. q = "accepting invalid domain name";
  809. }
  810. gothello = TRUE;
  811. /* print HELO response message */
  812. if (c->cmd_code != CMDEHLO)
  813. {
  814. message("250 %s Hello %s, %s",
  815. MyHostName, CurSmtpClient, q);
  816. break;
  817. }
  818. message("250-%s Hello %s, %s",
  819. MyHostName, CurSmtpClient, q);
  820. /* offer ENHSC even for nullserver */
  821. if (nullserver != NULL)
  822. {
  823. message("250 ENHANCEDSTATUSCODES");
  824. break;
  825. }
  826. /* print EHLO features list */
  827. message("250-ENHANCEDSTATUSCODES");
  828. if (!bitset(PRIV_NOEXPN, PrivacyFlags))
  829. {
  830. message("250-EXPN");
  831. if (!bitset(PRIV_NOVERB, PrivacyFlags))
  832. message("250-VERB");
  833. }
  834. # if MIME8TO7
  835. message("250-8BITMIME");
  836. # endif /* MIME8TO7 */
  837. if (MaxMessageSize > 0)
  838. message("250-SIZE %ld", MaxMessageSize);
  839. else
  840. message("250-SIZE");
  841. # if DSN
  842. if (SendMIMEErrors &&
  843.     !bitset(PRIV_NORECEIPTS, PrivacyFlags))
  844. message("250-DSN");
  845. # endif /* DSN */
  846. message("250-ONEX");
  847. if (!bitset(PRIV_NOETRN, PrivacyFlags) &&
  848.     !bitnset(D_NOETRN, d_flags))
  849. message("250-ETRN");
  850. message("250-XUSR");
  851. # if SASL
  852. if (sasl_ok && mechlist != NULL && *mechlist != '')
  853. message("250-AUTH %s", mechlist);
  854. # endif /* SASL */
  855. message("250 HELP");
  856. break;
  857.   case CMDMAIL: /* mail -- designate sender */
  858. SmtpPhase = "server MAIL";
  859. /* check for validity of this command */
  860. if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
  861. {
  862. usrerr("503 5.0.0 Polite people say HELO first");
  863. break;
  864. }
  865. if (gotmail)
  866. {
  867. usrerr("503 5.5.0 Sender already specified");
  868. break;
  869. }
  870. if (InChild)
  871. {
  872. errno = 0;
  873. syserr("503 5.5.0 Nested MAIL command: MAIL %s", p);
  874. finis(TRUE, ExitStat);
  875. }
  876. # if SASL
  877. if (bitnset(D_AUTHREQ, d_flags) &&
  878.     authenticating != SASL_IS_AUTH)
  879. {
  880. usrerr("530 5.7.0 Authentication required");
  881. break;
  882. }
  883. # endif /* SASL */
  884. if (tempfail)
  885. {
  886. if (LogLevel > 9)
  887. sm_syslog(LOG_INFO, e->e_id,
  888.   "MAIL From:<%.100s> from %.100s tempfailed (from previous HELO/EHLO check)",
  889.   args[0], CurSmtpClient);
  890. usrerr("451 4.7.1 Please try again later");
  891. break;
  892. }
  893. /* make sure we know who the sending host is */
  894. if (sendinghost == NULL)
  895. sendinghost = peerhostname;
  896. p = skipword(p, "from");
  897. if (p == NULL)
  898. break;
  899. /* fork a subprocess to process this command */
  900. if (runinchild("SMTP-MAIL", e) > 0)
  901. break;
  902. if (Errors > 0)
  903. goto undo_subproc_no_pm;
  904. if (!gothello)
  905. {
  906. auth_warning(e,
  907. "%s didn't use HELO protocol",
  908. CurSmtpClient);
  909. }
  910. # ifdef PICKY_HELO_CHECK
  911. if (strcasecmp(sendinghost, peerhostname) != 0 &&
  912.     (strcasecmp(peerhostname, "localhost") != 0 ||
  913.      strcasecmp(sendinghost, MyHostName) != 0))
  914. {
  915. auth_warning(e, "Host %s claimed to be %s",
  916. CurSmtpClient, sendinghost);
  917. }
  918. # endif /* PICKY_HELO_CHECK */
  919. if (protocol == NULL)
  920. protocol = "SMTP";
  921. define('r', protocol, e);
  922. define('s', sendinghost, e);
  923. if (Errors > 0)
  924. goto undo_subproc_no_pm;
  925. nrcpts = 0;
  926. define(macid("{ntries}", NULL), "0", e);
  927. e->e_flags |= EF_LOGSENDER|EF_CLRQUEUE;
  928. sm_setproctitle(TRUE, e, "%s %s: %.80s",
  929. qid_printname(e),
  930. CurSmtpClient, inp);
  931. /* child -- go do the processing */
  932. if (setjmp(TopFrame) > 0)
  933. {
  934. /* this failed -- undo work */
  935.  undo_subproc_no_pm:
  936. e->e_flags &= ~EF_PM_NOTIFY;
  937.  undo_subproc:
  938. if (InChild)
  939. {
  940. QuickAbort = FALSE;
  941. SuprErrs = TRUE;
  942. e->e_flags &= ~EF_FATALERRS;
  943. if (LogLevel > 4 &&
  944.     bitset(EF_LOGSENDER, e->e_flags))
  945. logsender(e, NULL);
  946. e->e_flags &= ~EF_LOGSENDER;
  947. finis(TRUE, ExitStat);
  948. }
  949. break;
  950. }
  951. QuickAbort = TRUE;
  952. /* must parse sender first */
  953. delimptr = NULL;
  954. setsender(p, e, &delimptr, ' ', FALSE);
  955. if (delimptr != NULL && *delimptr != '')
  956. *delimptr++ = '';
  957. if (Errors > 0)
  958. goto undo_subproc_no_pm;
  959. /* put resulting triple from parseaddr() into macros */
  960. if (e->e_from.q_mailer != NULL)
  961.  define(macid("{mail_mailer}", NULL),
  962. e->e_from.q_mailer->m_name, e);
  963. else
  964.  define(macid("{mail_mailer}", NULL),
  965. NULL, e);
  966. if (e->e_from.q_host != NULL)
  967. define(macid("{mail_host}", NULL),
  968.        e->e_from.q_host, e);
  969. else
  970. define(macid("{mail_host}", NULL),
  971.        "localhost", e);
  972. if (e->e_from.q_user != NULL)
  973. define(macid("{mail_addr}", NULL),
  974.        e->e_from.q_user, e);
  975. else
  976. define(macid("{mail_addr}", NULL),
  977.        NULL, e);
  978. if (Errors > 0)
  979.   goto undo_subproc_no_pm;
  980. /* check for possible spoofing */
  981. if (RealUid != 0 && OpMode == MD_SMTP &&
  982.     !wordinclass(RealUserName, 't') &&
  983.     (!bitnset(M_LOCALMAILER,
  984.       e->e_from.q_mailer->m_flags) ||
  985.      strcmp(e->e_from.q_user, RealUserName) != 0))
  986. {
  987. auth_warning(e, "%s owned process doing -bs",
  988. RealUserName);
  989. }
  990. /* now parse ESMTP arguments */
  991. e->e_msgsize = 0;
  992. addr = p;
  993. argno = 0;
  994. args[argno++] = p;
  995. p = delimptr;
  996. while (p != NULL && *p != '')
  997. {
  998. char *kp;
  999. char *vp = NULL;
  1000. char *equal = NULL;
  1001. /* locate the beginning of the keyword */
  1002. while (isascii(*p) && isspace(*p))
  1003. p++;
  1004. if (*p == '')
  1005. break;
  1006. kp = p;
  1007. /* skip to the value portion */
  1008. while ((isascii(*p) && isalnum(*p)) || *p == '-')
  1009. p++;
  1010. if (*p == '=')
  1011. {
  1012. equal = p;
  1013. *p++ = '';
  1014. vp = p;
  1015. /* skip to the end of the value */
  1016. while (*p != '' && *p != ' ' &&
  1017.        !(isascii(*p) && iscntrl(*p)) &&
  1018.        *p != '=')
  1019. p++;
  1020. }
  1021. if (*p != '')
  1022. *p++ = '';
  1023. if (tTd(19, 1))
  1024. dprintf("MAIL: got arg %s="%s"n", kp,
  1025. vp == NULL ? "<null>" : vp);
  1026. mail_esmtp_args(kp, vp, e);
  1027. if (equal != NULL)
  1028. *equal = '=';
  1029. args[argno++] = kp;
  1030. if (argno >= MAXSMTPARGS - 1)
  1031. usrerr("501 5.5.4 Too many parameters");
  1032. if (Errors > 0)
  1033. goto undo_subproc_no_pm;
  1034. }
  1035. args[argno] = NULL;
  1036. if (Errors > 0)
  1037. goto undo_subproc_no_pm;
  1038. /* do config file checking of the sender */
  1039. if (rscheck("check_mail", addr,
  1040.     NULL, e, TRUE, TRUE) != EX_OK ||
  1041.     Errors > 0)
  1042. goto undo_subproc_no_pm;
  1043. if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
  1044. {
  1045. usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
  1046. MaxMessageSize);
  1047. goto undo_subproc_no_pm;
  1048. }
  1049. if (!enoughdiskspace(e->e_msgsize, TRUE))
  1050. {
  1051. usrerr("452 4.4.5 Insufficient disk space; try again later");
  1052. goto undo_subproc_no_pm;
  1053. }
  1054. if (Errors > 0)
  1055. goto undo_subproc_no_pm;
  1056. if (Errors > 0)
  1057. goto undo_subproc_no_pm;
  1058. message("250 2.1.0 Sender ok");
  1059. gotmail = TRUE;
  1060. break;
  1061.   case CMDRCPT: /* rcpt -- designate recipient */
  1062. if (!gotmail)
  1063. {
  1064. usrerr("503 5.0.0 Need MAIL before RCPT");
  1065. break;
  1066. }
  1067. SmtpPhase = "server RCPT";
  1068. if (setjmp(TopFrame) > 0)
  1069. {
  1070. e->e_flags &= ~EF_FATALERRS;
  1071. break;
  1072. }
  1073. QuickAbort = TRUE;
  1074. LogUsrErrs = TRUE;
  1075. /* limit flooding of our machine */
  1076. if (MaxRcptPerMsg > 0 && nrcpts >= MaxRcptPerMsg)
  1077. {
  1078. usrerr("452 4.5.3 Too many recipients");
  1079. break;
  1080. }
  1081. if (e->e_sendmode != SM_DELIVER)
  1082. e->e_flags |= EF_VRFYONLY;
  1083. p = skipword(p, "to");
  1084. if (p == NULL)
  1085. break;
  1086. # if _FFR_ADDR_TYPE
  1087. define(macid("{addr_type}", NULL), "e r", e);
  1088. # endif /* _FFR_ADDR_TYPE */
  1089. a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e);
  1090. #if _FFR_ADDR_TYPE
  1091. define(macid("{addr_type}", NULL), NULL, e);
  1092. #endif /* _FFR_ADDR_TYPE */
  1093. if (Errors > 0)
  1094. break;
  1095. if (a == NULL)
  1096. {
  1097. usrerr("501 5.0.0 Missing recipient");
  1098. break;
  1099. }
  1100. if (delimptr != NULL && *delimptr != '')
  1101. *delimptr++ = '';
  1102. /* put resulting triple from parseaddr() into macros */
  1103. if (a->q_mailer != NULL)
  1104. define(macid("{rcpt_mailer}", NULL),
  1105.        a->q_mailer->m_name, e);
  1106. else
  1107. define(macid("{rcpt_mailer}", NULL),
  1108.        NULL, e);
  1109. if (a->q_host != NULL)
  1110. define(macid("{rcpt_host}", NULL),
  1111.        a->q_host, e);
  1112. else
  1113. define(macid("{rcpt_host}", NULL),
  1114.        "localhost", e);
  1115. if (a->q_user != NULL)
  1116. define(macid("{rcpt_addr}", NULL),
  1117.        a->q_user, e);
  1118. else
  1119. define(macid("{rcpt_addr}", NULL),
  1120.        NULL, e);
  1121. if (Errors > 0)
  1122. break;
  1123. /* now parse ESMTP arguments */
  1124. addr = p;
  1125. argno = 0;
  1126. args[argno++] = p;
  1127. p = delimptr;
  1128. while (p != NULL && *p != '')
  1129. {
  1130. char *kp;
  1131. char *vp = NULL;
  1132. char *equal = NULL;
  1133. /* locate the beginning of the keyword */
  1134. while (isascii(*p) && isspace(*p))
  1135. p++;
  1136. if (*p == '')
  1137. break;
  1138. kp = p;
  1139. /* skip to the value portion */
  1140. while ((isascii(*p) && isalnum(*p)) || *p == '-')
  1141. p++;
  1142. if (*p == '=')
  1143. {
  1144. equal = p;
  1145. *p++ = '';
  1146. vp = p;
  1147. /* skip to the end of the value */
  1148. while (*p != '' && *p != ' ' &&
  1149.        !(isascii(*p) && iscntrl(*p)) &&
  1150.        *p != '=')
  1151. p++;
  1152. }
  1153. if (*p != '')
  1154. *p++ = '';
  1155. if (tTd(19, 1))
  1156. dprintf("RCPT: got arg %s="%s"n", kp,
  1157. vp == NULL ? "<null>" : vp);
  1158. rcpt_esmtp_args(a, kp, vp, e);
  1159. if (equal != NULL)
  1160. *equal = '=';
  1161. args[argno++] = kp;
  1162. if (argno >= MAXSMTPARGS - 1)
  1163. usrerr("501 5.5.4 Too many parameters");
  1164. if (Errors > 0)
  1165. break;
  1166. }
  1167. args[argno] = NULL;
  1168. if (Errors > 0)
  1169. break;
  1170. /* do config file checking of the recipient */
  1171. if (rscheck("check_rcpt", addr,
  1172.     NULL, e, TRUE, TRUE) != EX_OK ||
  1173.     Errors > 0)
  1174. break;
  1175. define(macid("{rcpt_mailer}", NULL), NULL, e);
  1176. define(macid("{rcpt_relay}", NULL), NULL, e);
  1177. define(macid("{rcpt_addr}", NULL), NULL, e);
  1178. define(macid("{dsn_notify}", NULL), NULL, e);
  1179. if (Errors > 0)
  1180. break;
  1181. /* save in recipient list after ESMTP mods */
  1182. a = recipient(a, &e->e_sendqueue, 0, e);
  1183. if (Errors > 0)
  1184. break;
  1185. /* no errors during parsing, but might be a duplicate */
  1186. e->e_to = a->q_paddr;
  1187. if (!QS_IS_BADADDR(a->q_state))
  1188. {
  1189. if (e->e_queuedir == NOQDIR)
  1190. initsys(e);
  1191. message("250 2.1.5 Recipient ok%s",
  1192. QS_IS_QUEUEUP(a->q_state) ?
  1193. " (will queue)" : "");
  1194. nrcpts++;
  1195. }
  1196. else
  1197. {
  1198. /* punt -- should keep message in ADDRESS.... */
  1199. usrerr("550 5.1.1 Addressee unknown");
  1200. }
  1201. break;
  1202.   case CMDDATA: /* data -- text of mail */
  1203. SmtpPhase = "server DATA";
  1204. if (!gotmail)
  1205. {
  1206. usrerr("503 5.0.0 Need MAIL command");
  1207. break;
  1208. }
  1209. else if (nrcpts <= 0)
  1210. {
  1211. usrerr("503 5.0.0 Need RCPT (recipient)");
  1212. break;
  1213. }
  1214. /* put back discard bit */
  1215. if (discard)
  1216. e->e_flags |= EF_DISCARD;
  1217. /* check to see if we need to re-expand aliases */
  1218. /* also reset QS_BADADDR on already-diagnosted addrs */
  1219. doublequeue = FALSE;
  1220. for (a = e->e_sendqueue; a != NULL; a = a->q_next)
  1221. {
  1222. if (QS_IS_VERIFIED(a->q_state) &&
  1223.     !bitset(EF_DISCARD, e->e_flags))
  1224. {
  1225. /* need to re-expand aliases */
  1226. doublequeue = TRUE;
  1227. }
  1228. if (QS_IS_BADADDR(a->q_state))
  1229. {
  1230. /* make this "go away" */
  1231. a->q_state = QS_DONTSEND;
  1232. }
  1233. }
  1234. /* collect the text of the message */
  1235. SmtpPhase = "collect";
  1236. buffer_errors();
  1237. collect(InChannel, TRUE, NULL, e);
  1238. /* redefine message size */
  1239. if ((q = macvalue(macid("{msg_size}", NULL), e))
  1240.     != NULL)
  1241. free(q);
  1242. snprintf(inp, sizeof inp, "%ld", e->e_msgsize);
  1243. define(macid("{msg_size}", NULL), newstr(inp), e);
  1244. if (Errors > 0)
  1245. {
  1246. /* Log who the mail would have gone to */
  1247. if (LogLevel > 8 &&
  1248.     e->e_message != NULL)
  1249. {
  1250. for (a = e->e_sendqueue;
  1251.      a != NULL;
  1252.      a = a->q_next)
  1253. {
  1254. if (!QS_IS_UNDELIVERED(a->q_state))
  1255. continue;
  1256. e->e_to = a->q_paddr;
  1257. logdelivery(NULL, NULL,
  1258.     e->e_message,
  1259.     NULL,
  1260.     (time_t) 0, e);
  1261. }
  1262. e->e_to = NULL;
  1263. }
  1264. flush_errors(TRUE);
  1265. buffer_errors();
  1266. goto abortmessage;
  1267. }
  1268. /* make sure we actually do delivery */
  1269. e->e_flags &= ~EF_CLRQUEUE;
  1270. /* from now on, we have to operate silently */
  1271. buffer_errors();
  1272. e->e_errormode = EM_MAIL;
  1273. /*
  1274. **  Arrange to send to everyone.
  1275. ** If sending to multiple people, mail back
  1276. ** errors rather than reporting directly.
  1277. ** In any case, don't mail back errors for
  1278. ** anything that has happened up to
  1279. ** now (the other end will do this).
  1280. ** Truncate our transcript -- the mail has gotten
  1281. ** to us successfully, and if we have
  1282. ** to mail this back, it will be easier
  1283. ** on the reader.
  1284. ** Then send to everyone.
  1285. ** Finally give a reply code.  If an error has
  1286. ** already been given, don't mail a
  1287. ** message back.
  1288. ** We goose error returns by clearing error bit.
  1289. */
  1290. SmtpPhase = "delivery";
  1291. (void) bftruncate(e->e_xfp);
  1292. id = e->e_id;
  1293. if (doublequeue)
  1294. {
  1295. /* make sure it is in the queue */
  1296. queueup(e, FALSE);
  1297. }
  1298. else
  1299. {
  1300. /* send to all recipients */
  1301. # if NAMED_BIND
  1302. _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
  1303. _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
  1304. # endif /* NAMED_BIND */
  1305. sendall(e, SM_DEFAULT);
  1306. }
  1307. e->e_to = NULL;
  1308. /* issue success message */
  1309. message("250 2.0.0 %s Message accepted for delivery", id);
  1310. /* if we just queued, poke it */
  1311. if (doublequeue &&
  1312.     e->e_sendmode != SM_QUEUE &&
  1313.     e->e_sendmode != SM_DEFER)
  1314. {
  1315. CurrentLA = sm_getla(e);
  1316. if (!shouldqueue(e->e_msgpriority, e->e_ctime))
  1317. {
  1318. unlockqueue(e);
  1319. (void) dowork(e->e_queuedir, id,
  1320.       TRUE, TRUE, e);
  1321. }
  1322. }
  1323.   abortmessage:
  1324. if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
  1325. logsender(e, NULL);
  1326. e->e_flags &= ~EF_LOGSENDER;
  1327. /* if in a child, pop back to our parent */
  1328. if (InChild)
  1329. finis(TRUE, ExitStat);
  1330. /* clean up a bit */
  1331. gotmail = FALSE;
  1332. dropenvelope(e, TRUE);
  1333. CurEnv = e = newenvelope(e, CurEnv);
  1334. e->e_flags = BlankEnvelope.e_flags;
  1335. break;
  1336.   case CMDRSET: /* rset -- reset state */
  1337. if (tTd(94, 100))
  1338. message("451 4.0.0 Test failure");
  1339. else
  1340. message("250 2.0.0 Reset state");
  1341. /* arrange to ignore any current send list */
  1342. e->e_sendqueue = NULL;
  1343. e->e_flags |= EF_CLRQUEUE;
  1344. if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
  1345. logsender(e, NULL);
  1346. e->e_flags &= ~EF_LOGSENDER;
  1347. if (InChild)
  1348. finis(TRUE, ExitStat);
  1349. /* clean up a bit */
  1350. gotmail = FALSE;
  1351. SuprErrs = TRUE;
  1352. dropenvelope(e, TRUE);
  1353. CurEnv = e = newenvelope(e, CurEnv);
  1354. break;
  1355.   case CMDVRFY: /* vrfy -- verify address */
  1356.   case CMDEXPN: /* expn -- expand address */
  1357. wt = checksmtpattack(&nverifies, MAXVRFYCOMMANDS, FALSE,
  1358. c->cmd_code == CMDVRFY ? "VRFY" : "EXPN", e);
  1359. previous = curtime();
  1360. vrfy = c->cmd_code == CMDVRFY;
  1361. if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
  1362. PrivacyFlags))
  1363. {
  1364. if (vrfy)
  1365. message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
  1366. else
  1367. message("502 5.7.0 Sorry, we do not allow this operation");
  1368. if (LogLevel > 5)
  1369. sm_syslog(LOG_INFO, e->e_id,
  1370.   "%.100s: %s [rejected]",
  1371.   CurSmtpClient,
  1372.   shortenstring(inp, MAXSHORTSTR));
  1373. break;
  1374. }
  1375. else if (!gothello &&
  1376.  bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
  1377. PrivacyFlags))
  1378. {
  1379. usrerr("503 5.0.0 I demand that you introduce yourself first");
  1380. break;
  1381. }
  1382. if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0)
  1383. break;
  1384. if (Errors > 0)
  1385. goto undo_subproc;
  1386. if (LogLevel > 5)
  1387. sm_syslog(LOG_INFO, e->e_id,
  1388.   "%.100s: %s",
  1389.   CurSmtpClient,
  1390.   shortenstring(inp, MAXSHORTSTR));
  1391. if (setjmp(TopFrame) > 0)
  1392. goto undo_subproc;
  1393. QuickAbort = TRUE;
  1394. vrfyqueue = NULL;
  1395. if (vrfy)
  1396. e->e_flags |= EF_VRFYONLY;
  1397. while (*p != '' && isascii(*p) && isspace(*p))
  1398. p++;
  1399. if (*p == '')
  1400. {
  1401. usrerr("501 5.5.2 Argument required");
  1402. }
  1403. else
  1404. {
  1405. /* do config file checking of the address */
  1406. if (rscheck(vrfy ? "check_vrfy" : "check_expn",
  1407.     p, NULL, e, TRUE, FALSE) != EX_OK ||
  1408.     Errors > 0)
  1409. goto undo_subproc;
  1410. (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
  1411. }
  1412. if (wt > 0)
  1413. (void) sleep(wt - (curtime() - previous));
  1414. if (Errors > 0)
  1415. goto undo_subproc;
  1416. if (vrfyqueue == NULL)
  1417. {
  1418. usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
  1419. }
  1420. while (vrfyqueue != NULL)
  1421. {
  1422. if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
  1423. {
  1424. vrfyqueue = vrfyqueue->q_next;
  1425. continue;
  1426. }
  1427. /* see if there is more in the vrfy list */
  1428. a = vrfyqueue;
  1429. while ((a = a->q_next) != NULL &&
  1430.        (!QS_IS_UNDELIVERED(vrfyqueue->q_state)))
  1431. continue;
  1432. printvrfyaddr(vrfyqueue, a == NULL, vrfy);
  1433. vrfyqueue = a;
  1434. }
  1435. if (InChild)
  1436. finis(TRUE, ExitStat);
  1437. break;
  1438.   case CMDETRN: /* etrn -- force queue flush */
  1439. if (bitset(PRIV_NOETRN, PrivacyFlags) ||
  1440.     bitnset(D_NOETRN, d_flags))
  1441. {
  1442. /* different message for MSA ? */
  1443. message("502 5.7.0 Sorry, we do not allow this operation");
  1444. if (LogLevel > 5)
  1445. sm_syslog(LOG_INFO, e->e_id,
  1446.   "%.100s: %s [rejected]",
  1447.   CurSmtpClient,
  1448.   shortenstring(inp, MAXSHORTSTR));
  1449. break;
  1450. }
  1451. if (strlen(p) <= 0)
  1452. {
  1453. usrerr("500 5.5.2 Parameter required");
  1454. break;
  1455. }
  1456. /* crude way to avoid denial-of-service attacks */
  1457. (void) checksmtpattack(&n_etrn, MAXETRNCOMMANDS, TRUE,
  1458.      "ETRN", e);
  1459. /* do config file checking of the parameter */
  1460. if (rscheck("check_etrn", p, NULL, e, TRUE, FALSE)
  1461.     != EX_OK || Errors > 0)
  1462. break;
  1463. if (LogLevel > 5)
  1464. sm_syslog(LOG_INFO, e->e_id,
  1465.   "%.100s: ETRN %s",
  1466.   CurSmtpClient,
  1467.   shortenstring(p, MAXSHORTSTR));
  1468. id = p;
  1469. if (*id == '@')
  1470. id++;
  1471. else
  1472. *--id = '@';
  1473. if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL)
  1474. {
  1475. syserr("500 5.5.0 ETRN out of memory");
  1476. break;
  1477. }
  1478. new->queue_match = id;
  1479. new->queue_next = NULL;
  1480. QueueLimitRecipient = new;
  1481. ok = runqueue(TRUE, TRUE);
  1482. free(QueueLimitRecipient);
  1483. QueueLimitRecipient = NULL;
  1484. if (ok && Errors == 0)
  1485. message("250 2.0.0 Queuing for node %s started", p);
  1486. break;
  1487.   case CMDHELP: /* help -- give user info */
  1488. help(p, e);
  1489. break;
  1490.   case CMDNOOP: /* noop -- do nothing */
  1491. (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
  1492.        "NOOP", e);
  1493. message("250 2.0.0 OK");
  1494. break;
  1495.   case CMDQUIT: /* quit -- leave mail */
  1496. message("221 2.0.0 %s closing connection", MyHostName);
  1497. /* arrange to ignore any current send list */
  1498. e->e_sendqueue = NULL;
  1499. doquit:
  1500. /* avoid future 050 messages */
  1501. disconnect(1, e);
  1502. if (InChild)
  1503. ExitStat = EX_QUIT;
  1504. if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
  1505. logsender(e, NULL);
  1506. e->e_flags &= ~EF_LOGSENDER;
  1507. if (lognullconnection && LogLevel > 5)
  1508. {
  1509. char *d;
  1510. d = macvalue(macid("{daemon_name}", NULL), e);
  1511. if (d == NULL)
  1512. d = "stdin";
  1513. sm_syslog(LOG_INFO, NULL,
  1514.  "Null connection from %.100s to %s",
  1515.   CurSmtpClient, d);
  1516. }
  1517. finis(TRUE, ExitStat);
  1518. /* NOTREACHED */
  1519.   case CMDVERB: /* set verbose mode */
  1520. if (bitset(PRIV_NOEXPN, PrivacyFlags) ||
  1521.     bitset(PRIV_NOVERB, PrivacyFlags))
  1522. {
  1523. /* this would give out the same info */
  1524. message("502 5.7.0 Verbose unavailable");
  1525. break;
  1526. }
  1527. (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
  1528.        "VERB", e);
  1529. Verbose = 1;
  1530. set_delivery_mode(SM_DELIVER, e);
  1531. message("250 2.0.0 Verbose mode");
  1532. break;
  1533.   case CMDONEX: /* doing one transaction only */
  1534. (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
  1535.        "ONEX", e);
  1536. OneXact = TRUE;
  1537. message("250 2.0.0 Only one transaction");
  1538. break;
  1539.   case CMDXUSR: /* initial (user) submission */
  1540. (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE,
  1541.        "XUSR", e);
  1542. define(macid("{daemon_flags}", NULL), "cu", CurEnv);
  1543. message("250 2.0.0 Initial submission");
  1544. break;
  1545. # if SMTPDEBUG
  1546.   case CMDDBGQSHOW: /* show queues */
  1547. printf("Send Queue=");
  1548. printaddr(e->e_sendqueue, TRUE);
  1549. break;
  1550.   case CMDDBGDEBUG: /* set debug mode */
  1551. tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
  1552. tTflag(p);
  1553. message("200 Debug set");
  1554. break;
  1555. # else /* SMTPDEBUG */
  1556.   case CMDDBGQSHOW: /* show queues */
  1557.   case CMDDBGDEBUG: /* set debug mode */
  1558. # endif /* SMTPDEBUG */
  1559.   case CMDLOGBOGUS: /* bogus command */
  1560. if (LogLevel > 0)
  1561. sm_syslog(LOG_CRIT, e->e_id,
  1562.   ""%s" command from %.100s (%.100s)",
  1563.   c->cmd_name, CurSmtpClient,
  1564.   anynet_ntoa(&RealHostAddr));
  1565. /* FALLTHROUGH */
  1566.   case CMDERROR: /* unknown command */
  1567. if (++badcommands > MAXBADCOMMANDS)
  1568. {
  1569. message("421 4.7.0 %s Too many bad commands; closing connection",
  1570. MyHostName);
  1571. /* arrange to ignore any current send list */
  1572. e->e_sendqueue = NULL;
  1573. goto doquit;
  1574. }
  1575. usrerr("500 5.5.1 Command unrecognized: "%s"",
  1576.        shortenstring(inp, MAXSHORTSTR));
  1577. break;
  1578.   case CMDUNIMPL:
  1579. usrerr("502 5.5.1 Command not implemented: "%s"",
  1580.        shortenstring(inp, MAXSHORTSTR));
  1581. break;
  1582.   default:
  1583. errno = 0;
  1584. syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
  1585. break;
  1586. }
  1587. # if SASL
  1588. }
  1589. # endif /* SASL */
  1590. }
  1591. }
  1592. /*
  1593. **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
  1594. **
  1595. ** Parameters:
  1596. ** pcounter -- pointer to a counter for this command.
  1597. ** maxcount -- maximum value for this counter before we
  1598. ** slow down.
  1599. ** waitnow -- sleep now (in this routine)?
  1600. ** cname -- command name for logging.
  1601. ** e -- the current envelope.
  1602. **
  1603. ** Returns:
  1604. ** none.
  1605. **
  1606. ** Side Effects:
  1607. ** Slows down if we seem to be under attack.
  1608. */
  1609. static time_t
  1610. checksmtpattack(pcounter, maxcount, waitnow, cname, e)
  1611. volatile int *pcounter;
  1612. int maxcount;
  1613. bool waitnow;
  1614. char *cname;
  1615. ENVELOPE *e;
  1616. {
  1617. if (++(*pcounter) >= maxcount)
  1618. {
  1619. time_t s;
  1620. if (*pcounter == maxcount && LogLevel > 5)
  1621. {
  1622. sm_syslog(LOG_INFO, e->e_id,
  1623.   "%.100s: %.40s attack?",
  1624.   CurSmtpClient, cname);
  1625. }
  1626. s = 1 << (*pcounter - maxcount);
  1627. if (s >= MAXTIMEOUT)
  1628. s = MAXTIMEOUT;
  1629. /* sleep at least 1 second before returning */
  1630. (void) sleep(*pcounter / maxcount);
  1631. s -= *pcounter / maxcount;
  1632. if (waitnow)
  1633. {
  1634. (void) sleep(s);
  1635. return(0);
  1636. }
  1637. return(s);
  1638. }
  1639. return((time_t) 0);
  1640. }
  1641. /*
  1642. **  SKIPWORD -- skip a fixed word.
  1643. **
  1644. ** Parameters:
  1645. ** p -- place to start looking.
  1646. ** w -- word to skip.
  1647. **
  1648. ** Returns:
  1649. ** p following w.
  1650. ** NULL on error.
  1651. **
  1652. ** Side Effects:
  1653. ** clobbers the p data area.
  1654. */
  1655. static char *
  1656. skipword(p, w)
  1657. register char *volatile p;
  1658. char *w;
  1659. {
  1660. register char *q;
  1661. char *firstp = p;
  1662. /* find beginning of word */
  1663. while (isascii(*p) && isspace(*p))
  1664. p++;
  1665. q = p;
  1666. /* find end of word */
  1667. while (*p != '' && *p != ':' && !(isascii(*p) && isspace(*p)))
  1668. p++;
  1669. while (isascii(*p) && isspace(*p))
  1670. *p++ = '';
  1671. if (*p != ':')
  1672. {
  1673.   syntax:
  1674. usrerr("501 5.5.2 Syntax error in parameters scanning "%s"",
  1675. shortenstring(firstp, MAXSHORTSTR));
  1676. return NULL;
  1677. }
  1678. *p++ = '';
  1679. while (isascii(*p) && isspace(*p))
  1680. p++;
  1681. if (*p == '')
  1682. goto syntax;
  1683. /* see if the input word matches desired word */
  1684. if (strcasecmp(q, w))
  1685. goto syntax;
  1686. return p;
  1687. }
  1688. /*
  1689. **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
  1690. **
  1691. ** Parameters:
  1692. ** kp -- the parameter key.
  1693. ** vp -- the value of that parameter.
  1694. ** e -- the envelope.
  1695. **
  1696. ** Returns:
  1697. ** none.
  1698. */
  1699. static void
  1700. mail_esmtp_args(kp, vp, e)
  1701. char *kp;
  1702. char *vp;
  1703. ENVELOPE *e;
  1704. {
  1705. if (strcasecmp(kp, "size") == 0)
  1706. {
  1707. if (vp == NULL)
  1708. {
  1709. usrerr("501 5.5.2 SIZE requires a value");
  1710. /* NOTREACHED */
  1711. }
  1712. define(macid("{msg_size}", NULL), newstr(vp), e);
  1713. # if defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY)
  1714. e->e_msgsize = strtoul(vp, (char **) NULL, 10);
  1715. # else /* defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) */
  1716. e->e_msgsize = strtol(vp, (char **) NULL, 10);
  1717. # endif /* defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) */
  1718. }
  1719. else if (strcasecmp(kp, "body") == 0)
  1720. {
  1721. if (vp == NULL)
  1722. {
  1723. usrerr("501 5.5.2 BODY requires a value");
  1724. /* NOTREACHED */
  1725. }
  1726. else if (strcasecmp(vp, "8bitmime") == 0)
  1727. {
  1728. SevenBitInput = FALSE;
  1729. }
  1730. else if (strcasecmp(vp, "7bit") == 0)
  1731. {
  1732. SevenBitInput = TRUE;
  1733. }
  1734. else
  1735. {
  1736. usrerr("501 5.5.4 Unknown BODY type %s",
  1737. vp);
  1738. /* NOTREACHED */
  1739. }
  1740. e->e_bodytype = newstr(vp);
  1741. }
  1742. else if (strcasecmp(kp, "envid") == 0)
  1743. {
  1744. if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
  1745. {
  1746. usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
  1747. /* NOTREACHED */
  1748. }
  1749. if (vp == NULL)
  1750. {
  1751. usrerr("501 5.5.2 ENVID requires a value");
  1752. /* NOTREACHED */
  1753. }
  1754. if (!xtextok(vp))
  1755. {
  1756. usrerr("501 5.5.4 Syntax error in ENVID parameter value");
  1757. /* NOTREACHED */
  1758. }
  1759. if (e->e_envid != NULL)
  1760. {
  1761. usrerr("501 5.5.0 Duplicate ENVID parameter");
  1762. /* NOTREACHED */
  1763. }
  1764. e->e_envid = newstr(vp);
  1765. define(macid("{dsn_envid}", NULL), newstr(vp), e);
  1766. }
  1767. else if (strcasecmp(kp, "ret") == 0)
  1768. {
  1769. if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
  1770. {
  1771. usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
  1772. /* NOTREACHED */
  1773. }
  1774. if (vp == NULL)
  1775. {
  1776. usrerr("501 5.5.2 RET requires a value");
  1777. /* NOTREACHED */
  1778. }
  1779. if (bitset(EF_RET_PARAM, e->e_flags))
  1780. {
  1781. usrerr("501 5.5.0 Duplicate RET parameter");
  1782. /* NOTREACHED */
  1783. }
  1784. e->e_flags |= EF_RET_PARAM;
  1785. if (strcasecmp(vp, "hdrs") == 0)
  1786. e->e_flags |= EF_NO_BODY_RETN;
  1787. else if (strcasecmp(vp, "full") != 0)
  1788. {
  1789. usrerr("501 5.5.2 Bad argument "%s" to RET", vp);
  1790. /* NOTREACHED */
  1791. }
  1792. define(macid("{dsn_ret}", NULL), newstr(vp), e);
  1793. }
  1794. # if SASL
  1795. else if (strcasecmp(kp, "auth") == 0)
  1796. {
  1797. int len;
  1798. char *q;
  1799. char *auth_param; /* the value of the AUTH=x */
  1800. bool saveQuickAbort = QuickAbort;
  1801. bool saveSuprErrs = SuprErrs;
  1802. char pbuf[256];
  1803. if (vp == NULL)
  1804. {
  1805. usrerr("501 5.5.2 AUTH= requires a value");
  1806. /* NOTREACHED */
  1807. }
  1808. if (e->e_auth_param != NULL)
  1809. {
  1810. usrerr("501 5.5.0 Duplicate AUTH parameter");
  1811. /* NOTREACHED */
  1812. }
  1813. if ((q = strchr(vp, ' ')) != NULL)
  1814. len = q - vp + 1;
  1815. else
  1816. len = strlen(vp) + 1;
  1817. auth_param = xalloc(len);
  1818. (void) strlcpy(auth_param, vp, len);
  1819. if (!xtextok(auth_param))
  1820. {
  1821. usrerr("501 5.5.4 Syntax error in AUTH parameter value");
  1822. /* just a warning? */
  1823. /* NOTREACHED */
  1824. }
  1825. /* XXX this might be cut off */
  1826. snprintf(pbuf, sizeof pbuf, "%s", xuntextify(auth_param));
  1827. /* xalloc() the buffer instead? */
  1828. /* XXX define this always or only if trusted? */
  1829. define(macid("{auth_author}", NULL), newstr(pbuf), e);
  1830. /*
  1831. **  call Strust_auth to find out whether
  1832. **  auth_param is acceptable (trusted)
  1833. **  we shouldn't trust it if not authenticated
  1834. **  (required by RFC, leave it to ruleset?)
  1835. */
  1836. SuprErrs = TRUE;
  1837. QuickAbort = FALSE;
  1838. if (strcmp(auth_param, "<>") != 0 &&
  1839.      (rscheck("trust_auth", pbuf, NULL, e, TRUE, FALSE)
  1840.       != EX_OK || Errors > 0))
  1841. {
  1842. if (tTd(95, 8))
  1843. {
  1844. q = e->e_auth_param;
  1845. dprintf("auth="%.100s" not trusted user="%.100s"n",
  1846. pbuf, (q == NULL) ? "" : q);
  1847. }
  1848. /* not trusted */
  1849. e->e_auth_param = newstr("<>");
  1850. }
  1851. else
  1852. {
  1853. if (tTd(95, 8))
  1854. dprintf("auth="%.100s" trustedn", pbuf);
  1855. e->e_auth_param = newstr(auth_param);
  1856. }
  1857. free(auth_param);
  1858. /* reset values */
  1859. Errors = 0;
  1860. QuickAbort = saveQuickAbort;
  1861. SuprErrs = saveSuprErrs;
  1862. }
  1863. # endif /* SASL */
  1864. else
  1865. {
  1866. usrerr("501 5.5.4 %s parameter unrecognized", kp);
  1867. /* NOTREACHED */
  1868. }
  1869. }
  1870. /*
  1871. **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
  1872. **
  1873. ** Parameters:
  1874. ** a -- the address corresponding to the To: parameter.
  1875. ** kp -- the parameter key.
  1876. ** vp -- the value of that parameter.
  1877. ** e -- the envelope.
  1878. **
  1879. ** Returns:
  1880. ** none.
  1881. */
  1882. static void
  1883. rcpt_esmtp_args(a, kp, vp, e)
  1884. ADDRESS *a;
  1885. char *kp;
  1886. char *vp;
  1887. ENVELOPE *e;
  1888. {
  1889. if (strcasecmp(kp, "notify") == 0)
  1890. {
  1891. char *p;
  1892. if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
  1893. {
  1894. usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
  1895. /* NOTREACHED */
  1896. }
  1897. if (vp == NULL)
  1898. {
  1899. usrerr("501 5.5.2 NOTIFY requires a value");
  1900. /* NOTREACHED */
  1901. }
  1902. a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
  1903. a->q_flags |= QHASNOTIFY;
  1904. define(macid("{dsn_notify}", NULL), newstr(vp), e);
  1905. if (strcasecmp(vp, "never") == 0)
  1906. return;
  1907. for (p = vp; p != NULL; vp = p)
  1908. {
  1909. p = strchr(p, ',');
  1910. if (p != NULL)
  1911. *p++ = '';
  1912. if (strcasecmp(vp, "success") == 0)
  1913. a->q_flags |= QPINGONSUCCESS;
  1914. else if (strcasecmp(vp, "failure") == 0)
  1915. a->q_flags |= QPINGONFAILURE;
  1916. else if (strcasecmp(vp, "delay") == 0)
  1917. a->q_flags |= QPINGONDELAY;
  1918. else
  1919. {
  1920. usrerr("501 5.5.4 Bad argument "%s"  to NOTIFY",
  1921. vp);
  1922. /* NOTREACHED */
  1923. }
  1924. }
  1925. }
  1926. else if (strcasecmp(kp, "orcpt") == 0)
  1927. {
  1928. if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
  1929. {
  1930. usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
  1931. /* NOTREACHED */
  1932. }
  1933. if (vp == NULL)
  1934. {
  1935. usrerr("501 5.5.2 ORCPT requires a value");
  1936. /* NOTREACHED */
  1937. }
  1938. if (strchr(vp, ';') == NULL || !xtextok(vp))
  1939. {
  1940. usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
  1941. /* NOTREACHED */
  1942. }
  1943. if (a->q_orcpt != NULL)
  1944. {
  1945. usrerr("501 5.5.0 Duplicate ORCPT parameter");
  1946. /* NOTREACHED */
  1947. }
  1948. a->q_orcpt = newstr(vp);
  1949. }
  1950. else
  1951. {
  1952. usrerr("501 5.5.4 %s parameter unrecognized", kp);
  1953. /* NOTREACHED */
  1954. }
  1955. }
  1956. /*
  1957. **  PRINTVRFYADDR -- print an entry in the verify queue
  1958. **
  1959. ** Parameters:
  1960. ** a -- the address to print
  1961. ** last -- set if this is the last one.
  1962. ** vrfy -- set if this is a VRFY command.
  1963. **
  1964. ** Returns:
  1965. ** none.
  1966. **
  1967. ** Side Effects:
  1968. ** Prints the appropriate 250 codes.
  1969. */
  1970. #define OFFF (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */
  1971. static void
  1972. printvrfyaddr(a, last, vrfy)
  1973. register ADDRESS *a;
  1974. bool last;
  1975. bool vrfy;
  1976. {
  1977. char fmtbuf[30];
  1978. if (vrfy && a->q_mailer != NULL &&
  1979.     !bitnset(M_VRFY250, a->q_mailer->m_flags))
  1980. (void) strlcpy(fmtbuf, "252", sizeof fmtbuf);
  1981. else
  1982. (void) strlcpy(fmtbuf, "250", sizeof fmtbuf);
  1983. fmtbuf[3] = last ? ' ' : '-';
  1984. (void) strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
  1985. if (a->q_fullname == NULL)
  1986. {
  1987. if ((a->q_mailer == NULL ||
  1988.      a->q_mailer->m_addrtype == NULL ||
  1989.      strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
  1990.     strchr(a->q_user, '@') == NULL)
  1991. (void) strlcpy(&fmtbuf[OFFF], "<%s@%s>",
  1992.        sizeof fmtbuf - OFFF);
  1993. else
  1994. (void) strlcpy(&fmtbuf[OFFF], "<%s>",
  1995.        sizeof fmtbuf - OFFF);
  1996. message(fmtbuf, a->q_user, MyHostName);
  1997. }
  1998. else
  1999. {
  2000. if ((a->q_mailer == NULL ||
  2001.      a->q_mailer->m_addrtype == NULL ||
  2002.      strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
  2003.     strchr(a->q_user, '@') == NULL)
  2004. (void) strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
  2005.        sizeof fmtbuf - OFFF);
  2006. else
  2007. (void) strlcpy(&fmtbuf[OFFF], "%s <%s>",
  2008.        sizeof fmtbuf - OFFF);
  2009. message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
  2010. }
  2011. }
  2012. /*
  2013. **  RUNINCHILD -- return twice -- once in the child, then in the parent again
  2014. **
  2015. ** Parameters:
  2016. ** label -- a string used in error messages
  2017. **
  2018. ** Returns:
  2019. ** zero in the child
  2020. ** one in the parent
  2021. **
  2022. ** Side Effects:
  2023. ** none.
  2024. */
  2025. static int
  2026. runinchild(label, e)
  2027. char *label;
  2028. register ENVELOPE *e;
  2029. {
  2030. pid_t childpid;
  2031. if (!OneXact)
  2032. {
  2033. /*
  2034. **  Disable child process reaping, in case ETRN has preceded
  2035. **  MAIL command, and then fork.
  2036. */
  2037. (void) blocksignal(SIGCHLD);
  2038. childpid = dofork();
  2039. if (childpid < 0)
  2040. {
  2041. syserr("451 4.3.0 %s: cannot fork", label);
  2042. (void) releasesignal(SIGCHLD);
  2043. return 1;
  2044. }
  2045. if (childpid > 0)
  2046. {
  2047. auto int st;
  2048. /* parent -- wait for child to complete */
  2049. sm_setproctitle(TRUE, e, "server %s child wait",
  2050. CurSmtpClient);
  2051. st = waitfor(childpid);
  2052. if (st == -1)
  2053. syserr("451 4.3.0 %s: lost child", label);
  2054. else if (!WIFEXITED(st))
  2055. syserr("451 4.3.0 %s: died on signal %d",
  2056. label, st & 0177);
  2057. /* if we exited on a QUIT command, complete the process */
  2058. if (WEXITSTATUS(st) == EX_QUIT)
  2059. {
  2060. disconnect(1, e);
  2061. finis(TRUE, ExitStat);
  2062. }
  2063. /* restore the child signal */
  2064. (void) releasesignal(SIGCHLD);
  2065. return 1;
  2066. }
  2067. else
  2068. {
  2069. /* child */
  2070. InChild = TRUE;
  2071. QuickAbort = FALSE;
  2072. clearstats();
  2073. clearenvelope(e, FALSE);
  2074. assign_queueid(e);
  2075. (void) setsignal(SIGCHLD, SIG_DFL);
  2076. (void) releasesignal(SIGCHLD);
  2077. }
  2078. }
  2079. return 0;
  2080. }
  2081. # if SASL
  2082. int
  2083. proxy_policy(context, auth_identity, requested_user, user, errstr)
  2084. void *context;
  2085. const char *auth_identity;
  2086. const char *requested_user;
  2087. const char **user;
  2088. const char **errstr;
  2089. {
  2090. if (user != NULL)
  2091. {
  2092. *user = newstr(auth_identity);
  2093. return SASL_OK;
  2094. }
  2095. return SASL_FAIL;
  2096. }
  2097. # endif /* SASL */
  2098. #endif /* SMTP */
  2099. /*
  2100. **  HELP -- implement the HELP command.
  2101. **
  2102. ** Parameters:
  2103. ** topic -- the topic we want help for.
  2104. ** e -- envelope
  2105. **
  2106. ** Returns:
  2107. ** none.
  2108. **
  2109. ** Side Effects:
  2110. ** outputs the help file to message output.
  2111. */
  2112. #define HELPVSTR "#vers "
  2113. #define HELPVERSION 2
  2114. void
  2115. help(topic, e)
  2116. char *topic;
  2117. ENVELOPE *e;
  2118. {
  2119. register FILE *hf;
  2120. register char *p;
  2121. int len;
  2122. bool noinfo;
  2123. bool first = TRUE;
  2124. long sff = SFF_OPENASROOT|SFF_REGONLY;
  2125. char buf[MAXLINE];
  2126. char inp[MAXLINE];
  2127. static int foundvers = -1;
  2128. extern char Version[];
  2129. if (DontLockReadFiles)
  2130. sff |= SFF_NOLOCK;
  2131. if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
  2132. sff |= SFF_SAFEDIRPATH;
  2133. if (HelpFile == NULL ||
  2134.     (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
  2135. {
  2136. /* no help */
  2137. errno = 0;
  2138. message("502 5.3.0 Sendmail %s -- HELP not implemented",
  2139. Version);
  2140. return;
  2141. }
  2142. if (topic == NULL || *topic == '')
  2143. {
  2144. topic = "smtp";
  2145. noinfo = FALSE;
  2146. }
  2147. else
  2148. {
  2149. makelower(topic);
  2150. noinfo = TRUE;
  2151. }
  2152. len = strlen(topic);
  2153. while (fgets(buf, sizeof buf, hf) != NULL)
  2154. {
  2155. if (buf[0] == '#')
  2156. {
  2157. if (foundvers < 0 &&
  2158.     strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
  2159. {
  2160. int h;
  2161. if (sscanf(buf + strlen(HELPVSTR), "%d",
  2162.    &h) == 1)
  2163. foundvers = h;
  2164. }
  2165. continue;
  2166. }
  2167. if (strncmp(buf, topic, len) == 0)
  2168. {
  2169. if (first)
  2170. {
  2171. first = FALSE;
  2172. /* print version if no/old vers# in file */
  2173. if (foundvers < 2 && !noinfo)
  2174. message("214-2.0.0 This is Sendmail version %s", Version);
  2175. }
  2176. p = strpbrk(buf, " t");
  2177. if (p == NULL)
  2178. p = buf + strlen(buf) - 1;
  2179. else
  2180. p++;
  2181. fixcrlf(p, TRUE);
  2182. if (foundvers >= 2)
  2183. {
  2184. translate_dollars(p);
  2185. expand(p, inp, sizeof inp, e);
  2186. p = inp;
  2187. }
  2188. message("214-2.0.0 %s", p);
  2189. noinfo = FALSE;
  2190. }
  2191. }
  2192. if (noinfo)
  2193. message("504 5.3.0 HELP topic "%.10s" unknown", topic);
  2194. else
  2195. message("214 2.0.0 End of HELP info");
  2196. if (foundvers != 0 && foundvers < HELPVERSION)
  2197. {
  2198. if (LogLevel > 1)
  2199. sm_syslog(LOG_WARNING, e->e_id,
  2200.   "%s too old (require version %d)",
  2201.   HelpFile, HELPVERSION);
  2202. /* avoid log next time */
  2203. foundvers = 0;
  2204. }
  2205. (void) fclose(hf);
  2206. }