]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/src/srvrsmtp.c
Merge commit '850ef5ae11d69ea3381bd310f564f025fc8caea3'
[FreeBSD/FreeBSD.git] / contrib / sendmail / src / srvrsmtp.c
1 /*
2  * Copyright (c) 1998-2010, 2012-2014,2021-2024 Proofpoint, 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
14 #include <sendmail.h>
15 #if MILTER
16 # include <libmilter/mfapi.h>
17 # include <libmilter/mfdef.h>
18 #endif
19
20 SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.1016 2013-11-22 20:51:56 ca Exp $")
21
22 #include <sm/sendmail.h>
23 #if _FFR_8BITENVADDR
24 # include <sm/ixlen.h>
25 #endif
26 #include <sm/time.h>
27 #include <sm/fdset.h>
28
29 #if SASL || STARTTLS
30 # include <tls.h>
31 # include "sfsasl.h"
32 #endif
33 #if SASL
34 # define ENC64LEN(l)    (((l) + 2) * 4 / 3 + 1)
35 static int saslmechs __P((sasl_conn_t *, char **));
36 #endif
37 #if STARTTLS
38 # include <openssl/err.h>
39
40 static SSL_CTX  *srv_ctx = NULL;        /* TLS server context */
41 static SSL      *srv_ssl = NULL;        /* per connection context */
42 static tlsi_ctx_T tlsi_ctx;             /* TLS information context */
43
44 static bool     tls_ok_srv = false;
45
46 # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
47                                 bitset(SRV_VRFY_CLT, features))
48 #endif /* STARTTLS */
49
50 #if _FFR_DM_ONE
51 static bool     NotFirstDelivery = false;
52 #endif
53
54 /* server features */
55 #define SRV_NONE        0x00000000      /* none... */
56 #define SRV_OFFER_TLS   0x00000001      /* offer STARTTLS */
57 #define SRV_VRFY_CLT    0x00000002      /* request a cert */
58 #define SRV_OFFER_AUTH  0x00000004      /* offer AUTH */
59 #define SRV_OFFER_ETRN  0x00000008      /* offer ETRN */
60 #define SRV_OFFER_VRFY  0x00000010      /* offer VRFY (not yet used) */
61 #define SRV_OFFER_EXPN  0x00000020      /* offer EXPN */
62 #define SRV_OFFER_VERB  0x00000040      /* offer VERB */
63 #define SRV_OFFER_DSN   0x00000080      /* offer DSN */
64 #if PIPELINING
65 # define SRV_OFFER_PIPE 0x00000100      /* offer PIPELINING */
66 # if _FFR_NO_PIPE
67 #  define SRV_NO_PIPE   0x00000200      /* disable PIPELINING, sleep if used */
68 # endif
69 #endif /* PIPELINING */
70 #define SRV_REQ_AUTH    0x00000400      /* require AUTH */
71 #define SRV_REQ_SEC     0x00000800      /* require security - equiv to AuthOptions=p */
72 #define SRV_TMP_FAIL    0x00001000      /* ruleset caused a temporary failure */
73 #if USE_EAI
74 # define SRV_OFFER_EAI  0x00002000      /* offer SMTPUTF8 */
75 #endif
76 #define SRV_NO_HTTP_CMD 0x00004000      /* always reject HTTP commands */
77 #define SRV_BAD_PIPELINE        0x00008000      /* reject bad pipelining (see comment below) */
78 #define SRV_REQ_CRLF    0x00010000      /* require CRLF as EOL */
79 #define SRV_BARE_LF_421 0x00020000      /* bare LF - drop connection */
80 #define SRV_BARE_CR_421 0x00040000      /* bare CR - drop connection */
81 #define SRV_BARE_LF_SP  0x00080000
82 #define SRV_BARE_CR_SP  0x00100000
83
84 static unsigned long    srvfeatures __P((ENVELOPE *, char *, unsigned long));
85
86 #define STOP_ATTACK     ((time_t) -1)
87 static time_t   checksmtpattack __P((volatile unsigned int *, unsigned int,
88                                      bool, char *, ENVELOPE *));
89 static void     printvrfyaddr __P((ADDRESS *, bool, bool));
90 static char     *skipword __P((char *volatile, char *));
91 static void     setup_smtpd_io __P((void));
92 static struct timeval   *channel_readable __P((SM_FILE_T *, int));
93
94 #if SASL
95 # ifndef MAX_AUTH_USER_LEN
96 #  define MAX_AUTH_USER_LEN 256
97 # endif
98 # ifndef MAX_AUTH_LOG_LEN
99 #  define MAX_AUTH_LOG_LEN 64
100 # endif
101 static void get_sasl_user __P((char *, unsigned int, const char *, char *out, size_t));
102 # define RESET_AUTH_FAIL_LOG_USER       \
103         do      \
104         {       \
105                 (void) memset(auth_user, 0, sizeof(auth_user)); \
106                 (void) memset(auth_user_tmp, 0, sizeof(auth_user_tmp)); \
107                 auth_user_len = 0;      \
108         } while (0)
109 # define SET_AUTH_USER_TMP(s, len)      \
110         do      \
111         {       \
112                 auth_user_len = SM_MIN(len, MAX_AUTH_USER_LEN-1);       \
113                 (void) memcpy(auth_user_tmp, s, auth_user_len); \
114         } while (0)
115 # define SET_AUTH_USER  \
116         get_sasl_user(auth_user_tmp, auth_user_len, auth_type, auth_user, sizeof(auth_user))
117 # define SET_AUTH_USER_CONDITIONALLY    \
118                 if ('\0' == auth_user[0])       \
119                         SET_AUTH_USER;
120 # define LOG_AUTH_FAIL_USER ", user=", (int)MAX_AUTH_LOG_LEN, auth_user
121 # if SASL >= 20000
122 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
123                                 char *_remoteip, char *_localip,
124                                 char *_auth_id, sasl_ssf_t *_ext_ssf));
125
126 # define RESET_SASLCONN \
127         do                                                      \
128         {                                                       \
129                 RESET_AUTH_FAIL_LOG_USER;                       \
130                 result = reset_saslconn(&conn, AuthRealm, remoteip, \
131                                         localip, auth_id, &ext_ssf); \
132                 if (result != SASL_OK)                          \
133                         sasl_ok = false;                        \
134         } while (0)
135
136 # else /* SASL >= 20000 */
137 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
138                                 struct sockaddr_in *_saddr_r,
139                                 struct sockaddr_in *_saddr_l,
140                                 sasl_external_properties_t *_ext_ssf));
141 # define RESET_SASLCONN \
142         do                                                      \
143         {                                                       \
144                 RESET_AUTH_FAIL_LOG_USER;                       \
145                 result = reset_saslconn(&conn, AuthRealm, &saddr_r, \
146                                         &saddr_l, &ext_ssf);    \
147                 if (result != SASL_OK)                          \
148                         sasl_ok = false;                        \
149         } while (0)
150
151 # endif /* SASL >= 20000 */
152 #endif /* SASL */
153
154 #if !defined(RESET_AUTH_FAIL_LOG_USER)
155 # define RESET_AUTH_FAIL_LOG_USER
156 #endif
157
158 extern ENVELOPE BlankEnvelope;
159
160 #define NBADRCPTS                                               \
161         do                                                      \
162         {                                                       \
163                 char buf[16];                                   \
164                 (void) sm_snprintf(buf, sizeof(buf), "%d",      \
165                         BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
166                                 ? n_badrcpts - 1 : n_badrcpts); \
167                 macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
168         } while (0)
169
170 #define SKIP_SPACE(s)   while (SM_ISSPACE(*s))  \
171                                 (s)++
172
173 #if USE_EAI
174 /*
175 **  ADDR_IS_ASCII -- check whether a string (address) is ASCII
176 **
177 **      Parameters:
178 **              str -- a string
179 **
180 **      Returns:
181 **              TRUE iff str is non-NULL and points to only ASCII
182 */
183
184 bool
185 addr_is_ascii(str)
186         const char *str;
187 {
188         while (str != NULL && *str != '\0' && isascii((unsigned char)*str))
189                 str++;
190         return (str != NULL && *str == '\0');
191 }
192
193 /*
194 **  STR_IS_PRINT -- check whether a string is printable ASCII
195 **
196 **      Parameters:
197 **              str -- a string
198 **
199 **      Returns:
200 **              TRUE iff str is non-NULL and points to only printable ASCII
201 */
202
203 bool
204 str_is_print(str)
205         const char *str;
206 {
207         while (str != NULL && *str != '\0' && *str >= ' ' && (unsigned char)*str < 127)
208                 str++;
209         return (str != NULL && *str == '\0');
210 }
211
212
213 # define CHECK_UTF8_ADDR(a, q)  \
214         do      \
215         {       \
216                 q = NULL;       \
217                 if (addr_is_ascii(a))   \
218                         break;  \
219                 if (!SMTP_UTF8) \
220                         break;  \
221                 if (!e->e_smtputf8)     \
222                         q = "553 5.6.7 Address requires SMTPUTF8";      \
223                 else    \
224                 {       \
225                         char str[MAXNAME];      \
226                         dequote_internal_chars(a, str, sizeof(str));    \
227                         if (!utf8_valid(str, strlen(str)) && SMTP_UTF8 <= 1) \
228                                 q = "553 5.6.7 Address not valid UTF8"; \
229                 }       \
230         } while (0)
231 #endif /* USE_EAI */
232
233 /*
234 **  PARSE_ESMTP_ARGS -- parse ESMTP arguments (for MAIL, RCPT)
235 **
236 **      Parameters:
237 **              e -- the envelope
238 **              addr_st -- address (RCPT only)
239 **              p -- read buffer
240 **              delimptr -- current position in read buffer
241 **              which -- MAIL/RCPT
242 **              args -- arguments (output)
243 **              esmtp_args -- function to process a single ESMTP argument
244 **
245 **      Returns:
246 **              none
247 */
248
249 void
250 parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args)
251         ENVELOPE *e;
252         ADDRESS *addr_st;
253         char *p;
254         char *delimptr;
255         char *which;
256         char *args[];
257         esmtp_args_F esmtp_args;
258 {
259         int argno;
260
261         argno = 0;
262         if (args != NULL)
263                 args[argno++] = p;
264         p = delimptr;
265         while (p != NULL && *p != '\0')
266         {
267                 char *kp;
268                 char *vp = NULL;
269                 char *equal = NULL;
270
271                 /* locate the beginning of the keyword */
272                 SKIP_SPACE(p);
273                 if (*p == '\0')
274                         break;
275                 kp = p;
276
277                 /* skip to the value portion */
278                 while ((isascii(*p) && isalnum(*p)) || *p == '-')
279                         p++;
280                 if (*p == '=')
281                 {
282                         equal = p;
283                         *p++ = '\0';
284                         vp = p;
285
286                         /* skip to the end of the value */
287                         while (*p != '\0' && *p != ' ' &&
288                                !(isascii(*p) && iscntrl(*p)) &&
289                                *p != '=')
290                                 p++;
291                 }
292
293                 if (*p != '\0')
294                         *p++ = '\0';
295
296                 if (tTd(19, 1))
297                         sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp,
298                                 vp == NULL ? "<null>" : vp);
299
300                 esmtp_args(addr_st, kp, vp, e);
301                 if (equal != NULL)
302                         *equal = '=';
303                 if (args != NULL)
304                         args[argno] = kp;
305                 argno++;
306                 if (argno >= MAXSMTPARGS - 1)
307                         usrerr("501 5.5.4 Too many parameters");
308                 if (Errors > 0)
309                         break;
310         }
311         if (args != NULL)
312                 args[argno] = NULL;
313 }
314
315 #if _FFR_ADD_BCC
316
317 /*
318 **  ADDRCPT -- Add a rcpt to sendq list
319 **
320 **      Parameters:
321 **              rcpt -- rcpt [i]
322 **              sendq -- a pointer to the head of a queue to put
323 **                      these people into.
324 **              e -- the envelope in which to add these recipients.
325 **
326 **      Returns:
327 **              The number of addresses added to the list.
328 */
329
330 static int
331 addrcpt(rcpt, sendq, e)
332         char *rcpt;
333         ADDRESS **sendq;
334         ENVELOPE *e;
335 {
336         int r;
337         char *oldto;
338         ADDRESS *a;
339
340         SM_REQUIRE(rcpt != NULL);
341         SM_REQUIRE(sendq != NULL);
342         SM_REQUIRE(e != NULL);
343         oldto = e->e_to;
344         if (tTd(25, 1))
345                 sm_dprintf("addrcpt: rcpt=%s\n", rcpt);
346         r = Errors;
347         a = NULL;
348         SM_TRY
349         {
350                 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e b");
351 /* XXX rcpt must be [i] */
352                 a = parseaddr(rcpt, NULLADDR, RF_COPYALL, ' ', NULL, e, true);
353                 if (a == NULL)
354                         return 0;
355
356                 a->q_flags &= ~Q_PINGFLAGS;
357                 a->q_flags |= QINTBCC;
358                 a->q_owner = "<>";
359
360                 /* disable alias expansion? */
361                 a = recipient(a, sendq, 0, e);
362         }
363         SM_FINALLY
364         {
365                 e->e_to = oldto;
366                 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
367         }
368         SM_END_TRY
369         if (tTd(25, 1))
370                 sm_dprintf("addrcpt: rcpt=%s, flags=%#lx\n", rcpt,
371                         a != NULL ? a->q_flags : 0);
372         Errors = r;
373         return 1;
374 }
375
376 /*
377 **  ADDBCC -- Maybe create a copy of an e-mail
378 **
379 **      Parameters:
380 **              a -- current RCPT
381 **              e -- the envelope.
382 **
383 **      Returns:
384 **              nothing
385 **
386 **      Side Effects:
387 **              rscheck() can trigger an "exception"
388 */
389
390 static void
391 addbcc(a, e)
392         ADDRESS *a;
393         ENVELOPE *e;
394 {
395         int nobcc;
396         char *newrcpt, empty[1];
397
398         if (!AddBcc)
399                 return;
400
401         nobcc = false;
402         empty[0] = '\0';
403         newrcpt = empty;
404
405         nobcc = rscheck("bcc", a->q_paddr, NULL, e, RSF_ADDR, 12, NULL, NOQID,
406                         NULL, &newrcpt);
407         if (tTd(25, 1))
408                 sm_dprintf("addbcc: nobcc=%d, Errors=%d, newrcpt=<%s>\n", nobcc, Errors, newrcpt);
409         if (nobcc != EX_OK || Errors > 0 || *newrcpt == '\0')
410                 return;
411
412         (void) addrcpt(newrcpt, &e->e_sendqueue, e);
413         return;
414 }
415 #else /* _FFR_ADD_BCC */
416 # define addbcc(a, e)
417 #endif /* _FFR_ADD_BCC */
418
419 #if _FFR_RCPTFLAGS
420 /*
421 **  RCPTMODS -- Perform rcpt modifications if requested
422 **
423 **      Parameters:
424 **              rcpt -- current RCPT
425 **              e -- the envelope.
426 **
427 **      Returns:
428 **              nothing.
429 */
430
431 void
432 rcptmods(rcpt, e)
433         ADDRESS *rcpt;
434         ENVELOPE *e;
435 {
436         char *fl;
437
438         SM_REQUIRE(rcpt != NULL);
439         SM_REQUIRE(e != NULL);
440
441         fl = macvalue(macid("{rcpt_flags}"), e);
442         if (SM_IS_EMPTY(fl))
443                 return;
444         if (tTd(25, 1))
445                 sm_dprintf("rcptmods: rcpt=%s, flags=%s\n", rcpt->q_paddr, fl);
446
447         /* parse flags */
448         for ( ; *fl != '\0'; ++fl)
449         {
450                 switch (*fl)
451                 {
452                   case 'n':
453                         rcpt->q_flags &= ~Q_PINGFLAGS;
454                         rcpt->q_flags |= QINTBCC;
455                         rcpt->q_owner = "<>";
456                         break;
457
458                   case 'N':
459                         rcpt->q_flags &= ~Q_PINGFLAGS;
460                         rcpt->q_owner = "<>";
461                         break;
462
463                   case QDYNMAILFLG:
464                         rcpt->q_flags |= QDYNMAILER;
465                         newmodmailer(rcpt, *fl);
466                         break;
467
468                   default:
469                         sm_syslog(LOG_INFO, e->e_id,
470                                   "rcpt=%s, rcpt_flags=%s, status=unknown",
471                                   rcpt->q_paddr, fl);
472                         break;
473                 }
474         }
475
476         /* reset macro to avoid confusion later on */
477         macdefine(&e->e_macro, A_PERM, macid("{rcpt_flags}"), NULL);
478
479 }
480 #else /* _FFR_RCPTFLAGS */
481 # define rcptmods(a, e)
482 #endif /* _FFR_RCPTFLAGS */
483
484 #if _FFR_8BITENVADDR
485
486 /*
487 **  SEP_ARGS -- separate address and argument string for MAIL/RCPT command
488 **
489 **      Parameters:
490 **              args -- arguments (converted to and from internal format)
491 **              orig -- string after command (original data)
492 **              id -- envelope id (for logging only)
493 **              addr -- for logging only: address (original data)
494 **
495 **      Returns:
496 **              nothing
497 */
498
499 static void sep_args __P((char *, char *, const char *, const char *));
500
501 static void
502 sep_args(args, orig, id, addr)
503         char *args;
504         char *orig;
505         const char *id;
506         const char *addr;
507 {
508         int lr, lo;
509         char *q;
510
511         lr = strlen(args);
512         lo = strlen(orig);
513         if (lr >= lo)
514         {
515                 sm_syslog(LOG_ERR, id,
516                         "ERROR=ARGS_NOT_FOUND, address='%s', rest='%s', orig='%s', strlen(rest)=%d, strlen(orig)=%d",
517                         addr, args, orig, lr, lo);
518                 return;
519         }
520
521         q = orig + (lo - lr);
522         if (!(q > orig && *--q == ' '))
523         {
524                 sm_syslog(LOG_INFO, id,
525                         "ERROR=ARGS_DO_NOT_MATCH, address='%s', rest='%s', orig='%s', q='%s', strlen(rest)=%d, strlen(orig)=%d, cmp=%d",
526                         addr, args, orig, q, lr, lo, strcmp(args, q));
527                 return;
528         }
529
530         for (; q > orig && *q == ' '; q--)
531                 *q = '\0';
532 }
533 #endif /* _FFR_8BITENVADDR */
534
535 /*
536 **  CHANNEL_READBLE -- determine if data is readable from the SMTP channel
537 **
538 **      Parameters:
539 **              channel -- connect channel for reading
540 **              timeout -- how long to pause for data in milliseconds
541 **
542 **      Returns:
543 **              timeval contained how long we waited if data detected,
544 **                      NULL otherwise
545 */
546
547 static struct timeval *
548 channel_readable(channel, timeout)
549         SM_FILE_T *channel;
550         int timeout;
551 {
552         struct timeval bp, ep; /* {begin,end} pause */
553         static struct timeval tp; /* total pause */
554         int eoftest;
555
556         /* check if data is on the channel during the pause */
557         gettimeofday(&bp, NULL);
558         if ((eoftest = sm_io_getc(channel, timeout)) != SM_IO_EOF)
559         {
560                 gettimeofday(&ep, NULL);
561                 sm_io_ungetc(channel, SM_TIME_DEFAULT, eoftest);
562                 timersub(&ep, &bp, &tp);
563                 return &tp;
564         }
565         return NULL;
566 }
567
568 /*
569 **  SMTP -- run the SMTP protocol.
570 **
571 **      Parameters:
572 **              nullserver -- if non-NULL, rejection message for
573 **                      (almost) all SMTP commands.
574 **              d_flags -- daemon flags
575 **              e -- the envelope.
576 **
577 **      Returns:
578 **              never.
579 **
580 **      Side Effects:
581 **              Reads commands from the input channel and processes them.
582 */
583
584 /*
585 **  Notice: The smtp server doesn't have a session context like the client
586 **      side has (mci). Therefore some data (session oriented) is allocated
587 **      or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
588 **      This should be fixed in a successor version.
589 */
590
591 struct cmd
592 {
593         char    *cmd_name;      /* command name */
594         int     cmd_code;       /* internal code, see below */
595 };
596
597 /* values for cmd_code */
598 #define CMDERROR        0       /* bad command */
599 #define CMDMAIL 1       /* mail -- designate sender */
600 #define CMDRCPT 2       /* rcpt -- designate recipient */
601 #define CMDDATA 3       /* data -- send message text */
602 #define CMDRSET 4       /* rset -- reset state */
603 #define CMDVRFY 5       /* vrfy -- verify address */
604 #define CMDEXPN 6       /* expn -- expand address */
605 #define CMDNOOP 7       /* noop -- do nothing */
606 #define CMDQUIT 8       /* quit -- close connection and die */
607 #define CMDHELO 9       /* helo -- be polite */
608 #define CMDHELP 10      /* help -- give usage info */
609 #define CMDEHLO 11      /* ehlo -- extended helo (RFC 1425) */
610 #define CMDETRN 12      /* etrn -- flush queue */
611 #if SASL
612 # define CMDAUTH        13      /* auth -- SASL authenticate */
613 #endif
614 #if STARTTLS
615 # define CMDSTLS        14      /* STARTTLS -- start TLS session */
616 #endif
617 /* non-standard commands */
618 #define CMDVERB 17      /* verb -- go into verbose mode */
619 /* unimplemented commands from RFC 821 */
620 #define CMDUNIMPL       19      /* unimplemented rfc821 commands */
621 /* use this to catch and log "door handle" attempts on your system */
622 #define CMDLOGBOGUS     23      /* bogus command that should be logged */
623 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
624 #define CMDDBGQSHOW     24      /* showq -- show send queue */
625 #define CMDDBGDEBUG     25      /* debug -- set debug mode */
626
627 /*
628 **  Note: If you change this list, remember to update 'helpfile'
629 */
630
631 static struct cmd       CmdTab[] =
632 {
633         { "mail",       CMDMAIL         },
634         { "rcpt",       CMDRCPT         },
635         { "data",       CMDDATA         },
636         { "rset",       CMDRSET         },
637         { "vrfy",       CMDVRFY         },
638         { "expn",       CMDEXPN         },
639         { "help",       CMDHELP         },
640         { "noop",       CMDNOOP         },
641         { "quit",       CMDQUIT         },
642         { "helo",       CMDHELO         },
643         { "ehlo",       CMDEHLO         },
644         { "etrn",       CMDETRN         },
645         { "verb",       CMDVERB         },
646         { "send",       CMDUNIMPL       },
647         { "saml",       CMDUNIMPL       },
648         { "soml",       CMDUNIMPL       },
649         { "turn",       CMDUNIMPL       },
650 #if SASL
651         { "auth",       CMDAUTH,        },
652 #endif
653 #if STARTTLS
654         { "starttls",   CMDSTLS,        },
655 #endif
656     /* remaining commands are here only to trap and log attempts to use them */
657         { "showq",      CMDDBGQSHOW     },
658         { "debug",      CMDDBGDEBUG     },
659         { "wiz",        CMDLOGBOGUS     },
660
661         { NULL,         CMDERROR        }
662 };
663
664 static char     *CurSmtpClient;         /* who's at the other end of channel */
665
666 #ifndef MAXBADCOMMANDS
667 # define MAXBADCOMMANDS 25      /* maximum number of bad commands */
668 #endif
669 #ifndef MAXHELOCOMMANDS
670 # define MAXHELOCOMMANDS 3      /* max HELO/EHLO commands before slowdown */
671 #endif
672 #ifndef MAXVRFYCOMMANDS
673 # define MAXVRFYCOMMANDS 6      /* max VRFY/EXPN commands before slowdown */
674 #endif
675 #ifndef MAXETRNCOMMANDS
676 # define MAXETRNCOMMANDS 8      /* max ETRN commands before slowdown */
677 #endif
678 #ifndef MAXTIMEOUT
679 # define MAXTIMEOUT (4 * 60)    /* max timeout for bad commands */
680 #endif
681
682 /*
683 **  Maximum shift value to compute timeout for bad commands.
684 **  This introduces an upper limit of 2^MAXSHIFT for the timeout.
685 */
686
687 #ifndef MAXSHIFT
688 # define MAXSHIFT 8
689 #endif
690 #if MAXSHIFT > 31
691 # error "MAXSHIFT > 31 is invalid"
692 #endif
693
694
695 #if MAXBADCOMMANDS > 0
696 # define STOP_IF_ATTACK(r)      do              \
697         {                                       \
698                 if ((r) == STOP_ATTACK)         \
699                         goto stopattack;        \
700         } while (0)
701
702 #else /* MAXBADCOMMANDS > 0 */
703 # define STOP_IF_ATTACK(r)      r
704 #endif /* MAXBADCOMMANDS > 0 */
705
706
707 #if SM_HEAP_CHECK
708 static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
709         "@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
710 #endif
711
712 typedef struct
713 {
714         bool            sm_gotmail;     /* mail command received */
715         unsigned int    sm_nrcpts;      /* number of successful RCPT commands */
716         bool            sm_discard;
717 #if MILTER
718         bool            sm_milterize;
719         bool            sm_milterlist;  /* any filters in the list? */
720         milters_T       sm_milters;
721
722         /* e_nrcpts from envelope before recipient() call */
723         unsigned int    sm_e_nrcpts_orig;
724 #endif /* MILTER */
725         char            *sm_quarmsg;    /* carry quarantining across messages */
726 } SMTP_T;
727
728 static bool     smtp_data __P((SMTP_T *, ENVELOPE *, bool));
729
730 #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
731
732 #if MILTER
733 # define MILTER_ABORT(e)        milter_abort((e))
734
735 # define MILTER_REPLY(str)                                              \
736         {                                                               \
737                 int savelogusrerrs = LogUsrErrs;                        \
738                                                                         \
739                 milter_cmd_fail = true;                                 \
740                 switch (state)                                          \
741                 {                                                       \
742                   case SMFIR_SHUTDOWN:                                  \
743                         if (MilterLogLevel > 3)                         \
744                         {                                               \
745                                 sm_syslog(LOG_INFO, e->e_id,            \
746                                           "Milter: %s=%s, reject=421, errormode=4",     \
747                                           str, addr);                   \
748                                 LogUsrErrs = false;                     \
749                         }                                               \
750                         {                                               \
751                                 bool tsave = QuickAbort;                \
752                                                                         \
753                                 QuickAbort = false;                     \
754                                 usrerr("421 4.3.0 closing connection"); \
755                                 QuickAbort = tsave;                     \
756                                 e->e_sendqueue = NULL;                  \
757                                 goto doquit;                            \
758                         }                                               \
759                         break;                                          \
760                   case SMFIR_REPLYCODE:                                 \
761                         if (MilterLogLevel > 3)                         \
762                         {                                               \
763                                 sm_syslog(LOG_INFO, e->e_id,            \
764                                           "Milter: %s=%s, reject=%s",   \
765                                           str, addr, response);         \
766                                 LogUsrErrs = false;                     \
767                         }                                               \
768                         if (strncmp(response, "421 ", 4) == 0           \
769                             || strncmp(response, "421-", 4) == 0)       \
770                         {                                               \
771                                 bool tsave = QuickAbort;                \
772                                                                         \
773                                 QuickAbort = false;                     \
774                                 usrerr(response);                       \
775                                 QuickAbort = tsave;                     \
776                                 e->e_sendqueue = NULL;                  \
777                                 goto doquit;                            \
778                         }                                               \
779                         else                                            \
780                                 usrerr(response);                       \
781                         break;                                          \
782                                                                         \
783                   case SMFIR_REJECT:                                    \
784                         if (MilterLogLevel > 3)                         \
785                         {                                               \
786                                 sm_syslog(LOG_INFO, e->e_id,            \
787                                           "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
788                                           str, addr);                   \
789                                 LogUsrErrs = false;                     \
790                         }                                               \
791                         usrerr("550 5.7.1 Command rejected");           \
792                         break;                                          \
793                                                                         \
794                   case SMFIR_DISCARD:                                   \
795                         if (MilterLogLevel > 3)                         \
796                                 sm_syslog(LOG_INFO, e->e_id,            \
797                                           "Milter: %s=%s, discard",     \
798                                           str, addr);                   \
799                         e->e_flags |= EF_DISCARD;                       \
800                         milter_cmd_fail = false;                        \
801                         break;                                          \
802                                                                         \
803                   case SMFIR_TEMPFAIL:                                  \
804                         if (MilterLogLevel > 3)                         \
805                         {                                               \
806                                 sm_syslog(LOG_INFO, e->e_id,            \
807                                           "Milter: %s=%s, reject=%s",   \
808                                           str, addr, MSG_TEMPFAIL);     \
809                                 LogUsrErrs = false;                     \
810                         }                                               \
811                         usrerr(MSG_TEMPFAIL);                           \
812                         break;                                          \
813                   default:                                              \
814                         milter_cmd_fail = false;                        \
815                         break;                                          \
816                 }                                                       \
817                 LogUsrErrs = savelogusrerrs;                            \
818                 if (response != NULL)                                   \
819                         sm_free(response); /* XXX */                    \
820         }
821
822 #else /* MILTER */
823 # define MILTER_ABORT(e)
824 #endif /* MILTER */
825
826 /* clear all SMTP state (for HELO/EHLO/RSET) */
827 #define CLEAR_STATE(cmd)                                        \
828 do                                                              \
829 {                                                               \
830         /* abort milter filters */                              \
831         MILTER_ABORT(e);                                        \
832                                                                 \
833         if (smtp.sm_nrcpts > 0)                                 \
834         {                                                       \
835                 logundelrcpts(e, cmd, 10, false);               \
836                 smtp.sm_nrcpts = 0;                             \
837                 macdefine(&e->e_macro, A_PERM,                  \
838                           macid("{nrcpts}"), "0");              \
839         }                                                       \
840                                                                 \
841         e->e_sendqueue = NULL;                                  \
842         e->e_flags |= EF_CLRQUEUE;                              \
843                                                                 \
844         if (tTd(92, 2))                                         \
845                 sm_dprintf("CLEAR_STATE: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",\
846                         e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);\
847         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))   \
848                 logsender(e, NULL);                             \
849         e->e_flags &= ~EF_LOGSENDER;                            \
850                                                                 \
851         /* clean up a bit */                                    \
852         smtp.sm_gotmail = false;                                \
853         SuprErrs = true;                                        \
854         (void) dropenvelope(e, true, false);                    \
855         sm_rpool_free(e->e_rpool);                              \
856         e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));       \
857         CurEnv = e;                                             \
858         e->e_features = features;                               \
859                                                                 \
860         /* put back discard bit */                              \
861         if (smtp.sm_discard)                                    \
862                 e->e_flags |= EF_DISCARD;                       \
863                                                                 \
864         /* restore connection quarantining */                   \
865         if (smtp.sm_quarmsg == NULL)                            \
866         {                                                       \
867                 e->e_quarmsg = NULL;                            \
868                 macdefine(&e->e_macro, A_PERM,                  \
869                         macid("{quarantine}"), "");             \
870         }                                                       \
871         else                                                    \
872         {                                                       \
873                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,    \
874                                                 smtp.sm_quarmsg);       \
875                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"),   \
876                           e->e_quarmsg);                        \
877         }                                                       \
878 } while (0)
879
880 /* sleep to flatten out connection load */
881 #define MIN_DELAY_LOG   15      /* wait before logging this again */
882
883 /* is it worth setting the process title for 1s? */
884 #define DELAY_CONN(cmd)                                         \
885         if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)    \
886         {                                                       \
887                 time_t dnow;                                    \
888                                                                 \
889                 sm_setproctitle(true, e,                        \
890                                 "%s: %s: delaying %s: load average: %d", \
891                                 qid_printname(e), CurSmtpClient,        \
892                                 cmd, DelayLA);  \
893                 if (LogLevel > 8 && (dnow = curtime()) > log_delay)     \
894                 {                                               \
895                         sm_syslog(LOG_INFO, e->e_id,            \
896                                   "delaying=%s, load average=%d >= %d", \
897                                   cmd, CurrentLA, DelayLA);             \
898                         log_delay = dnow + MIN_DELAY_LOG;       \
899                 }                                               \
900                 (void) sleep(1);                                \
901                 sm_setproctitle(true, e, "%s %s: %.80s",        \
902                                 qid_printname(e), CurSmtpClient, inp);  \
903         }
904
905 /*
906 **  Determine the correct protocol keyword to use in the
907 **  Received: header, following RFC 3848.
908 */
909
910 #if !STARTTLS
911 # define tls_active     false
912 #endif
913 #if SASL
914 # define auth_active    (authenticating == SASL_IS_AUTH)
915 #else
916 # define auth_active    false
917 #endif
918 #if USE_EAI
919 #define GET_PROTOCOL()                                  \
920         (e->e_smtputf8                                  \
921             ? (auth_active                              \
922                 ? (tls_active ? "UTF8SMTPSA" : "UTF8SMTPA") \
923                 : (tls_active ? "UTF8SMTPS"  : "UTF8SMTP")) \
924             : (auth_active                              \
925                 ? (tls_active ? "ESMTPSA" : "ESMTPA")   \
926                 : (tls_active ? "ESMTPS"  : "ESMTP")))
927 #else /* USE_EAI */
928 #define GET_PROTOCOL()                                  \
929         (auth_active                                    \
930             ? (tls_active ? "ESMTPSA" : "ESMTPA")       \
931             : (tls_active ? "ESMTPS"  : "ESMTP"))
932 #endif /* USE_EAI */
933
934 #if _FFR_NOREFLECT
935 # define SHOWCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
936                 "(suppressed)" : inp)
937 # define SHOWSHRTCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
938                 "(suppressed)" : shortenstring(inp, MAXSHORTSTR))
939 #else
940 # define SHOWCMDINREPLY(inp) inp
941 # define SHOWSHRTCMDINREPLY(inp) shortenstring(inp, MAXSHORTSTR)
942 #endif
943
944 void
945 smtp(nullserver, d_flags, e)
946         char *volatile nullserver;
947         BITMAP256 d_flags;
948         register ENVELOPE *volatile e;
949 {
950         register char *volatile p;
951         register struct cmd *volatile c = NULL;
952         char *cmd;
953         auto ADDRESS *vrfyqueue;
954         ADDRESS *a;
955         volatile bool gothello;         /* helo command received */
956         bool vrfy;                      /* set if this is a vrfy command */
957         char *volatile protocol;        /* sending protocol */
958         char *volatile sendinghost;     /* sending hostname */
959         char *volatile peerhostname;    /* name of SMTP peer or "localhost" */
960         auto char *delimptr;
961         char *id;
962         volatile unsigned int n_badcmds = 0;    /* count of bad commands */
963         volatile unsigned int n_badrcpts = 0;   /* number of rejected RCPT */
964         volatile unsigned int n_verifies = 0;   /* count of VRFY/EXPN */
965         volatile unsigned int n_etrn = 0;       /* count of ETRN */
966         volatile unsigned int n_noop = 0;       /* count of NOOP/VERB/etc */
967         volatile unsigned int n_helo = 0;       /* count of HELO/EHLO */
968         bool ok;
969         volatile bool first;
970         volatile bool tempfail = false;
971         volatile time_t wt;             /* timeout after too many commands */
972         volatile time_t previous;       /* time after checksmtpattack() */
973         volatile bool lognullconnection = true;
974         register char *q;
975         SMTP_T smtp;
976         char *addr;
977         char *greetcode = "220";
978         const char *greetmsg = "not accepting messages";
979         char *hostname;                 /* my hostname ($j) */
980         QUEUE_CHAR *new;
981         char *args[MAXSMTPARGS];
982         char inp[MAXINPLINE];
983 #if MAXINPLINE < MAXLINE
984 # error "MAXINPLINE must NOT be less than MAXLINE"
985 #endif
986         char cmdbuf[MAXLINE];
987 #if SASL
988         sasl_conn_t *conn;
989         volatile bool sasl_ok;
990         volatile unsigned int n_auth = 0;       /* count of AUTH commands */
991         bool ismore;
992         int result;
993         volatile int authenticating;
994         char *user;
995         char *in, *out2;
996         char auth_user[MAX_AUTH_USER_LEN], auth_user_tmp[MAX_AUTH_USER_LEN];
997         unsigned int auth_user_len;
998 # if SASL >= 20000
999         char *auth_id = NULL;
1000         const char *out;
1001         sasl_ssf_t ext_ssf;
1002         char localip[60], remoteip[60];
1003 # else /* SASL >= 20000 */
1004         char *out;
1005         const char *errstr;
1006         sasl_external_properties_t ext_ssf;
1007         struct sockaddr_in saddr_l;
1008         struct sockaddr_in saddr_r;
1009 # endif /* SASL >= 20000 */
1010         sasl_security_properties_t ssp;
1011         sasl_ssf_t *ssf;
1012         unsigned int inlen, out2len;
1013         unsigned int outlen;
1014         char *volatile auth_type;
1015         char *mechlist;
1016         volatile unsigned int n_mechs;
1017         unsigned int len;
1018 #endif /* SASL */
1019         int r;
1020 #if STARTTLS
1021         int rfd, wfd;
1022         volatile bool tls_active = false;
1023         volatile bool smtps = bitnset(D_SMTPS, d_flags);
1024         bool gotostarttls = false;
1025         bool saveQuickAbort;
1026         bool saveSuprErrs;
1027         time_t tlsstart;
1028         int ssl_err, tlsret;
1029         int save_errno;
1030         extern int TLSsslidx;
1031 #endif /* STARTTLS */
1032         volatile unsigned long features;
1033 #if PIPELINING && _FFR_NO_PIPE
1034         int np_log = 0;
1035 #endif
1036         volatile time_t log_delay = (time_t) 0;
1037 #if MILTER
1038         volatile bool milter_cmd_done, milter_cmd_safe;
1039         volatile bool milter_rcpt_added, milter_cmd_fail;
1040         ADDRESS addr_st;
1041 # define p_addr_st      &addr_st
1042 #else /* MILTER */
1043 # define p_addr_st      NULL
1044 #endif /* MILTER */
1045         size_t inplen;
1046 #if _FFR_BADRCPT_SHUTDOWN
1047         int n_badrcpts_adj;
1048 #endif
1049         bool gotodoquit = false;
1050
1051         RESET_AUTH_FAIL_LOG_USER;
1052         smtp.sm_nrcpts = 0;
1053 #if MILTER
1054         smtp.sm_milterize = (nullserver == NULL);
1055         smtp.sm_milterlist = false;
1056         addr = NULL;
1057 #endif
1058
1059         /* setup I/O fd correctly for the SMTP server */
1060         setup_smtpd_io();
1061
1062 #if SM_HEAP_CHECK
1063         if (sm_debug_active(&DebugLeakSmtp, 1))
1064         {
1065                 sm_heap_newgroup();
1066                 sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
1067         }
1068 #endif /* SM_HEAP_CHECK */
1069
1070         /* XXX the rpool should be set when e is initialized in main() */
1071         e->e_rpool = sm_rpool_new_x(NULL);
1072         e->e_macro.mac_rpool = e->e_rpool;
1073
1074         settime(e);
1075         sm_getla();
1076         peerhostname = RealHostName;
1077         if (peerhostname == NULL)
1078                 peerhostname = "localhost";
1079         CurHostName = peerhostname;
1080         CurSmtpClient = macvalue('_', e);
1081         if (CurSmtpClient == NULL)
1082                 CurSmtpClient = CurHostName;
1083
1084         /* check_relay may have set discard bit, save for later */
1085         smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
1086
1087 #if PIPELINING
1088         /* auto-flush output when reading input */
1089         (void) sm_io_autoflush(InChannel, OutChannel);
1090 #endif
1091
1092         sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
1093
1094         maps_reset_chged("server:smtp");
1095
1096         /*
1097         **  Set default features for server.
1098         **
1099         **  Changing SRV_BARE_LF_421 | SRV_BARE_CR_421 below also
1100         **  requires changing srvfeatures() variant code.
1101         */
1102
1103         features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
1104                      bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
1105                 | (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
1106                 | (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
1107                         : (SRV_OFFER_EXPN
1108                           | (bitset(PRIV_NOVERB, PrivacyFlags)
1109                              ? SRV_NONE : SRV_OFFER_VERB)))
1110                 | ((bitset(PRIV_NORECEIPTS, PrivacyFlags) || !SendMIMEErrors)
1111                          ? SRV_NONE : SRV_OFFER_DSN)
1112 #if SASL
1113                 | (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
1114                 | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
1115                                                           : SRV_NONE)
1116 #endif /* SASL */
1117 #if PIPELINING
1118                 | SRV_OFFER_PIPE
1119 #endif
1120                 | SRV_BAD_PIPELINE
1121 #if STARTTLS
1122                 | (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
1123                 | (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
1124                                                        : SRV_VRFY_CLT)
1125 #endif
1126 #if USE_EAI
1127                 | (SMTP_UTF8 ? SRV_OFFER_EAI : 0)
1128 #endif
1129                 | SRV_REQ_CRLF | SRV_BARE_LF_421 | SRV_BARE_CR_421
1130                 ;
1131         if (nullserver == NULL)
1132         {
1133                 features = srvfeatures(e, CurSmtpClient, features);
1134                 if (bitset(SRV_TMP_FAIL, features))
1135                 {
1136                         if (LogLevel > 4)
1137                                 sm_syslog(LOG_ERR, NOQID,
1138                                           "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
1139                                           CurSmtpClient);
1140                         nullserver = "450 4.3.0 Please try again later.";
1141                 }
1142                 else
1143                 {
1144 #if PIPELINING && _FFR_NO_PIPE
1145                         if (bitset(SRV_NO_PIPE, features))
1146                         {
1147                                 /* for consistency */
1148                                 features &= ~SRV_OFFER_PIPE;
1149                         }
1150 #endif /* PIPELINING && _FFR_NO_PIPE */
1151 #if SASL
1152                         if (bitset(SRV_REQ_SEC, features))
1153                                 SASLOpts |= SASL_SEC_NOPLAINTEXT;
1154                         else
1155                                 SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
1156 #endif /* SASL */
1157                 }
1158         }
1159         else if (strncmp(nullserver, "421 ", 4) == 0)
1160         {
1161                 /* Can't use ("%s", ...) due to message() requirements */
1162                 message(nullserver);
1163                 gotodoquit = true;
1164                 goto cmdloop;
1165         }
1166
1167         e->e_features = features;
1168         hostname = macvalue('j', e);
1169 #if SASL
1170         if (AuthRealm == NULL)
1171                 AuthRealm = hostname;
1172         sasl_ok = bitset(SRV_OFFER_AUTH, features);
1173         n_mechs = 0;
1174         authenticating = SASL_NOT_AUTH;
1175
1176         /* SASL server new connection */
1177         if (sasl_ok)
1178         {
1179 # if SASL >= 20000
1180                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
1181                                          NULL, 0, &conn);
1182 # elif SASL > 10505
1183                 /* use empty realm: only works in SASL > 1.5.5 */
1184                 result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
1185 # else /* SASL >= 20000 */
1186                 /* use no realm -> realm is set to hostname by SASL lib */
1187                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
1188                                          &conn);
1189 # endif /* SASL >= 20000 */
1190                 sasl_ok = result == SASL_OK;
1191                 if (!sasl_ok)
1192                 {
1193                         if (LogLevel > 9)
1194                                 sm_syslog(LOG_WARNING, NOQID,
1195                                           "AUTH error: sasl_server_new failed=%d",
1196                                           result);
1197                 }
1198         }
1199         if (sasl_ok)
1200         {
1201                 /*
1202                 **  SASL set properties for sasl
1203                 **  set local/remote IP
1204                 **  XXX Cyrus SASL v1 only supports IPv4
1205                 **
1206                 **  XXX where exactly are these used/required?
1207                 **  Kerberos_v4
1208                 */
1209
1210 # if SASL >= 20000
1211                 localip[0] = remoteip[0] = '\0';
1212 #  if NETINET || NETINET6
1213                 in = macvalue(macid("{daemon_family}"), e);
1214                 if (in != NULL && (
1215 #   if NETINET6
1216                     strcmp(in, "inet6") == 0 ||
1217 #   endif
1218                     strcmp(in, "inet") == 0))
1219                 {
1220                         SOCKADDR_LEN_T addrsize;
1221                         SOCKADDR saddr_l;
1222                         SOCKADDR saddr_r;
1223
1224                         addrsize = sizeof(saddr_r);
1225                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1226                                                       NULL),
1227                                         (struct sockaddr *) &saddr_r,
1228                                         &addrsize) == 0)
1229                         {
1230                                 if (iptostring(&saddr_r, addrsize,
1231                                                remoteip, sizeof(remoteip)))
1232                                 {
1233                                         sasl_setprop(conn, SASL_IPREMOTEPORT,
1234                                                      remoteip);
1235                                 }
1236                                 addrsize = sizeof(saddr_l);
1237                                 if (getsockname(sm_io_getinfo(InChannel,
1238                                                               SM_IO_WHAT_FD,
1239                                                               NULL),
1240                                                 (struct sockaddr *) &saddr_l,
1241                                                 &addrsize) == 0)
1242                                 {
1243                                         if (iptostring(&saddr_l, addrsize,
1244                                                        localip,
1245                                                        sizeof(localip)))
1246                                         {
1247                                                 sasl_setprop(conn,
1248                                                              SASL_IPLOCALPORT,
1249                                                              localip);
1250                                         }
1251                                 }
1252                         }
1253                 }
1254 #  endif /* NETINET || NETINET6 */
1255 # else /* SASL >= 20000 */
1256 #  if NETINET
1257                 in = macvalue(macid("{daemon_family}"), e);
1258                 if (in != NULL && strcmp(in, "inet") == 0)
1259                 {
1260                         SOCKADDR_LEN_T addrsize;
1261
1262                         addrsize = sizeof(struct sockaddr_in);
1263                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1264                                                       NULL),
1265                                         (struct sockaddr *)&saddr_r,
1266                                         &addrsize) == 0)
1267                         {
1268                                 sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
1269                                 addrsize = sizeof(struct sockaddr_in);
1270                                 if (getsockname(sm_io_getinfo(InChannel,
1271                                                               SM_IO_WHAT_FD,
1272                                                               NULL),
1273                                                 (struct sockaddr *)&saddr_l,
1274                                                 &addrsize) == 0)
1275                                         sasl_setprop(conn, SASL_IP_LOCAL,
1276                                                      &saddr_l);
1277                         }
1278                 }
1279 #  endif /* NETINET */
1280 # endif /* SASL >= 20000 */
1281
1282                 auth_type = NULL;
1283                 mechlist = NULL;
1284                 user = NULL;
1285 # if 0
1286                 macdefine(&BlankEnvelope.e_macro, A_PERM,
1287                         macid("{auth_author}"), NULL);
1288 # endif
1289
1290                 /* set properties */
1291                 (void) memset(&ssp, '\0', sizeof(ssp));
1292
1293                 /* XXX should these be options settable via .cf ? */
1294                 /* ssp.min_ssf = 0; is default due to memset() */
1295                 ssp.max_ssf = MaxSLBits;
1296                 ssp.maxbufsize = MAXOUTLEN;
1297                 ssp.security_flags = SASLOpts & SASL_SEC_MASK;
1298                 sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
1299
1300                 if (sasl_ok)
1301                 {
1302                         /*
1303                         **  external security strength factor;
1304                         **      currently we have none so zero
1305                         */
1306
1307 # if SASL >= 20000
1308                         ext_ssf = 0;
1309                         auth_id = NULL;
1310                         sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
1311                                                  &ext_ssf) == SASL_OK) &&
1312                                    (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
1313                                                  auth_id) == SASL_OK));
1314 # else /* SASL >= 20000 */
1315                         ext_ssf.ssf = 0;
1316                         ext_ssf.auth_id = NULL;
1317                         sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
1318                                                &ext_ssf) == SASL_OK;
1319 # endif /* SASL >= 20000 */
1320                 }
1321                 if (sasl_ok)
1322                         n_mechs = saslmechs(conn, &mechlist);
1323         }
1324 #endif /* SASL */
1325
1326         (void) set_tls_rd_tmo(TimeOuts.to_nextcommand);
1327
1328 #if MILTER
1329         if (smtp.sm_milterize)
1330         {
1331                 char state;
1332
1333                 /* initialize mail filter connection */
1334                 smtp.sm_milterlist = milter_init(e, &state, &smtp.sm_milters);
1335                 switch (state)
1336                 {
1337                   case SMFIR_REJECT:
1338                         if (MilterLogLevel > 3)
1339                                 sm_syslog(LOG_INFO, e->e_id,
1340                                           "Milter: initialization failed, rejecting commands");
1341                         greetcode = "554";
1342                         nullserver = "Command rejected";
1343                         smtp.sm_milterize = false;
1344                         break;
1345
1346                   case SMFIR_TEMPFAIL:
1347                         if (MilterLogLevel > 3)
1348                                 sm_syslog(LOG_INFO, e->e_id,
1349                                           "Milter: initialization failed, temp failing commands");
1350                         tempfail = true;
1351                         smtp.sm_milterize = false;
1352                         break;
1353
1354                   case SMFIR_SHUTDOWN:
1355                         if (MilterLogLevel > 3)
1356                                 sm_syslog(LOG_INFO, e->e_id,
1357                                           "Milter: initialization failed, closing connection");
1358                         tempfail = true;
1359                         smtp.sm_milterize = false;
1360                         message("421 4.7.0 %s closing connection",
1361                                         MyHostName);
1362
1363                         /* arrange to ignore send list */
1364                         e->e_sendqueue = NULL;
1365                         lognullconnection = false;
1366                         gotodoquit = true;
1367                         goto cmdloop;
1368                 }
1369         }
1370
1371         if (smtp.sm_milterlist && smtp.sm_milterize &&
1372             !bitset(EF_DISCARD, e->e_flags))
1373         {
1374                 char state;
1375                 char *response;
1376
1377                 q = macvalue(macid("{client_name}"), e);
1378                 SM_ASSERT(q != NULL || OpMode == MD_SMTP);
1379                 if (q == NULL)
1380                         q = "localhost";
1381                 response = milter_connect(q, RealHostAddr, e, &state);
1382                 switch (state)
1383                 {
1384 # if _FFR_MILTER_CONNECT_REPLYCODE
1385                   case SMFIR_REPLYCODE:
1386                         if (*response == '5')
1387                         {
1388                                 if (MilterLogLevel > 3)
1389                                         sm_syslog(LOG_INFO, e->e_id,
1390                                                   "Milter: connect: host=%s, addr=%s, reject=%s",
1391                                                   peerhostname,
1392                                                   anynet_ntoa(&RealHostAddr),
1393                                                   response);
1394                                 greetcode = "554"; /* Required by 2821 3.1 */
1395                                 nullserver = newstr(response);
1396                                 if (strlen(nullserver) > 4)
1397                                 {
1398                                         int skip;
1399
1400                                         greetmsg = nullserver + 4;
1401
1402                                         /* skip over enhanced status code */
1403                                         skip = isenhsc(greetmsg, ' ');
1404                                         if (skip > 0)
1405                                                 greetmsg += skip + 1;
1406                                 }
1407                                 smtp.sm_milterize = false;
1408                                 break;
1409                         }
1410                         else if (strncmp(response, "421 ", 4) == 0)
1411                         {
1412                                 int skip;
1413                                 const char *msg = response + 4;
1414
1415                                 if (MilterLogLevel > 3)
1416                                         sm_syslog(LOG_INFO, e->e_id,
1417                                                   "Milter: connect: host=%s, addr=%s, shutdown=%s",
1418                                                   peerhostname,
1419                                                   anynet_ntoa(&RealHostAddr),
1420                                                   response);
1421                                 tempfail = true;
1422                                 smtp.sm_milterize = false;
1423
1424                                 /* skip over enhanced status code */
1425                                 skip = isenhsc(msg, ' ');
1426                                 if (skip > 0)
1427                                         msg += skip + 1;
1428                                 message("421 %s %s", MyHostName, msg);
1429
1430                                 /* arrange to ignore send list */
1431                                 e->e_sendqueue = NULL;
1432                                 gotodoquit = true;
1433                                 goto cmdloop;
1434                         }
1435                         else
1436                         {
1437                                 if (MilterLogLevel > 3)
1438                                         sm_syslog(LOG_INFO, e->e_id,
1439                                                   "Milter: connect: host=%s, addr=%s, temp failing commands=%s",
1440                                                   peerhostname,
1441                                                   anynet_ntoa(&RealHostAddr),
1442                                                   response);
1443                                 /*tempfail = true;*/
1444                                 smtp.sm_milterize = false;
1445                                 nullserver = newstr(response);
1446                                 break;
1447                         }
1448
1449 # else /* _FFR_MILTER_CONNECT_REPLYCODE */
1450                   case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */
1451 # endif /* _FFR_MILTER_CONNECT_REPLYCODE */
1452                   case SMFIR_REJECT:
1453                         if (MilterLogLevel > 3)
1454                                 sm_syslog(LOG_INFO, e->e_id,
1455                                           "Milter: connect: host=%s, addr=%s, rejecting commands",
1456                                           peerhostname,
1457                                           anynet_ntoa(&RealHostAddr));
1458                         greetcode = "554";
1459                         nullserver = "Command rejected";
1460                         smtp.sm_milterize = false;
1461                         break;
1462
1463                   case SMFIR_TEMPFAIL:
1464                         if (MilterLogLevel > 3)
1465                                 sm_syslog(LOG_INFO, e->e_id,
1466                                           "Milter: connect: host=%s, addr=%s, temp failing commands",
1467                                           peerhostname,
1468                                           anynet_ntoa(&RealHostAddr));
1469                         tempfail = true;
1470                         smtp.sm_milterize = false;
1471                         break;
1472
1473                   case SMFIR_SHUTDOWN:
1474                         if (MilterLogLevel > 3)
1475                                 sm_syslog(LOG_INFO, e->e_id,
1476                                           "Milter: connect: host=%s, addr=%s, shutdown",
1477                                           peerhostname,
1478                                           anynet_ntoa(&RealHostAddr));
1479                         tempfail = true;
1480                         smtp.sm_milterize = false;
1481                         message("421 4.7.0 %s closing connection",
1482                                         MyHostName);
1483
1484                         /* arrange to ignore send list */
1485                         e->e_sendqueue = NULL;
1486                         gotodoquit = true;
1487                         goto cmdloop;
1488                 }
1489                 if (response != NULL)
1490                         sm_free(response);
1491         }
1492 #endif /* MILTER */
1493
1494         /*
1495         **  Broken proxies and SMTP slammers
1496         **  push data without waiting, catch them
1497         */
1498
1499         if (
1500 #if STARTTLS
1501             !smtps &&
1502 #endif
1503             *greetcode == '2' && nullserver == NULL)
1504         {
1505                 time_t msecs = 0;
1506                 char **pvp;
1507                 char pvpbuf[PSBUFSIZE];
1508
1509                 /* Ask the rulesets how long to pause */
1510                 pvp = NULL;
1511                 r = rscap("greet_pause", peerhostname,
1512                           anynet_ntoa(&RealHostAddr), e,
1513                           &pvp, pvpbuf, sizeof(pvpbuf));
1514                 if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
1515                     (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
1516                 {
1517                         msecs = strtol(pvp[1], NULL, 10);
1518                 }
1519
1520                 if (msecs > 0)
1521                 {
1522                         struct timeval *tp; /* total pause */
1523
1524                         /* Obey RFC 2821: 4.5.3.2: 220 timeout of 5 minutes (300 seconds) */
1525                         if (msecs >= 300000)
1526                                 msecs = 300000;
1527
1528                         /* check if data is on the socket during the pause */
1529                         if ((tp = channel_readable(InChannel, msecs)) != NULL)
1530                         {
1531                                 greetcode = "554";
1532                                 nullserver = "Command rejected";
1533                                 sm_syslog(LOG_INFO, e->e_id,
1534                                           "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds",
1535                                           peerhostname,
1536                                           anynet_ntoa(&RealHostAddr),
1537                                           (int) tp->tv_sec +
1538                                                 (tp->tv_usec >= 500000 ? 1 : 0)
1539                                          );
1540                         }
1541                 }
1542         }
1543
1544 #if STARTTLS
1545         /* If this an smtps connection, start TLS now */
1546         if (smtps)
1547         {
1548                 if (!tls_ok_srv || srv_ctx == NULL)
1549                 {
1550                         sm_syslog(LOG_ERR, e->e_id,
1551                                 "smtps: TLS not available, exiting");
1552                         exit(EX_CONFIG);
1553                 }
1554                 Errors = 0;
1555                 first = true;
1556                 gothello = false;
1557                 smtp.sm_gotmail = false;
1558                 gotostarttls = true;
1559                 goto cmdloop;
1560         }
1561
1562   greeting:
1563
1564 #endif /* STARTTLS */
1565
1566         /* output the first line, inserting "ESMTP" as second word */
1567         if (*greetcode == '5')
1568                 (void) sm_snprintf(inp, sizeof(inp), "%s %s", hostname,
1569                                    greetmsg);
1570         else
1571                 expand(SmtpGreeting, inp, sizeof(inp), e);
1572
1573         p = strchr(inp, '\n');
1574         if (p != NULL)
1575                 *p++ = '\0';
1576         id = strchr(inp, ' ');
1577         if (id == NULL)
1578                 id = &inp[strlen(inp)];
1579         if (p == NULL)
1580                 (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1581                          "%s %%.*s ESMTP%%s", greetcode);
1582         else
1583                 (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1584                          "%s-%%.*s ESMTP%%s", greetcode);
1585         message(cmdbuf, (int) (id - inp), inp, id);
1586
1587         /* output remaining lines */
1588         while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
1589         {
1590                 *p++ = '\0';
1591                 if (SM_ISSPACE(*id))
1592                         id++;
1593                 (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s");
1594                 message(cmdbuf, id);
1595         }
1596         if (id != NULL)
1597         {
1598                 if (SM_ISSPACE(*id))
1599                         id++;
1600                 (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s");
1601                 message(cmdbuf, id);
1602         }
1603
1604         protocol = NULL;
1605         sendinghost = macvalue('s', e);
1606
1607         /* If quarantining by a connect/ehlo action, save between messages */
1608         if (e->e_quarmsg == NULL)
1609                 smtp.sm_quarmsg = NULL;
1610         else
1611                 smtp.sm_quarmsg = newstr(e->e_quarmsg);
1612
1613         /* sendinghost's storage must outlive the current envelope */
1614         if (sendinghost != NULL)
1615                 sendinghost = sm_strdup_x(sendinghost);
1616         first = true;
1617         gothello = false;
1618         smtp.sm_gotmail = false;
1619         for (;;)
1620         {
1621
1622   cmdloop:
1623             SM_TRY
1624             {
1625                 QuickAbort = false;
1626                 HoldErrs = false;
1627                 SuprErrs = false;
1628                 LogUsrErrs = false;
1629                 OnlyOneError = true;
1630                 e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
1631 #if MILTER
1632                 milter_cmd_fail = false;
1633 #endif
1634
1635                 /* setup for the read */
1636                 e->e_to = NULL;
1637                 Errors = 0;
1638                 FileName = NULL;
1639                 (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
1640
1641                 if (gotodoquit)
1642                 {
1643                         gotodoquit = false;
1644                         goto doquit;
1645                 }
1646 #if STARTTLS
1647                 if (gotostarttls)
1648                 {
1649                         gotostarttls = false;
1650                         goto starttls;
1651                 }
1652 #endif
1653
1654                 /* read the input line */
1655                 SmtpPhase = "server cmd read";
1656                 sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
1657
1658                 /* handle errors */
1659                 if (sm_io_error(OutChannel) ||
1660                     (p = sfgets(inp, sizeof(inp), InChannel,
1661                                 TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
1662                 {
1663                         char *d;
1664
1665                         d = macvalue(macid("{daemon_name}"), e);
1666                         if (d == NULL)
1667                                 d = "stdin";
1668                         /* end of file, just die */
1669                         disconnect(1, e);
1670
1671 #if MILTER
1672                         /* close out milter filters */
1673                         milter_quit(e);
1674 #endif
1675
1676                         message("421 4.4.1 %s Lost input channel from %s",
1677                                 MyHostName, CurSmtpClient);
1678                         if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
1679                                 sm_syslog(LOG_NOTICE, e->e_id,
1680                                           "lost input channel from %s to %s after %s",
1681                                           CurSmtpClient, d,
1682                                           (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
1683                         /*
1684                         **  If have not accepted mail (DATA), do not bounce
1685                         **  bad addresses back to sender.
1686                         */
1687
1688                         if (bitset(EF_CLRQUEUE, e->e_flags))
1689                                 e->e_sendqueue = NULL;
1690                         goto doquit;
1691                 }
1692
1693                 /* also used by "proxy" check below */
1694                 inplen = strlen(inp);
1695 #if SASL
1696                 /*
1697                 **  SMTP AUTH requires accepting any length,
1698                 **  at least for challenge/response. However, not imposing
1699                 **  a limit is a bad idea (denial of service).
1700                 */
1701
1702                 if (authenticating != SASL_PROC_AUTH
1703                     && sm_strncasecmp(inp, "AUTH ", 5) != 0
1704                     && inplen > MAXLINE)
1705                 {
1706                         message("421 4.7.0 %s Command too long, possible attack %s",
1707                                 MyHostName, CurSmtpClient);
1708                         sm_syslog(LOG_INFO, e->e_id,
1709                                   "%s: SMTP violation, input too long: %lu",
1710                                   CurSmtpClient, (unsigned long) inplen);
1711                         goto doquit;
1712                 }
1713 #endif /* SASL */
1714
1715                 if (first || bitset(SRV_NO_HTTP_CMD, features))
1716                 {
1717                         size_t cmdlen;
1718                         int idx;
1719                         char *http_cmd;
1720                         static char *http_cmds[] = { "GET", "POST",
1721                                                      "CONNECT", "USER", NULL };
1722
1723                         for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
1724                              idx++)
1725                         {
1726                                 cmdlen = strlen(http_cmd);
1727                                 if (cmdlen < inplen &&
1728                                     sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
1729                                     SM_ISSPACE(inp[cmdlen]))
1730                                 {
1731                                         /* Open proxy, drop it */
1732                                         message("421 4.7.0 %s %s %s",
1733                                                 MyHostName,
1734                                                 first ? "Rejecting open proxy"
1735                                                         : "HTTP command",
1736                                                 CurSmtpClient);
1737                                         sm_syslog(LOG_INFO, e->e_id,
1738                                                   "%s: probable open proxy: command=%.40s",
1739                                                   CurSmtpClient, inp);
1740                                         goto doquit;
1741                                 }
1742                         }
1743                         first = false;
1744                 }
1745
1746                 /* clean up end of line */
1747                 fixcrlf(inp, true);
1748
1749 #if PIPELINING && _FFR_NO_PIPE
1750                 /*
1751                 **  if there is more input and pipelining is disabled:
1752                 **      delay ... (and maybe discard the input?)
1753                 */
1754
1755                 if (bitset(SRV_NO_PIPE, features) &&
1756                     sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
1757                 {
1758                         if (++np_log < 3)
1759                                 sm_syslog(LOG_INFO, NOQID,
1760                                           "unauthorized PIPELINING, sleeping, relay=%.100s",
1761                                            CurSmtpClient);
1762                         sleep(1);
1763                 }
1764 #endif /* PIPELINING && _FFR_NO_PIPE */
1765
1766 #if SASL
1767                 if (authenticating == SASL_PROC_AUTH)
1768                 {
1769 # if 0
1770                         if (*inp == '\0')
1771                         {
1772                                 authenticating = SASL_NOT_AUTH;
1773                                 message("501 5.5.2 missing input");
1774                                 RESET_SASLCONN;
1775                                 continue;
1776                         }
1777 # endif /* 0 */
1778                         if (*inp == '*' && *(inp + 1) == '\0')
1779                         {
1780                                 authenticating = SASL_NOT_AUTH;
1781
1782                                 /* RFC 2554 4. */
1783                                 message("501 5.0.0 AUTH aborted");
1784                                 RESET_SASLCONN;
1785                                 continue;
1786                         }
1787
1788                         /* could this be shorter? XXX */
1789 # if SASL >= 20000
1790                         in = xalloc(strlen(inp) + 1);
1791                         result = sasl_decode64(inp, strlen(inp), in,
1792                                                strlen(inp), &inlen);
1793 # else /* SASL >= 20000 */
1794                         out = xalloc(strlen(inp));
1795                         result = sasl_decode64(inp, strlen(inp), out, &outlen);
1796 # endif /* SASL >= 20000 */
1797                         if (result != SASL_OK)
1798                         {
1799                                 authenticating = SASL_NOT_AUTH;
1800
1801                                 /* RFC 2554 4. */
1802                                 message("501 5.5.4 cannot decode AUTH parameter %s",
1803                                         inp);
1804 # if SASL >= 20000
1805                                 sm_free(in);
1806 # endif
1807                                 RESET_SASLCONN;
1808                                 continue;
1809                         }
1810
1811 # if SASL >= 20000
1812                         SET_AUTH_USER_TMP(in, inlen);
1813                         result = sasl_server_step(conn, in, inlen,
1814                                                   &out, &outlen);
1815                         sm_free(in);
1816 # else /* SASL >= 20000 */
1817                         SET_AUTH_USER_TMP(out, outlen);
1818                         result = sasl_server_step(conn, out, outlen,
1819                                                   &out, &outlen, &errstr);
1820 # endif /* SASL >= 20000 */
1821
1822                         /* get an OK if we're done */
1823                         if (result == SASL_OK)
1824                         {
1825   authenticated:
1826                                 message("235 2.0.0 OK Authenticated");
1827                                 authenticating = SASL_IS_AUTH;
1828                                 macdefine(&BlankEnvelope.e_macro, A_TEMP,
1829                                         macid("{auth_type}"), auth_type);
1830
1831 # if SASL >= 20000
1832                                 user = macvalue(macid("{auth_authen}"), e);
1833
1834                                 /* get security strength (features) */
1835                                 result = sasl_getprop(conn, SASL_SSF,
1836                                                       (const void **) &ssf);
1837 # else /* SASL >= 20000 */
1838                                 result = sasl_getprop(conn, SASL_USERNAME,
1839                                                       (void **)&user);
1840                                 if (result != SASL_OK)
1841                                 {
1842                                         user = "";
1843                                         macdefine(&BlankEnvelope.e_macro,
1844                                                   A_PERM,
1845                                                   macid("{auth_authen}"), NULL);
1846                                 }
1847                                 else
1848                                 {
1849                                         macdefine(&BlankEnvelope.e_macro,
1850                                                   A_TEMP,
1851                                                   macid("{auth_authen}"),
1852                                                   xtextify(user, "<>\")"));
1853                                 }
1854
1855 #  if 0
1856                                 /* get realm? */
1857                                 sasl_getprop(conn, SASL_REALM, (void **) &data);
1858 #  endif
1859
1860                                 /* get security strength (features) */
1861                                 result = sasl_getprop(conn, SASL_SSF,
1862                                                       (void **) &ssf);
1863 # endif /* SASL >= 20000 */
1864                                 if (result != SASL_OK)
1865                                 {
1866                                         macdefine(&BlankEnvelope.e_macro,
1867                                                   A_PERM,
1868                                                   macid("{auth_ssf}"), "0");
1869                                         ssf = NULL;
1870                                 }
1871                                 else
1872                                 {
1873                                         char pbuf[8];
1874
1875                                         (void) sm_snprintf(pbuf, sizeof(pbuf),
1876                                                            "%u", *ssf);
1877                                         macdefine(&BlankEnvelope.e_macro,
1878                                                   A_TEMP,
1879                                                   macid("{auth_ssf}"), pbuf);
1880                                         if (tTd(95, 8))
1881                                                 sm_dprintf("AUTH auth_ssf: %u\n",
1882                                                            *ssf);
1883                                 }
1884
1885                                 protocol = GET_PROTOCOL();
1886
1887                                 /*
1888                                 **  Only switch to encrypted connection
1889                                 **  if a security layer has been negotiated
1890                                 */
1891
1892                                 if (ssf != NULL && *ssf > 0)
1893                                 {
1894                                         int tmo;
1895
1896                                         /*
1897                                         **  Convert I/O layer to use SASL.
1898                                         **  If the call fails, the connection
1899                                         **  is aborted.
1900                                         */
1901
1902                                         tmo = TimeOuts.to_datablock * 1000;
1903                                         if (sfdcsasl(&InChannel, &OutChannel,
1904                                                      conn, tmo) == 0)
1905                                         {
1906                                                 /* restart dialogue */
1907                                                 n_helo = 0;
1908 # if PIPELINING
1909                                                 (void) sm_io_autoflush(InChannel,
1910                                                                        OutChannel);
1911 # endif /* PIPELINING */
1912                                         }
1913                                         else
1914                                                 syserr("503 5.3.3 SASL TLS failed");
1915                                 }
1916
1917                                 /* NULL pointer ok since it's our function */
1918                                 if (LogLevel > 8)
1919                                         sm_syslog(LOG_INFO, NOQID,
1920                                                   "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
1921                                                   CurSmtpClient,
1922                                                   shortenstring(user, 128),
1923                                                   auth_type, *ssf);
1924                         }
1925                         else if (result == SASL_CONTINUE)
1926                         {
1927                                 SET_AUTH_USER;
1928
1929                                 len = ENC64LEN(outlen);
1930                                 out2 = xalloc(len);
1931                                 result = sasl_encode64(out, outlen, out2, len,
1932                                                        &out2len);
1933                                 if (result != SASL_OK)
1934                                 {
1935                                         /* correct code? XXX */
1936                                         /* 454 Temp. authentication failure */
1937                                         message("454 4.5.4 Internal error: unable to encode64");
1938                                         if (LogLevel > 5)
1939                                                 sm_syslog(LOG_WARNING, e->e_id,
1940                                                           "AUTH encode64 error [%d for \"%s\"], relay=%.100s",
1941                                                           result, out,
1942                                                           CurSmtpClient);
1943                                         /* start over? */
1944                                         authenticating = SASL_NOT_AUTH;
1945                                 }
1946                                 else
1947                                 {
1948                                         message("334 %s", out2);
1949                                         if (tTd(95, 2))
1950                                                 sm_dprintf("AUTH continue: msg='%s' len=%u\n",
1951                                                            out2, out2len);
1952                                 }
1953 # if SASL >= 20000
1954                                 sm_free(out2);
1955 # endif
1956                         }
1957                         else
1958                         {
1959
1960 # if SASL >= 20000
1961 #  define SASLERR sasl_errdetail(conn)
1962 # else
1963 #  define SASLERR errstr == NULL ? "" : errstr
1964 # endif
1965 #define LOGAUTHFAIL     \
1966         do      \
1967         {       \
1968                 SET_AUTH_USER_CONDITIONALLY     \
1969                 message("535 5.7.0 authentication failed");     \
1970                 if (LogLevel >= 9)      \
1971                         sm_syslog(LOG_WARNING, e->e_id, \
1972                                   "AUTH failure (%s): %s (%d) %s%s%.*s, relay=%.100s",  \
1973                                   (auth_type != NULL) ? auth_type : "unknown", \
1974                                   sasl_errstring(result, NULL, NULL),   \
1975                                   result,       \
1976                                   SASLERR, \
1977                                   LOG_AUTH_FAIL_USER,   \
1978                                   CurSmtpClient);       \
1979                 RESET_SASLCONN; \
1980         } while (0)
1981
1982
1983                                 LOGAUTHFAIL;
1984                                 authenticating = SASL_NOT_AUTH;
1985                         }
1986                 }
1987                 else
1988                 {
1989                         /* don't want to do any of this if authenticating */
1990 #endif /* SASL */
1991
1992                 /* echo command to transcript */
1993                 if (e->e_xfp != NULL)
1994                         (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
1995                                              "<<< %s\n", inp);
1996
1997                 if (LogLevel > 14)
1998                         sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
1999
2000                 /* break off command */
2001                 for (p = inp; SM_ISSPACE(*p); p++)
2002                         continue;
2003                 cmd = cmdbuf;
2004                 while (*p != '\0' &&
2005                        !(SM_ISSPACE(*p)) &&
2006                        cmd < &cmdbuf[sizeof(cmdbuf) - 2])
2007                         *cmd++ = *p++;
2008                 *cmd = '\0';
2009
2010                 /* throw away leading whitespace */
2011                 SKIP_SPACE(p);
2012
2013                 /* decode command */
2014                 for (c = CmdTab; c->cmd_name != NULL; c++)
2015                 {
2016                         if (SM_STRCASEEQ(c->cmd_name, cmdbuf))
2017                                 break;
2018                 }
2019
2020                 /* reset errors */
2021                 errno = 0;
2022
2023                 /* check whether a "non-null" command has been used */
2024                 switch (c->cmd_code)
2025                 {
2026 #if SASL
2027                   case CMDAUTH:
2028                         /* avoid information leak; take first two words? */
2029                         q = "AUTH";
2030                         break;
2031 #endif /* SASL */
2032
2033                   case CMDMAIL:
2034                   case CMDEXPN:
2035                   case CMDVRFY:
2036                   case CMDETRN:
2037                         lognullconnection = false;
2038                         /* FALLTHROUGH */
2039                   default:
2040                         q = inp;
2041                         break;
2042                 }
2043
2044                 if (e->e_id == NULL)
2045                         sm_setproctitle(true, e, "%s: %.80s",
2046                                         CurSmtpClient, q);
2047                 else
2048                         sm_setproctitle(true, e, "%s %s: %.80s",
2049                                         qid_printname(e),
2050                                         CurSmtpClient, q);
2051
2052                 /*
2053                 **  Process command.
2054                 **
2055                 **      If we are running as a null server, return 550
2056                 **      to almost everything.
2057                 */
2058
2059                 if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
2060                 {
2061                         switch (c->cmd_code)
2062                         {
2063                           case CMDQUIT:
2064                           case CMDHELO:
2065                           case CMDEHLO:
2066                           case CMDNOOP:
2067                           case CMDRSET:
2068                           case CMDERROR:
2069                                 /* process normally */
2070                                 break;
2071
2072                           case CMDETRN:
2073                                 if (bitnset(D_ETRNONLY, d_flags) &&
2074                                     nullserver == NULL)
2075                                         break;
2076                                 DELAY_CONN("ETRN");
2077                                 /* FALLTHROUGH */
2078
2079                           default:
2080 #if MAXBADCOMMANDS > 0
2081                                 /* theoretically this could overflow */
2082                                 if (nullserver != NULL &&
2083                                     ++n_badcmds > MAXBADCOMMANDS)
2084                                 {
2085                                         message("421 4.7.0 %s Too many bad commands; closing connection",
2086                                                 MyHostName);
2087
2088                                         /* arrange to ignore send list */
2089                                         e->e_sendqueue = NULL;
2090                                         goto doquit;
2091                                 }
2092 #endif /* MAXBADCOMMANDS > 0 */
2093                                 if (nullserver != NULL)
2094                                 {
2095                                         if (ISSMTPREPLY(nullserver))
2096                                         {
2097                                                 /* Can't use ("%s", ...) due to usrerr() requirements */
2098                                                 usrerr(nullserver);
2099                                         }
2100                                         else
2101                                         {
2102                                                 usrerr("550 5.0.0 %s",
2103                                                        nullserver);
2104                                         }
2105                                 }
2106                                 else
2107                                         usrerr("452 4.4.5 Insufficient disk space; try again later");
2108                                 continue;
2109                         }
2110                 }
2111
2112                 switch (c->cmd_code)
2113                 {
2114 #if SASL
2115                   case CMDAUTH: /* sasl */
2116                         DELAY_CONN("AUTH");
2117                         if (!sasl_ok || n_mechs <= 0)
2118                         {
2119                                 message("503 5.3.3 AUTH not available");
2120                                 break;
2121                         }
2122                         if (auth_active)
2123                         {
2124                                 message("503 5.5.0 Already Authenticated");
2125                                 break;
2126                         }
2127                         if (smtp.sm_gotmail)
2128                         {
2129                                 message("503 5.5.0 AUTH not permitted during a mail transaction");
2130                                 break;
2131                         }
2132                         if (tempfail)
2133                         {
2134                                 if (LogLevel > 9)
2135                                         sm_syslog(LOG_INFO, e->e_id,
2136                                                   "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
2137                                                   p, CurSmtpClient);
2138                                 usrerr("454 4.3.0 Please try again later");
2139                                 break;
2140                         }
2141
2142                         ismore = false;
2143
2144                         /* crude way to avoid crack attempts */
2145                         STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
2146                                                         true, "AUTH", e));
2147
2148                         /* make sure mechanism (p) is a valid string */
2149                         for (q = p; *q != '\0' && isascii(*q); q++)
2150                         {
2151                                 if (isspace(*q))
2152                                 {
2153                                         *q = '\0';
2154                                         while (*++q != '\0' && SM_ISSPACE(*q))
2155                                                 continue;
2156                                         *(q - 1) = '\0';
2157                                         ismore = (*q != '\0');
2158                                         break;
2159                                 }
2160                         }
2161
2162                         if (*p == '\0')
2163                         {
2164                                 message("501 5.5.2 AUTH mechanism must be specified");
2165                                 break;
2166                         }
2167
2168                         /* check whether mechanism is available */
2169                         if (iteminlist(p, mechlist, " ") == NULL)
2170                         {
2171                                 message("504 5.3.3 AUTH mechanism %.32s not available",
2172                                         p);
2173                                 break;
2174                         }
2175
2176                         /*
2177                         **  RFC 2554 4.
2178                         **  Unlike a zero-length client answer to a
2179                         **  334 reply, a zero- length initial response
2180                         **  is sent as a single equals sign ("=").
2181                         */
2182
2183                         if (ismore && *q == '=' && *(q + 1) == '\0')
2184                         {
2185                                 /* will be free()d, don't use in=""; */
2186                                 in = xalloc(1);
2187                                 *in = '\0';
2188                                 inlen = 0;
2189                         }
2190                         else if (ismore)
2191                         {
2192                                 /* could this be shorter? XXX */
2193 # if SASL >= 20000
2194                                 in = xalloc(strlen(q) + 1);
2195                                 result = sasl_decode64(q, strlen(q), in,
2196                                                        strlen(q), &inlen);
2197 # else /* SASL >= 20000 */
2198                                 in = sm_rpool_malloc(e->e_rpool, strlen(q));
2199                                 result = sasl_decode64(q, strlen(q), in,
2200                                                        &inlen);
2201 # endif /* SASL >= 20000 */
2202
2203                                 if (result != SASL_OK)
2204                                 {
2205                                         message("501 5.5.4 cannot BASE64 decode '%s'",
2206                                                 q);
2207                                         if (LogLevel > 5)
2208                                                 sm_syslog(LOG_WARNING, e->e_id,
2209                                                           "AUTH decode64 error [%d for \"%s\"], relay=%.100s",
2210                                                           result, q,
2211                                                           CurSmtpClient);
2212                                         /* start over? */
2213                                         authenticating = SASL_NOT_AUTH;
2214 # if SASL >= 20000
2215                                         sm_free(in);
2216 # endif
2217                                         in = NULL;
2218                                         inlen = 0;
2219                                         break;
2220                                 }
2221                                 SET_AUTH_USER_TMP(in, inlen);
2222                         }
2223                         else
2224                         {
2225                                 in = NULL;
2226                                 inlen = 0;
2227                         }
2228
2229                         /* see if that auth type exists */
2230 # if SASL >= 20000
2231                         result = sasl_server_start(conn, p, in, inlen,
2232                                                    &out, &outlen);
2233                         SM_FREE(in);
2234 # else /* SASL >= 20000 */
2235                         result = sasl_server_start(conn, p, in, inlen,
2236                                                    &out, &outlen, &errstr);
2237 # endif /* SASL >= 20000 */
2238
2239                         if (p != NULL)
2240                                 auth_type = newstr(p);
2241                         if (result != SASL_OK && result != SASL_CONTINUE)
2242                         {
2243                                 LOGAUTHFAIL;
2244                                 break;
2245                         }
2246
2247                         if (result == SASL_OK)
2248                         {
2249                                 /* ugly, but same code */
2250                                 goto authenticated;
2251                                 /* authenticated by the initial response */
2252                         }
2253
2254                         SET_AUTH_USER;
2255
2256                         /* len is at least 2 */
2257                         len = ENC64LEN(outlen);
2258                         out2 = xalloc(len);
2259                         result = sasl_encode64(out, outlen, out2, len,
2260                                                &out2len);
2261
2262                         if (result != SASL_OK)
2263                         {
2264                                 message("454 4.5.4 Temporary authentication failure");
2265                                 if (LogLevel > 5)
2266                                         sm_syslog(LOG_WARNING, e->e_id,
2267                                                   "AUTH encode64 error [%d for \"%s\"]",
2268                                                   result, out);
2269
2270                                 /* start over? */
2271                                 authenticating = SASL_NOT_AUTH;
2272                                 RESET_SASLCONN;
2273                         }
2274                         else
2275                         {
2276                                 message("334 %s", out2);
2277                                 authenticating = SASL_PROC_AUTH;
2278                         }
2279 # if SASL >= 20000
2280                         sm_free(out2);
2281 # endif
2282                         break;
2283 #endif /* SASL */
2284
2285 #if STARTTLS
2286                   case CMDSTLS: /* starttls */
2287                         DELAY_CONN("STARTTLS");
2288                         if (*p != '\0')
2289                         {
2290                                 message("501 5.5.2 Syntax error (no parameters allowed)");
2291                                 break;
2292                         }
2293                         if (!bitset(SRV_OFFER_TLS, features))
2294                         {
2295                                 message("503 5.5.0 TLS not available");
2296                                 break;
2297                         }
2298   starttls:
2299                         if (!tls_ok_srv)
2300                         {
2301                                 message("454 4.3.3 TLS not available after start");
2302                                 break;
2303                         }
2304                         if (smtp.sm_gotmail)
2305                         {
2306                                 message("503 5.5.0 TLS not permitted during a mail transaction");
2307                                 break;
2308                         }
2309                         if (tempfail)
2310                         {
2311                                 if (LogLevel > 9)
2312                                         sm_syslog(LOG_INFO, e->e_id,
2313                                                   "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
2314                                                   p, CurSmtpClient);
2315                                 usrerr("454 4.7.0 Please try again later");
2316                                 break;
2317                         }
2318                         if (!TLS_set_engine(SSLEngine, false))
2319                         {
2320                                 sm_syslog(LOG_ERR, NOQID,
2321                                           "STARTTLS=server, engine=%s, TLS_set_engine=failed",
2322                                           SSLEngine);
2323                                 tls_ok_srv = false;
2324                                 message("454 4.3.3 TLS not available right now");
2325                                 break;
2326                         }
2327 # if TLS_NO_RSA
2328                         /*
2329                         **  XXX do we need a temp key ?
2330                         */
2331 # endif
2332
2333 # if TLS_VRFY_PER_CTX
2334                         /*
2335                         **  Note: this sets the verification globally
2336                         **  (per SSL_CTX)
2337                         **  it's ok since it applies only to one transaction
2338                         */
2339
2340                         TLS_VERIFY_CLIENT();
2341 # endif /* TLS_VRFY_PER_CTX */
2342
2343 #define SMTLSFAILED                             \
2344         do {                                    \
2345                 SM_SSL_FREE(srv_ssl);           \
2346                 goto tls_done;                  \
2347         } while (0)
2348
2349                         if (srv_ssl != NULL)
2350                                 SSL_clear(srv_ssl);
2351                         else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
2352                         {
2353                                 message("454 4.3.3 TLS not available: error generating SSL handle");
2354                                 tlslogerr(LOG_WARNING, 8, "server");
2355                                 goto tls_done;
2356                         }
2357 # if DANE
2358                         tlsi_ctx.tlsi_dvc.dane_vrfy_dane_enabled = false;
2359                         tlsi_ctx.tlsi_dvc.dane_vrfy_chk = DANE_NEVER;
2360 # endif
2361                         if (get_tls_se_features(e, srv_ssl, &tlsi_ctx, true)
2362                             != EX_OK)
2363                         {
2364                                 /* do not offer too much info to client */
2365                                 message("454 4.3.3 TLS currently not available");
2366                                 SMTLSFAILED;
2367                         }
2368                         r = SSL_set_ex_data(srv_ssl, TLSsslidx, &tlsi_ctx);
2369                         if (0 == r)
2370                         {
2371                                 if (LogLevel > 5)
2372                                 {
2373                                         sm_syslog(LOG_ERR, NOQID,
2374                                                 "STARTTLS=server, error: SSL_set_ex_data failed=%d, TLSsslidx=%d",
2375                                                 r, TLSsslidx);
2376                                         tlslogerr(LOG_WARNING, 9, "server");
2377                                 }
2378                                 SMTLSFAILED;
2379                         }
2380
2381 # if !TLS_VRFY_PER_CTX
2382                         /*
2383                         **  this could be used if it were possible to set
2384                         **  verification per SSL (connection)
2385                         **  not just per SSL_CTX (global)
2386                         */
2387
2388                         TLS_VERIFY_CLIENT();
2389 # endif /* !TLS_VRFY_PER_CTX */
2390
2391                         rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
2392                         wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
2393
2394                         if (rfd < 0 || wfd < 0 ||
2395                             SSL_set_rfd(srv_ssl, rfd) <= 0 ||
2396                             SSL_set_wfd(srv_ssl, wfd) <= 0)
2397                         {
2398                                 message("454 4.3.3 TLS not available: error set fd");
2399                                 SMTLSFAILED;
2400                         }
2401                         if (!smtps)
2402                                 message("220 2.0.0 Ready to start TLS");
2403 # if PIPELINING
2404                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2405 # endif
2406
2407                         SSL_set_accept_state(srv_ssl);
2408
2409                         tlsstart = curtime();
2410
2411                         ssl_err = SSL_ERROR_WANT_READ;
2412                         save_errno = 0;
2413                         do
2414                         {
2415                                 tlsret = tls_retry(srv_ssl, rfd, wfd, tlsstart,
2416                                                 TimeOuts.to_starttls, ssl_err,
2417                                                 "server");
2418                                 if (tlsret <= 0)
2419                                 {
2420                                         if (LogLevel > 5)
2421                                         {
2422                                                 unsigned long l;
2423                                                 const char *sr;
2424
2425                                                 l = ERR_peek_error();
2426                                                 sr = ERR_reason_error_string(l);
2427
2428                                                 sm_syslog(LOG_WARNING, NOQID,
2429                                                           "STARTTLS=server, error: accept failed=%d, reason=%s, SSL_error=%d, errno=%d, retry=%d, relay=%.100s",
2430                                                           r, sr == NULL ? "unknown"
2431                                                                         : sr,
2432                                                           ssl_err, save_errno,
2433                                                           tlsret, CurSmtpClient);
2434                                                 tlslogerr(LOG_WARNING, 9, "server");
2435                                         }
2436                                         tls_ok_srv = false;
2437                                         SM_SSL_FREE(srv_ssl);
2438
2439                                         /*
2440                                         **  according to the next draft of
2441                                         **  RFC 2487 the connection should
2442                                         **  be dropped
2443                                         **
2444                                         **  arrange to ignore any current
2445                                         **  send list
2446                                         */
2447
2448                                         e->e_sendqueue = NULL;
2449                                         goto doquit;
2450                                 }
2451
2452                                 r = SSL_accept(srv_ssl);
2453                                 save_errno = 0;
2454                                 if (r <= 0)
2455                                         ssl_err = SSL_get_error(srv_ssl, r);
2456                         } while (r <= 0);
2457
2458                         /* ignore return code for now, it's in {verify} */
2459                         (void) tls_get_info(srv_ssl, true,
2460                                             CurSmtpClient,
2461                                             &BlankEnvelope.e_macro,
2462                                             bitset(SRV_VRFY_CLT, features));
2463
2464                         /*
2465                         **  call Stls_client to find out whether
2466                         **  to accept the connection from the client
2467                         */
2468
2469                         saveQuickAbort = QuickAbort;
2470                         saveSuprErrs = SuprErrs;
2471                         SuprErrs = true;
2472                         QuickAbort = false;
2473                         if (rscheck("tls_client",
2474                                      macvalue(macid("{verify}"), e),
2475                                      "STARTTLS", e,
2476                                      RSF_RMCOMM|RSF_COUNT,
2477                                      5, NULL, NOQID, NULL, NULL) != EX_OK ||
2478                             Errors > 0)
2479                         {
2480                                 extern char MsgBuf[];
2481
2482                                 if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
2483                                         nullserver = newstr(MsgBuf);
2484                                 else
2485                                         nullserver = "503 5.7.0 Authentication required.";
2486                         }
2487                         QuickAbort = saveQuickAbort;
2488                         SuprErrs = saveSuprErrs;
2489
2490                         tls_ok_srv = false;     /* don't offer STARTTLS again */
2491                         first = true;
2492                         n_helo = 0;
2493 # if SASL
2494                         if (sasl_ok)
2495                         {
2496                                 int cipher_bits;
2497                                 bool verified;
2498                                 char *s, *v, *c;
2499
2500                                 s = macvalue(macid("{cipher_bits}"), e);
2501                                 v = macvalue(macid("{verify}"), e);
2502                                 c = macvalue(macid("{cert_subject}"), e);
2503                                 verified = (v != NULL && strcmp(v, "OK") == 0);
2504                                 if (s != NULL && (cipher_bits = atoi(s)) > 0)
2505                                 {
2506 #  if SASL >= 20000
2507                                         ext_ssf = cipher_bits;
2508                                         auth_id = verified ? c : NULL;
2509                                         sasl_ok = ((sasl_setprop(conn,
2510                                                         SASL_SSF_EXTERNAL,
2511                                                         &ext_ssf) == SASL_OK) &&
2512                                                    (sasl_setprop(conn,
2513                                                         SASL_AUTH_EXTERNAL,
2514                                                         auth_id) == SASL_OK));
2515 #  else /* SASL >= 20000 */
2516                                         ext_ssf.ssf = cipher_bits;
2517                                         ext_ssf.auth_id = verified ? c : NULL;
2518                                         sasl_ok = sasl_setprop(conn,
2519                                                         SASL_SSF_EXTERNAL,
2520                                                         &ext_ssf) == SASL_OK;
2521 #  endif /* SASL >= 20000 */
2522                                         mechlist = NULL;
2523                                         if (sasl_ok)
2524                                                 n_mechs = saslmechs(conn,
2525                                                                     &mechlist);
2526                                 }
2527                         }
2528 # endif /* SASL */
2529
2530                         /* switch to secure connection */
2531                         if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
2532                         {
2533                                 tls_active = true;
2534 # if PIPELINING
2535                                 (void) sm_io_autoflush(InChannel, OutChannel);
2536 # endif
2537                         }
2538                         else
2539                         {
2540                                 /*
2541                                 **  XXX this is an internal error
2542                                 **  how to deal with it?
2543                                 **  we can't generate an error message
2544                                 **  since the other side switched to an
2545                                 **  encrypted layer, but we could not...
2546                                 **  just "hang up"?
2547                                 */
2548
2549                                 nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
2550                                 syserr("STARTTLS: can't switch to encrypted layer");
2551                         }
2552                   tls_done:
2553                         if (smtps)
2554                         {
2555                                 if (tls_active)
2556                                         goto greeting;
2557                                 else
2558                                         goto doquit;
2559                         }
2560                         break;
2561 #endif /* STARTTLS */
2562
2563                   case CMDHELO:         /* hello -- introduce yourself */
2564                   case CMDEHLO:         /* extended hello */
2565                         DELAY_CONN("EHLO");
2566                         if (c->cmd_code == CMDEHLO)
2567                         {
2568                                 protocol = GET_PROTOCOL();
2569                                 SmtpPhase = "server EHLO";
2570                         }
2571                         else
2572                         {
2573                                 protocol = "SMTP";
2574                                 SmtpPhase = "server HELO";
2575                         }
2576
2577                         /* avoid denial-of-service */
2578                         STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
2579                                                         true, "HELO/EHLO", e));
2580
2581                         /*
2582                         **  Despite the fact that the name indicates this
2583                         **  a PIPELINE related feature, do not enclose
2584                         **  it in #if PIPELINING so we can protect SMTP
2585                         **  servers not compiled with PIPELINE support
2586                         **  from transaction stuffing.
2587                         */
2588
2589                         /* check if data is on the socket before the EHLO reply */
2590                         if (bitset(SRV_BAD_PIPELINE, features) &&
2591                             sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
2592                         {
2593                                 sm_syslog(LOG_INFO, e->e_id,
2594                                         "rejecting %s from %s [%s] due to traffic before response",
2595                                         SmtpPhase, CurHostName,
2596                                         anynet_ntoa(&RealHostAddr));
2597                                 usrerr("554 5.5.0 SMTP protocol error");
2598                                 nullserver = "Command rejected";
2599 #if MILTER
2600                                 smtp.sm_milterize = false;
2601 #endif
2602                                 break;
2603                         }
2604
2605 #if 0
2606                         /* RFC2821 4.1.4 allows duplicate HELO/EHLO */
2607                         /* check for duplicate HELO/EHLO per RFC 1651 4.2 */
2608                         if (gothello)
2609                         {
2610                                 usrerr("503 %s Duplicate HELO/EHLO",
2611                                        MyHostName);
2612                                 break;
2613                         }
2614 #endif /* 0 */
2615
2616                         /* check for valid domain name (re 1123 5.2.5) */
2617                         if (*p == '\0' && !AllowBogusHELO)
2618                         {
2619                                 usrerr("501 %s requires domain address",
2620                                         cmdbuf);
2621                                 break;
2622                         }
2623
2624                         /* check for long domain name (hides Received: info) */
2625                         if (strlen(p) > MAXNAME) /* EAI:ok:EHLO name must be ASCII */
2626                         {
2627                                 usrerr("501 Invalid domain name");
2628                                 if (LogLevel > 9)
2629                                         sm_syslog(LOG_INFO, CurEnv->e_id,
2630                                                   "invalid domain name (too long) from %s",
2631                                                   CurSmtpClient);
2632                                 break;
2633                         }
2634
2635                         ok = true;
2636                         for (q = p; *q != '\0'; q++)
2637                         {
2638                                 if (!isascii(*q))
2639                                         break;
2640                                 if (isalnum(*q))
2641                                         continue;
2642                                 if (isspace(*q))
2643                                 {
2644                                         *q = '\0';
2645
2646                                         /* only complain if strict check */
2647                                         ok = AllowBogusHELO;
2648
2649                                         /* allow trailing whitespace */
2650                                         while (!ok && *++q != '\0' &&
2651                                                isspace(*q))
2652                                                 ;
2653                                         if (*q == '\0')
2654                                                 ok = true;
2655                                         break;
2656                                 }
2657                                 if (strchr("[].-_#:", *q) == NULL)
2658                                         break;
2659                         }
2660
2661                         if (*q == '\0' && ok)
2662                         {
2663                                 q = "pleased to meet you";
2664                                 sendinghost = sm_strdup_x(p);
2665                         }
2666                         else if (!AllowBogusHELO)
2667                         {
2668                                 usrerr("501 Invalid domain name");
2669                                 if (LogLevel > 9)
2670                                         sm_syslog(LOG_INFO, CurEnv->e_id,
2671                                                   "invalid domain name (%s) from %.100s",
2672                                                   p, CurSmtpClient);
2673                                 break;
2674                         }
2675                         else
2676                         {
2677                                 q = "accepting invalid domain name";
2678                         }
2679
2680                         if (gothello || smtp.sm_gotmail)
2681                                 CLEAR_STATE(cmdbuf);
2682
2683 #if MILTER
2684                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2685                             !bitset(EF_DISCARD, e->e_flags))
2686                         {
2687                                 char state;
2688                                 char *response;
2689
2690                                 response = milter_helo(p, e, &state);
2691                                 switch (state)
2692                                 {
2693                                   case SMFIR_REJECT:
2694                                         if (MilterLogLevel > 3)
2695                                                 sm_syslog(LOG_INFO, e->e_id,
2696                                                           "Milter: helo=%s, reject=Command rejected",
2697                                                           p);
2698                                         nullserver = "Command rejected";
2699                                         smtp.sm_milterize = false;
2700                                         break;
2701
2702                                   case SMFIR_TEMPFAIL:
2703                                         if (MilterLogLevel > 3)
2704                                                 sm_syslog(LOG_INFO, e->e_id,
2705                                                           "Milter: helo=%s, reject=%s",
2706                                                           p, MSG_TEMPFAIL);
2707                                         tempfail = true;
2708                                         smtp.sm_milterize = false;
2709                                         break;
2710
2711                                   case SMFIR_REPLYCODE:
2712                                         if (MilterLogLevel > 3)
2713                                                 sm_syslog(LOG_INFO, e->e_id,
2714                                                           "Milter: helo=%s, reject=%s",
2715                                                           p, response);
2716                                         if (strncmp(response, "421 ", 4) != 0
2717                                             && strncmp(response, "421-", 4) != 0)
2718                                         {
2719                                                 nullserver = newstr(response);
2720                                                 smtp.sm_milterize = false;
2721                                                 break;
2722                                         }
2723                                         /* FALLTHROUGH */
2724
2725                                   case SMFIR_SHUTDOWN:
2726                                         if (MilterLogLevel > 3 &&
2727                                             response == NULL)
2728                                                 sm_syslog(LOG_INFO, e->e_id,
2729                                                           "Milter: helo=%s, reject=421 4.7.0 %s closing connection",
2730                                                           p, MyHostName);
2731                                         tempfail = true;
2732                                         smtp.sm_milterize = false;
2733                                         if (response != NULL)
2734                                         {
2735                                                 /* Can't use ("%s", ...) due to usrerr() requirements */
2736                                                 usrerr(response);
2737                                         }
2738                                         else
2739                                         {
2740                                                 message("421 4.7.0 %s closing connection",
2741                                                         MyHostName);
2742                                         }
2743                                         /* arrange to ignore send list */
2744                                         e->e_sendqueue = NULL;
2745                                         lognullconnection = false;
2746                                         goto doquit;
2747                                 }
2748                                 if (response != NULL)
2749                                         sm_free(response);
2750
2751                                 /*
2752                                 **  If quarantining by a connect/ehlo action,
2753                                 **  save between messages
2754                                 */
2755
2756                                 if (smtp.sm_quarmsg == NULL &&
2757                                     e->e_quarmsg != NULL)
2758                                         smtp.sm_quarmsg = newstr(e->e_quarmsg);
2759                         }
2760 #endif /* MILTER */
2761                         gothello = true;
2762
2763                         /* print HELO response message */
2764                         if (c->cmd_code != CMDEHLO)
2765                         {
2766                                 message("250 %s Hello %s, %s",
2767                                         MyHostName, CurSmtpClient, q);
2768                                 break;
2769                         }
2770
2771                         message("250-%s Hello %s, %s",
2772                                 MyHostName, CurSmtpClient, q);
2773
2774                         /* offer ENHSC even for nullserver */
2775                         if (nullserver != NULL)
2776                         {
2777                                 message("250 ENHANCEDSTATUSCODES");
2778                                 break;
2779                         }
2780
2781                         /*
2782                         **  print EHLO features list
2783                         **
2784                         **  Note: If you change this list,
2785                         **        remember to update 'helpfile'
2786                         */
2787
2788                         message("250-ENHANCEDSTATUSCODES");
2789 #if PIPELINING
2790                         if (bitset(SRV_OFFER_PIPE, features))
2791                                 message("250-PIPELINING");
2792 #endif
2793                         if (bitset(SRV_OFFER_EXPN, features))
2794                         {
2795                                 message("250-EXPN");
2796                                 if (bitset(SRV_OFFER_VERB, features))
2797                                         message("250-VERB");
2798                         }
2799 #if MIME8TO7
2800                         message("250-8BITMIME");
2801 #endif
2802                         if (MaxMessageSize > 0)
2803                                 message("250-SIZE %ld", MaxMessageSize);
2804                         else
2805                                 message("250-SIZE");
2806 #if DSN
2807                         if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
2808                                 message("250-DSN");
2809 #endif
2810 #if USE_EAI
2811                         if (bitset(SRV_OFFER_EAI, features))
2812                                 message("250-SMTPUTF8");
2813 #endif
2814                         if (bitset(SRV_OFFER_ETRN, features))
2815                                 message("250-ETRN");
2816 #if SASL
2817                         if (sasl_ok && mechlist != NULL && *mechlist != '\0')
2818                                 message("250-AUTH %s", mechlist);
2819 #endif
2820 #if STARTTLS
2821                         if (tls_ok_srv && bitset(SRV_OFFER_TLS, features))
2822                                 message("250-STARTTLS");
2823 #endif
2824                         if (DeliverByMin > 0)
2825                                 message("250-DELIVERBY %ld",
2826                                         (long) DeliverByMin);
2827                         else if (DeliverByMin == 0)
2828                                 message("250-DELIVERBY");
2829
2830                         /* < 0: no deliver-by */
2831
2832                         message("250 HELP");
2833                         break;
2834
2835                   case CMDMAIL:         /* mail -- designate sender */
2836                         SmtpPhase = "server MAIL";
2837                         DELAY_CONN("MAIL");
2838
2839                         /* check for validity of this command */
2840                         if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
2841                         {
2842                                 usrerr("503 5.0.0 Polite people say HELO first");
2843                                 break;
2844                         }
2845                         if (smtp.sm_gotmail)
2846                         {
2847                                 usrerr("503 5.5.0 Sender already specified");
2848                                 break;
2849                         }
2850 #if SASL
2851                         if (bitset(SRV_REQ_AUTH, features) &&
2852                             authenticating != SASL_IS_AUTH)
2853                         {
2854                                 usrerr("530 5.7.0 Authentication required");
2855                                 break;
2856                         }
2857 #endif /* SASL */
2858
2859                         p = skipword(p, "from");
2860                         if (p == NULL)
2861                                 break;
2862                         maps_reset_chged("server:MAIL");
2863                         if (tempfail)
2864                         {
2865                                 if (LogLevel > 9)
2866                                         sm_syslog(LOG_INFO, e->e_id,
2867                                                   "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2868                                                   p, CurSmtpClient);
2869                                 /* Can't use ("%s", ...) due to usrerr() requirements */
2870                                 usrerr(MSG_TEMPFAIL);
2871                                 break;
2872                         }
2873
2874                         /* make sure we know who the sending host is */
2875                         if (sendinghost == NULL)
2876                                 sendinghost = peerhostname;
2877
2878
2879 #if SM_HEAP_CHECK
2880                         if (sm_debug_active(&DebugLeakSmtp, 1))
2881                         {
2882                                 sm_heap_newgroup();
2883                                 sm_dprintf("smtp() heap group #%d\n",
2884                                         sm_heap_group());
2885                         }
2886 #endif /* SM_HEAP_CHECK */
2887
2888                         if (Errors > 0)
2889                                 goto undo_no_pm;
2890                         if (!gothello)
2891                         {
2892                                 auth_warning(e, "%s didn't use HELO protocol",
2893                                              CurSmtpClient);
2894                         }
2895 #ifdef PICKY_HELO_CHECK
2896                         if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2897                             (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2898                              sm_strcasecmp(sendinghost, MyHostName) != 0))
2899                         {
2900                                 auth_warning(e, "Host %s claimed to be %s",
2901                                              CurSmtpClient, sendinghost);
2902                         }
2903 #endif /* PICKY_HELO_CHECK */
2904
2905                         if (protocol == NULL)
2906                                 protocol = "SMTP";
2907                         macdefine(&e->e_macro, A_PERM, 'r', protocol);
2908                         macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2909
2910                         if (Errors > 0)
2911                                 goto undo_no_pm;
2912                         smtp.sm_nrcpts = 0;
2913                         n_badrcpts = 0;
2914                         macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2915                         macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2916                         macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
2917                                 "0");
2918                         e->e_flags |= EF_CLRQUEUE;
2919                         sm_setproctitle(true, e, "%s %s: %.80s",
2920                                         qid_printname(e),
2921                                         CurSmtpClient, inp);
2922
2923                         /* do the processing */
2924                     SM_TRY
2925                     {
2926                         extern char *FullName;
2927 #if _FFR_8BITENVADDR
2928                         char *origp;
2929                         char iaddr[MAXLINE * 2];
2930                         int len;
2931 #else
2932 # define origp  p
2933 #endif
2934
2935                         QuickAbort = true;
2936                         SM_FREE(FullName);
2937 #if _FFR_8BITENVADDR
2938                         len = sizeof(iaddr);
2939                         origp = p;
2940
2941                         /* HACK!!!! p is more than the address! */
2942                         p = quote_internal_chars(p, iaddr, &len, NULL);
2943 #endif
2944
2945                         /* must parse sender first */
2946                         delimptr = NULL;
2947                         setsender(p, e, &delimptr, ' ', false);
2948                         if (delimptr != NULL && *delimptr != '\0')
2949                         {
2950                                 *delimptr++ = '\0';
2951 #if _FFR_8BITENVADDR
2952                                 len = sizeof(iaddr) - (delimptr - iaddr);
2953                                 (void) dequote_internal_chars(delimptr, delimptr, len);
2954                                 sep_args(delimptr, origp, e->e_id, p);
2955 #endif
2956                         }
2957                         if (Errors > 0)
2958                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2959
2960                         /* Successfully set e_from, allow logging */
2961                         e->e_flags |= EF_LOGSENDER;
2962
2963                         /* put resulting triple from parseaddr() into macros */
2964                         if (e->e_from.q_mailer != NULL)
2965                                  macdefine(&e->e_macro, A_PERM,
2966                                         macid("{mail_mailer}"),
2967                                         e->e_from.q_mailer->m_name);
2968                         else
2969                                  macdefine(&e->e_macro, A_PERM,
2970                                         macid("{mail_mailer}"), NULL);
2971                         if (e->e_from.q_host != NULL)
2972                                 macdefine(&e->e_macro, A_PERM,
2973                                         macid("{mail_host}"),
2974                                         e->e_from.q_host);
2975                         else
2976                                 macdefine(&e->e_macro, A_PERM,
2977                                         macid("{mail_host}"), "localhost");
2978                         if (e->e_from.q_user != NULL)
2979                                 macdefine(&e->e_macro, A_PERM,
2980                                         macid("{mail_addr}"),
2981                                         e->e_from.q_user);
2982                         else
2983                                 macdefine(&e->e_macro, A_PERM,
2984                                         macid("{mail_addr}"), NULL);
2985                         if (Errors > 0)
2986                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2987
2988                         /* check for possible spoofing */
2989                         if (RealUid != 0 && OpMode == MD_SMTP &&
2990                             !wordinclass(RealUserName, 't') &&
2991                             (!bitnset(M_LOCALMAILER,
2992                                       e->e_from.q_mailer->m_flags) ||
2993                              strcmp(e->e_from.q_user, RealUserName) != 0))
2994                         {
2995                                 auth_warning(e, "%s owned process doing -bs",
2996                                         RealUserName);
2997                         }
2998
2999                         /* reset to default value */
3000                         e->e_flags &= ~EF_7BITBODY;
3001
3002                         /* now parse ESMTP arguments */
3003                         e->e_msgsize = 0;
3004                         addr = p;
3005                         parse_esmtp_args(e, NULL, origp, delimptr, "MAIL", args,
3006                                         mail_esmtp_args);
3007                         if (Errors > 0)
3008                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3009
3010 #if USE_EAI
3011                         if (e->e_smtputf8)
3012                         {
3013                                 protocol = GET_PROTOCOL();
3014                                 macdefine(&e->e_macro, A_PERM, 'r', protocol);
3015                         }
3016
3017                         /* UTF8 addresses are only legal with SMTPUTF8 */
3018 /* XXX different error if SMTPUTF8 is not enabled? */
3019                         CHECK_UTF8_ADDR(e->e_from.q_paddr, q);
3020                         if (q != NULL)
3021                         {
3022                                 usrerr(q);
3023                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3024                         }
3025 #endif
3026
3027 #if SASL
3028 # if _FFR_AUTH_PASSING
3029                         /* set the default AUTH= if the sender didn't */
3030                         if (e->e_auth_param == NULL)
3031                         {
3032                                 /* XXX only do this for an MSA? */
3033                                 e->e_auth_param = macvalue(macid("{auth_authen}"),
3034                                                            e);
3035                                 if (e->e_auth_param == NULL)
3036                                         e->e_auth_param = "<>";
3037
3038                                 /*
3039                                 **  XXX should we invoke Strust_auth now?
3040                                 **  authorizing as the client that just
3041                                 **  authenticated, so we'll trust implicitly
3042                                 */
3043                         }
3044 # endif /* _FFR_AUTH_PASSING */
3045 #endif /* SASL */
3046
3047                         /* do config file checking of the sender */
3048                         macdefine(&e->e_macro, A_PERM,
3049                                 macid("{addr_type}"), "e s");
3050 #if _FFR_MAIL_MACRO
3051                         /* make the "real" sender address available */
3052                         macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
3053                                   e->e_from.q_paddr);
3054 #endif
3055                         if (rscheck("check_mail", addr,
3056                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
3057                                     NULL, e->e_id, NULL, NULL) != EX_OK ||
3058                             Errors > 0)
3059                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3060                         macdefine(&e->e_macro, A_PERM,
3061                                   macid("{addr_type}"), NULL);
3062
3063                         if (MaxMessageSize > 0 &&
3064                             (e->e_msgsize > MaxMessageSize ||
3065                              e->e_msgsize < 0))
3066                         {
3067                                 usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
3068                                         MaxMessageSize);
3069                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3070                         }
3071
3072                         /*
3073                         **  XXX always check whether there is at least one fs
3074                         **  with enough space?
3075                         **  However, this may not help much: the queue group
3076                         **  selection may later on select a FS that hasn't
3077                         **  enough space.
3078                         */
3079
3080                         if ((NumFileSys == 1 || NumQueue == 1) &&
3081                             !enoughdiskspace(e->e_msgsize, e)
3082 #if _FFR_ANY_FREE_FS
3083                             && !filesys_free(e->e_msgsize)
3084 #endif
3085                            )
3086                         {
3087                                 /*
3088                                 **  We perform this test again when the
3089                                 **  queue directory is selected, in collect.
3090                                 */
3091
3092                                 usrerr("452 4.4.5 Insufficient disk space; try again later");
3093                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3094                         }
3095                         if (Errors > 0)
3096                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3097
3098                         LogUsrErrs = true;
3099 #if MILTER
3100                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3101                             !bitset(EF_DISCARD, e->e_flags))
3102                         {
3103                                 char state;
3104                                 char *response;
3105
3106                                 response = milter_envfrom(args, e, &state);
3107                                 MILTER_REPLY("from");
3108                         }
3109 #endif /* MILTER */
3110                         if (Errors > 0)
3111                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3112
3113                         message("250 2.1.0 Sender ok");
3114                         smtp.sm_gotmail = true;
3115                     }
3116                     SM_EXCEPT(exc, "[!F]*")
3117                     {
3118                         /*
3119                         **  An error occurred while processing a MAIL command.
3120                         **  Jump to the common error handling code.
3121                         */
3122
3123                         sm_exc_free(exc);
3124                         goto undo_no_pm;
3125                     }
3126                     SM_END_TRY
3127                         break;
3128
3129                   undo_no_pm:
3130                         e->e_flags &= ~EF_PM_NOTIFY;
3131                   undo:
3132                         break;
3133
3134                   case CMDRCPT:         /* rcpt -- designate recipient */
3135                         DELAY_CONN("RCPT");
3136                         macdefine(&e->e_macro, A_PERM,
3137                                 macid("{rcpt_mailer}"), NULL);
3138                         macdefine(&e->e_macro, A_PERM,
3139                                 macid("{rcpt_host}"), NULL);
3140                         macdefine(&e->e_macro, A_PERM,
3141                                 macid("{rcpt_addr}"), NULL);
3142 #if MILTER
3143                         (void) memset(&addr_st, '\0', sizeof(addr_st));
3144                         a = NULL;
3145                         milter_rcpt_added = false;
3146                         smtp.sm_e_nrcpts_orig = e->e_nrcpts;
3147 #endif
3148 #if _FFR_BADRCPT_SHUTDOWN
3149                         /*
3150                         **  hack to deal with hack, see below:
3151                         **  n_badrcpts is increased if limit is reached.
3152                         */
3153
3154                         n_badrcpts_adj = (BadRcptThrottle > 0 &&
3155                                           n_badrcpts > BadRcptThrottle &&
3156                                           LogLevel > 5)
3157                                           ? n_badrcpts - 1 : n_badrcpts;
3158                         if (BadRcptShutdown > 0 &&
3159                             n_badrcpts_adj >= BadRcptShutdown &&
3160                             (BadRcptShutdownGood == 0 ||
3161                              smtp.sm_nrcpts == 0 ||
3162                              (n_badrcpts_adj * 100 /
3163                               (smtp.sm_nrcpts + n_badrcpts) >=
3164                               BadRcptShutdownGood)))
3165                         {
3166                                 if (LogLevel > 5)
3167                                         sm_syslog(LOG_INFO, e->e_id,
3168                                                   "%s: Possible SMTP RCPT flood, shutting down connection.",
3169                                                   CurSmtpClient);
3170                                 message("421 4.7.0 %s Too many bad recipients; closing connection",
3171                                 MyHostName);
3172
3173                                 /* arrange to ignore any current send list */
3174                                 e->e_sendqueue = NULL;
3175                                 goto doquit;
3176                         }
3177 #endif /* _FFR_BADRCPT_SHUTDOWN */
3178                         if (BadRcptThrottle > 0 &&
3179                             n_badrcpts >= BadRcptThrottle)
3180                         {
3181                                 if (LogLevel > 5 &&
3182                                     n_badrcpts == BadRcptThrottle)
3183                                 {
3184                                         sm_syslog(LOG_INFO, e->e_id,
3185                                                   "%s: Possible SMTP RCPT flood, throttling.",
3186                                                   CurSmtpClient);
3187
3188                                         /* To avoid duplicated message */
3189                                         n_badrcpts++;
3190                                 }
3191                                 NBADRCPTS;
3192
3193                                 /*
3194                                 **  Don't use exponential backoff for now.
3195                                 **  Some systems will open more connections
3196                                 **  and actually overload the receiver even
3197                                 **  more.
3198                                 */
3199
3200                                 (void) sleep(BadRcptThrottleDelay);
3201                         }
3202                         if (!smtp.sm_gotmail)
3203                         {
3204                                 usrerr("503 5.0.0 Need MAIL before RCPT");
3205                                 break;
3206                         }
3207                         SmtpPhase = "server RCPT";
3208                     SM_TRY
3209                     {
3210 #if _FFR_8BITENVADDR
3211                         char iaddr[MAXLINE * 2];
3212                         int len;
3213                         char *origp;
3214 #endif
3215
3216                         QuickAbort = true;
3217                         LogUsrErrs = true;
3218
3219                         /* limit flooding of our machine */
3220                         if (MaxRcptPerMsg > 0 &&
3221                             smtp.sm_nrcpts >= MaxRcptPerMsg)
3222                         {
3223                                 /* sleep(1); / * slow down? */
3224                                 usrerr("452 4.5.3 Too many recipients");
3225                                 goto rcpt_done;
3226                         }
3227
3228                         if (!SM_IS_INTERACTIVE(e->e_sendmode)
3229 #if _FFR_DM_ONE
3230                             && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode)
3231 #endif
3232                            )
3233                                 e->e_flags |= EF_VRFYONLY;
3234
3235 #if MILTER
3236                         /*
3237                         **  Do not expand recipients at RCPT time (in the call
3238                         **  to recipient()) if a milter can delete or reject
3239                         **  a RCPT.  If they are expanded, it is impossible
3240                         **  for removefromlist() to figure out the expanded
3241                         **  members of the original recipient and mark them
3242                         **  as QS_DONTSEND.
3243                         */
3244
3245                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3246                               !bitset(EF_DISCARD, e->e_flags) &&
3247                             (smtp.sm_milters.mis_flags &
3248                              (MIS_FL_DEL_RCPT|MIS_FL_REJ_RCPT)) != 0)
3249                                 e->e_flags |= EF_VRFYONLY;
3250                         milter_cmd_done = false;
3251                         milter_cmd_safe = false;
3252 #endif /* MILTER */
3253
3254                         p = skipword(p, "to");
3255                         if (p == NULL)
3256                                 goto rcpt_done;
3257                         macdefine(&e->e_macro, A_PERM,
3258                                 macid("{addr_type}"), "e r");
3259 #if _FFR_8BITENVADDR
3260                         len = sizeof(iaddr);
3261                         origp = p;
3262
3263                         /* HACK!!!! p is more than the address! */
3264                         p = quote_internal_chars(p, iaddr, &len, NULL);
3265 #endif
3266                         a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
3267                                       e, true);
3268                         macdefine(&e->e_macro, A_PERM,
3269                                 macid("{addr_type}"), NULL);
3270                         if (Errors > 0)
3271                                 goto rcpt_done;
3272                         if (a == NULL)
3273                         {
3274                                 usrerr("501 5.0.0 Missing recipient");
3275                                 goto rcpt_done;
3276                         }
3277 #if USE_EAI
3278                         CHECK_UTF8_ADDR(a->q_paddr, q);
3279                         if (q != NULL)
3280                         {
3281                                 usrerr(q);
3282                                 goto rcpt_done;
3283                         }
3284 #endif
3285
3286                         if (delimptr != NULL && *delimptr != '\0')
3287                         {
3288                                 *delimptr++ = '\0';
3289 #if _FFR_8BITENVADDR
3290                                 len = sizeof(iaddr) - (delimptr - iaddr);
3291                                 (void) dequote_internal_chars(delimptr, delimptr, len);
3292                                 sep_args(delimptr, origp, e->e_id, p);
3293 #endif
3294                         }
3295
3296                         /* put resulting triple from parseaddr() into macros */
3297                         if (a->q_mailer != NULL)
3298                                 macdefine(&e->e_macro, A_PERM,
3299                                         macid("{rcpt_mailer}"),
3300                                         a->q_mailer->m_name);
3301                         else
3302                                 macdefine(&e->e_macro, A_PERM,
3303                                         macid("{rcpt_mailer}"), NULL);
3304                         if (a->q_host != NULL)
3305                                 macdefine(&e->e_macro, A_PERM,
3306                                         macid("{rcpt_host}"), a->q_host);
3307                         else
3308                                 macdefine(&e->e_macro, A_PERM,
3309                                         macid("{rcpt_host}"), "localhost");
3310                         if (a->q_user != NULL)
3311                                 macdefine(&e->e_macro, A_PERM,
3312                                         macid("{rcpt_addr}"), a->q_user);
3313                         else
3314                                 macdefine(&e->e_macro, A_PERM,
3315                                         macid("{rcpt_addr}"), NULL);
3316                         if (Errors > 0)
3317                                 goto rcpt_done;
3318
3319                         /* now parse ESMTP arguments */
3320                         addr = sm_rpool_strdup_x(e->e_rpool, p);
3321                         parse_esmtp_args(e, a, origp, delimptr, "RCPT", args,
3322                                         rcpt_esmtp_args);
3323                         if (Errors > 0)
3324                                 goto rcpt_done;
3325
3326 #if MILTER
3327                         /*
3328                         **  rscheck() can trigger an "exception"
3329                         **  in which case the execution continues at
3330                         **  SM_EXCEPT(exc, "[!F]*")
3331                         **  This means milter_cmd_safe is not set
3332                         **  and hence milter is not invoked.
3333                         **  Would it be "safe" to change that, i.e., use
3334                         **  milter_cmd_safe = true;
3335                         **  here so a milter is informed (if requested)
3336                         **  about RCPTs that are rejected by check_rcpt?
3337                         */
3338 # if _FFR_MILTER_CHECK_REJECTIONS_TOO
3339                         milter_cmd_safe = true;
3340 # endif
3341 #endif
3342
3343                         /* do config file checking of the recipient */
3344                         macdefine(&e->e_macro, A_PERM,
3345                                 macid("{addr_type}"), "e r");
3346                         if (rscheck("check_rcpt", addr,
3347                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
3348                                     NULL, e->e_id, p_addr_st, NULL) != EX_OK ||
3349                             Errors > 0)
3350                                 goto rcpt_done;
3351                         macdefine(&e->e_macro, A_PERM,
3352                                 macid("{addr_type}"), NULL);
3353
3354                         /* If discarding, don't bother to verify user */
3355                         if (bitset(EF_DISCARD, e->e_flags))
3356                                 a->q_state = QS_VERIFIED;
3357 #if MILTER
3358                         milter_cmd_safe = true;
3359 #endif
3360
3361                         addbcc(a, e);
3362                         rcptmods(a, e);
3363
3364                         /* save in recipient list after ESMTP mods */
3365                         a = recipient(a, &e->e_sendqueue, 0, e);
3366                         /* may trigger exception... */
3367
3368 #if MILTER
3369                         milter_rcpt_added = true;
3370 #endif
3371
3372                         if(!(Errors > 0) && QS_IS_BADADDR(a->q_state))
3373                         {
3374                                 /* punt -- should keep message in ADDRESS.... */
3375                                 usrerr("550 5.1.1 Addressee unknown");
3376                         }
3377
3378 #if MILTER
3379                 rcpt_done:
3380                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3381                             !bitset(EF_DISCARD, e->e_flags))
3382                         {
3383                                 char state;
3384                                 char *response;
3385
3386                                 /* how to get the error codes? */
3387                                 if (Errors > 0)
3388                                 {
3389                                         macdefine(&e->e_macro, A_PERM,
3390                                                 macid("{rcpt_mailer}"),
3391                                                 "error");
3392                                         if (a != NULL &&
3393                                             a->q_status != NULL &&
3394                                             a->q_rstatus != NULL)
3395                                         {
3396                                                 macdefine(&e->e_macro, A_PERM,
3397                                                         macid("{rcpt_host}"),
3398                                                         a->q_status);
3399                                                 macdefine(&e->e_macro, A_PERM,
3400                                                         macid("{rcpt_addr}"),
3401                                                         a->q_rstatus);
3402                                         }
3403                                         else
3404                                         {
3405                                                 if (addr_st.q_host != NULL)
3406                                                         macdefine(&e->e_macro,
3407                                                                 A_PERM,
3408                                                                 macid("{rcpt_host}"),
3409                                                                 addr_st.q_host);
3410                                                 if (addr_st.q_user != NULL)
3411                                                         macdefine(&e->e_macro,
3412                                                                 A_PERM,
3413                                                                 macid("{rcpt_addr}"),
3414                                                                 addr_st.q_user);
3415                                         }
3416                                 }
3417
3418                                 response = milter_envrcpt(args, e, &state,
3419                                                         Errors > 0);
3420                                 milter_cmd_done = true;
3421                                 MILTER_REPLY("to");
3422                         }
3423 #endif /* MILTER */
3424
3425                         /* no errors during parsing, but might be a duplicate */
3426                         e->e_to = a->q_paddr;
3427                         if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state))
3428                         {
3429                                 if (smtp.sm_nrcpts == 0)
3430                                         initsys(e);
3431                                 message("250 2.1.5 Recipient ok%s",
3432                                         QS_IS_QUEUEUP(a->q_state) ?
3433                                                 " (will queue)" : "");
3434                                 smtp.sm_nrcpts++;
3435                         }
3436
3437                         /* Is this needed? */
3438 #if !MILTER
3439                 rcpt_done:
3440 #endif
3441
3442                         macdefine(&e->e_macro, A_PERM,
3443                                 macid("{rcpt_mailer}"), NULL);
3444                         macdefine(&e->e_macro, A_PERM,
3445                                 macid("{rcpt_host}"), NULL);
3446                         macdefine(&e->e_macro, A_PERM,
3447                                 macid("{rcpt_addr}"), NULL);
3448                         macdefine(&e->e_macro, A_PERM,
3449                                 macid("{dsn_notify}"), NULL);
3450
3451                         if (Errors > 0)
3452                         {
3453                                 ++n_badrcpts;
3454                                 NBADRCPTS;
3455                         }
3456                     }
3457                     SM_EXCEPT(exc, "[!F]*")
3458                     {
3459                         /* An exception occurred while processing RCPT */
3460                         e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
3461                         ++n_badrcpts;
3462                         NBADRCPTS;
3463 #if MILTER
3464                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3465                             !bitset(EF_DISCARD, e->e_flags) &&
3466                             !milter_cmd_done && milter_cmd_safe)
3467                         {
3468                                 char state;
3469                                 char *response;
3470
3471                                 macdefine(&e->e_macro, A_PERM,
3472                                         macid("{rcpt_mailer}"), "error");
3473
3474                                 /* how to get the error codes? */
3475                                 if (addr_st.q_host != NULL)
3476                                         macdefine(&e->e_macro, A_PERM,
3477                                                 macid("{rcpt_host}"),
3478                                                 addr_st.q_host);
3479                                 else if (a != NULL && a->q_status != NULL)
3480                                         macdefine(&e->e_macro, A_PERM,
3481                                                 macid("{rcpt_host}"),
3482                                                 a->q_status);
3483
3484                                 if (addr_st.q_user != NULL)
3485                                         macdefine(&e->e_macro, A_PERM,
3486                                                 macid("{rcpt_addr}"),
3487                                                 addr_st.q_user);
3488                                 else if (a != NULL && a->q_rstatus != NULL)
3489                                         macdefine(&e->e_macro, A_PERM,
3490                                                 macid("{rcpt_addr}"),
3491                                                 a->q_rstatus);
3492
3493                                 response = milter_envrcpt(args, e, &state,
3494                                                         true);
3495                                 milter_cmd_done = true;
3496                                 MILTER_REPLY("to");
3497                                 macdefine(&e->e_macro, A_PERM,
3498                                         macid("{rcpt_mailer}"), NULL);
3499                                 macdefine(&e->e_macro, A_PERM,
3500                                         macid("{rcpt_host}"), NULL);
3501                                 macdefine(&e->e_macro, A_PERM,
3502                                         macid("{rcpt_addr}"), NULL);
3503                         }
3504                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3505                             milter_rcpt_added && milter_cmd_done &&
3506                             milter_cmd_fail)
3507                         {
3508                                 (void) removefromlist(addr, &e->e_sendqueue, e);
3509                                 milter_cmd_fail = false;
3510                                 if (smtp.sm_e_nrcpts_orig < e->e_nrcpts)
3511                                         e->e_nrcpts = smtp.sm_e_nrcpts_orig;
3512                         }
3513 #endif /* MILTER */
3514                     }
3515                     SM_END_TRY
3516                         break;
3517
3518                   case CMDDATA:         /* data -- text of mail */
3519                         DELAY_CONN("DATA");
3520                         if (!smtp_data(&smtp, e,
3521                                         bitset(SRV_BAD_PIPELINE, features)))
3522                                 goto doquit;
3523                         break;
3524
3525                   case CMDRSET:         /* rset -- reset state */
3526                         if (tTd(94, 100))
3527                                 message("451 4.0.0 Test failure");
3528                         else
3529                                 message("250 2.0.0 Reset state");
3530                         CLEAR_STATE(cmdbuf);
3531                         break;
3532
3533                   case CMDVRFY:         /* vrfy -- verify address */
3534                   case CMDEXPN:         /* expn -- expand address */
3535                         vrfy = c->cmd_code == CMDVRFY;
3536                         DELAY_CONN(vrfy ? "VRFY" : "EXPN");
3537                         if (tempfail)
3538                         {
3539                                 if (LogLevel > 9)
3540                                         sm_syslog(LOG_INFO, e->e_id,
3541                                                   "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
3542                                                   vrfy ? "VRFY" : "EXPN",
3543                                                   p, CurSmtpClient);
3544
3545                                 /* RFC 821 doesn't allow 4xy reply code */
3546                                 usrerr("550 5.7.1 Please try again later");
3547                                 break;
3548                         }
3549                         wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
3550                                              false, vrfy ? "VRFY" : "EXPN", e);
3551                         STOP_IF_ATTACK(wt);
3552                         previous = curtime();
3553                         if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
3554                             (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
3555                         {
3556                                 if (vrfy)
3557                                         message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
3558                                 else
3559                                         message("502 5.7.0 Sorry, we do not allow this operation");
3560                                 if (LogLevel > 5)
3561                                         sm_syslog(LOG_INFO, e->e_id,
3562                                                   "%s: %s [rejected]",
3563                                                   CurSmtpClient,
3564                                                   shortenstring(inp, MAXSHORTSTR));
3565                                 break;
3566                         }
3567                         else if (!gothello &&
3568                                  bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
3569                                                 PrivacyFlags))
3570                         {
3571                                 usrerr("503 5.0.0 I demand that you introduce yourself first");
3572                                 break;
3573                         }
3574                         if (Errors > 0)
3575                                 break;
3576                         if (LogLevel > 5)
3577                                 sm_syslog(LOG_INFO, e->e_id, "%s: %s",
3578                                           CurSmtpClient,
3579                                           shortenstring(inp, MAXSHORTSTR));
3580                     SM_TRY
3581                     {
3582                         QuickAbort = true;
3583                         vrfyqueue = NULL;
3584                         if (vrfy)
3585                                 e->e_flags |= EF_VRFYONLY;
3586                         while (*p != '\0' && SM_ISSPACE(*p))
3587                                 p++;
3588                         if (*p == '\0')
3589                         {
3590                                 usrerr("501 5.5.2 Argument required");
3591                         }
3592                         else
3593                         {
3594                                 /* do config file checking of the address */
3595                                 if (rscheck(vrfy ? "check_vrfy" : "check_expn",
3596                                             p, NULL, e, RSF_RMCOMM, 3, NULL,
3597                                             NOQID, NULL, NULL) != EX_OK ||
3598                                     Errors > 0)
3599                                         sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3600                                 (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
3601                         }
3602                         if (wt > 0)
3603                         {
3604                                 time_t t;
3605
3606                                 t = wt - (curtime() - previous);
3607                                 if (t > 0)
3608                                         (void) sleep(t);
3609                         }
3610                         if (Errors > 0)
3611                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3612                         if (vrfyqueue == NULL)
3613                         {
3614                                 usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
3615                         }
3616                         while (vrfyqueue != NULL)
3617                         {
3618                                 if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
3619                                 {
3620                                         vrfyqueue = vrfyqueue->q_next;
3621                                         continue;
3622                                 }
3623
3624                                 /* see if there is more in the vrfy list */
3625                                 a = vrfyqueue;
3626                                 while ((a = a->q_next) != NULL &&
3627                                        (!QS_IS_UNDELIVERED(a->q_state)))
3628                                         continue;
3629                                 printvrfyaddr(vrfyqueue, a == NULL, vrfy);
3630                                 vrfyqueue = a;
3631                         }
3632                     }
3633                     SM_EXCEPT(exc, "[!F]*")
3634                     {
3635                         /*
3636                         **  An exception occurred while processing VRFY/EXPN
3637                         */
3638
3639                         sm_exc_free(exc);
3640                         goto undo;
3641                     }
3642                     SM_END_TRY
3643                         break;
3644
3645                   case CMDETRN:         /* etrn -- force queue flush */
3646                         DELAY_CONN("ETRN");
3647
3648                         /* Don't leak queue information via debug flags */
3649                         if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
3650                             (RealUid != 0 && RealUid != TrustedUid &&
3651                              OpMode == MD_SMTP))
3652                         {
3653                                 /* different message for MSA ? */
3654                                 message("502 5.7.0 Sorry, we do not allow this operation");
3655                                 if (LogLevel > 5)
3656                                         sm_syslog(LOG_INFO, e->e_id,
3657                                                   "%s: %s [rejected]",
3658                                                   CurSmtpClient,
3659                                                   shortenstring(inp, MAXSHORTSTR));
3660                                 break;
3661                         }
3662                         if (tempfail)
3663                         {
3664                                 if (LogLevel > 9)
3665                                         sm_syslog(LOG_INFO, e->e_id,
3666                                                   "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
3667                                                   p, CurSmtpClient);
3668                                 /* Can't use ("%s", ...) due to usrerr() requirements */
3669                                 usrerr(MSG_TEMPFAIL);
3670                                 break;
3671                         }
3672
3673                         if (strlen(p) <= 0)
3674                         {
3675                                 usrerr("500 5.5.2 Parameter required");
3676                                 break;
3677                         }
3678
3679                         /* crude way to avoid denial-of-service attacks */
3680                         STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
3681                                                         true, "ETRN", e));
3682
3683                         /*
3684                         **  Do config file checking of the parameter.
3685                         **  Even though we have srv_features now, we still
3686                         **  need this ruleset because the former is called
3687                         **  when the connection has been established, while
3688                         **  this ruleset is called when the command is
3689                         **  actually issued and therefore has all information
3690                         **  available to make a decision.
3691                         */
3692
3693                         if (rscheck("check_etrn", p, NULL, e, RSF_RMCOMM, 3,
3694                                     NULL, NOQID, NULL, NULL) != EX_OK ||
3695                             Errors > 0)
3696                                 break;
3697
3698                         if (LogLevel > 5)
3699                                 sm_syslog(LOG_INFO, e->e_id,
3700                                           "%s: ETRN %s", CurSmtpClient,
3701                                           shortenstring(p, MAXSHORTSTR));
3702
3703                         id = p;
3704                         if (*id == '#')
3705                         {
3706                                 int i, qgrp;
3707
3708                                 id++;
3709                                 qgrp = name2qid(id);
3710                                 if (!ISVALIDQGRP(qgrp))
3711                                 {
3712                                         usrerr("459 4.5.4 Queue %s unknown",
3713                                                id);
3714                                         break;
3715                                 }
3716                                 for (i = 0; i < NumQueue && Queue[i] != NULL;
3717                                      i++)
3718                                         Queue[i]->qg_nextrun = (time_t) -1;
3719                                 Queue[qgrp]->qg_nextrun = 0;
3720                                 ok = run_work_group(Queue[qgrp]->qg_wgrp,
3721                                                     RWG_FORK|RWG_FORCE);
3722                                 if (ok && Errors == 0)
3723                                         message("250 2.0.0 Queuing for queue group %s started", id);
3724                                 break;
3725                         }
3726
3727                         if (*id == '@')
3728                                 id++;
3729                         else
3730                                 *--id = '@';
3731
3732                         new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
3733                         if (new == NULL)
3734                         {
3735                                 syserr("500 5.5.0 ETRN out of memory");
3736                                 break;
3737                         }
3738                         new->queue_match = id;
3739                         new->queue_negate = false;
3740                         new->queue_next = NULL;
3741                         QueueLimitRecipient = new;
3742                         ok = runqueue(true, false, false, true);
3743                         sm_free(QueueLimitRecipient); /* XXX */
3744                         QueueLimitRecipient = NULL;
3745                         if (ok && Errors == 0)
3746                                 message("250 2.0.0 Queuing for node %s started", p);
3747                         break;
3748
3749                   case CMDHELP:         /* help -- give user info */
3750                         DELAY_CONN("HELP");
3751                         help(p, e);
3752                         break;
3753
3754 #define CHECK_OTHER(type) do    \
3755         {                                                       \
3756                 bool saveQuickAbort = QuickAbort;               \
3757                 extern char MsgBuf[];                           \
3758                 int rsc;                                        \
3759                 QuickAbort = false;                             \
3760                 if ((rsc = rscheck("check_other", inp, type, e, \
3761                             RSF_UNSTRUCTURED, 3, NULL, NOQID, NULL, NULL)) \
3762                         != EX_OK ||                             \
3763                     Errors > 0)                                 \
3764                 {                                               \
3765                         if (strncmp(MsgBuf, "421 ", 4) == 0)    \
3766                         {                                       \
3767                                 e->e_sendqueue = NULL;          \
3768                                 goto doquit;                    \
3769                         }                                       \
3770                 }                                               \
3771                 QuickAbort = saveQuickAbort;                    \
3772         } while (0)
3773
3774                   case CMDNOOP:         /* noop -- do nothing */
3775                         DELAY_CONN("NOOP");
3776                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3777                                                         true, "NOOP", e));
3778                         CHECK_OTHER("2");
3779                         message("250 2.0.0 OK");
3780                         break;
3781
3782                   case CMDQUIT:         /* quit -- leave mail */
3783                         message("221 2.0.0 %s closing connection", MyHostName);
3784 #if PIPELINING
3785                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3786 #endif
3787
3788                         if (smtp.sm_nrcpts > 0)
3789                                 logundelrcpts(e, "aborted by sender", 9, false);
3790
3791                         /* arrange to ignore any current send list */
3792                         e->e_sendqueue = NULL;
3793
3794 #if STARTTLS
3795                         /* shutdown TLS connection */
3796                         if (tls_active)
3797                         {
3798                                 (void) endtls(&srv_ssl, "server");
3799                                 tls_active = false;
3800                         }
3801 #endif /* STARTTLS */
3802 #if SASL
3803                         if (auth_active)
3804                         {
3805                                 sasl_dispose(&conn);
3806                                 authenticating = SASL_NOT_AUTH;
3807                                 /* XXX sasl_done(); this is a child */
3808                         }
3809 #endif /* SASL */
3810
3811   doquit:
3812                         /* avoid future 050 messages */
3813                         disconnect(1, e);
3814
3815 #if MILTER
3816                         /* close out milter filters */
3817                         milter_quit(e);
3818 #endif
3819
3820                         if (tTd(92, 2))
3821                                 sm_dprintf("QUIT: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
3822                                         e->e_id,
3823                                         bitset(EF_LOGSENDER, e->e_flags),
3824                                         LogLevel);
3825                         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3826                                 logsender(e, NULL);
3827                         e->e_flags &= ~EF_LOGSENDER;
3828
3829                         if (lognullconnection && LogLevel > 5 &&
3830                             nullserver == NULL)
3831                         {
3832                                 char *d;
3833
3834                                 d = macvalue(macid("{daemon_name}"), e);
3835                                 if (d == NULL)
3836                                         d = "stdin";
3837
3838                                 /*
3839                                 **  even though this id is "bogus", it makes
3840                                 **  it simpler to "grep" related events, e.g.,
3841                                 **  timeouts for the same connection.
3842                                 */
3843
3844                                 sm_syslog(LOG_INFO, e->e_id,
3845                                           "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
3846                                           CurSmtpClient, d);
3847                         }
3848                         if (tTd(93, 100))
3849                         {
3850                                 /* return to handle next connection */
3851 #if SM_HEAP_CHECK
3852 # define SM_HC_TRIGGER "heapdump"
3853                                 if (sm_debug_active(&SmHeapCheck, 2)
3854                                     && access(SM_HC_TRIGGER, F_OK) == 0
3855                                    )
3856                                 {
3857                                         SM_FILE_T *out;
3858
3859                                         remove(SM_HC_TRIGGER);
3860                                         out = sm_io_open(SmFtStdio,
3861                                                 SM_TIME_DEFAULT, SM_HC_TRIGGER ".heap",
3862                                                 SM_IO_APPEND, NULL);
3863                                         if (out != NULL)
3864                                         {
3865                                                 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n");
3866                                                 sm_heap_report(out,
3867                                                         sm_debug_level(&SmHeapCheck) - 1);
3868                                                 (void) sm_io_close(out, SM_TIME_DEFAULT);
3869                                         }
3870                                 }
3871 #endif /* SM_HEAP_CHECK */
3872                                 return;
3873                         }
3874                         finis(true, true, ExitStat);
3875                         /* NOTREACHED */
3876
3877                         /* just to avoid bogus warning from some compilers */
3878                         exit(EX_OSERR);
3879
3880                   case CMDVERB:         /* set verbose mode */
3881                         DELAY_CONN("VERB");
3882                         if (!bitset(SRV_OFFER_EXPN, features) ||
3883                             !bitset(SRV_OFFER_VERB, features))
3884                         {
3885                                 /* this would give out the same info */
3886                                 message("502 5.7.0 Verbose unavailable");
3887                                 break;
3888                         }
3889                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3890                                                         true, "VERB", e));
3891                         CHECK_OTHER("2");
3892                         Verbose = 1;
3893                         set_delivery_mode(SM_DELIVER, e);
3894                         message("250 2.0.0 Verbose mode");
3895                         break;
3896
3897 #if SMTPDEBUG
3898                   case CMDDBGQSHOW:     /* show queues */
3899                         CHECK_OTHER("2");
3900                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
3901                                              "Send Queue=");
3902                         printaddr(smioout, e->e_sendqueue, true);
3903                         break;
3904
3905                   case CMDDBGDEBUG:     /* set debug mode */
3906                         CHECK_OTHER("2");
3907                         tTsetup(tTdvect, sizeof(tTdvect), "0-99.1");
3908                         tTflag(p);
3909                         message("200 2.0.0 Debug set");
3910                         break;
3911
3912 #else /* SMTPDEBUG */
3913                   case CMDDBGQSHOW:     /* show queues */
3914                   case CMDDBGDEBUG:     /* set debug mode */
3915 #endif /* SMTPDEBUG */
3916                   case CMDLOGBOGUS:     /* bogus command */
3917                         DELAY_CONN("Bogus");
3918                         if (LogLevel > 0)
3919                                 sm_syslog(LOG_CRIT, e->e_id,
3920                                           "\"%s\" command from %s (%.100s)",
3921                                           c->cmd_name, CurSmtpClient,
3922                                           anynet_ntoa(&RealHostAddr));
3923                         /* FALLTHROUGH */
3924
3925                   case CMDERROR:        /* unknown command */
3926 #if MAXBADCOMMANDS > 0
3927                         if (++n_badcmds > MAXBADCOMMANDS)
3928                         {
3929   stopattack:
3930                                 message("421 4.7.0 %s Too many bad commands; closing connection",
3931                                         MyHostName);
3932
3933                                 /* arrange to ignore any current send list */
3934                                 e->e_sendqueue = NULL;
3935                                 goto doquit;
3936                         }
3937 #endif /* MAXBADCOMMANDS > 0 */
3938
3939 #if MILTER && SMFI_VERSION > 2
3940                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3941                             !bitset(EF_DISCARD, e->e_flags))
3942                         {
3943                                 char state;
3944                                 char *response;
3945
3946                                 if (MilterLogLevel > 9)
3947                                         sm_syslog(LOG_INFO, e->e_id,
3948                                                 "Sending \"%s\" to Milter", inp);
3949                                 response = milter_unknown(inp, e, &state);
3950                                 MILTER_REPLY("unknown");
3951                                 if (state == SMFIR_REPLYCODE ||
3952                                     state == SMFIR_REJECT ||
3953                                     state == SMFIR_TEMPFAIL ||
3954                                     state == SMFIR_SHUTDOWN)
3955                                 {
3956                                         /* MILTER_REPLY already gave an error */
3957                                         break;
3958                                 }
3959                         }
3960 #endif /* MILTER && SMFI_VERSION > 2 */
3961
3962                         CHECK_OTHER("5");
3963                         usrerr("500 5.5.1 Command unrecognized: \"%s\"",
3964                                SHOWSHRTCMDINREPLY(inp));
3965                         break;
3966
3967                   case CMDUNIMPL:
3968                         DELAY_CONN("Unimpl");
3969                         CHECK_OTHER("5");
3970                         usrerr("502 5.5.1 Command not implemented: \"%s\"",
3971                                SHOWSHRTCMDINREPLY(inp));
3972                         break;
3973
3974                   default:
3975                         DELAY_CONN("default");
3976                         CHECK_OTHER("5");
3977                         errno = 0;
3978                         syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
3979                         break;
3980                 }
3981 #if SASL
3982                 }
3983 #endif
3984             }
3985             SM_EXCEPT(exc, "[!F]*")
3986             {
3987                 /*
3988                 **  The only possible exception is "E:mta.quickabort".
3989                 **  There is nothing to do except fall through and loop.
3990                 */
3991             }
3992             SM_END_TRY
3993         }
3994 }
3995 /*
3996 **  SMTP_DATA -- implement the SMTP DATA command.
3997 **
3998 **      Parameters:
3999 **              smtp -- status of SMTP connection.
4000 **              e -- envelope.
4001 **              check_stuffing -- check for transaction stuffing.
4002 **
4003 **      Returns:
4004 **              true iff SMTP session can continue.
4005 **
4006 **      Side Effects:
4007 **              possibly sends message.
4008 */
4009
4010 static bool
4011 smtp_data(smtp, e, check_stuffing)
4012         SMTP_T *smtp;
4013         ENVELOPE *e;
4014         bool check_stuffing;
4015 {
4016 #if MILTER
4017         bool milteraccept;
4018 #endif
4019         bool aborting;
4020         bool doublequeue;
4021         bool rv = true;
4022         ADDRESS *a;
4023         ENVELOPE *ee;
4024         char *id;
4025         char *oldid;
4026         unsigned long features;
4027         char buf[32];
4028
4029         SmtpPhase = "server DATA";
4030         if (!smtp->sm_gotmail)
4031         {
4032                 usrerr("503 5.0.0 Need MAIL command");
4033                 return true;
4034         }
4035         else if (smtp->sm_nrcpts <= 0)
4036         {
4037                 usrerr("503 5.0.0 Need RCPT (recipient)");
4038                 return true;
4039         }
4040
4041         /* check if data is on the socket before the DATA reply */
4042         if (check_stuffing &&
4043             sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
4044         {
4045                 sm_syslog(LOG_INFO, e->e_id,
4046                         "rejecting %s from %s [%s] due to traffic before response",
4047                         SmtpPhase, CurHostName, anynet_ntoa(&RealHostAddr));
4048                 usrerr("554 5.5.0 SMTP protocol error");
4049                 return false;
4050         }
4051
4052         (void) sm_snprintf(buf, sizeof(buf), "%u", smtp->sm_nrcpts);
4053         if (rscheck("check_data", buf, NULL, e,
4054                     RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
4055                     e->e_id, NULL, NULL) != EX_OK)
4056                 return true;
4057
4058 #if MILTER && SMFI_VERSION > 3
4059         if (smtp->sm_milterlist && smtp->sm_milterize &&
4060             !bitset(EF_DISCARD, e->e_flags))
4061         {
4062                 char state;
4063                 char *response;
4064                 int savelogusrerrs = LogUsrErrs;
4065
4066                 response = milter_data_cmd(e, &state);
4067                 switch (state)
4068                 {
4069                   case SMFIR_REPLYCODE:
4070                         if (MilterLogLevel > 3)
4071                         {
4072                                 sm_syslog(LOG_INFO, e->e_id,
4073                                           "Milter: cmd=data, reject=%s",
4074                                           response);
4075                                 LogUsrErrs = false;
4076                         }
4077 # if _FFR_MILTER_ENHSC
4078                         if (ISSMTPCODE(response))
4079                                 (void) extenhsc(response + 4, ' ', e->e_enhsc);
4080 # endif
4081
4082                         /* Can't use ("%s", ...) due to usrerr() requirements */
4083                         usrerr(response);
4084                         if (strncmp(response, "421 ", 4) == 0
4085                             || strncmp(response, "421-", 4) == 0)
4086                         {
4087                                 e->e_sendqueue = NULL;
4088                                 return false;
4089                         }
4090                         return true;
4091
4092                   case SMFIR_REJECT:
4093                         if (MilterLogLevel > 3)
4094                         {
4095                                 sm_syslog(LOG_INFO, e->e_id,
4096                                           "Milter: cmd=data, reject=550 5.7.1 Command rejected");
4097                                 LogUsrErrs = false;
4098                         }
4099 # if _FFR_MILTER_ENHSC
4100                         (void) sm_strlcpy(e->e_enhsc, "5.7.1",
4101                                          sizeof(e->e_enhsc));
4102 # endif
4103                         usrerr("550 5.7.1 Command rejected");
4104                         return true;
4105
4106                   case SMFIR_DISCARD:
4107                         if (MilterLogLevel > 3)
4108                                 sm_syslog(LOG_INFO, e->e_id,
4109                                           "Milter: cmd=data, discard");
4110                         e->e_flags |= EF_DISCARD;
4111                         break;
4112
4113                   case SMFIR_TEMPFAIL:
4114                         if (MilterLogLevel > 3)
4115                         {
4116                                 sm_syslog(LOG_INFO, e->e_id,
4117                                           "Milter: cmd=data, reject=%s",
4118                                           MSG_TEMPFAIL);
4119                                 LogUsrErrs = false;
4120                         }
4121 # if _FFR_MILTER_ENHSC
4122                         (void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
4123 # endif
4124                         /* Can't use ("%s", ...) due to usrerr() requirements */
4125                         usrerr(MSG_TEMPFAIL);
4126                         return true;
4127
4128                   case SMFIR_SHUTDOWN:
4129                         if (MilterLogLevel > 3)
4130                         {
4131                                 sm_syslog(LOG_INFO, e->e_id,
4132                                           "Milter: cmd=data, reject=421 4.7.0 %s closing connection",
4133                                           MyHostName);
4134                                 LogUsrErrs = false;
4135                         }
4136                         usrerr("421 4.7.0 %s closing connection", MyHostName);
4137                         e->e_sendqueue = NULL;
4138                         return false;
4139                 }
4140                 LogUsrErrs = savelogusrerrs;
4141                 if (response != NULL)
4142                         sm_free(response); /* XXX */
4143         }
4144 #endif /* MILTER && SMFI_VERSION > 3 */
4145
4146         /* put back discard bit */
4147         if (smtp->sm_discard)
4148                 e->e_flags |= EF_DISCARD;
4149
4150         /* check to see if we need to re-expand aliases */
4151         /* also reset QS_BADADDR on already-diagnosted addrs */
4152         doublequeue = false;
4153         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4154         {
4155                 if (QS_IS_VERIFIED(a->q_state) &&
4156                     !bitset(EF_DISCARD, e->e_flags))
4157                 {
4158                         /* need to re-expand aliases */
4159                         doublequeue = true;
4160                 }
4161                 if (QS_IS_BADADDR(a->q_state))
4162                 {
4163                         /* make this "go away" */
4164                         a->q_state = QS_DONTSEND;
4165                 }
4166         }
4167
4168         /* collect the text of the message */
4169         SmtpPhase = "collect";
4170         buffer_errors();
4171
4172         collect(InChannel, SMTPMODE_LAX
4173                 | (bitset(SRV_BARE_LF_421, e->e_features) ? SMTPMODE_LF_421 : 0)
4174                 | (bitset(SRV_BARE_CR_421, e->e_features) ? SMTPMODE_CR_421 : 0)
4175                 | (bitset(SRV_BARE_LF_SP, e->e_features) ? SMTPMODE_LF_SP : 0)
4176                 | (bitset(SRV_BARE_CR_SP, e->e_features) ? SMTPMODE_CR_SP : 0)
4177                 | (bitset(SRV_REQ_CRLF, e->e_features) ? SMTPMODE_CRLF : 0),
4178                 NULL, e, true);
4179
4180         /* redefine message size */
4181         (void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4182         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4183
4184         /* rscheck() will set Errors or EF_DISCARD if it trips */
4185         (void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
4186                        3, NULL, e->e_id, NULL, NULL);
4187
4188 #if MILTER
4189         milteraccept = true;
4190         if (smtp->sm_milterlist && smtp->sm_milterize &&
4191             Errors <= 0 &&
4192             !bitset(EF_DISCARD, e->e_flags))
4193         {
4194                 char state;
4195                 char *response;
4196
4197                 response = milter_data(e, &state);
4198                 switch (state)
4199                 {
4200                   case SMFIR_REPLYCODE:
4201                         if (MilterLogLevel > 3)
4202                                 sm_syslog(LOG_INFO, e->e_id,
4203                                           "Milter: data, reject=%s",
4204                                           response);
4205                         milteraccept = false;
4206 # if _FFR_MILTER_ENHSC
4207                         if (ISSMTPCODE(response))
4208                                 (void) extenhsc(response + 4, ' ', e->e_enhsc);
4209 # endif
4210                         /* Can't use ("%s", ...) due to usrerr() requirements */
4211                         usrerr(response);
4212                         if (strncmp(response, "421 ", 4) == 0
4213                             || strncmp(response, "421-", 4) == 0)
4214                                 rv = false;
4215                         break;
4216
4217                   case SMFIR_REJECT:
4218                         milteraccept = false;
4219                         if (MilterLogLevel > 3)
4220                                 sm_syslog(LOG_INFO, e->e_id,
4221                                           "Milter: data, reject=554 5.7.1 Command rejected");
4222                         usrerr("554 5.7.1 Command rejected");
4223                         break;
4224
4225                   case SMFIR_DISCARD:
4226                         if (MilterLogLevel > 3)
4227                                 sm_syslog(LOG_INFO, e->e_id,
4228                                           "Milter: data, discard");
4229                         milteraccept = false;
4230                         e->e_flags |= EF_DISCARD;
4231                         break;
4232
4233                   case SMFIR_TEMPFAIL:
4234                         if (MilterLogLevel > 3)
4235                                 sm_syslog(LOG_INFO, e->e_id,
4236                                           "Milter: data, reject=%s",
4237                                           MSG_TEMPFAIL);
4238                         milteraccept = false;
4239 # if _FFR_MILTER_ENHSC
4240                         (void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
4241 # endif
4242                         /* Can't use ("%s", ...) due to usrerr() requirements */
4243                         usrerr(MSG_TEMPFAIL);
4244                         break;
4245
4246                   case SMFIR_SHUTDOWN:
4247                         if (MilterLogLevel > 3)
4248                                 sm_syslog(LOG_INFO, e->e_id,
4249                                           "Milter: data, reject=421 4.7.0 %s closing connection",
4250                                           MyHostName);
4251                         milteraccept = false;
4252                         usrerr("421 4.7.0 %s closing connection", MyHostName);
4253                         rv = false;
4254                         break;
4255                 }
4256                 if (response != NULL)
4257                         sm_free(response);
4258         }
4259
4260         /* Milter may have changed message size */
4261         (void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4262         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4263
4264         /* abort message filters that didn't get the body & log msg is OK */
4265         if (smtp->sm_milterlist && smtp->sm_milterize)
4266         {
4267                 milter_abort(e);
4268                 if (milteraccept && MilterLogLevel > 9)
4269                         sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
4270         }
4271
4272         /*
4273         **  If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
4274         **  milter accepted message, sync it now
4275         **
4276         **  XXX This is almost a copy of the code in collect(): put it into
4277         **      a function that is called from both places?
4278         */
4279
4280         if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
4281         {
4282                 int afd;
4283                 SM_FILE_T *volatile df;
4284                 char *dfname;
4285
4286                 df = e->e_dfp;
4287                 dfname = queuename(e, DATAFL_LETTER);
4288                 if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
4289                     && errno != EINVAL)
4290                 {
4291                         int save_errno;
4292
4293                         save_errno = errno;
4294                         if (save_errno == EEXIST)
4295                         {
4296                                 struct stat st;
4297                                 int dfd;
4298
4299                                 if (stat(dfname, &st) < 0)
4300                                         st.st_size = -1;
4301                                 errno = EEXIST;
4302                                 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
4303                                        dfname, (long) st.st_size);
4304                                 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
4305                                 if (dfd >= 0)
4306                                         dumpfd(dfd, true, true);
4307                         }
4308                         errno = save_errno;
4309                         dferror(df, "bfcommit", e);
4310                         flush_errors(true);
4311                         finis(save_errno != EEXIST, true, ExitStat);
4312                 }
4313                 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
4314                 {
4315                         dferror(df, "sm_io_getinfo", e);
4316                         flush_errors(true);
4317                         finis(true, true, ExitStat);
4318                         /* NOTREACHED */
4319                 }
4320                 else if (fsync(afd) < 0)
4321                 {
4322                         dferror(df, "fsync", e);
4323                         flush_errors(true);
4324                         finis(true, true, ExitStat);
4325                         /* NOTREACHED */
4326                 }
4327                 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
4328                 {
4329                         dferror(df, "sm_io_close", e);
4330                         flush_errors(true);
4331                         finis(true, true, ExitStat);
4332                         /* NOTREACHED */
4333                 }
4334
4335                 /* Now reopen the df file */
4336                 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
4337                                         SM_IO_RDONLY, NULL);
4338                 if (e->e_dfp == NULL)
4339                 {
4340                         /* we haven't acked receipt yet, so just chuck this */
4341                         syserr("@Cannot reopen %s", dfname);
4342                         finis(true, true, ExitStat);
4343                         /* NOTREACHED */
4344                 }
4345         }
4346 #endif /* MILTER */
4347
4348         /* Check if quarantining stats should be updated */
4349         if (e->e_quarmsg != NULL)
4350                 markstats(e, NULL, STATS_QUARANTINE);
4351
4352         /*
4353         **  If a header/body check (header checks or milter)
4354         **  set EF_DISCARD, don't queueup the message --
4355         **  that would lose the EF_DISCARD bit and deliver
4356         **  the message.
4357         */
4358
4359         if (bitset(EF_DISCARD, e->e_flags))
4360                 doublequeue = false;
4361
4362         aborting = Errors > 0;
4363         if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
4364             (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
4365             !split_by_recipient(e))
4366                 aborting = bitset(EF_FATALERRS, e->e_flags);
4367
4368         if (aborting)
4369         {
4370                 ADDRESS *q;
4371
4372                 /* Log who the mail would have gone to */
4373                 logundelrcpts(e, e->e_message, 8, false);
4374
4375                 /*
4376                 **  If something above refused the message, we still haven't
4377                 **  accepted responsibility for it.  Don't send DSNs.
4378                 */
4379
4380                 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
4381                         q->q_flags &= ~Q_PINGFLAGS;
4382
4383                 flush_errors(true);
4384                 buffer_errors();
4385                 goto abortmessage;
4386         }
4387
4388         /* from now on, we have to operate silently */
4389         buffer_errors();
4390
4391 #if 0
4392         /*
4393         **  Clear message, it may contain an error from the SMTP dialogue.
4394         **  This error must not show up in the queue.
4395         **      Some error message should show up, e.g., alias database
4396         **      not available, but others shouldn't, e.g., from check_rcpt.
4397         */
4398
4399         e->e_message = NULL;
4400 #endif /* 0 */
4401
4402         /*
4403         **  Arrange to send to everyone.
4404         **      If sending to multiple people, mail back
4405         **              errors rather than reporting directly.
4406         **      In any case, don't mail back errors for
4407         **              anything that has happened up to
4408         **              now (the other end will do this).
4409         **      Truncate our transcript -- the mail has gotten
4410         **              to us successfully, and if we have
4411         **              to mail this back, it will be easier
4412         **              on the reader.
4413         **      Then send to everyone.
4414         **      Finally give a reply code.  If an error has
4415         **              already been given, don't mail a
4416         **              message back.
4417         **      We goose error returns by clearing error bit.
4418         */
4419
4420         SmtpPhase = "delivery";
4421         (void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
4422         id = e->e_id;
4423
4424 #if NAMED_BIND
4425         _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
4426         _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
4427 #endif
4428
4429 #if _FFR_PROXY
4430         if (SM_PROXY_REQ == e->e_sendmode)
4431         {
4432                 /* is proxy mode possible? */
4433                 if (e->e_sibling == NULL && e->e_nrcpts == 1
4434                     && smtp->sm_nrcpts == 1
4435                     && (a = e->e_sendqueue) != NULL && a->q_next == NULL)
4436                 {
4437                         a->q_flags &= ~(QPINGONFAILURE|QPINGONSUCCESS|
4438                                         QPINGONDELAY);
4439                         e->e_errormode = EM_QUIET;
4440                         e->e_sendmode = SM_PROXY;
4441                 }
4442                 else
4443                 {
4444                         if (tTd(87, 2))
4445                         {
4446                                 a = e->e_sendqueue;
4447                                 sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, sm_nrcpts=%d, sendqueue=%p, next=%p\n",
4448                                 e->e_sendmode, e, e->e_sibling, e->e_nrcpts,
4449                                 smtp->sm_nrcpts, a,
4450                                 (a == NULL) ? (void *)0 : a->q_next);
4451                         }
4452
4453                         /* switch to interactive mode */
4454                         e->e_sendmode = SM_DELIVER;
4455                         if (LogLevel > 9)
4456                                 sm_syslog(LOG_DEBUG, e->e_id,
4457                                           "proxy mode requested but not possible");
4458                 }
4459         }
4460 #endif /* _FFR_PROXY */
4461
4462 #if _FFR_DMTRIGGER
4463         if (SM_TRIGGER == e->e_sendmode)
4464                 doublequeue = true;
4465 #endif
4466         for (ee = e; ee != NULL; ee = ee->e_sibling)
4467         {
4468                 /* make sure we actually do delivery */
4469                 ee->e_flags &= ~EF_CLRQUEUE;
4470
4471                 /* from now on, operate silently */
4472                 ee->e_errormode = EM_MAIL;
4473
4474                 if (doublequeue)
4475                 {
4476                         unsigned int qup_flags;
4477
4478                         qup_flags = QUP_FL_MSYNC;
4479 #if _FFR_DMTRIGGER
4480                         if (IS_SM_TRIGGER(ee->e_sendmode))
4481                                 qup_flags |= QUP_FL_UNLOCK;
4482 #endif
4483                         /* make sure it is in the queue */
4484                         queueup(ee, qup_flags);
4485                 }
4486                 else
4487                 {
4488                         int mode;
4489
4490                         /* send to all recipients */
4491                         mode = SM_DEFAULT;
4492 #if _FFR_DM_ONE
4493                         if (SM_DM_ONE == e->e_sendmode)
4494                         {
4495                                 if (NotFirstDelivery)
4496                                 {
4497                                         mode = SM_QUEUE;
4498                                         e->e_sendmode = SM_QUEUE;
4499                                 }
4500                                 else
4501                                 {
4502                                         mode = SM_FORK;
4503                                         NotFirstDelivery = true;
4504                                 }
4505                         }
4506 #endif /* _FFR_DM_ONE */
4507                         sendall(ee, mode);
4508                 }
4509                 ee->e_to = NULL;
4510         }
4511
4512         /* put back id for SMTP logging in putoutmsg() */
4513         oldid = CurEnv->e_id;
4514         CurEnv->e_id = id;
4515
4516 #if _FFR_PROXY
4517         a = e->e_sendqueue;
4518         if (tTd(87, 1))
4519         {
4520                 sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, msg=%s, sendqueue=%p, next=%p, state=%d, SmtpError=%s, rcode=%d, renhsc=%s, text=%s\n",
4521                 e->e_sendmode, e, e->e_sibling, e->e_nrcpts, e->e_message, a,
4522                 (a == NULL) ? (void *)0 : a->q_next,
4523                 (a == NULL) ? -1 : a->q_state, SmtpError, e->e_rcode,
4524                 e->e_renhsc, e->e_text);
4525         }
4526
4527         if (SM_PROXY == e->e_sendmode && a->q_state != QS_SENT &&
4528             a->q_state != QS_VERIFIED) /* discarded! */
4529         {
4530                 char *m, *errtext;
4531                 char replycode[4];
4532                 char enhsc[10];
4533                 int offset;
4534
4535 #define NN_MSG(e)       (((e)->e_message != NULL) ? (e)->e_message : "")
4536                 m = e->e_message;
4537 #define SM_MSG_DEFERRED "Deferred: "
4538                 if (m != NULL && strncmp(SM_MSG_DEFERRED, m,
4539                                          sizeof(SM_MSG_DEFERRED) - 1) == 0)
4540                         m += sizeof(SM_MSG_DEFERRED) - 1;
4541                 offset = extsc(m, ' ', replycode, enhsc);
4542
4543                 if (tTd(87, 2))
4544                 {
4545                         sm_dprintf("srv: SmtpError=%s, rcode=%d, renhsc=%s, replycode=%s, enhsc=%s, offset=%d\n",
4546                                 SmtpError, e->e_rcode, e->e_renhsc,
4547                                 replycode, enhsc, offset);
4548                 }
4549
4550 #define DIG2CHAR(d)     ((d) + '0')
4551                 if (e->e_rcode != 0 && (replycode[0] == '\0' ||
4552                     replycode[0] == DIG2CHAR(REPLYTYPE(e->e_rcode))))
4553                 {
4554                         replycode[0] = DIG2CHAR(REPLYTYPE(e->e_rcode));
4555                         replycode[1] = DIG2CHAR(REPLYCLASS(e->e_rcode));
4556                         replycode[2] = DIG2CHAR(REPLYMINOR(e->e_rcode));
4557                         replycode[3] = '\0';
4558                         if (e->e_renhsc[0] == replycode[0])
4559                                 sm_strlcpy(enhsc, e->e_renhsc, sizeof(enhsc));
4560                         if (offset < 0)
4561                                 offset = 0;
4562                 }
4563                 if (e->e_text != NULL)
4564                 {
4565                         (void) strreplnonprt(e->e_text, '_');
4566                         errtext = e->e_text;
4567                 }
4568                 else
4569                         errtext = m + offset;
4570
4571                 if (replycode[0] != '\0' && enhsc[0] != '\0')
4572                         emessage(replycode, enhsc, "%s", errtext);
4573                 else if (replycode[0] != '\0')
4574                         emessage(replycode, smtptodsn(atoi(replycode)),
4575                                  "%s", errtext);
4576                 else if (QS_IS_TEMPFAIL(a->q_state))
4577                 {
4578                         if (m != NULL)
4579                                 message("450 4.5.1 %s", m);
4580                         else
4581                                 message("450 4.5.1 Temporary error");
4582                 }
4583                 else
4584                 {
4585                         if (m != NULL)
4586                                 message("550 5.5.1 %s", m);
4587                         else
4588                                 message("550 5.0.0 Permanent error");
4589                 }
4590         }
4591         else
4592         {
4593 #endif /* _FFR_PROXY */
4594                 /* issue success message */
4595 #if _FFR_MSG_ACCEPT
4596                 if (MessageAccept != NULL && *MessageAccept != '\0')
4597                 {
4598                         char msg[MAXLINE];
4599
4600                         expand(MessageAccept, msg, sizeof(msg), e);
4601                         message("250 2.0.0 %s", msg);
4602                 }
4603                 else
4604 #endif /* _FFR_MSG_ACCEPT */
4605                 /* "else" in #if code above */
4606                 message("250 2.0.0 %s Message accepted for delivery", id);
4607 #if _FFR_PROXY
4608         }
4609 #endif
4610         CurEnv->e_id = oldid;
4611
4612         /* if we just queued, poke it */
4613         if (doublequeue)
4614         {
4615                 bool anything_to_send = false;
4616
4617                 sm_getla();
4618                 for (ee = e; ee != NULL; ee = ee->e_sibling)
4619                 {
4620 #if _FFR_DMTRIGGER
4621                         if (SM_TRIGGER == ee->e_sendmode)
4622                         {
4623                                 sm_syslog(LOG_DEBUG, ee->e_id,
4624                                         "smtp: doublequeue, mode=%c", ee->e_sendmode);
4625                                 ee->e_sendmode = SM_DELIVER;
4626
4627                                 /* close all the queue files */
4628                                 /* almost the same as below */
4629                                 closexscript(ee);
4630                                 SM_CLOSE_FP(ee->e_dfp);
4631                                 continue;
4632                         }
4633 #endif /* _FFR_DMTRIGGER */
4634                         if (WILL_BE_QUEUED(ee->e_sendmode))
4635                                 continue;
4636                         if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
4637                         {
4638                                 ee->e_sendmode = SM_QUEUE;
4639                                 continue;
4640                         }
4641                         else if (QueueMode != QM_QUARANTINE &&
4642                                  ee->e_quarmsg != NULL)
4643                         {
4644                                 ee->e_sendmode = SM_QUEUE;
4645                                 continue;
4646                         }
4647                         anything_to_send = true;
4648
4649                         /* close all the queue files */
4650                         closexscript(ee);
4651                         SM_CLOSE_FP(ee->e_dfp);
4652                         unlockqueue(ee);
4653                 }
4654                 if (anything_to_send)
4655                 {
4656 #if PIPELINING
4657                         /*
4658                         **  XXX if we don't do this, we get 250 twice
4659                         **      because it is also flushed in the child.
4660                         */
4661
4662                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
4663 #endif /* PIPELINING */
4664 #if _FFR_DMTRIGGER
4665                         sm_syslog(LOG_DEBUG, e->e_id, "smtp: doublequeue=send");
4666 #endif
4667                         (void) doworklist(e, true, true);
4668                 }
4669         }
4670
4671   abortmessage:
4672         if (tTd(92, 2))
4673                 sm_dprintf("abortmessage: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
4674                         e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);
4675         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
4676                 logsender(e, NULL);
4677         e->e_flags &= ~EF_LOGSENDER;
4678
4679         /* clean up a bit */
4680         smtp->sm_gotmail = false;
4681
4682         /*
4683         **  Call dropenvelope if and only if the envelope is *not*
4684         **  being processed by the child process forked by doworklist().
4685         */
4686
4687         if (aborting || bitset(EF_DISCARD, e->e_flags))
4688                 (void) dropenvelope(e, true, false);
4689         else
4690         {
4691                 for (ee = e; ee != NULL; ee = ee->e_sibling)
4692                 {
4693                         if (!doublequeue &&
4694                             QueueMode != QM_QUARANTINE &&
4695                             ee->e_quarmsg != NULL)
4696                         {
4697                                 (void) dropenvelope(ee, true, false);
4698                                 continue;
4699                         }
4700                         if (WILL_BE_QUEUED(ee->e_sendmode))
4701                                 (void) dropenvelope(ee, true, false);
4702                 }
4703         }
4704
4705         CurEnv = e;
4706         features = e->e_features;
4707         sm_rpool_free(e->e_rpool);
4708         newenvelope(e, e, sm_rpool_new_x(NULL));
4709         e->e_flags = BlankEnvelope.e_flags;
4710         e->e_features = features;
4711
4712         /* restore connection quarantining */
4713         if (smtp->sm_quarmsg == NULL)
4714         {
4715                 e->e_quarmsg = NULL;
4716                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
4717         }
4718         else
4719         {
4720                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
4721                 macdefine(&e->e_macro, A_PERM,
4722                           macid("{quarantine}"), e->e_quarmsg);
4723         }
4724         return rv;
4725 }
4726 /*
4727 **  LOGUNDELRCPTS -- log undelivered (or all) recipients.
4728 **
4729 **      Parameters:
4730 **              e -- envelope.
4731 **              msg -- message for Stat=
4732 **              level -- log level.
4733 **              all -- log all recipients.
4734 **
4735 **      Returns:
4736 **              none.
4737 **
4738 **      Side Effects:
4739 **              logs undelivered (or all) recipients
4740 */
4741
4742 void
4743 logundelrcpts(e, msg, level, all)
4744         ENVELOPE *e;
4745         char *msg;
4746         int level;
4747         bool all;
4748 {
4749         ADDRESS *a;
4750
4751         if (LogLevel <= level || msg == NULL || *msg == '\0')
4752                 return;
4753
4754         /* Clear $h so relay= doesn't get mislogged by logdelivery() */
4755         macdefine(&e->e_macro, A_PERM, 'h', NULL);
4756
4757         /* Log who the mail would have gone to */
4758         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4759         {
4760                 if (!QS_IS_UNDELIVERED(a->q_state) && !all)
4761                         continue;
4762                 e->e_to = a->q_paddr;
4763                 logdelivery(NULL, NULL,
4764 #if _FFR_MILTER_ENHSC
4765                             (a->q_status == NULL && e->e_enhsc[0] != '\0')
4766                             ? e->e_enhsc :
4767 #endif
4768 /* not yet documented or tested */
4769 #if _FFR_USE_E_STATUS
4770                             (NULL == a->q_status) ? e->e_status :
4771 #endif
4772                             a->q_status,
4773                             msg, NULL, (time_t) 0, e, a, EX_OK /* ??? */);
4774         }
4775         e->e_to = NULL;
4776 }
4777 /*
4778 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
4779 **
4780 **      Parameters:
4781 **              pcounter -- pointer to a counter for this command.
4782 **              maxcount -- maximum value for this counter before we
4783 **                      slow down.
4784 **              waitnow -- sleep now (in this routine)?
4785 **              cname -- command name for logging.
4786 **              e -- the current envelope.
4787 **
4788 **      Returns:
4789 **              time to wait,
4790 **              STOP_ATTACK if twice as many commands as allowed and
4791 **                      MaxChildren > 0.
4792 **
4793 **      Side Effects:
4794 **              Slows down if we seem to be under attack.
4795 */
4796
4797 static time_t
4798 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
4799         volatile unsigned int *pcounter;
4800         unsigned int maxcount;
4801         bool waitnow;
4802         char *cname;
4803         ENVELOPE *e;
4804 {
4805         if (maxcount <= 0)      /* no limit */
4806                 return (time_t) 0;
4807
4808         if (++(*pcounter) >= maxcount)
4809         {
4810                 unsigned int shift;
4811                 time_t s;
4812
4813                 if (*pcounter == maxcount && LogLevel > 5)
4814                 {
4815                         sm_syslog(LOG_INFO, e->e_id,
4816                                   "%s: possible SMTP attack: command=%.40s, count=%u",
4817                                   CurSmtpClient, cname, *pcounter);
4818                 }
4819                 shift = *pcounter - maxcount;
4820                 s = 1 << shift;
4821                 if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
4822                         s = MAXTIMEOUT;
4823
4824 #define IS_ATTACK(s)    ((MaxChildren > 0 && *pcounter >= maxcount * 2) \
4825                                 ? STOP_ATTACK : (time_t) s)
4826
4827                 /* sleep at least 1 second before returning */
4828                 (void) sleep(*pcounter / maxcount);
4829                 s -= *pcounter / maxcount;
4830                 if (s >= MAXTIMEOUT || s < 0)
4831                         s = MAXTIMEOUT;
4832                 if (waitnow && s > 0)
4833                 {
4834                         (void) sleep(s);
4835                         return IS_ATTACK(0);
4836                 }
4837                 return IS_ATTACK(s);
4838         }
4839         return (time_t) 0;
4840 }
4841 /*
4842 **  SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
4843 **
4844 **      Parameters:
4845 **              none.
4846 **
4847 **      Returns:
4848 **              nothing.
4849 **
4850 **      Side Effects:
4851 **              may change I/O fd.
4852 */
4853
4854 static void
4855 setup_smtpd_io()
4856 {
4857         int inchfd, outchfd, outfd;
4858
4859         inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
4860         outchfd  = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
4861         outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
4862         if (outchfd != outfd)
4863         {
4864                 /* arrange for debugging output to go to remote host */
4865                 (void) dup2(outchfd, outfd);
4866         }
4867
4868         /*
4869         **  if InChannel and OutChannel are stdin/stdout
4870         **  and connected to ttys
4871         **  and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
4872         **  then "chain" them together.
4873         */
4874
4875         if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
4876             isatty(inchfd) && isatty(outchfd))
4877         {
4878                 int inmode, outmode;
4879
4880                 inmode = fcntl(inchfd, F_GETFL, 0);
4881                 if (inmode == -1)
4882                 {
4883                         if (LogLevel > 11)
4884                                 sm_syslog(LOG_INFO, NOQID,
4885                                         "fcntl(inchfd, F_GETFL) failed: %s",
4886                                         sm_errstring(errno));
4887                         return;
4888                 }
4889                 outmode = fcntl(outchfd, F_GETFL, 0);
4890                 if (outmode == -1)
4891                 {
4892                         if (LogLevel > 11)
4893                                 sm_syslog(LOG_INFO, NOQID,
4894                                         "fcntl(outchfd, F_GETFL) failed: %s",
4895                                         sm_errstring(errno));
4896                         return;
4897                 }
4898                 if (bitset(O_NONBLOCK, inmode) ||
4899                     bitset(O_NONBLOCK, outmode) ||
4900                     fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
4901                         return;
4902                 outmode = fcntl(outchfd, F_GETFL, 0);
4903                 if (outmode != -1 && bitset(O_NONBLOCK, outmode))
4904                 {
4905                         /* changing InChannel also changes OutChannel */
4906                         sm_io_automode(OutChannel, InChannel);
4907                         if (tTd(97, 4) && LogLevel > 9)
4908                                 sm_syslog(LOG_INFO, NOQID,
4909                                           "set automode for I (%d)/O (%d) in SMTP server",
4910                                           inchfd, outchfd);
4911                 }
4912
4913                 /* undo change of inchfd */
4914                 (void) fcntl(inchfd, F_SETFL, inmode);
4915         }
4916 }
4917 /*
4918 **  SKIPWORD -- skip a fixed word.
4919 **
4920 **      Parameters:
4921 **              p -- place to start looking.
4922 **              w -- word to skip.
4923 **
4924 **      Returns:
4925 **              p following w.
4926 **              NULL on error.
4927 **
4928 **      Side Effects:
4929 **              clobbers the p data area.
4930 */
4931
4932 static char *
4933 skipword(p, w)
4934         register char *volatile p;
4935         char *w;
4936 {
4937         register char *q;
4938         char *firstp = p;
4939
4940         /* find beginning of word */
4941         SKIP_SPACE(p);
4942         q = p;
4943
4944         /* find end of word */
4945         while (*p != '\0' && *p != ':' && !(SM_ISSPACE(*p)))
4946                 p++;
4947         while (SM_ISSPACE(*p))
4948                 *p++ = '\0';
4949         if (*p != ':')
4950         {
4951           syntax:
4952                 usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
4953                         SHOWSHRTCMDINREPLY(firstp));
4954                 return NULL;
4955         }
4956         *p++ = '\0';
4957         SKIP_SPACE(p);
4958
4959         if (*p == '\0')
4960                 goto syntax;
4961
4962         /* see if the input word matches desired word */
4963         if (sm_strcasecmp(q, w))
4964                 goto syntax;
4965
4966         return p;
4967 }
4968
4969 /*
4970 **  RESET_MAIL_ESMTP_ARGS -- reset ESMTP arguments for MAIL
4971 **
4972 **      Parameters:
4973 **              e -- the envelope.
4974 **
4975 **      Returns:
4976 **              none.
4977 */
4978
4979 void
4980 reset_mail_esmtp_args(e)
4981         ENVELOPE *e;
4982 {
4983         /* "size": no reset */
4984
4985         /* "body" */
4986         e->e_flags &= ~EF_7BITBODY;
4987         e->e_bodytype = NULL;
4988
4989         /* "envid" */
4990         e->e_envid = NULL;
4991         macdefine(&e->e_macro, A_PERM, macid("{dsn_envid}"), NULL);
4992
4993         /* "ret" */
4994         e->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
4995         macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), NULL);
4996
4997 #if SASL
4998         /* "auth" */
4999         macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), NULL);
5000         e->e_auth_param = "";
5001 # if _FFR_AUTH_PASSING
5002         macdefine(&BlankEnvelope.e_macro, A_PERM,
5003                                   macid("{auth_author}"), NULL);
5004 # endif
5005 #endif /* SASL */
5006
5007         /* "by" */
5008         e->e_deliver_by = 0;
5009         e->e_dlvr_flag = 0;
5010 }
5011
5012 /*
5013 **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
5014 **
5015 **      Parameters:
5016 **              a -- address (unused, for compatibility with rcpt_esmtp_args)
5017 **              kp -- the parameter key.
5018 **              vp -- the value of that parameter.
5019 **              e -- the envelope.
5020 **
5021 **      Returns:
5022 **              none.
5023 */
5024
5025 void
5026 mail_esmtp_args(a, kp, vp, e)
5027         ADDRESS *a;
5028         char *kp;
5029         char *vp;
5030         ENVELOPE *e;
5031 {
5032         if (SM_STRCASEEQ(kp, "size"))
5033         {
5034                 if (vp == NULL)
5035                 {
5036                         usrerr("501 5.5.2 SIZE requires a value");
5037                         /* NOTREACHED */
5038                 }
5039                 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
5040                 errno = 0;
5041                 e->e_msgsize = strtol(vp, (char **) NULL, 10);
5042                 if (e->e_msgsize == LONG_MAX && errno == ERANGE)
5043                 {
5044                         usrerr("552 5.2.3 Message size exceeds maximum value");
5045                         /* NOTREACHED */
5046                 }
5047                 if (e->e_msgsize < 0)
5048                 {
5049                         usrerr("552 5.2.3 Message size invalid");
5050                         /* NOTREACHED */
5051                 }
5052         }
5053         else if (SM_STRCASEEQ(kp, "body"))
5054         {
5055                 if (vp == NULL)
5056                 {
5057                         usrerr("501 5.5.2 BODY requires a value");
5058                         /* NOTREACHED */
5059                 }
5060                 else if (SM_STRCASEEQ(vp, "8bitmime"))
5061                         ;
5062                 else if (SM_STRCASEEQ(vp, "7bit"))
5063                         e->e_flags |= EF_7BITBODY;
5064                 else
5065                 {
5066                         usrerr("501 5.5.4 Unknown BODY type %s",
5067                                 SHOWCMDINREPLY(vp));
5068                         /* NOTREACHED */
5069                 }
5070                 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
5071         }
5072         else if (SM_STRCASEEQ(kp, "envid"))
5073         {
5074                 if (!bitset(SRV_OFFER_DSN, e->e_features))
5075                 {
5076                         usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
5077                         /* NOTREACHED */
5078                 }
5079                 if (vp == NULL)
5080                 {
5081                         usrerr("501 5.5.2 ENVID requires a value");
5082                         /* NOTREACHED */
5083                 }
5084                 if (!xtextok(vp))
5085                 {
5086                         usrerr("501 5.5.4 Syntax error in ENVID parameter value");
5087                         /* NOTREACHED */
5088                 }
5089                 if (e->e_envid != NULL)
5090                 {
5091                         usrerr("501 5.5.0 Duplicate ENVID parameter");
5092                         /* NOTREACHED */
5093                 }
5094                 e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
5095                 macdefine(&e->e_macro, A_PERM,
5096                         macid("{dsn_envid}"), e->e_envid);
5097         }
5098         else if (SM_STRCASEEQ(kp, "ret"))
5099         {
5100                 if (!bitset(SRV_OFFER_DSN, e->e_features))
5101                 {
5102                         usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
5103                         /* NOTREACHED */
5104                 }
5105                 if (vp == NULL)
5106                 {
5107                         usrerr("501 5.5.2 RET requires a value");
5108                         /* NOTREACHED */
5109                 }
5110                 if (bitset(EF_RET_PARAM, e->e_flags))
5111                 {
5112                         usrerr("501 5.5.0 Duplicate RET parameter");
5113                         /* NOTREACHED */
5114                 }
5115                 e->e_flags |= EF_RET_PARAM;
5116                 if (SM_STRCASEEQ(vp, "hdrs"))
5117                         e->e_flags |= EF_NO_BODY_RETN;
5118                 else if (sm_strcasecmp(vp, "full") != 0)
5119                 {
5120                         usrerr("501 5.5.2 Bad argument \"%s\" to RET",
5121                                 SHOWCMDINREPLY(vp));
5122                         /* NOTREACHED */
5123                 }
5124                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
5125         }
5126 #if SASL
5127         else if (SM_STRCASEEQ(kp, "auth"))
5128         {
5129                 int len;
5130                 char *q;
5131                 char *auth_param;       /* the value of the AUTH=x */
5132                 bool saveQuickAbort = QuickAbort;
5133                 bool saveSuprErrs = SuprErrs;
5134                 bool saveExitStat = ExitStat;
5135
5136                 if (vp == NULL)
5137                 {
5138                         usrerr("501 5.5.2 AUTH= requires a value");
5139                         /* NOTREACHED */
5140                 }
5141                 if (e->e_auth_param != NULL)
5142                 {
5143                         usrerr("501 5.5.0 Duplicate AUTH parameter");
5144                         /* NOTREACHED */
5145                 }
5146                 if ((q = strchr(vp, ' ')) != NULL)
5147                         len = q - vp + 1;
5148                 else
5149                         len = strlen(vp) + 1;
5150                 auth_param = xalloc(len);
5151                 (void) sm_strlcpy(auth_param, vp, len);
5152                 if (!xtextok(auth_param))
5153                 {
5154                         usrerr("501 5.5.4 Syntax error in AUTH parameter value");
5155                         /* just a warning? */
5156                         /* NOTREACHED */
5157                 }
5158
5159                 /* XXX define this always or only if trusted? */
5160                 macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
5161                           auth_param);
5162
5163                 /*
5164                 **  call Strust_auth to find out whether
5165                 **  auth_param is acceptable (trusted)
5166                 **  we shouldn't trust it if not authenticated
5167                 **  (required by RFC, leave it to ruleset?)
5168                 */
5169
5170                 SuprErrs = true;
5171                 QuickAbort = false;
5172                 if (strcmp(auth_param, "<>") != 0 &&
5173                      (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM, 9,
5174                               NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0))
5175                 {
5176                         if (tTd(95, 8))
5177                         {
5178                                 q = e->e_auth_param;
5179                                 sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
5180                                         auth_param, (q == NULL) ? "" : q);
5181                         }
5182
5183                         /* not trusted */
5184                         e->e_auth_param = "<>";
5185 # if _FFR_AUTH_PASSING
5186                         macdefine(&BlankEnvelope.e_macro, A_PERM,
5187                                   macid("{auth_author}"), NULL);
5188 # endif
5189                 }
5190                 else
5191                 {
5192                         if (tTd(95, 8))
5193                                 sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
5194                         e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
5195                                                             auth_param);
5196                 }
5197                 sm_free(auth_param); /* XXX */
5198
5199                 /* reset values */
5200                 Errors = 0;
5201                 QuickAbort = saveQuickAbort;
5202                 SuprErrs = saveSuprErrs;
5203                 ExitStat = saveExitStat;
5204         }
5205 #endif /* SASL */
5206 #define PRTCHAR(c)      ((isascii(c) && isprint(c)) ? (c) : '?')
5207
5208         /*
5209         **  "by" is only accepted if DeliverByMin >= 0.
5210         **  We maybe could add this to the list of server_features.
5211         */
5212
5213         else if (SM_STRCASEEQ(kp, "by") && DeliverByMin >= 0)
5214         {
5215                 char *s;
5216
5217                 if (vp == NULL)
5218                 {
5219                         usrerr("501 5.5.2 BY= requires a value");
5220                         /* NOTREACHED */
5221                 }
5222                 errno = 0;
5223                 e->e_deliver_by = strtol(vp, &s, 10);
5224                 if (e->e_deliver_by == LONG_MIN ||
5225                     e->e_deliver_by == LONG_MAX ||
5226                     e->e_deliver_by > 999999999l ||
5227                     e->e_deliver_by < -999999999l)
5228                 {
5229                         usrerr("501 5.5.2 BY=%s out of range",
5230                                 SHOWCMDINREPLY(vp));
5231                         /* NOTREACHED */
5232                 }
5233                 if (s == NULL || *s != ';')
5234                 {
5235                         usrerr("501 5.5.2 BY= missing ';'");
5236                         /* NOTREACHED */
5237                 }
5238                 e->e_dlvr_flag = 0;
5239                 ++s;    /* XXX: spaces allowed? */
5240                 SKIP_SPACE(s);
5241                 switch (tolower(*s))
5242                 {
5243                   case 'n':
5244                         e->e_dlvr_flag = DLVR_NOTIFY;
5245                         break;
5246                   case 'r':
5247                         e->e_dlvr_flag = DLVR_RETURN;
5248                         if (e->e_deliver_by <= 0)
5249                         {
5250                                 usrerr("501 5.5.4 mode R requires BY time > 0");
5251                                 /* NOTREACHED */
5252                         }
5253                         if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
5254                             e->e_deliver_by < DeliverByMin)
5255                         {
5256                                 usrerr("555 5.5.2 time %ld less than %ld",
5257                                         e->e_deliver_by, (long) DeliverByMin);
5258                                 /* NOTREACHED */
5259                         }
5260                         break;
5261                   default:
5262                         usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
5263                         /* NOTREACHED */
5264                 }
5265                 ++s;    /* XXX: spaces allowed? */
5266                 SKIP_SPACE(s);
5267                 switch (tolower(*s))
5268                 {
5269                   case 't':
5270                         e->e_dlvr_flag |= DLVR_TRACE;
5271                         break;
5272                   case '\0':
5273                         break;
5274                   default:
5275                         usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
5276                         /* NOTREACHED */
5277                 }
5278
5279                 /* XXX: check whether more characters follow? */
5280         }
5281 #if USE_EAI
5282         else if (SM_STRCASEEQ(kp, "smtputf8"))
5283         {
5284                 if (!bitset(SRV_OFFER_EAI, e->e_features))
5285                 {
5286                         usrerr("504 5.7.0 Sorry, SMTPUTF8 not supported");
5287                         /* NOTREACHED */
5288                 }
5289                 e->e_smtputf8 = true;
5290         }
5291 #endif
5292         else
5293         {
5294                 usrerr("555 5.5.4 %s parameter unrecognized",
5295                         SHOWCMDINREPLY(kp));
5296                 /* NOTREACHED */
5297         }
5298 }
5299
5300 /*
5301 **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
5302 **
5303 **      Parameters:
5304 **              a -- the address corresponding to the To: parameter.
5305 **              kp -- the parameter key.
5306 **              vp -- the value of that parameter.
5307 **              e -- the envelope.
5308 **
5309 **      Returns:
5310 **              none.
5311 */
5312
5313 void
5314 rcpt_esmtp_args(a, kp, vp, e)
5315         ADDRESS *a;
5316         char *kp;
5317         char *vp;
5318         ENVELOPE *e;
5319 {
5320         if (SM_STRCASEEQ(kp, "notify"))
5321         {
5322                 char *p;
5323
5324                 if (!bitset(SRV_OFFER_DSN, e->e_features))
5325                 {
5326                         usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
5327                         /* NOTREACHED */
5328                 }
5329                 if (vp == NULL)
5330                 {
5331                         usrerr("501 5.5.2 NOTIFY requires a value");
5332                         /* NOTREACHED */
5333                 }
5334                 a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
5335                 a->q_flags |= QHASNOTIFY;
5336                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
5337
5338                 if (SM_STRCASEEQ(vp, "never"))
5339                         return;
5340                 for (p = vp; p != NULL; vp = p)
5341                 {
5342                         char *s;
5343
5344                         s = p = strchr(p, ',');
5345                         if (p != NULL)
5346                                 *p++ = '\0';
5347                         if (SM_STRCASEEQ(vp, "success"))
5348                                 a->q_flags |= QPINGONSUCCESS;
5349                         else if (SM_STRCASEEQ(vp, "failure"))
5350                                 a->q_flags |= QPINGONFAILURE;
5351                         else if (SM_STRCASEEQ(vp, "delay"))
5352                                 a->q_flags |= QPINGONDELAY;
5353                         else
5354                         {
5355                                 usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
5356                                         SHOWCMDINREPLY(vp));
5357                                 /* NOTREACHED */
5358                         }
5359                         if (s != NULL)
5360                                 *s = ',';
5361                 }
5362         }
5363         else if (SM_STRCASEEQ(kp, "orcpt"))
5364         {
5365                 char *p;
5366
5367                 if (!bitset(SRV_OFFER_DSN, e->e_features))
5368                 {
5369                         usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
5370                         /* NOTREACHED */
5371                 }
5372                 if (vp == NULL)
5373                 {
5374                         usrerr("501 5.5.2 ORCPT requires a value");
5375                         /* NOTREACHED */
5376                 }
5377                 if (a->q_orcpt != NULL)
5378                 {
5379                         usrerr("501 5.5.0 Duplicate ORCPT parameter");
5380                         /* NOTREACHED */
5381                 }
5382                 p = strchr(vp, ';');
5383                 if (p == NULL)
5384                 {
5385                         usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5386                         /* NOTREACHED */
5387                 }
5388                 *p = '\0';
5389 #if USE_EAI
5390                 if (SM_STRCASEEQ(vp, "utf-8"))
5391                 {
5392                         /* XXX check syntax of p+1 ! */
5393                         if (!xtextok(p + 1) &&
5394                             uxtext_unquote(p + 1, NULL, MAXNAME_I) <= 0)
5395                         {
5396                                 *p = ';';
5397                                 usrerr("501 5.5.4 Syntax error in UTF-8 ORCPT parameter value");
5398                                 /* NOTREACHED */
5399                         }
5400 # if 0
5401 complicated... see grammar!
5402 RFC 6533 Internationalized Delivery Status and Disposition Notifications
5403 utf-8-enc-addr = utf-8-addr-xtext / utf-8-addr-unitext / utf-8-address
5404 # endif
5405                 }
5406                 else
5407 #endif /* USE_EAI */
5408                 /* "else" in #if code above */
5409                 if (!isatom(vp) || !xtextok(p + 1))
5410                 {
5411                         *p = ';';
5412                         usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5413                         /* NOTREACHED */
5414                 }
5415                 *p = ';';
5416                 a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
5417         }
5418         else
5419         {
5420                 usrerr("555 5.5.4 %s parameter unrecognized",
5421                         SHOWCMDINREPLY(kp));
5422                 /* NOTREACHED */
5423         }
5424 }
5425 /*
5426 **  PRINTVRFYADDR -- print an entry in the verify queue
5427 **
5428 **      Parameters:
5429 **              a -- the address to print.
5430 **              last -- set if this is the last one.
5431 **              vrfy -- set if this is a VRFY command.
5432 **
5433 **      Returns:
5434 **              none.
5435 **
5436 **      Side Effects:
5437 **              Prints the appropriate 250 codes.
5438 */
5439 #define OFFF    (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */
5440
5441 static void
5442 printvrfyaddr(a, last, vrfy)
5443         register ADDRESS *a;
5444         bool last;
5445         bool vrfy;
5446 {
5447         char fmtbuf[30];
5448
5449         if (vrfy && a->q_mailer != NULL &&
5450             !bitnset(M_VRFY250, a->q_mailer->m_flags))
5451                 (void) sm_strlcpy(fmtbuf, "252", sizeof(fmtbuf));
5452         else
5453                 (void) sm_strlcpy(fmtbuf, "250", sizeof(fmtbuf));
5454         fmtbuf[3] = last ? ' ' : '-';
5455         (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof(fmtbuf) - 4);
5456         if (a->q_fullname == NULL)
5457         {
5458                 if ((a->q_mailer == NULL ||
5459                      a->q_mailer->m_addrtype == NULL ||
5460                      SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5461                     strchr(a->q_user, '@') == NULL)
5462                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
5463                                        sizeof(fmtbuf) - OFFF);
5464                 else
5465                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
5466                                        sizeof(fmtbuf) - OFFF);
5467                 message(fmtbuf, a->q_user, MyHostName);
5468         }
5469         else
5470         {
5471                 if ((a->q_mailer == NULL ||
5472                      a->q_mailer->m_addrtype == NULL ||
5473                      SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5474                     strchr(a->q_user, '@') == NULL)
5475                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
5476                                        sizeof(fmtbuf) - OFFF);
5477                 else
5478                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
5479                                        sizeof(fmtbuf) - OFFF);
5480                 message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
5481         }
5482 }
5483
5484 #if SASL
5485 /*
5486 **  SASLMECHS -- get list of possible AUTH mechanisms
5487 **
5488 **      Parameters:
5489 **              conn -- SASL connection info.
5490 **              mechlist -- output parameter for list of mechanisms.
5491 **
5492 **      Returns:
5493 **              number of mechs.
5494 */
5495
5496 static int
5497 saslmechs(conn, mechlist)
5498         sasl_conn_t *conn;
5499         char **mechlist;
5500 {
5501         int len, num, result;
5502
5503         /* "user" is currently unused */
5504 # if SASL >= 20000
5505         result = sasl_listmech(conn, NULL,
5506                                "", " ", "", (const char **) mechlist,
5507                                (unsigned int *)&len, &num);
5508 # else /* SASL >= 20000 */
5509         result = sasl_listmech(conn, "user", /* XXX */
5510                                "", " ", "", mechlist,
5511                                (unsigned int *)&len, (unsigned int *)&num);
5512 # endif /* SASL >= 20000 */
5513         if (result != SASL_OK)
5514         {
5515                 if (LogLevel > 9)
5516                         sm_syslog(LOG_WARNING, NOQID,
5517                                   "AUTH error: listmech=%d, num=%d",
5518                                   result, num);
5519                 num = 0;
5520         }
5521         if (num > 0)
5522         {
5523                 if (LogLevel > 11)
5524                         sm_syslog(LOG_INFO, NOQID,
5525                                   "AUTH: available mech=%s, allowed mech=%s",
5526                                   *mechlist, AuthMechanisms);
5527                 *mechlist = intersect(AuthMechanisms, *mechlist, NULL);
5528         }
5529         else
5530         {
5531                 *mechlist = NULL;       /* be paranoid... */
5532                 if (result == SASL_OK && LogLevel > 9)
5533                         sm_syslog(LOG_WARNING, NOQID,
5534                                   "AUTH warning: no mechanisms");
5535         }
5536         return num;
5537 }
5538
5539 # if SASL >= 20000
5540 /*
5541 **  PROXY_POLICY -- define proxy policy for AUTH
5542 **
5543 **      Parameters:
5544 **              conn -- unused.
5545 **              context -- unused.
5546 **              requested_user -- authorization identity.
5547 **              rlen -- authorization identity length.
5548 **              auth_identity -- authentication identity.
5549 **              alen -- authentication identity length.
5550 **              def_realm -- default user realm.
5551 **              urlen -- user realm length.
5552 **              propctx -- unused.
5553 **
5554 **      Returns:
5555 **              ok?
5556 **
5557 **      Side Effects:
5558 **              sets {auth_authen} macro.
5559 */
5560
5561 int
5562 proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
5563              def_realm, urlen, propctx)
5564         sasl_conn_t *conn;
5565         void *context;
5566         const char *requested_user;
5567         unsigned rlen;
5568         const char *auth_identity;
5569         unsigned alen;
5570         const char *def_realm;
5571         unsigned urlen;
5572         struct propctx *propctx;
5573 {
5574         if (auth_identity == NULL)
5575                 return SASL_FAIL;
5576
5577         macdefine(&BlankEnvelope.e_macro, A_TEMP,
5578                   macid("{auth_authen}"),
5579                   xtextify((char *) auth_identity, "=<>\")"));
5580
5581         return SASL_OK;
5582 }
5583 # else /* SASL >= 20000 */
5584
5585 /*
5586 **  PROXY_POLICY -- define proxy policy for AUTH
5587 **
5588 **      Parameters:
5589 **              context -- unused.
5590 **              auth_identity -- authentication identity.
5591 **              requested_user -- authorization identity.
5592 **              user -- allowed user (output).
5593 **              errstr -- possible error string (output).
5594 **
5595 **      Returns:
5596 **              ok?
5597 */
5598
5599 int
5600 proxy_policy(context, auth_identity, requested_user, user, errstr)
5601         void *context;
5602         const char *auth_identity;
5603         const char *requested_user;
5604         const char **user;
5605         const char **errstr;
5606 {
5607         if (user == NULL || auth_identity == NULL)
5608                 return SASL_FAIL;
5609         *user = newstr(auth_identity);
5610         return SASL_OK;
5611 }
5612 # endif /* SASL >= 20000 */
5613 #endif /* SASL */
5614
5615 #if STARTTLS
5616 /*
5617 **  INITSRVTLS -- initialize server side TLS
5618 **
5619 **      Parameters:
5620 **              tls_ok -- should tls initialization be done?
5621 **
5622 **      Returns:
5623 **              succeeded?
5624 **
5625 **      Side Effects:
5626 **              sets tls_ok_srv which is a static variable in this module.
5627 **              Do NOT remove assignments to it!
5628 */
5629
5630 bool
5631 initsrvtls(tls_ok)
5632         bool tls_ok;
5633 {
5634         if (!tls_ok)
5635                 return false;
5636
5637         /* do NOT remove assignment */
5638         tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, Srv_SSL_Options, true,
5639                              SrvCertFile, SrvKeyFile,
5640                              CACertPath, CACertFile, DHParams);
5641         return tls_ok_srv;
5642 }
5643 #endif /* STARTTLS */
5644 /*
5645 **  SRVFEATURES -- get features for SMTP server
5646 **
5647 **      Parameters:
5648 **              e -- envelope (should be session context).
5649 **              clientname -- name of client.
5650 **              features -- default features for this invocation.
5651 **
5652 **      Returns:
5653 **              server features.
5654 */
5655
5656 /* table with options: it uses just one character, how about strings? */
5657 static struct
5658 {
5659         char            srvf_opt;
5660         unsigned long   srvf_flag;
5661         unsigned long   srvf_flag2;
5662 } srv_feat_table[] =
5663 {
5664         { 'A',  SRV_OFFER_AUTH  , 0     },
5665         { 'B',  SRV_OFFER_VERB  , 0     },
5666         { 'C',  SRV_REQ_SEC     , 0     },
5667         { 'D',  SRV_OFFER_DSN   , 0     },
5668         { 'E',  SRV_OFFER_ETRN  , 0     },
5669         { 'F',  SRV_BAD_PIPELINE        , 0     },
5670         { 'G',  SRV_BARE_LF_421 , SRV_BARE_LF_SP        },
5671         { 'H',  SRV_NO_HTTP_CMD , 0     },
5672 #if USE_EAI
5673         { 'I',  SRV_OFFER_EAI   , 0     },
5674 #endif
5675 /*      { 'J',  0       , 0     },      */
5676 /*      { 'K',  0       , 0     },      */
5677         { 'L',  SRV_REQ_AUTH    , 0     },
5678 /*      { 'M',  0       , 0     },      */
5679 #if PIPELINING && _FFR_NO_PIPE
5680         { 'N',  SRV_NO_PIPE     , 0     },
5681 #endif
5682         { 'O',  SRV_REQ_CRLF    , 0     },      /* eOl */
5683 #if PIPELINING
5684         { 'P',  SRV_OFFER_PIPE  , 0     },
5685 #endif
5686 /*      { 'Q',  0       , 0     },      */
5687         { 'R',  SRV_VRFY_CLT    , 0     },      /* same as V; not documented */
5688         { 'S',  SRV_OFFER_TLS   , 0     },
5689 /*      { 'T',  SRV_TMP_FAIL    , 0     },      */
5690         { 'U',  SRV_BARE_CR_421 , SRV_BARE_CR_SP        },
5691         { 'V',  SRV_VRFY_CLT    , 0     },
5692 /*      { 'W',  0       , 0     },      */
5693         { 'X',  SRV_OFFER_EXPN  , 0     },
5694 /*      { 'Y',  SRV_OFFER_VRFY  , 0     },      */
5695 /*      { 'Z',  0       , 0     },      */
5696         { '\0', SRV_NONE        , 0     }
5697 };
5698
5699 static unsigned long
5700 srvfeatures(e, clientname, features)
5701         ENVELOPE *e;
5702         char *clientname;
5703         unsigned long features;
5704 {
5705         int r, i, j;
5706         char **pvp, c, opt;
5707         char pvpbuf[PSBUFSIZE];
5708
5709         pvp = NULL;
5710         r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
5711                   sizeof(pvpbuf));
5712         if (r != EX_OK)
5713                 return features;
5714         if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
5715                 return features;
5716         if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
5717                 return SRV_TMP_FAIL;
5718
5719         /*
5720         **  General rule (see sendmail.h, d_flags):
5721         **  lower case: required/offered, upper case: Not required/available
5722         **
5723         **  Since we can change some features per daemon, we have both
5724         **  cases here: turn on/off a feature.
5725         */
5726
5727         for (i = 1; pvp[i] != NULL; i++)
5728         {
5729                 c = pvp[i][0];
5730                 j = 0;
5731                 for (;;)
5732                 {
5733                         if ((opt = srv_feat_table[j].srvf_opt) == '\0')
5734                         {
5735                                 if (LogLevel > 9)
5736                                         sm_syslog(LOG_WARNING, e->e_id,
5737                                                   "srv_features: unknown feature %s",
5738                                                   pvp[i]);
5739                                 break;
5740                         }
5741                         if (c == opt)
5742                         {
5743                                 features &= ~(srv_feat_table[j].srvf_flag);
5744                                 break;
5745                         }
5746
5747                         /*
5748                         **  Note: the "noflag" code below works ONLY for
5749                         **  the current situation:
5750                         **  - _flag itself is set by default
5751                         **    (drop session if bare CR or LF is found)
5752                         **  - _flag2 is only "effective" if _flag is not set,
5753                         **    hence using it turns off _flag.
5754                         **  If that situation changes, the code must be changed!
5755                         */
5756
5757                         if (c == tolower(opt))
5758                         {
5759                                 unsigned long flag, noflag;
5760
5761                                 c = pvp[i][1];
5762                                 flag = noflag = 0;
5763                                 if ('2' == c)
5764                                 {
5765                                         flag = srv_feat_table[j].srvf_flag2;
5766                                         noflag = srv_feat_table[j].srvf_flag;
5767                                 }
5768                                 else if ('\0' == c)
5769                                         flag = srv_feat_table[j].srvf_flag;
5770                                 if (0 != flag)
5771                                 {
5772                                         features |= flag;
5773                                         if (0 != noflag)
5774                                                 features &= ~noflag;
5775                                 }
5776                                 else if (LogLevel > 9)
5777                                         sm_syslog(LOG_WARNING, e->e_id,
5778                                                   "srv_features: unknown variant %s",
5779                                                   pvp[i]);
5780                                 break;
5781                         }
5782                         ++j;
5783                 }
5784         }
5785         return features;
5786 }
5787
5788 /*
5789 **  HELP -- implement the HELP command.
5790 **
5791 **      Parameters:
5792 **              topic -- the topic we want help for.
5793 **              e -- envelope.
5794 **
5795 **      Returns:
5796 **              none.
5797 **
5798 **      Side Effects:
5799 **              outputs the help file to message output.
5800 */
5801 #define HELPVSTR        "#vers  "
5802 #define HELPVERSION     2
5803
5804 void
5805 help(topic, e)
5806         char *topic;
5807         ENVELOPE *e;
5808 {
5809         register SM_FILE_T *hf;
5810         register char *p;
5811         char *lstr;
5812         int len;
5813         bool noinfo;
5814         bool first = true;
5815         long sff = SFF_OPENASROOT|SFF_REGONLY;
5816         char buf[MAXLINE];
5817         char inp[MAXLINE];
5818         static int foundvers = -1;
5819         extern char Version[];
5820
5821         if (DontLockReadFiles)
5822                 sff |= SFF_NOLOCK;
5823         if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
5824                 sff |= SFF_SAFEDIRPATH;
5825
5826         if (HelpFile == NULL ||
5827             (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
5828         {
5829                 /* no help */
5830                 errno = 0;
5831                 message("502 5.3.0 Sendmail %s -- HELP not implemented",
5832                         Version);
5833                 return;
5834         }
5835
5836         lstr = NULL;
5837         if (SM_IS_EMPTY(topic))
5838         {
5839                 topic = "smtp";
5840                 noinfo = false;
5841         }
5842         else
5843         {
5844
5845                 lstr = makelower_a(&topic, NULL);
5846                 if (lstr != topic)
5847                         topic = lstr;
5848                 else
5849                         lstr = NULL;
5850                 noinfo = true;
5851         }
5852
5853         len = strlen(topic);
5854
5855         while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
5856         {
5857                 if (buf[0] == '#')
5858                 {
5859                         if (foundvers < 0 &&
5860                             strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
5861                         {
5862                                 int h;
5863
5864                                 if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
5865                                                  &h) == 1)
5866                                         foundvers = h;
5867                         }
5868                         continue;
5869                 }
5870                 if (strncmp(buf, topic, len) == 0)
5871                 {
5872                         if (first)
5873                         {
5874                                 first = false;
5875
5876                                 /* print version if no/old vers# in file */
5877                                 if (foundvers < 2 && !noinfo)
5878                                         message("214-2.0.0 This is Sendmail version %s", Version);
5879                         }
5880                         p = strpbrk(buf, " \t");
5881                         if (p == NULL)
5882                                 p = buf + strlen(buf) - 1;
5883                         else
5884                                 p++;
5885                         fixcrlf(p, true);
5886                         if (foundvers >= 2)
5887                         {
5888                                 char *lbp;
5889                                 int lbs = sizeof(buf) - (p - buf);
5890
5891                                 lbp = translate_dollars(p, p, &lbs);
5892                                 expand(lbp, inp, sizeof(inp), e);
5893                                 if (p != lbp)
5894                                         sm_free(lbp);
5895                                 p = inp;
5896                         }
5897                         message("214-2.0.0 %s", p);
5898                         noinfo = false;
5899                 }
5900         }
5901
5902         if (noinfo)
5903                 message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
5904         else
5905                 message("214 2.0.0 End of HELP info");
5906
5907         if (foundvers != 0 && foundvers < HELPVERSION)
5908         {
5909                 if (LogLevel > 1)
5910                         sm_syslog(LOG_WARNING, e->e_id,
5911                                   "%s too old (require version %d)",
5912                                   HelpFile, HELPVERSION);
5913
5914                 /* avoid log next time */
5915                 foundvers = 0;
5916         }
5917
5918         (void) sm_io_close(hf, SM_TIME_DEFAULT);
5919         SM_FREE(lstr);
5920 }
5921
5922 #if SASL
5923 /*
5924 **  RESET_SASLCONN -- reset SASL connection data
5925 **
5926 **      Parameters:
5927 **              conn -- SASL connection context
5928 **              hostname -- host name
5929 **              various connection data
5930 **
5931 **      Returns:
5932 **              SASL result
5933 */
5934
5935 #ifdef __STDC__
5936 static int
5937 reset_saslconn(sasl_conn_t **conn, char *hostname,
5938 # if SASL >= 20000
5939                char *remoteip, char *localip,
5940                char *auth_id, sasl_ssf_t * ext_ssf)
5941 # else /* SASL >= 20000 */
5942                struct sockaddr_in *saddr_r, struct sockaddr_in *saddr_l,
5943                sasl_external_properties_t * ext_ssf)
5944 # endif /* SASL >= 20000 */
5945 #else /* __STDC__ */
5946 # error "SASL requires __STDC__"
5947 #endif /* __STDC__ */
5948 {
5949         int result;
5950
5951         sasl_dispose(conn);
5952 # if SASL >= 20000
5953         result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
5954                                  NULL, 0, conn);
5955 # elif SASL > 10505
5956         /* use empty realm: only works in SASL > 1.5.5 */
5957         result = sasl_server_new("smtp", hostname, "", NULL, 0, conn);
5958 # else /* SASL >= 20000 */
5959         /* use no realm -> realm is set to hostname by SASL lib */
5960         result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
5961                                  conn);
5962 # endif /* SASL >= 20000 */
5963         if (result != SASL_OK)
5964                 return result;
5965
5966 # if SASL >= 20000
5967 #  if NETINET || NETINET6
5968         if (remoteip != NULL && *remoteip != '\0')
5969                 result = sasl_setprop(*conn, SASL_IPREMOTEPORT, remoteip);
5970         if (result != SASL_OK)
5971                 return result;
5972
5973         if (localip != NULL && *localip != '\0')
5974                 result = sasl_setprop(*conn, SASL_IPLOCALPORT, localip);
5975         if (result != SASL_OK)
5976                 return result;
5977 #  endif /* NETINET || NETINET6 */
5978
5979         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
5980         if (result != SASL_OK)
5981                 return result;
5982
5983         result = sasl_setprop(*conn, SASL_AUTH_EXTERNAL, auth_id);
5984         if (result != SASL_OK)
5985                 return result;
5986 # else /* SASL >= 20000 */
5987 #  if NETINET
5988         if (saddr_r != NULL)
5989                 result = sasl_setprop(*conn, SASL_IP_REMOTE, saddr_r);
5990         if (result != SASL_OK)
5991                 return result;
5992
5993         if (saddr_l != NULL)
5994                 result = sasl_setprop(*conn, SASL_IP_LOCAL, saddr_l);
5995         if (result != SASL_OK)
5996                 return result;
5997 #  endif /* NETINET */
5998
5999         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
6000         if (result != SASL_OK)
6001                 return result;
6002 # endif /* SASL >= 20000 */
6003         return SASL_OK;
6004 }
6005
6006 /*
6007 **  GET_SASL_USER -- extract user part from SASL reply
6008 **
6009 **      Parameters:
6010 **              val -- sasl reply (may contain NUL)
6011 **              len -- length of val
6012 **              auth_type -- auth_type (can be NULL)
6013 **              user -- output buffer for extract user
6014 **              user_len -- length of output buffer (user)
6015 **
6016 **      Returns:
6017 **              none.
6018 **
6019 **      Note: val is supplied by the client and hence may contain "bad"
6020 **              (non-printable) characters, but the returned value (user)
6021 **              is only used for logging which converts those characters.
6022 */
6023
6024 static void
6025 get_sasl_user(val, len, auth_type, user, user_len)
6026         char *val;
6027         unsigned int len;
6028         const char *auth_type;
6029         char *user;
6030         size_t user_len;
6031 {
6032         unsigned int u;
6033
6034         SM_ASSERT(val != NULL);
6035         SM_ASSERT(user != NULL);
6036         SM_ASSERT(user_len > 0);
6037
6038         *user = '\0';
6039         if (SM_IS_EMPTY(auth_type))
6040                 return;
6041         if (0 == len)
6042                 return;
6043
6044 # define DIGMD5U        "username=\""
6045 # define DIGMD5U_L      (sizeof(DIGMD5U) - 1)
6046         if (SM_STRCASEEQ(auth_type, "digest-md5") &&
6047             strncmp(val, DIGMD5U, DIGMD5U_L) == 0)
6048         {
6049                 char *s;
6050
6051                 val += DIGMD5U_L;
6052                 if (len <= DIGMD5U_L)
6053                         return;
6054                 len -= DIGMD5U_L;
6055
6056                 /* format? could there be a quoted '"'? */
6057                 for (s = val, u = 0; *s != '\0' && u < len; s++)
6058                 {
6059                         if ('"' == *s)
6060                         {
6061                                 *s = '\0';
6062                                 break;
6063                         }
6064                         if ('\\' == *s)
6065                         {
6066                                 ++s;
6067                                 if ('\0' == *s)
6068                                         break;
6069                         }
6070                 }
6071         }
6072         else if (SM_STRCASEEQ(auth_type, "cram-md5"))
6073         {
6074                 char *s;
6075
6076                 for (s = val, u = 0; *s != '\0' && u < len; s++)
6077                 {
6078                         if (' ' == *s)
6079                         {
6080                                 *s = '\0';
6081                                 break;
6082                         }
6083                 }
6084         }
6085
6086         else if (SM_STRCASEEQ(auth_type, "plain") ||
6087                  SM_STRCASEEQ(auth_type, "login"))
6088         {
6089                 /*
6090                 **  RFC 4616: The PLAIN Simple Authentication and
6091                 **      Security Layer (SASL) Mechanism
6092                 **    message   = [authzid] UTF8NUL authcid UTF8NUL passwd
6093                 **  each part: 1*SAFE ; MUST accept up to 255 octets
6094                 **  UTF8NUL   = %x00 ; UTF-8 encoded NUL character
6095                 **
6096                 **  draft-murchison-sasl-login: it's just username by its own
6097                 */
6098
6099                 for (u = 0; u < len; u++)
6100                 {
6101                         if (val[u] == '\0')
6102                         {
6103                                 val[u] = '/';
6104                                 (void) sm_strlcpy(user,
6105                                                 val + ((0 == u) ? 1 : 0),
6106                                                 user_len);
6107                                 return;
6108                         }
6109                 }
6110         }
6111         else
6112         {
6113                 /*
6114                 **  Extracting the "user" from other mechanisms
6115                 **  is currently not supported.
6116                 */
6117
6118                 return;
6119         }
6120
6121         /*
6122         **  Does the input buffer has an NUL in it so it can be treated
6123         **  as a C string?
6124         */
6125
6126         /* SM_ASSERT(len > 0); see above */
6127         u = len - 1;
6128         if (val[u] != '\0')
6129         {
6130                 for (u = 0; u < len; u++)
6131                 {
6132                         if (val[u] == '\0')
6133                                 break;
6134                 }
6135         }
6136         if (val[u] != '\0')
6137                 user_len = SM_MIN(len, user_len);
6138
6139         (void) sm_strlcpy(user, val, user_len);
6140 }
6141 #endif /* SASL */