Merge from vendor branch OPENPAM:
[dragonfly.git] / contrib / sendmail-8.13.4 / sendmail / srvrsmtp.c
1 /*
2  * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5  * Copyright (c) 1988, 1993
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * By using this file, you agree to the terms and conditions set
9  * forth in the LICENSE file which can be found at the top level of
10  * the sendmail distribution.
11  *
12  */
13
14 #include <sendmail.h>
15 #if MILTER
16 # include <libmilter/mfapi.h>
17 # include <libmilter/mfdef.h>
18 #endif /* MILTER */
19
20 SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.906 2005/03/16 00:36:09 ca Exp $")
21
22 #include <sys/time.h>
23 #include <sm/fdset.h>
24
25 #if SASL || STARTTLS
26 # include "sfsasl.h"
27 #endif /* SASL || STARTTLS */
28 #if SASL
29 # define ENC64LEN(l)    (((l) + 2) * 4 / 3 + 1)
30 static int saslmechs __P((sasl_conn_t *, char **));
31 #endif /* SASL */
32 #if STARTTLS
33 # include <sysexits.h>
34
35 static SSL_CTX  *srv_ctx = NULL;        /* TLS server context */
36 static SSL      *srv_ssl = NULL;        /* per connection context */
37
38 static bool     tls_ok_srv = false;
39
40 extern void     tls_set_verify __P((SSL_CTX *, SSL *, bool));
41 # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
42                                 bitset(SRV_VRFY_CLT, features))
43 #endif /* STARTTLS */
44
45 /* server features */
46 #define SRV_NONE        0x0000  /* none... */
47 #define SRV_OFFER_TLS   0x0001  /* offer STARTTLS */
48 #define SRV_VRFY_CLT    0x0002  /* request a cert */
49 #define SRV_OFFER_AUTH  0x0004  /* offer AUTH */
50 #define SRV_OFFER_ETRN  0x0008  /* offer ETRN */
51 #define SRV_OFFER_VRFY  0x0010  /* offer VRFY (not yet used) */
52 #define SRV_OFFER_EXPN  0x0020  /* offer EXPN */
53 #define SRV_OFFER_VERB  0x0040  /* offer VERB */
54 #define SRV_OFFER_DSN   0x0080  /* offer DSN */
55 #if PIPELINING
56 # define SRV_OFFER_PIPE 0x0100  /* offer PIPELINING */
57 # if _FFR_NO_PIPE
58 #  define SRV_NO_PIPE   0x0200  /* disable PIPELINING, sleep if used */
59 # endif /* _FFR_NO_PIPE */
60 #endif /* PIPELINING */
61 #define SRV_REQ_AUTH    0x0400  /* require AUTH */
62 #define SRV_REQ_SEC     0x0800  /* require security - equiv to AuthOptions=p */
63 #define SRV_TMP_FAIL    0x1000  /* ruleset caused a temporary failure */
64
65 static unsigned int     srvfeatures __P((ENVELOPE *, char *, unsigned int));
66
67 #define STOP_ATTACK     ((time_t) -1)
68 static time_t   checksmtpattack __P((volatile unsigned int *, unsigned int,
69                                      bool, char *, ENVELOPE *));
70 static void     mail_esmtp_args __P((char *, char *, ENVELOPE *));
71 static void     printvrfyaddr __P((ADDRESS *, bool, bool));
72 static void     rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
73 static char     *skipword __P((char *volatile, char *));
74 static void     setup_smtpd_io __P((void));
75
76 #if SASL
77 # if SASL >= 20000
78 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
79                                 char *_remoteip, char *_localip,
80                                 char *_auth_id, sasl_ssf_t *_ext_ssf));
81
82 # define RESET_SASLCONN \
83         do                                                      \
84         {                                                       \
85                 result = reset_saslconn(&conn, AuthRealm, remoteip, \
86                                         localip, auth_id, &ext_ssf); \
87                 if (result != SASL_OK)                          \
88                         sasl_ok = false;                        \
89         } while (0)
90
91 # else /* SASL >= 20000 */
92 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
93                                 struct sockaddr_in *_saddr_r,
94                                 struct sockaddr_in *_saddr_l,
95                                 sasl_external_properties_t *_ext_ssf));
96 # define RESET_SASLCONN \
97         do                                                      \
98         {                                                       \
99                 result = reset_saslconn(&conn, AuthRealm, &saddr_r, \
100                                         &saddr_l, &ext_ssf);    \
101                 if (result != SASL_OK)                          \
102                         sasl_ok = false;                        \
103         } while (0)
104
105 # endif /* SASL >= 20000 */
106 #endif /* SASL */
107
108 extern ENVELOPE BlankEnvelope;
109
110 #define NBADRCPTS                                               \
111         do                                                      \
112         {                                                       \
113                 char buf[16];                                   \
114                 (void) sm_snprintf(buf, sizeof buf, "%d",       \
115                         BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
116                                 ? n_badrcpts - 1 : n_badrcpts); \
117                 macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
118         } while (0)
119
120 #define SKIP_SPACE(s)   while (isascii(*s) && isspace(*s))      \
121                                 (s)++
122
123 /*
124 **  SMTP -- run the SMTP protocol.
125 **
126 **      Parameters:
127 **              nullserver -- if non-NULL, rejection message for
128 **                      (almost) all SMTP commands.
129 **              d_flags -- daemon flags
130 **              e -- the envelope.
131 **
132 **      Returns:
133 **              never.
134 **
135 **      Side Effects:
136 **              Reads commands from the input channel and processes them.
137 */
138
139 /*
140 **  Notice: The smtp server doesn't have a session context like the client
141 **      side has (mci). Therefore some data (session oriented) is allocated
142 **      or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
143 **      This should be fixed in a successor version.
144 */
145
146 struct cmd
147 {
148         char    *cmd_name;      /* command name */
149         int     cmd_code;       /* internal code, see below */
150 };
151
152 /* values for cmd_code */
153 #define CMDERROR        0       /* bad command */
154 #define CMDMAIL 1       /* mail -- designate sender */
155 #define CMDRCPT 2       /* rcpt -- designate recipient */
156 #define CMDDATA 3       /* data -- send message text */
157 #define CMDRSET 4       /* rset -- reset state */
158 #define CMDVRFY 5       /* vrfy -- verify address */
159 #define CMDEXPN 6       /* expn -- expand address */
160 #define CMDNOOP 7       /* noop -- do nothing */
161 #define CMDQUIT 8       /* quit -- close connection and die */
162 #define CMDHELO 9       /* helo -- be polite */
163 #define CMDHELP 10      /* help -- give usage info */
164 #define CMDEHLO 11      /* ehlo -- extended helo (RFC 1425) */
165 #define CMDETRN 12      /* etrn -- flush queue */
166 #if SASL
167 # define CMDAUTH        13      /* auth -- SASL authenticate */
168 #endif /* SASL */
169 #if STARTTLS
170 # define CMDSTLS        14      /* STARTTLS -- start TLS session */
171 #endif /* STARTTLS */
172 /* non-standard commands */
173 #define CMDVERB 17      /* verb -- go into verbose mode */
174 /* unimplemented commands from RFC 821 */
175 #define CMDUNIMPL       19      /* unimplemented rfc821 commands */
176 /* use this to catch and log "door handle" attempts on your system */
177 #define CMDLOGBOGUS     23      /* bogus command that should be logged */
178 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
179 #define CMDDBGQSHOW     24      /* showq -- show send queue */
180 #define CMDDBGDEBUG     25      /* debug -- set debug mode */
181
182 /*
183 **  Note: If you change this list, remember to update 'helpfile'
184 */
185
186 static struct cmd       CmdTab[] =
187 {
188         { "mail",       CMDMAIL         },
189         { "rcpt",       CMDRCPT         },
190         { "data",       CMDDATA         },
191         { "rset",       CMDRSET         },
192         { "vrfy",       CMDVRFY         },
193         { "expn",       CMDEXPN         },
194         { "help",       CMDHELP         },
195         { "noop",       CMDNOOP         },
196         { "quit",       CMDQUIT         },
197         { "helo",       CMDHELO         },
198         { "ehlo",       CMDEHLO         },
199         { "etrn",       CMDETRN         },
200         { "verb",       CMDVERB         },
201         { "send",       CMDUNIMPL       },
202         { "saml",       CMDUNIMPL       },
203         { "soml",       CMDUNIMPL       },
204         { "turn",       CMDUNIMPL       },
205 #if SASL
206         { "auth",       CMDAUTH,        },
207 #endif /* SASL */
208 #if STARTTLS
209         { "starttls",   CMDSTLS,        },
210 #endif /* STARTTLS */
211     /* remaining commands are here only to trap and log attempts to use them */
212         { "showq",      CMDDBGQSHOW     },
213         { "debug",      CMDDBGDEBUG     },
214         { "wiz",        CMDLOGBOGUS     },
215
216         { NULL,         CMDERROR        }
217 };
218
219 static char     *CurSmtpClient;         /* who's at the other end of channel */
220
221 #ifndef MAXBADCOMMANDS
222 # define MAXBADCOMMANDS 25      /* maximum number of bad commands */
223 #endif /* ! MAXBADCOMMANDS */
224 #ifndef MAXNOOPCOMMANDS
225 # define MAXNOOPCOMMANDS 20     /* max "noise" commands before slowdown */
226 #endif /* ! MAXNOOPCOMMANDS */
227 #ifndef MAXHELOCOMMANDS
228 # define MAXHELOCOMMANDS 3      /* max HELO/EHLO commands before slowdown */
229 #endif /* ! MAXHELOCOMMANDS */
230 #ifndef MAXVRFYCOMMANDS
231 # define MAXVRFYCOMMANDS 6      /* max VRFY/EXPN commands before slowdown */
232 #endif /* ! MAXVRFYCOMMANDS */
233 #ifndef MAXETRNCOMMANDS
234 # define MAXETRNCOMMANDS 8      /* max ETRN commands before slowdown */
235 #endif /* ! MAXETRNCOMMANDS */
236 #ifndef MAXTIMEOUT
237 # define MAXTIMEOUT (4 * 60)    /* max timeout for bad commands */
238 #endif /* ! MAXTIMEOUT */
239
240 /*
241 **  Maximum shift value to compute timeout for bad commands.
242 **  This introduces an upper limit of 2^MAXSHIFT for the timeout.
243 */
244
245 #ifndef MAXSHIFT
246 # define MAXSHIFT 8
247 #endif /* ! MAXSHIFT */
248 #if MAXSHIFT > 31
249  ERROR _MAXSHIFT > 31 is invalid
250 #endif /* MAXSHIFT */
251
252
253 #if MAXBADCOMMANDS > 0
254 # define STOP_IF_ATTACK(r)      do              \
255         {                                       \
256                 if ((r) == STOP_ATTACK)         \
257                         goto stopattack;        \
258         } while (0)
259
260 #else /* MAXBADCOMMANDS > 0 */
261 # define STOP_IF_ATTACK(r)      r
262 #endif /* MAXBADCOMMANDS > 0 */
263
264
265 #if SM_HEAP_CHECK
266 static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
267         "@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
268 #endif /* SM_HEAP_CHECK */
269
270 typedef struct
271 {
272         bool    sm_gotmail;     /* mail command received */
273         unsigned int sm_nrcpts; /* number of successful RCPT commands */
274         bool    sm_discard;
275 #if MILTER
276         bool    sm_milterize;
277         bool    sm_milterlist;  /* any filters in the list? */
278 #endif /* MILTER */
279         char    *sm_quarmsg;    /* carry quarantining across messages */
280 } SMTP_T;
281
282 static bool     smtp_data __P((SMTP_T *, ENVELOPE *));
283
284 #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
285
286 #if MILTER
287 # define MILTER_ABORT(e)        milter_abort((e))
288
289 # define MILTER_REPLY(str)                                              \
290         {                                                               \
291                 int savelogusrerrs = LogUsrErrs;                        \
292                                                                         \
293                 switch (state)                                          \
294                 {                                                       \
295                   case SMFIR_REPLYCODE:                                 \
296                         if (MilterLogLevel > 3)                         \
297                         {                                               \
298                                 sm_syslog(LOG_INFO, e->e_id,            \
299                                           "Milter: %s=%s, reject=%s",   \
300                                           str, addr, response);         \
301                                 LogUsrErrs = false;                     \
302                         }                                               \
303                         if (strncmp(response, "421 ", 4) == 0)          \
304                         {                                               \
305                                 bool tsave = QuickAbort;                \
306                                                                         \
307                                 QuickAbort = false;                     \
308                                 usrerr(response);                       \
309                                 QuickAbort = tsave;                     \
310                                 e->e_sendqueue = NULL;                  \
311                                 goto doquit;                            \
312                         }                                               \
313                         else                                            \
314                                 usrerr(response);                       \
315                         break;                                          \
316                                                                         \
317                   case SMFIR_REJECT:                                    \
318                         if (MilterLogLevel > 3)                         \
319                         {                                               \
320                                 sm_syslog(LOG_INFO, e->e_id,            \
321                                           "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
322                                           str, addr);                   \
323                                 LogUsrErrs = false;                     \
324                         }                                               \
325                         usrerr("550 5.7.1 Command rejected");           \
326                         break;                                          \
327                                                                         \
328                   case SMFIR_DISCARD:                                   \
329                         if (MilterLogLevel > 3)                         \
330                                 sm_syslog(LOG_INFO, e->e_id,            \
331                                           "Milter: %s=%s, discard",     \
332                                           str, addr);                   \
333                         e->e_flags |= EF_DISCARD;                       \
334                         break;                                          \
335                                                                         \
336                   case SMFIR_TEMPFAIL:                                  \
337                         if (MilterLogLevel > 3)                         \
338                         {                                               \
339                                 sm_syslog(LOG_INFO, e->e_id,            \
340                                           "Milter: %s=%s, reject=%s",   \
341                                           str, addr, MSG_TEMPFAIL);     \
342                                 LogUsrErrs = false;                     \
343                         }                                               \
344                         usrerr(MSG_TEMPFAIL);                           \
345                         break;                                          \
346                 }                                                       \
347                 LogUsrErrs = savelogusrerrs;                            \
348                 if (response != NULL)                                   \
349                         sm_free(response); /* XXX */                    \
350         }
351
352 #else /* MILTER */
353 # define MILTER_ABORT(e)
354 #endif /* MILTER */
355
356 /* clear all SMTP state (for HELO/EHLO/RSET) */
357 #define CLEAR_STATE(cmd)                                        \
358 do                                                              \
359 {                                                               \
360         /* abort milter filters */                              \
361         MILTER_ABORT(e);                                        \
362                                                                 \
363         if (smtp.sm_nrcpts > 0)                                 \
364         {                                                       \
365                 logundelrcpts(e, cmd, 10, false);               \
366                 smtp.sm_nrcpts = 0;                             \
367                 macdefine(&e->e_macro, A_PERM,                  \
368                           macid("{nrcpts}"), "0");              \
369         }                                                       \
370                                                                 \
371         e->e_sendqueue = NULL;                                  \
372         e->e_flags |= EF_CLRQUEUE;                              \
373                                                                 \
374         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))   \
375                 logsender(e, NULL);                             \
376         e->e_flags &= ~EF_LOGSENDER;                            \
377                                                                 \
378         /* clean up a bit */                                    \
379         smtp.sm_gotmail = false;                                \
380         SuprErrs = true;                                        \
381         dropenvelope(e, true, false);                           \
382         sm_rpool_free(e->e_rpool);                              \
383         e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));       \
384         CurEnv = e;                                             \
385                                                                 \
386         /* put back discard bit */                              \
387         if (smtp.sm_discard)                                    \
388                 e->e_flags |= EF_DISCARD;                       \
389                                                                 \
390         /* restore connection quarantining */                   \
391         if (smtp.sm_quarmsg == NULL)                            \
392         {                                                       \
393                 e->e_quarmsg = NULL;                            \
394                 macdefine(&e->e_macro, A_PERM,                  \
395                         macid("{quarantine}"), "");             \
396         }                                                       \
397         else                                                    \
398         {                                                       \
399                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,    \
400                                                 smtp.sm_quarmsg);       \
401                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"),   \
402                           e->e_quarmsg);                        \
403         }                                                       \
404 } while (0)
405
406 /* sleep to flatten out connection load */
407 #define MIN_DELAY_LOG   15      /* wait before logging this again */
408
409 /* is it worth setting the process title for 1s? */
410 #define DELAY_CONN(cmd)                                         \
411         if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)    \
412         {                                                       \
413                 time_t dnow;                                    \
414                                                                 \
415                 sm_setproctitle(true, e,                        \
416                                 "%s: %s: delaying %s: load average: %d", \
417                                 qid_printname(e), CurSmtpClient,        \
418                                 cmd, DelayLA);  \
419                 if (LogLevel > 8 && (dnow = curtime()) > log_delay)     \
420                 {                                               \
421                         sm_syslog(LOG_INFO, e->e_id,            \
422                                   "delaying=%s, load average=%d >= %d", \
423                                   cmd, CurrentLA, DelayLA);             \
424                         log_delay = dnow + MIN_DELAY_LOG;       \
425                 }                                               \
426                 (void) sleep(1);                                \
427                 sm_setproctitle(true, e, "%s %s: %.80s",        \
428                                 qid_printname(e), CurSmtpClient, inp);  \
429         }
430
431
432 void
433 smtp(nullserver, d_flags, e)
434         char *volatile nullserver;
435         BITMAP256 d_flags;
436         register ENVELOPE *volatile e;
437 {
438         register char *volatile p;
439         register struct cmd *volatile c = NULL;
440         char *cmd;
441         auto ADDRESS *vrfyqueue;
442         ADDRESS *a;
443         volatile bool gothello;         /* helo command received */
444         bool vrfy;                      /* set if this is a vrfy command */
445         char *volatile protocol;        /* sending protocol */
446         char *volatile sendinghost;     /* sending hostname */
447         char *volatile peerhostname;    /* name of SMTP peer or "localhost" */
448         auto char *delimptr;
449         char *id;
450         volatile unsigned int n_badcmds = 0;    /* count of bad commands */
451         volatile unsigned int n_badrcpts = 0;   /* number of rejected RCPT */
452         volatile unsigned int n_verifies = 0;   /* count of VRFY/EXPN */
453         volatile unsigned int n_etrn = 0;       /* count of ETRN */
454         volatile unsigned int n_noop = 0;       /* count of NOOP/VERB/etc */
455         volatile unsigned int n_helo = 0;       /* count of HELO/EHLO */
456         volatile int save_sevenbitinput;
457         bool ok;
458 #if _FFR_BLOCK_PROXIES
459         volatile bool first;
460 #endif /* _FFR_BLOCK_PROXIES */
461         volatile bool tempfail = false;
462         volatile time_t wt;             /* timeout after too many commands */
463         volatile time_t previous;       /* time after checksmtpattack() */
464         volatile bool lognullconnection = true;
465         register char *q;
466         SMTP_T smtp;
467         char *addr;
468         char *greetcode = "220";
469         char *hostname;                 /* my hostname ($j) */
470         QUEUE_CHAR *new;
471         int argno;
472         char *args[MAXSMTPARGS];
473         char inp[MAXLINE];
474         char cmdbuf[MAXLINE];
475 #if SASL
476         sasl_conn_t *conn;
477         volatile bool sasl_ok;
478         volatile unsigned int n_auth = 0;       /* count of AUTH commands */
479         bool ismore;
480         int result;
481         volatile int authenticating;
482         char *user;
483         char *in, *out2;
484 # if SASL >= 20000
485         char *auth_id;
486         const char *out;
487         sasl_ssf_t ext_ssf;
488         char localip[60], remoteip[60];
489 # else /* SASL >= 20000 */
490         char *out;
491         const char *errstr;
492         sasl_external_properties_t ext_ssf;
493         struct sockaddr_in saddr_l;
494         struct sockaddr_in saddr_r;
495 # endif /* SASL >= 20000 */
496         sasl_security_properties_t ssp;
497         sasl_ssf_t *ssf;
498         unsigned int inlen, out2len;
499         unsigned int outlen;
500         char *volatile auth_type;
501         char *mechlist;
502         volatile unsigned int n_mechs;
503         unsigned int len;
504 #endif /* SASL */
505         int r;
506 #if STARTTLS
507         int fdfl;
508         int rfd, wfd;
509         volatile bool tls_active = false;
510         volatile bool smtps = bitnset(D_SMTPS, d_flags);
511         bool saveQuickAbort;
512         bool saveSuprErrs;
513         time_t tlsstart;
514 #endif /* STARTTLS */
515         volatile unsigned int features;
516 #if PIPELINING
517 # if _FFR_NO_PIPE
518         int np_log = 0;
519 # endif /* _FFR_NO_PIPE */
520 #endif /* PIPELINING */
521         volatile time_t log_delay = (time_t) 0;
522
523         save_sevenbitinput = SevenBitInput;
524         smtp.sm_nrcpts = 0;
525 #if MILTER
526         smtp.sm_milterize = (nullserver == NULL);
527         smtp.sm_milterlist = false;
528 #endif /* MILTER */
529
530         /* setup I/O fd correctly for the SMTP server */
531         setup_smtpd_io();
532
533 #if SM_HEAP_CHECK
534         if (sm_debug_active(&DebugLeakSmtp, 1))
535         {
536                 sm_heap_newgroup();
537                 sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
538         }
539 #endif /* SM_HEAP_CHECK */
540
541         /* XXX the rpool should be set when e is initialized in main() */
542         e->e_rpool = sm_rpool_new_x(NULL);
543         e->e_macro.mac_rpool = e->e_rpool;
544
545         settime(e);
546         sm_getla();
547         peerhostname = RealHostName;
548         if (peerhostname == NULL)
549                 peerhostname = "localhost";
550         CurHostName = peerhostname;
551         CurSmtpClient = macvalue('_', e);
552         if (CurSmtpClient == NULL)
553                 CurSmtpClient = CurHostName;
554
555         /* check_relay may have set discard bit, save for later */
556         smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
557
558 #if PIPELINING
559         /* auto-flush output when reading input */
560         (void) sm_io_autoflush(InChannel, OutChannel);
561 #endif /* PIPELINING */
562
563         sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
564
565         /* Set default features for server. */
566         features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
567                      bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
568                 | (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
569                 | (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
570                         : (SRV_OFFER_EXPN
571                           | (bitset(PRIV_NOVERB, PrivacyFlags)
572                              ? SRV_NONE : SRV_OFFER_VERB)))
573                 | (bitset(PRIV_NORECEIPTS, PrivacyFlags) ? SRV_NONE
574                                                          : SRV_OFFER_DSN)
575 #if SASL
576                 | (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
577                 | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
578                                                           : SRV_NONE)
579 #endif /* SASL */
580 #if PIPELINING
581                 | SRV_OFFER_PIPE
582 #endif /* PIPELINING */
583 #if STARTTLS
584                 | (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
585                 | (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
586                                                        : SRV_VRFY_CLT)
587 #endif /* STARTTLS */
588                 ;
589         if (nullserver == NULL)
590         {
591                 features = srvfeatures(e, CurSmtpClient, features);
592                 if (bitset(SRV_TMP_FAIL, features))
593                 {
594                         if (LogLevel > 4)
595                                 sm_syslog(LOG_ERR, NOQID,
596                                           "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
597                                           CurSmtpClient);
598                         nullserver = "450 4.3.0 Please try again later.";
599                 }
600                 else
601                 {
602 #if PIPELINING
603 # if _FFR_NO_PIPE
604                         if (bitset(SRV_NO_PIPE, features))
605                         {
606                                 /* for consistency */
607                                 features &= ~SRV_OFFER_PIPE;
608                         }
609 # endif /* _FFR_NO_PIPE */
610 #endif /* PIPELINING */
611 #if SASL
612                         if (bitset(SRV_REQ_SEC, features))
613                                 SASLOpts |= SASL_SEC_NOPLAINTEXT;
614                         else
615                                 SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
616 #endif /* SASL */
617                 }
618         }
619         else if (strncmp(nullserver, "421 ", 4) == 0)
620         {
621                 message(nullserver);
622                 goto doquit;
623         }
624
625         hostname = macvalue('j', e);
626 #if SASL
627         if (AuthRealm == NULL)
628                 AuthRealm = hostname;
629         sasl_ok = bitset(SRV_OFFER_AUTH, features);
630         n_mechs = 0;
631         authenticating = SASL_NOT_AUTH;
632
633         /* SASL server new connection */
634         if (sasl_ok)
635         {
636 # if SASL >= 20000
637                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
638                                          NULL, 0, &conn);
639 # elif SASL > 10505
640                 /* use empty realm: only works in SASL > 1.5.5 */
641                 result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
642 # else /* SASL >= 20000 */
643                 /* use no realm -> realm is set to hostname by SASL lib */
644                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
645                                          &conn);
646 # endif /* SASL >= 20000 */
647                 sasl_ok = result == SASL_OK;
648                 if (!sasl_ok)
649                 {
650                         if (LogLevel > 9)
651                                 sm_syslog(LOG_WARNING, NOQID,
652                                           "AUTH error: sasl_server_new failed=%d",
653                                           result);
654                 }
655         }
656         if (sasl_ok)
657         {
658                 /*
659                 **  SASL set properties for sasl
660                 **  set local/remote IP
661                 **  XXX Cyrus SASL v1 only supports IPv4
662                 **
663                 **  XXX where exactly are these used/required?
664                 **  Kerberos_v4
665                 */
666
667 # if SASL >= 20000
668                 localip[0] = remoteip[0] = '\0';
669 #  if NETINET || NETINET6
670                 in = macvalue(macid("{daemon_family}"), e);
671                 if (in != NULL && (
672 #   if NETINET6
673                     strcmp(in, "inet6") == 0 ||
674 #   endif /* NETINET6 */
675                     strcmp(in, "inet") == 0))
676                 {
677                         SOCKADDR_LEN_T addrsize;
678                         SOCKADDR saddr_l;
679                         SOCKADDR saddr_r;
680
681                         addrsize = sizeof(saddr_r);
682                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
683                                                       NULL),
684                                         (struct sockaddr *) &saddr_r,
685                                         &addrsize) == 0)
686                         {
687                                 if (iptostring(&saddr_r, addrsize,
688                                                remoteip, sizeof remoteip))
689                                 {
690                                         sasl_setprop(conn, SASL_IPREMOTEPORT,
691                                                      remoteip);
692                                 }
693                                 addrsize = sizeof(saddr_l);
694                                 if (getsockname(sm_io_getinfo(InChannel,
695                                                               SM_IO_WHAT_FD,
696                                                               NULL),
697                                                 (struct sockaddr *) &saddr_l,
698                                                 &addrsize) == 0)
699                                 {
700                                         if (iptostring(&saddr_l, addrsize,
701                                                        localip,
702                                                        sizeof localip))
703                                         {
704                                                 sasl_setprop(conn,
705                                                              SASL_IPLOCALPORT,
706                                                              localip);
707                                         }
708                                 }
709                         }
710                 }
711 #  endif /* NETINET || NETINET6 */
712 # else /* SASL >= 20000 */
713 #  if NETINET
714                 in = macvalue(macid("{daemon_family}"), e);
715                 if (in != NULL && strcmp(in, "inet") == 0)
716                 {
717                         SOCKADDR_LEN_T addrsize;
718
719                         addrsize = sizeof(struct sockaddr_in);
720                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
721                                                       NULL),
722                                         (struct sockaddr *)&saddr_r,
723                                         &addrsize) == 0)
724                         {
725                                 sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
726                                 addrsize = sizeof(struct sockaddr_in);
727                                 if (getsockname(sm_io_getinfo(InChannel,
728                                                               SM_IO_WHAT_FD,
729                                                               NULL),
730                                                 (struct sockaddr *)&saddr_l,
731                                                 &addrsize) == 0)
732                                         sasl_setprop(conn, SASL_IP_LOCAL,
733                                                      &saddr_l);
734                         }
735                 }
736 #  endif /* NETINET */
737 # endif /* SASL >= 20000 */
738
739                 auth_type = NULL;
740                 mechlist = NULL;
741                 user = NULL;
742 # if 0
743                 macdefine(&BlankEnvelope.e_macro, A_PERM,
744                         macid("{auth_author}"), NULL);
745 # endif /* 0 */
746
747                 /* set properties */
748                 (void) memset(&ssp, '\0', sizeof ssp);
749
750                 /* XXX should these be options settable via .cf ? */
751                 /* ssp.min_ssf = 0; is default due to memset() */
752                 {
753                         ssp.max_ssf = MaxSLBits;
754                         ssp.maxbufsize = MAXOUTLEN;
755                 }
756                 ssp.security_flags = SASLOpts & SASL_SEC_MASK;
757                 sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
758
759                 if (sasl_ok)
760                 {
761                         /*
762                         **  external security strength factor;
763                         **      currently we have none so zero
764                         */
765
766 # if SASL >= 20000
767                         ext_ssf = 0;
768                         auth_id = NULL;
769                         sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
770                                                  &ext_ssf) == SASL_OK) &&
771                                    (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
772                                                  auth_id) == SASL_OK));
773 # else /* SASL >= 20000 */
774                         ext_ssf.ssf = 0;
775                         ext_ssf.auth_id = NULL;
776                         sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
777                                                &ext_ssf) == SASL_OK;
778 # endif /* SASL >= 20000 */
779                 }
780                 if (sasl_ok)
781                         n_mechs = saslmechs(conn, &mechlist);
782         }
783 #endif /* SASL */
784
785 #if STARTTLS
786 #endif /* STARTTLS */
787
788 #if MILTER
789         if (smtp.sm_milterize)
790         {
791                 char state;
792
793                 /* initialize mail filter connection */
794                 smtp.sm_milterlist = milter_init(e, &state);
795                 switch (state)
796                 {
797                   case SMFIR_REJECT:
798                         if (MilterLogLevel > 3)
799                                 sm_syslog(LOG_INFO, e->e_id,
800                                           "Milter: initialization failed, rejecting commands");
801                         greetcode = "554";
802                         nullserver = "Command rejected";
803                         smtp.sm_milterize = false;
804                         break;
805
806                   case SMFIR_TEMPFAIL:
807                         if (MilterLogLevel > 3)
808                                 sm_syslog(LOG_INFO, e->e_id,
809                                           "Milter: initialization failed, temp failing commands");
810                         tempfail = true;
811                         smtp.sm_milterize = false;
812                         break;
813                 }
814         }
815
816         if (smtp.sm_milterlist && smtp.sm_milterize &&
817             !bitset(EF_DISCARD, e->e_flags))
818         {
819                 char state;
820                 char *response;
821
822                 response = milter_connect(peerhostname, RealHostAddr,
823                                           e, &state);
824                 switch (state)
825                 {
826                   case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */
827                   case SMFIR_REJECT:
828                         if (MilterLogLevel > 3)
829                                 sm_syslog(LOG_INFO, e->e_id,
830                                           "Milter: connect: host=%s, addr=%s, rejecting commands",
831                                           peerhostname,
832                                           anynet_ntoa(&RealHostAddr));
833                         greetcode = "554";
834                         nullserver = "Command rejected";
835                         smtp.sm_milterize = false;
836                         break;
837
838                   case SMFIR_TEMPFAIL:
839                         if (MilterLogLevel > 3)
840                                 sm_syslog(LOG_INFO, e->e_id,
841                                           "Milter: connect: host=%s, addr=%s, temp failing commands",
842                                           peerhostname,
843                                           anynet_ntoa(&RealHostAddr));
844                         tempfail = true;
845                         smtp.sm_milterize = false;
846                         break;
847
848                   case SMFIR_SHUTDOWN:
849                         if (MilterLogLevel > 3)
850                                 sm_syslog(LOG_INFO, e->e_id,
851                                           "Milter: connect: host=%s, addr=%s, shutdown",
852                                           peerhostname,
853                                           anynet_ntoa(&RealHostAddr));
854                         tempfail = true;
855                         smtp.sm_milterize = false;
856                         message("421 4.7.0 %s closing connection",
857                                         MyHostName);
858
859                         /* arrange to ignore send list */
860                         e->e_sendqueue = NULL;
861                         goto doquit;
862                 }
863                 if (response != NULL)
864                         sm_free(response); /* XXX */
865         }
866 #endif /* MILTER */
867
868         /*
869         **  Broken proxies and SMTP slammers
870         **  push data without waiting, catch them
871         */
872
873         if (
874 #if STARTTLS
875             !smtps &&
876 #endif /* STARTTLS */
877             *greetcode == '2')
878         {
879                 time_t msecs = 0;
880                 char **pvp;
881                 char pvpbuf[PSBUFSIZE];
882
883                 /* Ask the rulesets how long to pause */
884                 pvp = NULL;
885                 r = rscap("greet_pause", peerhostname,
886                           anynet_ntoa(&RealHostAddr), e,
887                           &pvp, pvpbuf, sizeof(pvpbuf));
888                 if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
889                     (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
890                 {
891                         msecs = strtol(pvp[1], NULL, 10);
892                 }
893
894                 if (msecs > 0)
895                 {
896                         int fd;
897                         fd_set readfds;
898                         struct timeval timeout;
899
900                         /* pause for a moment */
901                         timeout.tv_sec = msecs / 1000;
902                         timeout.tv_usec = (msecs % 1000) * 1000;
903
904                         /* Obey RFC 2821: 4.3.5.2: 220 timeout of 5 minutes */
905                         if (timeout.tv_sec >= 300)
906                         {
907                                 timeout.tv_sec = 300;
908                                 timeout.tv_usec = 0;
909                         }
910
911                         /* check if data is on the socket during the pause */
912                         fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
913                         FD_ZERO(&readfds);
914                         SM_FD_SET(fd, &readfds);
915                         if (select(fd + 1, FDSET_CAST &readfds,
916                             NULL, NULL, &timeout) > 0 &&
917                             FD_ISSET(fd, &readfds))
918                         {
919                                 greetcode = "554";
920                                 nullserver = "Command rejected";
921                                 sm_syslog(LOG_INFO, e->e_id,
922                                           "rejecting commands from %s [%s] due to pre-greeting traffic",
923                                           peerhostname,
924                                           anynet_ntoa(&RealHostAddr));
925                         }
926                 }
927         }
928
929 #if STARTTLS
930         /* If this an smtps connection, start TLS now */
931         if (smtps)
932         {
933                 Errors = 0;
934                 goto starttls;
935         }
936
937   greeting:
938
939 #endif /* STARTTLS */
940
941         /* output the first line, inserting "ESMTP" as second word */
942         if (*greetcode == '5')
943                 (void) sm_snprintf(inp, sizeof inp, "%s not accepting messages",
944                                    hostname);
945         else
946                 expand(SmtpGreeting, inp, sizeof inp, e);
947
948         p = strchr(inp, '\n');
949         if (p != NULL)
950                 *p++ = '\0';
951         id = strchr(inp, ' ');
952         if (id == NULL)
953                 id = &inp[strlen(inp)];
954         if (p == NULL)
955                 (void) sm_snprintf(cmdbuf, sizeof cmdbuf,
956                          "%s %%.*s ESMTP%%s", greetcode);
957         else
958                 (void) sm_snprintf(cmdbuf, sizeof cmdbuf,
959                          "%s-%%.*s ESMTP%%s", greetcode);
960         message(cmdbuf, (int) (id - inp), inp, id);
961
962         /* output remaining lines */
963         while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
964         {
965                 *p++ = '\0';
966                 if (isascii(*id) && isspace(*id))
967                         id++;
968                 (void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, "-%s");
969                 message(cmdbuf, id);
970         }
971         if (id != NULL)
972         {
973                 if (isascii(*id) && isspace(*id))
974                         id++;
975                 (void) sm_strlcpyn(cmdbuf, sizeof cmdbuf, 2, greetcode, " %s");
976                 message(cmdbuf, id);
977         }
978
979         protocol = NULL;
980         sendinghost = macvalue('s', e);
981
982         /* If quarantining by a connect/ehlo action, save between messages */
983         if (e->e_quarmsg == NULL)
984                 smtp.sm_quarmsg = NULL;
985         else
986                 smtp.sm_quarmsg = newstr(e->e_quarmsg);
987
988         /* sendinghost's storage must outlive the current envelope */
989         if (sendinghost != NULL)
990                 sendinghost = sm_strdup_x(sendinghost);
991 #if _FFR_BLOCK_PROXIES
992         first = true;
993 #endif /* _FFR_BLOCK_PROXIES */
994         gothello = false;
995         smtp.sm_gotmail = false;
996         for (;;)
997         {
998             SM_TRY
999             {
1000                 QuickAbort = false;
1001                 HoldErrs = false;
1002                 SuprErrs = false;
1003                 LogUsrErrs = false;
1004                 OnlyOneError = true;
1005                 e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
1006
1007                 /* setup for the read */
1008                 e->e_to = NULL;
1009                 Errors = 0;
1010                 FileName = NULL;
1011                 (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
1012
1013                 /* read the input line */
1014                 SmtpPhase = "server cmd read";
1015                 sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
1016 #if SASL
1017                 /*
1018                 **  XXX SMTP AUTH requires accepting any length,
1019                 **      at least for challenge/response
1020                 */
1021 #endif /* SASL */
1022
1023                 /* handle errors */
1024                 if (sm_io_error(OutChannel) ||
1025                     (p = sfgets(inp, sizeof inp, InChannel,
1026                                 TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
1027                 {
1028                         char *d;
1029
1030                         d = macvalue(macid("{daemon_name}"), e);
1031                         if (d == NULL)
1032                                 d = "stdin";
1033                         /* end of file, just die */
1034                         disconnect(1, e);
1035
1036 #if MILTER
1037                         /* close out milter filters */
1038                         milter_quit(e);
1039 #endif /* MILTER */
1040
1041                         message("421 4.4.1 %s Lost input channel from %s",
1042                                 MyHostName, CurSmtpClient);
1043                         if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
1044                                 sm_syslog(LOG_NOTICE, e->e_id,
1045                                           "lost input channel from %s to %s after %s",
1046                                           CurSmtpClient, d,
1047                                           (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
1048                         /*
1049                         **  If have not accepted mail (DATA), do not bounce
1050                         **  bad addresses back to sender.
1051                         */
1052
1053                         if (bitset(EF_CLRQUEUE, e->e_flags))
1054                                 e->e_sendqueue = NULL;
1055                         goto doquit;
1056                 }
1057
1058 #if _FFR_BLOCK_PROXIES
1059                 if (first)
1060                 {
1061                         size_t inplen, cmdlen;
1062                         int idx;
1063                         char *http_cmd;
1064                         static char *http_cmds[] = { "GET", "POST",
1065                                                      "CONNECT", "USER", NULL };
1066
1067                         inplen = strlen(inp);
1068                         for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
1069                              idx++)
1070                         {
1071                                 cmdlen = strlen(http_cmd);
1072                                 if (cmdlen < inplen &&
1073                                     sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
1074                                     isascii(inp[cmdlen]) && isspace(inp[cmdlen]))
1075                                 {
1076                                         /* Open proxy, drop it */
1077                                         message("421 4.7.0 %s Rejecting open proxy %s",
1078                                                 MyHostName, CurSmtpClient);
1079                                         sm_syslog(LOG_INFO, e->e_id,
1080                                                   "%s: probable open proxy: command=%.40s",
1081                                                   CurSmtpClient, inp);
1082                                         goto doquit;
1083                                 }
1084                         }
1085                         first = false;
1086                 }
1087 #endif /* _FFR_BLOCK_PROXIES */
1088
1089                 /* clean up end of line */
1090                 fixcrlf(inp, true);
1091
1092 #if PIPELINING
1093 # if _FFR_NO_PIPE
1094                 /*
1095                 **  if there is more input and pipelining is disabled:
1096                 **      delay ... (and maybe discard the input?)
1097                 **  XXX this doesn't really work, at least in tests using
1098                 **  telnet SM_IO_IS_READABLE only returns 1 if there were
1099                 **  more than 2 input lines available.
1100                 */
1101
1102                 if (bitset(SRV_NO_PIPE, features) &&
1103                     sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
1104                 {
1105                         if (++np_log < 3)
1106                                 sm_syslog(LOG_INFO, NOQID,
1107                                           "unauthorized PIPELINING, sleeping");
1108                         sleep(1);
1109                 }
1110
1111 # endif /* _FFR_NO_PIPE */
1112 #endif /* PIPELINING */
1113
1114 #if SASL
1115                 if (authenticating == SASL_PROC_AUTH)
1116                 {
1117 # if 0
1118                         if (*inp == '\0')
1119                         {
1120                                 authenticating = SASL_NOT_AUTH;
1121                                 message("501 5.5.2 missing input");
1122                                 RESET_SASLCONN;
1123                                 continue;
1124                         }
1125 # endif /* 0 */
1126                         if (*inp == '*' && *(inp + 1) == '\0')
1127                         {
1128                                 authenticating = SASL_NOT_AUTH;
1129
1130                                 /* rfc 2254 4. */
1131                                 message("501 5.0.0 AUTH aborted");
1132                                 RESET_SASLCONN;
1133                                 continue;
1134                         }
1135
1136                         /* could this be shorter? XXX */
1137 # if SASL >= 20000
1138                         in = xalloc(strlen(inp) + 1);
1139                         result = sasl_decode64(inp, strlen(inp), in,
1140                                                strlen(inp), &inlen);
1141 # else /* SASL >= 20000 */
1142                         out = xalloc(strlen(inp));
1143                         result = sasl_decode64(inp, strlen(inp), out, &outlen);
1144 # endif /* SASL >= 20000 */
1145                         if (result != SASL_OK)
1146                         {
1147                                 authenticating = SASL_NOT_AUTH;
1148
1149                                 /* rfc 2254 4. */
1150                                 message("501 5.5.4 cannot decode AUTH parameter %s",
1151                                         inp);
1152 # if SASL >= 20000
1153                                 sm_free(in);
1154 # endif /* SASL >= 20000 */
1155                                 RESET_SASLCONN;
1156                                 continue;
1157                         }
1158
1159 # if SASL >= 20000
1160                         result = sasl_server_step(conn, in, inlen,
1161                                                   &out, &outlen);
1162                         sm_free(in);
1163 # else /* SASL >= 20000 */
1164                         result = sasl_server_step(conn, out, outlen,
1165                                                   &out, &outlen, &errstr);
1166 # endif /* SASL >= 20000 */
1167
1168                         /* get an OK if we're done */
1169                         if (result == SASL_OK)
1170                         {
1171   authenticated:
1172                                 message("235 2.0.0 OK Authenticated");
1173                                 authenticating = SASL_IS_AUTH;
1174                                 macdefine(&BlankEnvelope.e_macro, A_TEMP,
1175                                         macid("{auth_type}"), auth_type);
1176
1177 # if SASL >= 20000
1178                                 user = macvalue(macid("{auth_authen}"), e);
1179
1180                                 /* get security strength (features) */
1181                                 result = sasl_getprop(conn, SASL_SSF,
1182                                                       (const void **) &ssf);
1183 # else /* SASL >= 20000 */
1184                                 result = sasl_getprop(conn, SASL_USERNAME,
1185                                                       (void **)&user);
1186                                 if (result != SASL_OK)
1187                                 {
1188                                         user = "";
1189                                         macdefine(&BlankEnvelope.e_macro,
1190                                                   A_PERM,
1191                                                   macid("{auth_authen}"), NULL);
1192                                 }
1193                                 else
1194                                 {
1195                                         macdefine(&BlankEnvelope.e_macro,
1196                                                   A_TEMP,
1197                                                   macid("{auth_authen}"),
1198                                                   xtextify(user, "<>\")"));
1199                                 }
1200
1201 # if 0
1202                                 /* get realm? */
1203                                 sasl_getprop(conn, SASL_REALM, (void **) &data);
1204 # endif /* 0 */
1205
1206                                 /* get security strength (features) */
1207                                 result = sasl_getprop(conn, SASL_SSF,
1208                                                       (void **) &ssf);
1209 # endif /* SASL >= 20000 */
1210                                 if (result != SASL_OK)
1211                                 {
1212                                         macdefine(&BlankEnvelope.e_macro,
1213                                                   A_PERM,
1214                                                   macid("{auth_ssf}"), "0");
1215                                         ssf = NULL;
1216                                 }
1217                                 else
1218                                 {
1219                                         char pbuf[8];
1220
1221                                         (void) sm_snprintf(pbuf, sizeof pbuf,
1222                                                            "%u", *ssf);
1223                                         macdefine(&BlankEnvelope.e_macro,
1224                                                   A_TEMP,
1225                                                   macid("{auth_ssf}"), pbuf);
1226                                         if (tTd(95, 8))
1227                                                 sm_dprintf("AUTH auth_ssf: %u\n",
1228                                                            *ssf);
1229                                 }
1230
1231                                 /*
1232                                 **  Only switch to encrypted connection
1233                                 **  if a security layer has been negotiated
1234                                 */
1235
1236                                 if (ssf != NULL && *ssf > 0)
1237                                 {
1238                                         /*
1239                                         **  Convert I/O layer to use SASL.
1240                                         **  If the call fails, the connection
1241                                         **  is aborted.
1242                                         */
1243
1244                                         if (sfdcsasl(&InChannel, &OutChannel,
1245                                                      conn) == 0)
1246                                         {
1247                                                 /* restart dialogue */
1248                                                 n_helo = 0;
1249 # if PIPELINING
1250                                                 (void) sm_io_autoflush(InChannel,
1251                                                                        OutChannel);
1252 # endif /* PIPELINING */
1253                                         }
1254                                         else
1255                                                 syserr("503 5.3.3 SASL TLS failed");
1256                                 }
1257
1258                                 /* NULL pointer ok since it's our function */
1259                                 if (LogLevel > 8)
1260                                         sm_syslog(LOG_INFO, NOQID,
1261                                                   "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
1262                                                   CurSmtpClient,
1263                                                   shortenstring(user, 128),
1264                                                   auth_type, *ssf);
1265                         }
1266                         else if (result == SASL_CONTINUE)
1267                         {
1268                                 len = ENC64LEN(outlen);
1269                                 out2 = xalloc(len);
1270                                 result = sasl_encode64(out, outlen, out2, len,
1271                                                        &out2len);
1272                                 if (result != SASL_OK)
1273                                 {
1274                                         /* correct code? XXX */
1275                                         /* 454 Temp. authentication failure */
1276                                         message("454 4.5.4 Internal error: unable to encode64");
1277                                         if (LogLevel > 5)
1278                                                 sm_syslog(LOG_WARNING, e->e_id,
1279                                                           "AUTH encode64 error [%d for \"%s\"]",
1280                                                           result, out);
1281                                         /* start over? */
1282                                         authenticating = SASL_NOT_AUTH;
1283                                 }
1284                                 else
1285                                 {
1286                                         message("334 %s", out2);
1287                                         if (tTd(95, 2))
1288                                                 sm_dprintf("AUTH continue: msg='%s' len=%u\n",
1289                                                            out2, out2len);
1290                                 }
1291 # if SASL >= 20000
1292                                 sm_free(out2);
1293 # endif /* SASL >= 20000 */
1294                         }
1295                         else
1296                         {
1297                                 /* not SASL_OK or SASL_CONT */
1298                                 message("535 5.7.0 authentication failed");
1299                                 if (LogLevel > 9)
1300                                         sm_syslog(LOG_WARNING, e->e_id,
1301                                                   "AUTH failure (%s): %s (%d) %s",
1302                                                   auth_type,
1303                                                   sasl_errstring(result, NULL,
1304                                                                  NULL),
1305                                                   result,
1306 # if SASL >= 20000
1307                                                   sasl_errdetail(conn));
1308 # else /* SASL >= 20000 */
1309                                                   errstr == NULL ? "" : errstr);
1310 # endif /* SASL >= 20000 */
1311                                 RESET_SASLCONN;
1312                                 authenticating = SASL_NOT_AUTH;
1313                         }
1314                 }
1315                 else
1316                 {
1317                         /* don't want to do any of this if authenticating */
1318 #endif /* SASL */
1319
1320                 /* echo command to transcript */
1321                 if (e->e_xfp != NULL)
1322                         (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
1323                                              "<<< %s\n", inp);
1324
1325                 if (LogLevel > 14)
1326                         sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
1327
1328                 /* break off command */
1329                 for (p = inp; isascii(*p) && isspace(*p); p++)
1330                         continue;
1331                 cmd = cmdbuf;
1332                 while (*p != '\0' &&
1333                        !(isascii(*p) && isspace(*p)) &&
1334                        cmd < &cmdbuf[sizeof cmdbuf - 2])
1335                         *cmd++ = *p++;
1336                 *cmd = '\0';
1337
1338                 /* throw away leading whitespace */
1339                 SKIP_SPACE(p);
1340
1341                 /* decode command */
1342                 for (c = CmdTab; c->cmd_name != NULL; c++)
1343                 {
1344                         if (sm_strcasecmp(c->cmd_name, cmdbuf) == 0)
1345                                 break;
1346                 }
1347
1348                 /* reset errors */
1349                 errno = 0;
1350
1351                 /* check whether a "non-null" command has been used */
1352                 switch (c->cmd_code)
1353                 {
1354 #if SASL
1355                   case CMDAUTH:
1356                         /* avoid information leak; take first two words? */
1357                         q = "AUTH";
1358                         break;
1359 #endif /* SASL */
1360
1361                   case CMDMAIL:
1362                   case CMDEXPN:
1363                   case CMDVRFY:
1364                   case CMDETRN:
1365                         lognullconnection = false;
1366                         /* FALLTHROUGH */
1367                   default:
1368                         q = inp;
1369                         break;
1370                 }
1371
1372                 if (e->e_id == NULL)
1373                         sm_setproctitle(true, e, "%s: %.80s",
1374                                         CurSmtpClient, q);
1375                 else
1376                         sm_setproctitle(true, e, "%s %s: %.80s",
1377                                         qid_printname(e),
1378                                         CurSmtpClient, q);
1379
1380                 /*
1381                 **  Process command.
1382                 **
1383                 **      If we are running as a null server, return 550
1384                 **      to almost everything.
1385                 */
1386
1387                 if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
1388                 {
1389                         switch (c->cmd_code)
1390                         {
1391                           case CMDQUIT:
1392                           case CMDHELO:
1393                           case CMDEHLO:
1394                           case CMDNOOP:
1395                           case CMDRSET:
1396                           case CMDERROR:
1397                                 /* process normally */
1398                                 break;
1399
1400                           case CMDETRN:
1401                                 if (bitnset(D_ETRNONLY, d_flags) &&
1402                                     nullserver == NULL)
1403                                         break;
1404                                 DELAY_CONN("ETRN");
1405                                 /* FALLTHROUGH */
1406
1407                           default:
1408 #if MAXBADCOMMANDS > 0
1409                                 /* theoretically this could overflow */
1410                                 if (nullserver != NULL &&
1411                                     ++n_badcmds > MAXBADCOMMANDS)
1412                                 {
1413                                         message("421 4.7.0 %s Too many bad commands; closing connection",
1414                                                 MyHostName);
1415
1416                                         /* arrange to ignore send list */
1417                                         e->e_sendqueue = NULL;
1418                                         goto doquit;
1419                                 }
1420 #endif /* MAXBADCOMMANDS > 0 */
1421                                 if (nullserver != NULL)
1422                                 {
1423                                         if (ISSMTPREPLY(nullserver))
1424                                                 usrerr(nullserver);
1425                                         else
1426                                                 usrerr("550 5.0.0 %s",
1427                                                        nullserver);
1428                                 }
1429                                 else
1430                                         usrerr("452 4.4.5 Insufficient disk space; try again later");
1431                                 continue;
1432                         }
1433                 }
1434
1435                 switch (c->cmd_code)
1436                 {
1437 #if SASL
1438                   case CMDAUTH: /* sasl */
1439                         DELAY_CONN("AUTH");
1440                         if (!sasl_ok || n_mechs <= 0)
1441                         {
1442                                 message("503 5.3.3 AUTH not available");
1443                                 break;
1444                         }
1445                         if (authenticating == SASL_IS_AUTH)
1446                         {
1447                                 message("503 5.5.0 Already Authenticated");
1448                                 break;
1449                         }
1450                         if (smtp.sm_gotmail)
1451                         {
1452                                 message("503 5.5.0 AUTH not permitted during a mail transaction");
1453                                 break;
1454                         }
1455                         if (tempfail)
1456                         {
1457                                 if (LogLevel > 9)
1458                                         sm_syslog(LOG_INFO, e->e_id,
1459                                                   "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
1460                                                   p, CurSmtpClient);
1461                                 usrerr("454 4.3.0 Please try again later");
1462                                 break;
1463                         }
1464
1465                         ismore = false;
1466
1467                         /* crude way to avoid crack attempts */
1468                         STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
1469                                                         true, "AUTH", e));
1470
1471                         /* make sure mechanism (p) is a valid string */
1472                         for (q = p; *q != '\0' && isascii(*q); q++)
1473                         {
1474                                 if (isspace(*q))
1475                                 {
1476                                         *q = '\0';
1477                                         while (*++q != '\0' &&
1478                                                isascii(*q) && isspace(*q))
1479                                                 continue;
1480                                         *(q - 1) = '\0';
1481                                         ismore = (*q != '\0');
1482                                         break;
1483                                 }
1484                         }
1485
1486                         if (*p == '\0')
1487                         {
1488                                 message("501 5.5.2 AUTH mechanism must be specified");
1489                                 break;
1490                         }
1491
1492                         /* check whether mechanism is available */
1493                         if (iteminlist(p, mechlist, " ") == NULL)
1494                         {
1495                                 message("504 5.3.3 AUTH mechanism %.32s not available",
1496                                         p);
1497                                 break;
1498                         }
1499
1500                         if (ismore)
1501                         {
1502                                 /* could this be shorter? XXX */
1503 # if SASL >= 20000
1504                                 in = xalloc(strlen(q) + 1);
1505                                 result = sasl_decode64(q, strlen(q), in,
1506                                                        strlen(q), &inlen);
1507 # else /* SASL >= 20000 */
1508                                 in = sm_rpool_malloc(e->e_rpool, strlen(q));
1509                                 result = sasl_decode64(q, strlen(q), in,
1510                                                        &inlen);
1511 # endif /* SASL >= 20000 */
1512                                 if (result != SASL_OK)
1513                                 {
1514                                         message("501 5.5.4 cannot BASE64 decode '%s'",
1515                                                 q);
1516                                         if (LogLevel > 5)
1517                                                 sm_syslog(LOG_WARNING, e->e_id,
1518                                                           "AUTH decode64 error [%d for \"%s\"]",
1519                                                           result, q);
1520                                         /* start over? */
1521                                         authenticating = SASL_NOT_AUTH;
1522 # if SASL >= 20000
1523                                         sm_free(in);
1524 # endif /* SASL >= 20000 */
1525                                         in = NULL;
1526                                         inlen = 0;
1527                                         break;
1528                                 }
1529                         }
1530                         else
1531                         {
1532                                 in = NULL;
1533                                 inlen = 0;
1534                         }
1535
1536                         /* see if that auth type exists */
1537 # if SASL >= 20000
1538                         result = sasl_server_start(conn, p, in, inlen,
1539                                                    &out, &outlen);
1540                         if (in != NULL)
1541                                 sm_free(in);
1542 # else /* SASL >= 20000 */
1543                         result = sasl_server_start(conn, p, in, inlen,
1544                                                    &out, &outlen, &errstr);
1545 # endif /* SASL >= 20000 */
1546
1547                         if (result != SASL_OK && result != SASL_CONTINUE)
1548                         {
1549                                 message("535 5.7.0 authentication failed");
1550                                 if (LogLevel > 9)
1551                                         sm_syslog(LOG_ERR, e->e_id,
1552                                                   "AUTH failure (%s): %s (%d) %s",
1553                                                   p,
1554                                                   sasl_errstring(result, NULL,
1555                                                                  NULL),
1556                                                   result,
1557 # if SASL >= 20000
1558                                                   sasl_errdetail(conn));
1559 # else /* SASL >= 20000 */
1560                                                   errstr);
1561 # endif /* SASL >= 20000 */
1562                                 RESET_SASLCONN;
1563                                 break;
1564                         }
1565                         auth_type = newstr(p);
1566
1567                         if (result == SASL_OK)
1568                         {
1569                                 /* ugly, but same code */
1570                                 goto authenticated;
1571                                 /* authenticated by the initial response */
1572                         }
1573
1574                         /* len is at least 2 */
1575                         len = ENC64LEN(outlen);
1576                         out2 = xalloc(len);
1577                         result = sasl_encode64(out, outlen, out2, len,
1578                                                &out2len);
1579
1580                         if (result != SASL_OK)
1581                         {
1582                                 message("454 4.5.4 Temporary authentication failure");
1583                                 if (LogLevel > 5)
1584                                         sm_syslog(LOG_WARNING, e->e_id,
1585                                                   "AUTH encode64 error [%d for \"%s\"]",
1586                                                   result, out);
1587
1588                                 /* start over? */
1589                                 authenticating = SASL_NOT_AUTH;
1590                                 RESET_SASLCONN;
1591                         }
1592                         else
1593                         {
1594                                 message("334 %s", out2);
1595                                 authenticating = SASL_PROC_AUTH;
1596                         }
1597 # if SASL >= 20000
1598                         sm_free(out2);
1599 # endif /* SASL >= 20000 */
1600                         break;
1601 #endif /* SASL */
1602
1603 #if STARTTLS
1604                   case CMDSTLS: /* starttls */
1605                         DELAY_CONN("STARTTLS");
1606                         if (*p != '\0')
1607                         {
1608                                 message("501 5.5.2 Syntax error (no parameters allowed)");
1609                                 break;
1610                         }
1611                         if (!bitset(SRV_OFFER_TLS, features))
1612                         {
1613                                 message("503 5.5.0 TLS not available");
1614                                 break;
1615                         }
1616                         if (!tls_ok_srv)
1617                         {
1618                                 message("454 4.3.3 TLS not available after start");
1619                                 break;
1620                         }
1621                         if (smtp.sm_gotmail)
1622                         {
1623                                 message("503 5.5.0 TLS not permitted during a mail transaction");
1624                                 break;
1625                         }
1626                         if (tempfail)
1627                         {
1628                                 if (LogLevel > 9)
1629                                         sm_syslog(LOG_INFO, e->e_id,
1630                                                   "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
1631                                                   p, CurSmtpClient);
1632                                 usrerr("454 4.7.0 Please try again later");
1633                                 break;
1634                         }
1635   starttls:
1636 # if TLS_NO_RSA
1637                         /*
1638                         **  XXX do we need a temp key ?
1639                         */
1640 # else /* TLS_NO_RSA */
1641 # endif /* TLS_NO_RSA */
1642
1643 # if TLS_VRFY_PER_CTX
1644                         /*
1645                         **  Note: this sets the verification globally
1646                         **  (per SSL_CTX)
1647                         **  it's ok since it applies only to one transaction
1648                         */
1649
1650                         TLS_VERIFY_CLIENT();
1651 # endif /* TLS_VRFY_PER_CTX */
1652
1653                         if (srv_ssl != NULL)
1654                                 SSL_clear(srv_ssl);
1655                         else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
1656                         {
1657                                 message("454 4.3.3 TLS not available: error generating SSL handle");
1658                                 if (LogLevel > 8)
1659                                         tlslogerr("server");
1660                                 goto tls_done;
1661                         }
1662
1663 # if !TLS_VRFY_PER_CTX
1664                         /*
1665                         **  this could be used if it were possible to set
1666                         **  verification per SSL (connection)
1667                         **  not just per SSL_CTX (global)
1668                         */
1669
1670                         TLS_VERIFY_CLIENT();
1671 # endif /* !TLS_VRFY_PER_CTX */
1672
1673                         rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
1674                         wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
1675
1676                         if (rfd < 0 || wfd < 0 ||
1677                             SSL_set_rfd(srv_ssl, rfd) <= 0 ||
1678                             SSL_set_wfd(srv_ssl, wfd) <= 0)
1679                         {
1680                                 message("454 4.3.3 TLS not available: error set fd");
1681                                 SSL_free(srv_ssl);
1682                                 srv_ssl = NULL;
1683                                 goto tls_done;
1684                         }
1685                         if (!smtps)
1686                                 message("220 2.0.0 Ready to start TLS");
1687 # if PIPELINING
1688                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
1689 # endif /* PIPELINING */
1690
1691                         SSL_set_accept_state(srv_ssl);
1692
1693 #  define SSL_ACC(s)    SSL_accept(s)
1694
1695                         tlsstart = curtime();
1696                         fdfl = fcntl(rfd, F_GETFL);
1697                         if (fdfl != -1)
1698                                 fcntl(rfd, F_SETFL, fdfl|O_NONBLOCK);
1699   ssl_retry:
1700                         if ((r = SSL_ACC(srv_ssl)) <= 0)
1701                         {
1702                                 int i;
1703                                 bool timedout;
1704                                 time_t left;
1705                                 time_t now = curtime();
1706                                 struct timeval tv;
1707
1708                                 /* what to do in this case? */
1709                                 i = SSL_get_error(srv_ssl, r);
1710
1711                                 /*
1712                                 **  For SSL_ERROR_WANT_{READ,WRITE}:
1713                                 **  There is no SSL record available yet
1714                                 **  or there is only a partial SSL record
1715                                 **  removed from the network (socket) buffer
1716                                 **  into the SSL buffer. The SSL_accept will
1717                                 **  only succeed when a full SSL record is
1718                                 **  available (assuming a "real" error
1719                                 **  doesn't happen). To handle when a "real"
1720                                 **  error does happen the select is set for
1721                                 **  exceptions too.
1722                                 **  The connection may be re-negotiated
1723                                 **  during this time so both read and write
1724                                 **  "want errors" need to be handled.
1725                                 **  A select() exception loops back so that
1726                                 **  a proper SSL error message can be gotten.
1727                                 */
1728
1729                                 left = TimeOuts.to_starttls - (now - tlsstart);
1730                                 timedout = left <= 0;
1731                                 if (!timedout)
1732                                 {
1733                                         tv.tv_sec = left;
1734                                         tv.tv_usec = 0;
1735                                 }
1736
1737                                 if (!timedout && FD_SETSIZE > 0 &&
1738                                     (rfd >= FD_SETSIZE ||
1739                                      (i == SSL_ERROR_WANT_WRITE &&
1740                                       wfd >= FD_SETSIZE)))
1741                                 {
1742                                         if (LogLevel > 5)
1743                                         {
1744                                                 sm_syslog(LOG_ERR, NOQID,
1745                                                           "STARTTLS=server, error: fd %d/%d too large",
1746                                                           rfd, wfd);
1747                                                 if (LogLevel > 8)
1748                                                         tlslogerr("server");
1749                                         }
1750                                         goto tlsfail;
1751                                 }
1752
1753                                 /* XXX what about SSL_pending() ? */
1754                                 if (!timedout && i == SSL_ERROR_WANT_READ)
1755                                 {
1756                                         fd_set ssl_maskr, ssl_maskx;
1757
1758                                         FD_ZERO(&ssl_maskr);
1759                                         FD_SET(rfd, &ssl_maskr);
1760                                         FD_ZERO(&ssl_maskx);
1761                                         FD_SET(rfd, &ssl_maskx);
1762                                         if (select(rfd + 1, &ssl_maskr, NULL,
1763                                                    &ssl_maskx, &tv) > 0)
1764                                                 goto ssl_retry;
1765                                 }
1766                                 if (!timedout && i == SSL_ERROR_WANT_WRITE)
1767                                 {
1768                                         fd_set ssl_maskw, ssl_maskx;
1769
1770                                         FD_ZERO(&ssl_maskw);
1771                                         FD_SET(wfd, &ssl_maskw);
1772                                         FD_ZERO(&ssl_maskx);
1773                                         FD_SET(rfd, &ssl_maskx);
1774                                         if (select(wfd + 1, NULL, &ssl_maskw,
1775                                                    &ssl_maskx, &tv) > 0)
1776                                                 goto ssl_retry;
1777                                 }
1778                                 if (LogLevel > 5)
1779                                 {
1780                                         sm_syslog(LOG_WARNING, NOQID,
1781                                                   "STARTTLS=server, error: accept failed=%d, SSL_error=%d, timedout=%d, errno=%d",
1782                                                   r, i, (int) timedout, errno);
1783                                         if (LogLevel > 8)
1784                                                 tlslogerr("server");
1785                                 }
1786 tlsfail:
1787                                 tls_ok_srv = false;
1788                                 SSL_free(srv_ssl);
1789                                 srv_ssl = NULL;
1790
1791                                 /*
1792                                 **  according to the next draft of
1793                                 **  RFC 2487 the connection should be dropped
1794                                 */
1795
1796                                 /* arrange to ignore any current send list */
1797                                 e->e_sendqueue = NULL;
1798                                 goto doquit;
1799                         }
1800
1801                         if (fdfl != -1)
1802                                 fcntl(rfd, F_SETFL, fdfl);
1803
1804                         /* ignore return code for now, it's in {verify} */
1805                         (void) tls_get_info(srv_ssl, true,
1806                                             CurSmtpClient,
1807                                             &BlankEnvelope.e_macro,
1808                                             bitset(SRV_VRFY_CLT, features));
1809
1810                         /*
1811                         **  call Stls_client to find out whether
1812                         **  to accept the connection from the client
1813                         */
1814
1815                         saveQuickAbort = QuickAbort;
1816                         saveSuprErrs = SuprErrs;
1817                         SuprErrs = true;
1818                         QuickAbort = false;
1819                         if (rscheck("tls_client",
1820                                      macvalue(macid("{verify}"), e),
1821                                      "STARTTLS", e,
1822                                      RSF_RMCOMM|RSF_COUNT,
1823                                      5, NULL, NOQID) != EX_OK ||
1824                             Errors > 0)
1825                         {
1826                                 extern char MsgBuf[];
1827
1828                                 if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
1829                                         nullserver = newstr(MsgBuf);
1830                                 else
1831                                         nullserver = "503 5.7.0 Authentication required.";
1832                         }
1833                         QuickAbort = saveQuickAbort;
1834                         SuprErrs = saveSuprErrs;
1835
1836                         tls_ok_srv = false;     /* don't offer STARTTLS again */
1837                         n_helo = 0;
1838 # if SASL
1839                         if (sasl_ok)
1840                         {
1841                                 int cipher_bits;
1842                                 bool verified;
1843                                 char *s, *v, *c;
1844
1845                                 s = macvalue(macid("{cipher_bits}"), e);
1846                                 v = macvalue(macid("{verify}"), e);
1847                                 c = macvalue(macid("{cert_subject}"), e);
1848                                 verified = (v != NULL && strcmp(v, "OK") == 0);
1849                                 if (s != NULL && (cipher_bits = atoi(s)) > 0)
1850                                 {
1851 #  if SASL >= 20000
1852                                         ext_ssf = cipher_bits;
1853                                         auth_id = verified ? c : NULL;
1854                                         sasl_ok = ((sasl_setprop(conn,
1855                                                         SASL_SSF_EXTERNAL,
1856                                                         &ext_ssf) == SASL_OK) &&
1857                                                    (sasl_setprop(conn,
1858                                                         SASL_AUTH_EXTERNAL,
1859                                                         auth_id) == SASL_OK));
1860 #  else /* SASL >= 20000 */
1861                                         ext_ssf.ssf = cipher_bits;
1862                                         ext_ssf.auth_id = verified ? c : NULL;
1863                                         sasl_ok = sasl_setprop(conn,
1864                                                         SASL_SSF_EXTERNAL,
1865                                                         &ext_ssf) == SASL_OK;
1866 #  endif /* SASL >= 20000 */
1867                                         mechlist = NULL;
1868                                         if (sasl_ok)
1869                                                 n_mechs = saslmechs(conn,
1870                                                                     &mechlist);
1871                                 }
1872                         }
1873 # endif /* SASL */
1874
1875                         /* switch to secure connection */
1876                         if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
1877                         {
1878                                 tls_active = true;
1879 # if PIPELINING
1880                                 (void) sm_io_autoflush(InChannel, OutChannel);
1881 # endif /* PIPELINING */
1882                         }
1883                         else
1884                         {
1885                                 /*
1886                                 **  XXX this is an internal error
1887                                 **  how to deal with it?
1888                                 **  we can't generate an error message
1889                                 **  since the other side switched to an
1890                                 **  encrypted layer, but we could not...
1891                                 **  just "hang up"?
1892                                 */
1893
1894                                 nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
1895                                 syserr("STARTTLS: can't switch to encrypted layer");
1896                         }
1897                   tls_done:
1898                         if (smtps)
1899                         {
1900                                 if (tls_active)
1901                                         goto greeting;
1902                                 else
1903                                         goto doquit;
1904                         }
1905                         break;
1906 #endif /* STARTTLS */
1907
1908                   case CMDHELO:         /* hello -- introduce yourself */
1909                   case CMDEHLO:         /* extended hello */
1910                         DELAY_CONN("EHLO");
1911                         if (c->cmd_code == CMDEHLO)
1912                         {
1913                                 protocol = "ESMTP";
1914                                 SmtpPhase = "server EHLO";
1915                         }
1916                         else
1917                         {
1918                                 protocol = "SMTP";
1919                                 SmtpPhase = "server HELO";
1920                         }
1921
1922                         /* avoid denial-of-service */
1923                         STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
1924                                                         true, "HELO/EHLO", e));
1925
1926 #if 0
1927                         /* RFC2821 4.1.4 allows duplicate HELO/EHLO */
1928                         /* check for duplicate HELO/EHLO per RFC 1651 4.2 */
1929                         if (gothello)
1930                         {
1931                                 usrerr("503 %s Duplicate HELO/EHLO",
1932                                        MyHostName);
1933                                 break;
1934                         }
1935 #endif /* 0 */
1936
1937                         /* check for valid domain name (re 1123 5.2.5) */
1938                         if (*p == '\0' && !AllowBogusHELO)
1939                         {
1940                                 usrerr("501 %s requires domain address",
1941                                         cmdbuf);
1942                                 break;
1943                         }
1944
1945                         /* check for long domain name (hides Received: info) */
1946                         if (strlen(p) > MAXNAME)
1947                         {
1948                                 usrerr("501 Invalid domain name");
1949                                 if (LogLevel > 9)
1950                                         sm_syslog(LOG_INFO, CurEnv->e_id,
1951                                                   "invalid domain name (too long) from %s",
1952                                                   CurSmtpClient);
1953                                 break;
1954                         }
1955
1956                         ok = true;
1957                         for (q = p; *q != '\0'; q++)
1958                         {
1959                                 if (!isascii(*q))
1960                                         break;
1961                                 if (isalnum(*q))
1962                                         continue;
1963                                 if (isspace(*q))
1964                                 {
1965                                         *q = '\0';
1966
1967                                         /* only complain if strict check */
1968                                         ok = AllowBogusHELO;
1969
1970                                         /* allow trailing whitespace */
1971                                         while (!ok && *++q != '\0' &&
1972                                                isspace(*q))
1973                                                 ;
1974                                         if (*q == '\0')
1975                                                 ok = true;
1976                                         break;
1977                                 }
1978                                 if (strchr("[].-_#:", *q) == NULL)
1979                                         break;
1980                         }
1981
1982                         if (*q == '\0' && ok)
1983                         {
1984                                 q = "pleased to meet you";
1985                                 sendinghost = sm_strdup_x(p);
1986                         }
1987                         else if (!AllowBogusHELO)
1988                         {
1989                                 usrerr("501 Invalid domain name");
1990                                 if (LogLevel > 9)
1991                                         sm_syslog(LOG_INFO, CurEnv->e_id,
1992                                                   "invalid domain name (%s) from %.100s",
1993                                                   p, CurSmtpClient);
1994                                 break;
1995                         }
1996                         else
1997                         {
1998                                 q = "accepting invalid domain name";
1999                         }
2000
2001                         if (gothello)
2002                         {
2003                                 CLEAR_STATE(cmdbuf);
2004                         }
2005
2006 #if MILTER
2007                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2008                             !bitset(EF_DISCARD, e->e_flags))
2009                         {
2010                                 char state;
2011                                 char *response;
2012
2013                                 response = milter_helo(p, e, &state);
2014                                 switch (state)
2015                                 {
2016                                   case SMFIR_REPLYCODE:
2017                                         if (MilterLogLevel > 3)
2018                                                 sm_syslog(LOG_INFO, e->e_id,
2019                                                           "Milter: helo=%s, reject=%s",
2020                                                           p, response);
2021                                         nullserver = newstr(response);
2022                                         smtp.sm_milterize = false;
2023                                         break;
2024
2025                                   case SMFIR_REJECT:
2026                                         if (MilterLogLevel > 3)
2027                                                 sm_syslog(LOG_INFO, e->e_id,
2028                                                           "Milter: helo=%s, reject=Command rejected",
2029                                                           p);
2030                                         nullserver = "Command rejected";
2031                                         smtp.sm_milterize = false;
2032                                         break;
2033
2034                                   case SMFIR_TEMPFAIL:
2035                                         if (MilterLogLevel > 3)
2036                                                 sm_syslog(LOG_INFO, e->e_id,
2037                                                           "Milter: helo=%s, reject=%s",
2038                                                           p, MSG_TEMPFAIL);
2039                                         tempfail = true;
2040                                         smtp.sm_milterize = false;
2041                                         break;
2042                                 }
2043                                 if (response != NULL)
2044                                         sm_free(response);
2045
2046                                 /*
2047                                 **  If quarantining by a connect/ehlo action,
2048                                 **  save between messages
2049                                 */
2050
2051                                 if (smtp.sm_quarmsg == NULL &&
2052                                     e->e_quarmsg != NULL)
2053                                         smtp.sm_quarmsg = newstr(e->e_quarmsg);
2054                         }
2055 #endif /* MILTER */
2056                         gothello = true;
2057
2058                         /* print HELO response message */
2059                         if (c->cmd_code != CMDEHLO)
2060                         {
2061                                 message("250 %s Hello %s, %s",
2062                                         MyHostName, CurSmtpClient, q);
2063                                 break;
2064                         }
2065
2066                         message("250-%s Hello %s, %s",
2067                                 MyHostName, CurSmtpClient, q);
2068
2069                         /* offer ENHSC even for nullserver */
2070                         if (nullserver != NULL)
2071                         {
2072                                 message("250 ENHANCEDSTATUSCODES");
2073                                 break;
2074                         }
2075
2076                         /*
2077                         **  print EHLO features list
2078                         **
2079                         **  Note: If you change this list,
2080                         **        remember to update 'helpfile'
2081                         */
2082
2083                         message("250-ENHANCEDSTATUSCODES");
2084 #if PIPELINING
2085                         if (bitset(SRV_OFFER_PIPE, features))
2086                                 message("250-PIPELINING");
2087 #endif /* PIPELINING */
2088                         if (bitset(SRV_OFFER_EXPN, features))
2089                         {
2090                                 message("250-EXPN");
2091                                 if (bitset(SRV_OFFER_VERB, features))
2092                                         message("250-VERB");
2093                         }
2094 #if MIME8TO7
2095                         message("250-8BITMIME");
2096 #endif /* MIME8TO7 */
2097                         if (MaxMessageSize > 0)
2098                                 message("250-SIZE %ld", MaxMessageSize);
2099                         else
2100                                 message("250-SIZE");
2101 #if DSN
2102                         if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
2103                                 message("250-DSN");
2104 #endif /* DSN */
2105                         if (bitset(SRV_OFFER_ETRN, features))
2106                                 message("250-ETRN");
2107 #if SASL
2108                         if (sasl_ok && mechlist != NULL && *mechlist != '\0')
2109                                 message("250-AUTH %s", mechlist);
2110 #endif /* SASL */
2111 #if STARTTLS
2112                         if (tls_ok_srv &&
2113                             bitset(SRV_OFFER_TLS, features))
2114                                 message("250-STARTTLS");
2115 #endif /* STARTTLS */
2116                         if (DeliverByMin > 0)
2117                                 message("250-DELIVERBY %ld",
2118                                         (long) DeliverByMin);
2119                         else if (DeliverByMin == 0)
2120                                 message("250-DELIVERBY");
2121
2122                         /* < 0: no deliver-by */
2123
2124                         message("250 HELP");
2125                         break;
2126
2127                   case CMDMAIL:         /* mail -- designate sender */
2128                         SmtpPhase = "server MAIL";
2129                         DELAY_CONN("MAIL");
2130
2131                         /* check for validity of this command */
2132                         if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
2133                         {
2134                                 usrerr("503 5.0.0 Polite people say HELO first");
2135                                 break;
2136                         }
2137                         if (smtp.sm_gotmail)
2138                         {
2139                                 usrerr("503 5.5.0 Sender already specified");
2140                                 break;
2141                         }
2142 #if SASL
2143                         if (bitset(SRV_REQ_AUTH, features) &&
2144                             authenticating != SASL_IS_AUTH)
2145                         {
2146                                 usrerr("530 5.7.0 Authentication required");
2147                                 break;
2148                         }
2149 #endif /* SASL */
2150
2151                         p = skipword(p, "from");
2152                         if (p == NULL)
2153                                 break;
2154                         if (tempfail)
2155                         {
2156                                 if (LogLevel > 9)
2157                                         sm_syslog(LOG_INFO, e->e_id,
2158                                                   "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2159                                                   p, CurSmtpClient);
2160                                 usrerr(MSG_TEMPFAIL);
2161                                 break;
2162                         }
2163
2164                         /* make sure we know who the sending host is */
2165                         if (sendinghost == NULL)
2166                                 sendinghost = peerhostname;
2167
2168
2169 #if SM_HEAP_CHECK
2170                         if (sm_debug_active(&DebugLeakSmtp, 1))
2171                         {
2172                                 sm_heap_newgroup();
2173                                 sm_dprintf("smtp() heap group #%d\n",
2174                                         sm_heap_group());
2175                         }
2176 #endif /* SM_HEAP_CHECK */
2177
2178                         if (Errors > 0)
2179                                 goto undo_no_pm;
2180                         if (!gothello)
2181                         {
2182                                 auth_warning(e, "%s didn't use HELO protocol",
2183                                              CurSmtpClient);
2184                         }
2185 #ifdef PICKY_HELO_CHECK
2186                         if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2187                             (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2188                              sm_strcasecmp(sendinghost, MyHostName) != 0))
2189                         {
2190                                 auth_warning(e, "Host %s claimed to be %s",
2191                                              CurSmtpClient, sendinghost);
2192                         }
2193 #endif /* PICKY_HELO_CHECK */
2194
2195                         if (protocol == NULL)
2196                                 protocol = "SMTP";
2197                         macdefine(&e->e_macro, A_PERM, 'r', protocol);
2198                         macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2199
2200                         if (Errors > 0)
2201                                 goto undo_no_pm;
2202                         smtp.sm_nrcpts = 0;
2203                         n_badrcpts = 0;
2204                         macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2205                         macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2206                         macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
2207                                 "0");
2208                         e->e_flags |= EF_CLRQUEUE;
2209                         sm_setproctitle(true, e, "%s %s: %.80s",
2210                                         qid_printname(e),
2211                                         CurSmtpClient, inp);
2212
2213                         /* do the processing */
2214                     SM_TRY
2215                     {
2216                         extern char *FullName;
2217
2218                         QuickAbort = true;
2219                         SM_FREE_CLR(FullName);
2220
2221                         /* must parse sender first */
2222                         delimptr = NULL;
2223                         setsender(p, e, &delimptr, ' ', false);
2224                         if (delimptr != NULL && *delimptr != '\0')
2225                                 *delimptr++ = '\0';
2226                         if (Errors > 0)
2227                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2228
2229                         /* Successfully set e_from, allow logging */
2230                         e->e_flags |= EF_LOGSENDER;
2231
2232                         /* put resulting triple from parseaddr() into macros */
2233                         if (e->e_from.q_mailer != NULL)
2234                                  macdefine(&e->e_macro, A_PERM,
2235                                         macid("{mail_mailer}"),
2236                                         e->e_from.q_mailer->m_name);
2237                         else
2238                                  macdefine(&e->e_macro, A_PERM,
2239                                         macid("{mail_mailer}"), NULL);
2240                         if (e->e_from.q_host != NULL)
2241                                 macdefine(&e->e_macro, A_PERM,
2242                                         macid("{mail_host}"),
2243                                         e->e_from.q_host);
2244                         else
2245                                 macdefine(&e->e_macro, A_PERM,
2246                                         macid("{mail_host}"), "localhost");
2247                         if (e->e_from.q_user != NULL)
2248                                 macdefine(&e->e_macro, A_PERM,
2249                                         macid("{mail_addr}"),
2250                                         e->e_from.q_user);
2251                         else
2252                                 macdefine(&e->e_macro, A_PERM,
2253                                         macid("{mail_addr}"), NULL);
2254                         if (Errors > 0)
2255                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2256
2257                         /* check for possible spoofing */
2258                         if (RealUid != 0 && OpMode == MD_SMTP &&
2259                             !wordinclass(RealUserName, 't') &&
2260                             (!bitnset(M_LOCALMAILER,
2261                                       e->e_from.q_mailer->m_flags) ||
2262                              strcmp(e->e_from.q_user, RealUserName) != 0))
2263                         {
2264                                 auth_warning(e, "%s owned process doing -bs",
2265                                         RealUserName);
2266                         }
2267
2268                         /* reset to default value */
2269                         SevenBitInput = save_sevenbitinput;
2270
2271                         /* now parse ESMTP arguments */
2272                         e->e_msgsize = 0;
2273                         addr = p;
2274                         argno = 0;
2275                         args[argno++] = p;
2276                         p = delimptr;
2277                         while (p != NULL && *p != '\0')
2278                         {
2279                                 char *kp;
2280                                 char *vp = NULL;
2281                                 char *equal = NULL;
2282
2283                                 /* locate the beginning of the keyword */
2284                                 SKIP_SPACE(p);
2285                                 if (*p == '\0')
2286                                         break;
2287                                 kp = p;
2288
2289                                 /* skip to the value portion */
2290                                 while ((isascii(*p) && isalnum(*p)) || *p == '-')
2291                                         p++;
2292                                 if (*p == '=')
2293                                 {
2294                                         equal = p;
2295                                         *p++ = '\0';
2296                                         vp = p;
2297
2298                                         /* skip to the end of the value */
2299                                         while (*p != '\0' && *p != ' ' &&
2300                                                !(isascii(*p) && iscntrl(*p)) &&
2301                                                *p != '=')
2302                                                 p++;
2303                                 }
2304
2305                                 if (*p != '\0')
2306                                         *p++ = '\0';
2307
2308                                 if (tTd(19, 1))
2309                                         sm_dprintf("MAIL: got arg %s=\"%s\"\n", kp,
2310                                                 vp == NULL ? "<null>" : vp);
2311
2312                                 mail_esmtp_args(kp, vp, e);
2313                                 if (equal != NULL)
2314                                         *equal = '=';
2315                                 args[argno++] = kp;
2316                                 if (argno >= MAXSMTPARGS - 1)
2317                                         usrerr("501 5.5.4 Too many parameters");
2318                                 if (Errors > 0)
2319                                         sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2320                         }
2321                         args[argno] = NULL;
2322                         if (Errors > 0)
2323                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2324
2325 #if SASL
2326 # if _FFR_AUTH_PASSING
2327                         /* set the default AUTH= if the sender didn't */
2328                         if (e->e_auth_param == NULL)
2329                         {
2330                                 /* XXX only do this for an MSA? */
2331                                 e->e_auth_param = macvalue(macid("{auth_authen}"),
2332                                                            e);
2333                                 if (e->e_auth_param == NULL)
2334                                         e->e_auth_param = "<>";
2335
2336                                 /*
2337                                 **  XXX should we invoke Strust_auth now?
2338                                 **  authorizing as the client that just
2339                                 **  authenticated, so we'll trust implicitly
2340                                 */
2341                         }
2342 # endif /* _FFR_AUTH_PASSING */
2343 #endif /* SASL */
2344
2345                         /* do config file checking of the sender */
2346                         macdefine(&e->e_macro, A_PERM,
2347                                 macid("{addr_type}"), "e s");
2348 #if _FFR_MAIL_MACRO
2349                         /* make the "real" sender address available */
2350                         macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
2351                                   e->e_from.q_paddr);
2352 #endif /* _FFR_MAIL_MACRO */
2353                         if (rscheck("check_mail", addr,
2354                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2355                                     NULL, e->e_id) != EX_OK ||
2356                             Errors > 0)
2357                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2358                         macdefine(&e->e_macro, A_PERM,
2359                                   macid("{addr_type}"), NULL);
2360
2361                         if (MaxMessageSize > 0 &&
2362                             (e->e_msgsize > MaxMessageSize ||
2363                              e->e_msgsize < 0))
2364                         {
2365                                 usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
2366                                         MaxMessageSize);
2367                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2368                         }
2369
2370                         /*
2371                         **  XXX always check whether there is at least one fs
2372                         **  with enough space?
2373                         **  However, this may not help much: the queue group
2374                         **  selection may later on select a FS that hasn't
2375                         **  enough space.
2376                         */
2377
2378                         if ((NumFileSys == 1 || NumQueue == 1) &&
2379                             !enoughdiskspace(e->e_msgsize, e)
2380 #if _FFR_ANY_FREE_FS
2381                             && !filesys_free(e->e_msgsize)
2382 #endif /* _FFR_ANY_FREE_FS */
2383                            )
2384                         {
2385                                 /*
2386                                 **  We perform this test again when the
2387                                 **  queue directory is selected, in collect.
2388                                 */
2389
2390                                 usrerr("452 4.4.5 Insufficient disk space; try again later");
2391                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2392                         }
2393                         if (Errors > 0)
2394                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2395
2396                         LogUsrErrs = true;
2397 #if MILTER
2398                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2399                             !bitset(EF_DISCARD, e->e_flags))
2400                         {
2401                                 char state;
2402                                 char *response;
2403
2404                                 response = milter_envfrom(args, e, &state);
2405                                 MILTER_REPLY("from");
2406                         }
2407 #endif /* MILTER */
2408                         if (Errors > 0)
2409                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2410
2411                         message("250 2.1.0 Sender ok");
2412                         smtp.sm_gotmail = true;
2413                     }
2414                     SM_EXCEPT(exc, "[!F]*")
2415                     {
2416                         /*
2417                         **  An error occurred while processing a MAIL command.
2418                         **  Jump to the common error handling code.
2419                         */
2420
2421                         sm_exc_free(exc);
2422                         goto undo_no_pm;
2423                     }
2424                     SM_END_TRY
2425                         break;
2426
2427                   undo_no_pm:
2428                         e->e_flags &= ~EF_PM_NOTIFY;
2429                   undo:
2430                         break;
2431
2432                   case CMDRCPT:         /* rcpt -- designate recipient */
2433                         DELAY_CONN("RCPT");
2434                         if (BadRcptThrottle > 0 &&
2435                             n_badrcpts >= BadRcptThrottle)
2436                         {
2437                                 if (LogLevel > 5 &&
2438                                     n_badrcpts == BadRcptThrottle)
2439                                 {
2440                                         sm_syslog(LOG_INFO, e->e_id,
2441                                                   "%s: Possible SMTP RCPT flood, throttling.",
2442                                                   CurSmtpClient);
2443
2444                                         /* To avoid duplicated message */
2445                                         n_badrcpts++;
2446                                 }
2447                                 NBADRCPTS;
2448
2449                                 /*
2450                                 **  Don't use exponential backoff for now.
2451                                 **  Some servers will open more connections
2452                                 **  and actually overload the receiver even
2453                                 **  more.
2454                                 */
2455
2456                                 (void) sleep(1);
2457                         }
2458                         if (!smtp.sm_gotmail)
2459                         {
2460                                 usrerr("503 5.0.0 Need MAIL before RCPT");
2461                                 break;
2462                         }
2463                         SmtpPhase = "server RCPT";
2464                     SM_TRY
2465                     {
2466                         QuickAbort = true;
2467                         LogUsrErrs = true;
2468
2469                         /* limit flooding of our machine */
2470                         if (MaxRcptPerMsg > 0 &&
2471                             smtp.sm_nrcpts >= MaxRcptPerMsg)
2472                         {
2473                                 /* sleep(1); / * slow down? */
2474                                 usrerr("452 4.5.3 Too many recipients");
2475                                 goto rcpt_done;
2476                         }
2477
2478                         if (e->e_sendmode != SM_DELIVER)
2479                                 e->e_flags |= EF_VRFYONLY;
2480
2481 #if MILTER
2482                         /*
2483                         **  If the filter will be deleting recipients,
2484                         **  don't expand them at RCPT time (in the call
2485                         **  to recipient()).  If they are expanded, it
2486                         **  is impossible for removefromlist() to figure
2487                         **  out the expanded members of the original
2488                         **  recipient and mark them as QS_DONTSEND.
2489                         */
2490
2491                         if (milter_can_delrcpts())
2492                                 e->e_flags |= EF_VRFYONLY;
2493 #endif /* MILTER */
2494
2495                         p = skipword(p, "to");
2496                         if (p == NULL)
2497                                 goto rcpt_done;
2498                         macdefine(&e->e_macro, A_PERM,
2499                                 macid("{addr_type}"), "e r");
2500                         a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
2501                                       e, true);
2502                         macdefine(&e->e_macro, A_PERM,
2503                                 macid("{addr_type}"), NULL);
2504                         if (Errors > 0)
2505                                 goto rcpt_done;
2506                         if (a == NULL)
2507                         {
2508                                 usrerr("501 5.0.0 Missing recipient");
2509                                 goto rcpt_done;
2510                         }
2511
2512                         if (delimptr != NULL && *delimptr != '\0')
2513                                 *delimptr++ = '\0';
2514
2515                         /* put resulting triple from parseaddr() into macros */
2516                         if (a->q_mailer != NULL)
2517                                 macdefine(&e->e_macro, A_PERM,
2518                                         macid("{rcpt_mailer}"),
2519                                         a->q_mailer->m_name);
2520                         else
2521                                 macdefine(&e->e_macro, A_PERM,
2522                                         macid("{rcpt_mailer}"), NULL);
2523                         if (a->q_host != NULL)
2524                                 macdefine(&e->e_macro, A_PERM,
2525                                         macid("{rcpt_host}"), a->q_host);
2526                         else
2527                                 macdefine(&e->e_macro, A_PERM,
2528                                         macid("{rcpt_host}"), "localhost");
2529                         if (a->q_user != NULL)
2530                                 macdefine(&e->e_macro, A_PERM,
2531                                         macid("{rcpt_addr}"), a->q_user);
2532                         else
2533                                 macdefine(&e->e_macro, A_PERM,
2534                                         macid("{rcpt_addr}"), NULL);
2535                         if (Errors > 0)
2536                                 goto rcpt_done;
2537
2538                         /* now parse ESMTP arguments */
2539                         addr = p;
2540                         argno = 0;
2541                         args[argno++] = p;
2542                         p = delimptr;
2543                         while (p != NULL && *p != '\0')
2544                         {
2545                                 char *kp;
2546                                 char *vp = NULL;
2547                                 char *equal = NULL;
2548
2549                                 /* locate the beginning of the keyword */
2550                                 SKIP_SPACE(p);
2551                                 if (*p == '\0')
2552                                         break;
2553                                 kp = p;
2554
2555                                 /* skip to the value portion */
2556                                 while ((isascii(*p) && isalnum(*p)) || *p == '-')
2557                                         p++;
2558                                 if (*p == '=')
2559                                 {
2560                                         equal = p;
2561                                         *p++ = '\0';
2562                                         vp = p;
2563
2564                                         /* skip to the end of the value */
2565                                         while (*p != '\0' && *p != ' ' &&
2566                                                !(isascii(*p) && iscntrl(*p)) &&
2567                                                *p != '=')
2568                                                 p++;
2569                                 }
2570
2571                                 if (*p != '\0')
2572                                         *p++ = '\0';
2573
2574                                 if (tTd(19, 1))
2575                                         sm_dprintf("RCPT: got arg %s=\"%s\"\n", kp,
2576                                                 vp == NULL ? "<null>" : vp);
2577
2578                                 rcpt_esmtp_args(a, kp, vp, e);
2579                                 if (equal != NULL)
2580                                         *equal = '=';
2581                                 args[argno++] = kp;
2582                                 if (argno >= MAXSMTPARGS - 1)
2583                                         usrerr("501 5.5.4 Too many parameters");
2584                                 if (Errors > 0)
2585                                         break;
2586                         }
2587                         args[argno] = NULL;
2588                         if (Errors > 0)
2589                                 goto rcpt_done;
2590
2591                         /* do config file checking of the recipient */
2592                         macdefine(&e->e_macro, A_PERM,
2593                                 macid("{addr_type}"), "e r");
2594                         if (rscheck("check_rcpt", addr,
2595                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2596                                     NULL, e->e_id) != EX_OK ||
2597                             Errors > 0)
2598                                 goto rcpt_done;
2599                         macdefine(&e->e_macro, A_PERM,
2600                                 macid("{addr_type}"), NULL);
2601
2602                         /* If discarding, don't bother to verify user */
2603                         if (bitset(EF_DISCARD, e->e_flags))
2604                                 a->q_state = QS_VERIFIED;
2605
2606 #if MILTER
2607                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2608                             !bitset(EF_DISCARD, e->e_flags))
2609                         {
2610                                 char state;
2611                                 char *response;
2612
2613                                 response = milter_envrcpt(args, e, &state);
2614                                 MILTER_REPLY("to");
2615                         }
2616 #endif /* MILTER */
2617
2618                         macdefine(&e->e_macro, A_PERM,
2619                                 macid("{rcpt_mailer}"), NULL);
2620                         macdefine(&e->e_macro, A_PERM,
2621                                 macid("{rcpt_host}"), NULL);
2622                         macdefine(&e->e_macro, A_PERM,
2623                                 macid("{rcpt_addr}"), NULL);
2624                         macdefine(&e->e_macro, A_PERM,
2625                                 macid("{dsn_notify}"), NULL);
2626                         if (Errors > 0)
2627                                 goto rcpt_done;
2628
2629                         /* save in recipient list after ESMTP mods */
2630                         a = recipient(a, &e->e_sendqueue, 0, e);
2631                         if (Errors > 0)
2632                                 goto rcpt_done;
2633
2634                         /* no errors during parsing, but might be a duplicate */
2635                         e->e_to = a->q_paddr;
2636                         if (!QS_IS_BADADDR(a->q_state))
2637                         {
2638                                 if (smtp.sm_nrcpts == 0)
2639                                         initsys(e);
2640                                 message("250 2.1.5 Recipient ok%s",
2641                                         QS_IS_QUEUEUP(a->q_state) ?
2642                                                 " (will queue)" : "");
2643                                 smtp.sm_nrcpts++;
2644                         }
2645                         else
2646                         {
2647                                 /* punt -- should keep message in ADDRESS.... */
2648                                 usrerr("550 5.1.1 Addressee unknown");
2649                         }
2650                     rcpt_done:
2651                         if (Errors > 0)
2652                         {
2653                                 ++n_badrcpts;
2654                                 NBADRCPTS;
2655                         }
2656                     }
2657                     SM_EXCEPT(exc, "[!F]*")
2658                     {
2659                         /* An exception occurred while processing RCPT */
2660                         e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
2661                         ++n_badrcpts;
2662                         NBADRCPTS;
2663                     }
2664                     SM_END_TRY
2665                         break;
2666
2667                   case CMDDATA:         /* data -- text of mail */
2668                         DELAY_CONN("DATA");
2669                         if (!smtp_data(&smtp, e))
2670                                 goto doquit;
2671                         break;
2672
2673                   case CMDRSET:         /* rset -- reset state */
2674                         if (tTd(94, 100))
2675                                 message("451 4.0.0 Test failure");
2676                         else
2677                                 message("250 2.0.0 Reset state");
2678                         CLEAR_STATE(cmdbuf);
2679                         break;
2680
2681                   case CMDVRFY:         /* vrfy -- verify address */
2682                   case CMDEXPN:         /* expn -- expand address */
2683                         vrfy = c->cmd_code == CMDVRFY;
2684                         DELAY_CONN(vrfy ? "VRFY" : "EXPN");
2685                         if (tempfail)
2686                         {
2687                                 if (LogLevel > 9)
2688                                         sm_syslog(LOG_INFO, e->e_id,
2689                                                   "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
2690                                                   vrfy ? "VRFY" : "EXPN",
2691                                                   p, CurSmtpClient);
2692
2693                                 /* RFC 821 doesn't allow 4xy reply code */
2694                                 usrerr("550 5.7.1 Please try again later");
2695                                 break;
2696                         }
2697                         wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
2698                                              false, vrfy ? "VRFY" : "EXPN", e);
2699                         STOP_IF_ATTACK(wt);
2700                         previous = curtime();
2701                         if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
2702                             (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
2703                         {
2704                                 if (vrfy)
2705                                         message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
2706                                 else
2707                                         message("502 5.7.0 Sorry, we do not allow this operation");
2708                                 if (LogLevel > 5)
2709                                         sm_syslog(LOG_INFO, e->e_id,
2710                                                   "%s: %s [rejected]",
2711                                                   CurSmtpClient,
2712                                                   shortenstring(inp, MAXSHORTSTR));
2713                                 break;
2714                         }
2715                         else if (!gothello &&
2716                                  bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
2717                                                 PrivacyFlags))
2718                         {
2719                                 usrerr("503 5.0.0 I demand that you introduce yourself first");
2720                                 break;
2721                         }
2722                         if (Errors > 0)
2723                                 break;
2724                         if (LogLevel > 5)
2725                                 sm_syslog(LOG_INFO, e->e_id, "%s: %s",
2726                                           CurSmtpClient,
2727                                           shortenstring(inp, MAXSHORTSTR));
2728                     SM_TRY
2729                     {
2730                         QuickAbort = true;
2731                         vrfyqueue = NULL;
2732                         if (vrfy)
2733                                 e->e_flags |= EF_VRFYONLY;
2734                         while (*p != '\0' && isascii(*p) && isspace(*p))
2735                                 p++;
2736                         if (*p == '\0')
2737                         {
2738                                 usrerr("501 5.5.2 Argument required");
2739                         }
2740                         else
2741                         {
2742                                 /* do config file checking of the address */
2743                                 if (rscheck(vrfy ? "check_vrfy" : "check_expn",
2744                                             p, NULL, e, RSF_RMCOMM,
2745                                             3, NULL, NOQID) != EX_OK ||
2746                                     Errors > 0)
2747                                         sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2748                                 (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
2749                         }
2750                         if (wt > 0)
2751                         {
2752                                 time_t t;
2753
2754                                 t = wt - (curtime() - previous);
2755                                 if (t > 0)
2756                                         (void) sleep(t);
2757                         }
2758                         if (Errors > 0)
2759                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2760                         if (vrfyqueue == NULL)
2761                         {
2762                                 usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
2763                         }
2764                         while (vrfyqueue != NULL)
2765                         {
2766                                 if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
2767                                 {
2768                                         vrfyqueue = vrfyqueue->q_next;
2769                                         continue;
2770                                 }
2771
2772                                 /* see if there is more in the vrfy list */
2773                                 a = vrfyqueue;
2774                                 while ((a = a->q_next) != NULL &&
2775                                        (!QS_IS_UNDELIVERED(a->q_state)))
2776                                         continue;
2777                                 printvrfyaddr(vrfyqueue, a == NULL, vrfy);
2778                                 vrfyqueue = a;
2779                         }
2780                     }
2781                     SM_EXCEPT(exc, "[!F]*")
2782                     {
2783                         /*
2784                         **  An exception occurred while processing VRFY/EXPN
2785                         */
2786
2787                         sm_exc_free(exc);
2788                         goto undo;
2789                     }
2790                     SM_END_TRY
2791                         break;
2792
2793                   case CMDETRN:         /* etrn -- force queue flush */
2794                         DELAY_CONN("ETRN");
2795
2796                         /* Don't leak queue information via debug flags */
2797                         if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
2798                             (RealUid != 0 && RealUid != TrustedUid &&
2799                              OpMode == MD_SMTP))
2800                         {
2801                                 /* different message for MSA ? */
2802                                 message("502 5.7.0 Sorry, we do not allow this operation");
2803                                 if (LogLevel > 5)
2804                                         sm_syslog(LOG_INFO, e->e_id,
2805                                                   "%s: %s [rejected]",
2806                                                   CurSmtpClient,
2807                                                   shortenstring(inp, MAXSHORTSTR));
2808                                 break;
2809                         }
2810                         if (tempfail)
2811                         {
2812                                 if (LogLevel > 9)
2813                                         sm_syslog(LOG_INFO, e->e_id,
2814                                                   "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
2815                                                   p, CurSmtpClient);
2816                                 usrerr(MSG_TEMPFAIL);
2817                                 break;
2818                         }
2819
2820                         if (strlen(p) <= 0)
2821                         {
2822                                 usrerr("500 5.5.2 Parameter required");
2823                                 break;
2824                         }
2825
2826                         /* crude way to avoid denial-of-service attacks */
2827                         STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
2828                                                         true, "ETRN", e));
2829
2830                         /*
2831                         **  Do config file checking of the parameter.
2832                         **  Even though we have srv_features now, we still
2833                         **  need this ruleset because the former is called
2834                         **  when the connection has been established, while
2835                         **  this ruleset is called when the command is
2836                         **  actually issued and therefore has all information
2837                         **  available to make a decision.
2838                         */
2839
2840                         if (rscheck("check_etrn", p, NULL, e,
2841                                     RSF_RMCOMM, 3, NULL, NOQID) != EX_OK ||
2842                             Errors > 0)
2843                                 break;
2844
2845                         if (LogLevel > 5)
2846                                 sm_syslog(LOG_INFO, e->e_id,
2847                                           "%s: ETRN %s", CurSmtpClient,
2848                                           shortenstring(p, MAXSHORTSTR));
2849
2850                         id = p;
2851                         if (*id == '#')
2852                         {
2853                                 int i, qgrp;
2854
2855                                 id++;
2856                                 qgrp = name2qid(id);
2857                                 if (!ISVALIDQGRP(qgrp))
2858                                 {
2859                                         usrerr("459 4.5.4 Queue %s unknown",
2860                                                id);
2861                                         break;
2862                                 }
2863                                 for (i = 0; i < NumQueue && Queue[i] != NULL;
2864                                      i++)
2865                                         Queue[i]->qg_nextrun = (time_t) -1;
2866                                 Queue[qgrp]->qg_nextrun = 0;
2867                                 ok = run_work_group(Queue[qgrp]->qg_wgrp,
2868                                                     RWG_FORK|RWG_FORCE);
2869                                 if (ok && Errors == 0)
2870                                         message("250 2.0.0 Queuing for queue group %s started", id);
2871                                 break;
2872                         }
2873
2874                         if (*id == '@')
2875                                 id++;
2876                         else
2877                                 *--id = '@';
2878
2879                         new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
2880                         if (new == NULL)
2881                         {
2882                                 syserr("500 5.5.0 ETRN out of memory");
2883                                 break;
2884                         }
2885                         new->queue_match = id;
2886                         new->queue_negate = false;
2887                         new->queue_next = NULL;
2888                         QueueLimitRecipient = new;
2889                         ok = runqueue(true, false, false, true);
2890                         sm_free(QueueLimitRecipient); /* XXX */
2891                         QueueLimitRecipient = NULL;
2892                         if (ok && Errors == 0)
2893                                 message("250 2.0.0 Queuing for node %s started", p);
2894                         break;
2895
2896                   case CMDHELP:         /* help -- give user info */
2897                         DELAY_CONN("HELP");
2898                         help(p, e);
2899                         break;
2900
2901                   case CMDNOOP:         /* noop -- do nothing */
2902                         DELAY_CONN("NOOP");
2903                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
2904                                                         true, "NOOP", e));
2905                         message("250 2.0.0 OK");
2906                         break;
2907
2908                   case CMDQUIT:         /* quit -- leave mail */
2909                         message("221 2.0.0 %s closing connection", MyHostName);
2910 #if PIPELINING
2911                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2912 #endif /* PIPELINING */
2913
2914                         if (smtp.sm_nrcpts > 0)
2915                                 logundelrcpts(e, "aborted by sender", 9, false);
2916
2917                         /* arrange to ignore any current send list */
2918                         e->e_sendqueue = NULL;
2919
2920 #if STARTTLS
2921                         /* shutdown TLS connection */
2922                         if (tls_active)
2923                         {
2924                                 (void) endtls(srv_ssl, "server");
2925                                 tls_active = false;
2926                         }
2927 #endif /* STARTTLS */
2928 #if SASL
2929                         if (authenticating == SASL_IS_AUTH)
2930                         {
2931                                 sasl_dispose(&conn);
2932                                 authenticating = SASL_NOT_AUTH;
2933                                 /* XXX sasl_done(); this is a child */
2934                         }
2935 #endif /* SASL */
2936
2937 doquit:
2938                         /* avoid future 050 messages */
2939                         disconnect(1, e);
2940
2941 #if MILTER
2942                         /* close out milter filters */
2943                         milter_quit(e);
2944 #endif /* MILTER */
2945
2946                         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
2947                                 logsender(e, NULL);
2948                         e->e_flags &= ~EF_LOGSENDER;
2949
2950                         if (lognullconnection && LogLevel > 5 &&
2951                             nullserver == NULL)
2952                         {
2953                                 char *d;
2954
2955                                 d = macvalue(macid("{daemon_name}"), e);
2956                                 if (d == NULL)
2957                                         d = "stdin";
2958
2959                                 /*
2960                                 **  even though this id is "bogus", it makes
2961                                 **  it simpler to "grep" related events, e.g.,
2962                                 **  timeouts for the same connection.
2963                                 */
2964
2965                                 sm_syslog(LOG_INFO, e->e_id,
2966                                           "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
2967                                           CurSmtpClient, d);
2968                         }
2969                         if (tTd(93, 100))
2970                         {
2971                                 /* return to handle next connection */
2972                                 return;
2973                         }
2974                         finis(true, true, ExitStat);
2975                         /* NOTREACHED */
2976
2977                   case CMDVERB:         /* set verbose mode */
2978                         DELAY_CONN("VERB");
2979                         if (!bitset(SRV_OFFER_EXPN, features) ||
2980                             !bitset(SRV_OFFER_VERB, features))
2981                         {
2982                                 /* this would give out the same info */
2983                                 message("502 5.7.0 Verbose unavailable");
2984                                 break;
2985                         }
2986                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
2987                                                         true, "VERB", e));
2988                         Verbose = 1;
2989                         set_delivery_mode(SM_DELIVER, e);
2990                         message("250 2.0.0 Verbose mode");
2991                         break;
2992
2993 #if SMTPDEBUG
2994                   case CMDDBGQSHOW:     /* show queues */
2995                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2996                                              "Send Queue=");
2997                         printaddr(smioout, e->e_sendqueue, true);
2998                         break;
2999
3000                   case CMDDBGDEBUG:     /* set debug mode */
3001                         tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
3002                         tTflag(p);
3003                         message("200 2.0.0 Debug set");
3004                         break;
3005
3006 #else /* SMTPDEBUG */
3007                   case CMDDBGQSHOW:     /* show queues */
3008                   case CMDDBGDEBUG:     /* set debug mode */
3009 #endif /* SMTPDEBUG */
3010                   case CMDLOGBOGUS:     /* bogus command */
3011                         DELAY_CONN("Bogus");
3012                         if (LogLevel > 0)
3013                                 sm_syslog(LOG_CRIT, e->e_id,
3014                                           "\"%s\" command from %s (%.100s)",
3015                                           c->cmd_name, CurSmtpClient,
3016                                           anynet_ntoa(&RealHostAddr));
3017                         /* FALLTHROUGH */
3018
3019                   case CMDERROR:        /* unknown command */
3020 #if MAXBADCOMMANDS > 0
3021                         if (++n_badcmds > MAXBADCOMMANDS)
3022                         {
3023   stopattack:
3024                                 message("421 4.7.0 %s Too many bad commands; closing connection",
3025                                         MyHostName);
3026
3027                                 /* arrange to ignore any current send list */
3028                                 e->e_sendqueue = NULL;
3029                                 goto doquit;
3030                         }
3031 #endif /* MAXBADCOMMANDS > 0 */
3032
3033 #if MILTER && SMFI_VERSION > 2
3034                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3035                             !bitset(EF_DISCARD, e->e_flags))
3036                         {
3037                                 char state;
3038                                 char *response;
3039
3040                                 if (MilterLogLevel > 9)
3041                                         sm_syslog(LOG_INFO, e->e_id,
3042                                                 "Sending \"%s\" to Milter", inp);
3043                                 response = milter_unknown(inp, e, &state);
3044                                 MILTER_REPLY("unknown");
3045                                 if (state == SMFIR_REPLYCODE ||
3046                                     state == SMFIR_REJECT ||
3047                                     state == SMFIR_TEMPFAIL)
3048                                 {
3049                                         /* MILTER_REPLY already gave an error */
3050                                         break;
3051                                 }
3052                         }
3053 #endif /* MILTER && SMFI_VERSION > 2 */
3054
3055                         usrerr("500 5.5.1 Command unrecognized: \"%s\"",
3056                                shortenstring(inp, MAXSHORTSTR));
3057                         break;
3058
3059                   case CMDUNIMPL:
3060                         DELAY_CONN("Unimpl");
3061                         usrerr("502 5.5.1 Command not implemented: \"%s\"",
3062                                shortenstring(inp, MAXSHORTSTR));
3063                         break;
3064
3065                   default:
3066                         DELAY_CONN("default");
3067                         errno = 0;
3068                         syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
3069                         break;
3070                 }
3071 #if SASL
3072                 }
3073 #endif /* SASL */
3074             }
3075             SM_EXCEPT(exc, "[!F]*")
3076             {
3077                 /*
3078                 **  The only possible exception is "E:mta.quickabort".
3079                 **  There is nothing to do except fall through and loop.
3080                 */
3081             }
3082             SM_END_TRY
3083         }
3084 }
3085 /*
3086 **  SMTP_DATA -- implement the SMTP DATA command.
3087 **
3088 **      Parameters:
3089 **              smtp -- status of SMTP connection.
3090 **              e -- envelope.
3091 **
3092 **      Returns:
3093 **              true iff SMTP session can continue.
3094 **
3095 **      Side Effects:
3096 **              possibly sends message.
3097 */
3098
3099 static bool
3100 smtp_data(smtp, e)
3101         SMTP_T *smtp;
3102         ENVELOPE *e;
3103 {
3104 #if MILTER
3105         bool milteraccept;
3106 #endif /* MILTER */
3107         bool aborting;
3108         bool doublequeue;
3109         ADDRESS *a;
3110         ENVELOPE *ee;
3111         char *id;
3112         char *oldid;
3113         char buf[32];
3114
3115         SmtpPhase = "server DATA";
3116         if (!smtp->sm_gotmail)
3117         {
3118                 usrerr("503 5.0.0 Need MAIL command");
3119                 return true;
3120         }
3121         else if (smtp->sm_nrcpts <= 0)
3122         {
3123                 usrerr("503 5.0.0 Need RCPT (recipient)");
3124                 return true;
3125         }
3126         (void) sm_snprintf(buf, sizeof buf, "%u", smtp->sm_nrcpts);
3127         if (rscheck("check_data", buf, NULL, e,
3128                     RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
3129                     e->e_id) != EX_OK)
3130                 return true;
3131
3132 #if MILTER && SMFI_VERSION > 3
3133         if (smtp->sm_milterlist && smtp->sm_milterize &&
3134             !bitset(EF_DISCARD, e->e_flags))
3135         {
3136                 char state;
3137                 char *response;
3138                 int savelogusrerrs = LogUsrErrs;
3139
3140                 response = milter_data_cmd(e, &state);
3141                 switch (state)
3142                 {
3143                   case SMFIR_REPLYCODE:
3144                         if (MilterLogLevel > 3)
3145                         {
3146                                 sm_syslog(LOG_INFO, e->e_id,
3147                                           "Milter: cmd=data, reject=%s",
3148                                           response);
3149                                 LogUsrErrs = false;
3150                         }
3151                         usrerr(response);
3152                         if (strncmp(response, "421 ", 4) == 0)
3153                         {
3154                                 e->e_sendqueue = NULL;
3155                                 return false;
3156                         }
3157                         return true;
3158
3159                   case SMFIR_REJECT:
3160                         if (MilterLogLevel > 3)
3161                         {
3162                                 sm_syslog(LOG_INFO, e->e_id,
3163                                           "Milter: cmd=data, reject=550 5.7.1 Command rejected");
3164                                 LogUsrErrs = false;
3165                         }
3166                         usrerr("550 5.7.1 Command rejected");
3167                         return true;
3168
3169                   case SMFIR_DISCARD:
3170                         if (MilterLogLevel > 3)
3171                                 sm_syslog(LOG_INFO, e->e_id,
3172                                           "Milter: cmd=data, discard");
3173                         e->e_flags |= EF_DISCARD;
3174                         break;
3175
3176                   case SMFIR_TEMPFAIL:
3177                         if (MilterLogLevel > 3)
3178                         {
3179                                 sm_syslog(LOG_INFO, e->e_id,
3180                                           "Milter: cmd=data, reject=%s",
3181                                           MSG_TEMPFAIL);
3182                                 LogUsrErrs = false;
3183                         }
3184                         usrerr(MSG_TEMPFAIL);
3185                         return true;
3186                 }
3187                 LogUsrErrs = savelogusrerrs;
3188                 if (response != NULL)
3189                         sm_free(response); /* XXX */
3190         }
3191 #endif /* MILTER && SMFI_VERSION > 3 */
3192
3193         /* put back discard bit */
3194         if (smtp->sm_discard)
3195                 e->e_flags |= EF_DISCARD;
3196
3197         /* check to see if we need to re-expand aliases */
3198         /* also reset QS_BADADDR on already-diagnosted addrs */
3199         doublequeue = false;
3200         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
3201         {
3202                 if (QS_IS_VERIFIED(a->q_state) &&
3203                     !bitset(EF_DISCARD, e->e_flags))
3204                 {
3205                         /* need to re-expand aliases */
3206                         doublequeue = true;
3207                 }
3208                 if (QS_IS_BADADDR(a->q_state))
3209                 {
3210                         /* make this "go away" */
3211                         a->q_state = QS_DONTSEND;
3212                 }
3213         }
3214
3215         /* collect the text of the message */
3216         SmtpPhase = "collect";
3217         buffer_errors();
3218
3219         collect(InChannel, true, NULL, e, true);
3220
3221         /* redefine message size */
3222         (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3223         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3224
3225 #if _FFR_CHECK_EOM
3226         /* rscheck() will set Errors or EF_DISCARD if it trips */
3227         (void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
3228                        3, NULL, e->e_id);
3229 #endif /* _FFR_CHECK_EOM */
3230
3231 #if MILTER
3232         milteraccept = true;
3233         if (smtp->sm_milterlist && smtp->sm_milterize &&
3234             Errors <= 0 &&
3235             !bitset(EF_DISCARD, e->e_flags))
3236         {
3237                 char state;
3238                 char *response;
3239
3240                 response = milter_data(e, &state);
3241                 switch (state)
3242                 {
3243                   case SMFIR_REPLYCODE:
3244                         if (MilterLogLevel > 3)
3245                                 sm_syslog(LOG_INFO, e->e_id,
3246                                           "Milter: data, reject=%s",
3247                                           response);
3248                         milteraccept = false;
3249                         usrerr(response);
3250                         break;
3251
3252                   case SMFIR_REJECT:
3253                         milteraccept = false;
3254                         if (MilterLogLevel > 3)
3255                                 sm_syslog(LOG_INFO, e->e_id,
3256                                           "Milter: data, reject=554 5.7.1 Command rejected");
3257                         usrerr("554 5.7.1 Command rejected");
3258                         break;
3259
3260                   case SMFIR_DISCARD:
3261                         if (MilterLogLevel > 3)
3262                                 sm_syslog(LOG_INFO, e->e_id,
3263                                           "Milter: data, discard");
3264                         milteraccept = false;
3265                         e->e_flags |= EF_DISCARD;
3266                         break;
3267
3268                   case SMFIR_TEMPFAIL:
3269                         if (MilterLogLevel > 3)
3270                                 sm_syslog(LOG_INFO, e->e_id,
3271                                           "Milter: data, reject=%s",
3272                                           MSG_TEMPFAIL);
3273                         milteraccept = false;
3274                         usrerr(MSG_TEMPFAIL);
3275                         break;
3276                 }
3277                 if (response != NULL)
3278                         sm_free(response);
3279         }
3280
3281         /* Milter may have changed message size */
3282         (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3283         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3284
3285         /* abort message filters that didn't get the body & log msg is OK */
3286         if (smtp->sm_milterlist && smtp->sm_milterize)
3287         {
3288                 milter_abort(e);
3289                 if (milteraccept && MilterLogLevel > 9)
3290                         sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
3291         }
3292
3293         /*
3294         **  If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
3295         **  milter accepted message, sync it now
3296         **
3297         **  XXX This is almost a copy of the code in collect(): put it into
3298         **      a function that is called from both places?
3299         */
3300
3301         if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
3302         {
3303                 int afd;
3304                 SM_FILE_T *volatile df;
3305                 char *dfname;
3306
3307                 df = e->e_dfp;
3308                 dfname = queuename(e, DATAFL_LETTER);
3309                 if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
3310                     && errno != EINVAL)
3311                 {
3312                         int save_errno;
3313
3314                         save_errno = errno;
3315                         if (save_errno == EEXIST)
3316                         {
3317                                 struct stat st;
3318                                 int dfd;
3319
3320                                 if (stat(dfname, &st) < 0)
3321                                         st.st_size = -1;
3322                                 errno = EEXIST;
3323                                 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
3324                                        dfname, (long) st.st_size);
3325                                 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
3326                                 if (dfd >= 0)
3327                                         dumpfd(dfd, true, true);
3328                         }
3329                         errno = save_errno;
3330                         dferror(df, "bfcommit", e);
3331                         flush_errors(true);
3332                         finis(save_errno != EEXIST, true, ExitStat);
3333                 }
3334                 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
3335                 {
3336                         dferror(df, "sm_io_getinfo", e);
3337                         flush_errors(true);
3338                         finis(true, true, ExitStat);
3339                         /* NOTREACHED */
3340                 }
3341                 else if (fsync(afd) < 0)
3342                 {
3343                         dferror(df, "fsync", e);
3344                         flush_errors(true);
3345                         finis(true, true, ExitStat);
3346                         /* NOTREACHED */
3347                 }
3348                 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
3349                 {
3350                         dferror(df, "sm_io_close", e);
3351                         flush_errors(true);
3352                         finis(true, true, ExitStat);
3353                         /* NOTREACHED */
3354                 }
3355
3356                 /* Now reopen the df file */
3357                 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
3358                                         SM_IO_RDONLY, NULL);
3359                 if (e->e_dfp == NULL)
3360                 {
3361                         /* we haven't acked receipt yet, so just chuck this */
3362                         syserr("@Cannot reopen %s", dfname);
3363                         finis(true, true, ExitStat);
3364                         /* NOTREACHED */
3365                 }
3366         }
3367 #endif /* MILTER */
3368
3369         /* Check if quarantining stats should be updated */
3370         if (e->e_quarmsg != NULL)
3371                 markstats(e, NULL, STATS_QUARANTINE);
3372
3373         /*
3374         **  If a header/body check (header checks or milter)
3375         **  set EF_DISCARD, don't queueup the message --
3376         **  that would lose the EF_DISCARD bit and deliver
3377         **  the message.
3378         */
3379
3380         if (bitset(EF_DISCARD, e->e_flags))
3381                 doublequeue = false;
3382
3383         aborting = Errors > 0;
3384         if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
3385             (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
3386             !split_by_recipient(e))
3387                 aborting = bitset(EF_FATALERRS, e->e_flags);
3388
3389         if (aborting)
3390         {
3391                 /* Log who the mail would have gone to */
3392                 logundelrcpts(e, e->e_message, 8, false);
3393                 flush_errors(true);
3394                 buffer_errors();
3395                 goto abortmessage;
3396         }
3397
3398         /* from now on, we have to operate silently */
3399         buffer_errors();
3400
3401 #if 0
3402         /*
3403         **  Clear message, it may contain an error from the SMTP dialogue.
3404         **  This error must not show up in the queue.
3405         **      Some error message should show up, e.g., alias database
3406         **      not available, but others shouldn't, e.g., from check_rcpt.
3407         */
3408
3409         e->e_message = NULL;
3410 #endif /* 0 */
3411
3412         /*
3413         **  Arrange to send to everyone.
3414         **      If sending to multiple people, mail back
3415         **              errors rather than reporting directly.
3416         **      In any case, don't mail back errors for
3417         **              anything that has happened up to
3418         **              now (the other end will do this).
3419         **      Truncate our transcript -- the mail has gotten
3420         **              to us successfully, and if we have
3421         **              to mail this back, it will be easier
3422         **              on the reader.
3423         **      Then send to everyone.
3424         **      Finally give a reply code.  If an error has
3425         **              already been given, don't mail a
3426         **              message back.
3427         **      We goose error returns by clearing error bit.
3428         */
3429
3430         SmtpPhase = "delivery";
3431         (void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
3432         id = e->e_id;
3433
3434 #if NAMED_BIND
3435         _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
3436         _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
3437 #endif /* NAMED_BIND */
3438
3439         for (ee = e; ee != NULL; ee = ee->e_sibling)
3440         {
3441                 /* make sure we actually do delivery */
3442                 ee->e_flags &= ~EF_CLRQUEUE;
3443
3444                 /* from now on, operate silently */
3445                 ee->e_errormode = EM_MAIL;
3446
3447                 if (doublequeue)
3448                 {
3449                         /* make sure it is in the queue */
3450                         queueup(ee, false, true);
3451                 }
3452                 else
3453                 {
3454                         /* send to all recipients */
3455                         sendall(ee, SM_DEFAULT);
3456                 }
3457                 ee->e_to = NULL;
3458         }
3459
3460         /* put back id for SMTP logging in putoutmsg() */
3461         oldid = CurEnv->e_id;
3462         CurEnv->e_id = id;
3463
3464         /* issue success message */
3465         message("250 2.0.0 %s Message accepted for delivery", id);
3466         CurEnv->e_id = oldid;
3467
3468         /* if we just queued, poke it */
3469         if (doublequeue)
3470         {
3471                 bool anything_to_send = false;
3472
3473                 sm_getla();
3474                 for (ee = e; ee != NULL; ee = ee->e_sibling)
3475                 {
3476                         if (WILL_BE_QUEUED(ee->e_sendmode))
3477                                 continue;
3478                         if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
3479                         {
3480                                 ee->e_sendmode = SM_QUEUE;
3481                                 continue;
3482                         }
3483                         else if (QueueMode != QM_QUARANTINE &&
3484                                  ee->e_quarmsg != NULL)
3485                         {
3486                                 ee->e_sendmode = SM_QUEUE;
3487                                 continue;
3488                         }
3489                         anything_to_send = true;
3490
3491                         /* close all the queue files */
3492                         closexscript(ee);
3493                         if (ee->e_dfp != NULL)
3494                         {
3495                                 (void) sm_io_close(ee->e_dfp, SM_TIME_DEFAULT);
3496                                 ee->e_dfp = NULL;
3497                         }
3498                         unlockqueue(ee);
3499                 }
3500                 if (anything_to_send)
3501                 {
3502 #if PIPELINING
3503                         /*
3504                         **  XXX if we don't do this, we get 250 twice
3505                         **      because it is also flushed in the child.
3506                         */
3507
3508                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3509 #endif /* PIPELINING */
3510                         (void) doworklist(e, true, true);
3511                 }
3512         }
3513
3514   abortmessage:
3515         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3516                 logsender(e, NULL);
3517         e->e_flags &= ~EF_LOGSENDER;
3518
3519         /* clean up a bit */
3520         smtp->sm_gotmail = false;
3521
3522         /*
3523         **  Call dropenvelope if and only if the envelope is *not*
3524         **  being processed by the child process forked by doworklist().
3525         */
3526
3527         if (aborting || bitset(EF_DISCARD, e->e_flags))
3528                 dropenvelope(e, true, false);
3529         else
3530         {
3531                 for (ee = e; ee != NULL; ee = ee->e_sibling)
3532                 {
3533                         if (!doublequeue &&
3534                             QueueMode != QM_QUARANTINE &&
3535                             ee->e_quarmsg != NULL)
3536                         {
3537                                 dropenvelope(ee, true, false);
3538                                 continue;
3539                         }
3540                         if (WILL_BE_QUEUED(ee->e_sendmode))
3541                                 dropenvelope(ee, true, false);
3542                 }
3543         }
3544         sm_rpool_free(e->e_rpool);
3545
3546         /*
3547         **  At this point, e == &MainEnvelope, but if we did splitting,
3548         **  then CurEnv may point to an envelope structure that was just
3549         **  freed with the rpool.  So reset CurEnv *before* calling
3550         **  newenvelope.
3551         */
3552
3553         CurEnv = e;
3554         newenvelope(e, e, sm_rpool_new_x(NULL));
3555         e->e_flags = BlankEnvelope.e_flags;
3556
3557         /* restore connection quarantining */
3558         if (smtp->sm_quarmsg == NULL)
3559         {
3560                 e->e_quarmsg = NULL;
3561                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
3562         }
3563         else
3564         {
3565                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
3566                 macdefine(&e->e_macro, A_PERM,
3567                           macid("{quarantine}"), e->e_quarmsg);
3568         }
3569         return true;
3570 }
3571 /*
3572 **  LOGUNDELRCPTS -- log undelivered (or all) recipients.
3573 **
3574 **      Parameters:
3575 **              e -- envelope.
3576 **              msg -- message for Stat=
3577 **              level -- log level.
3578 **              all -- log all recipients.
3579 **
3580 **      Returns:
3581 **              none.
3582 **
3583 **      Side Effects:
3584 **              logs undelivered (or all) recipients
3585 */
3586
3587 void
3588 logundelrcpts(e, msg, level, all)
3589         ENVELOPE *e;
3590         char *msg;
3591         int level;
3592         bool all;
3593 {
3594         ADDRESS *a;
3595
3596         if (LogLevel <= level || msg == NULL || *msg == '\0')
3597                 return;
3598
3599         /* Clear $h so relay= doesn't get mislogged by logdelivery() */
3600         macdefine(&e->e_macro, A_PERM, 'h', NULL);
3601
3602         /* Log who the mail would have gone to */
3603         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
3604         {
3605                 if (!QS_IS_UNDELIVERED(a->q_state) && !all)
3606                         continue;
3607                 e->e_to = a->q_paddr;
3608                 logdelivery(NULL, NULL, a->q_status, msg, NULL,
3609                             (time_t) 0, e);
3610         }
3611         e->e_to = NULL;
3612 }
3613 /*
3614 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
3615 **
3616 **      Parameters:
3617 **              pcounter -- pointer to a counter for this command.
3618 **              maxcount -- maximum value for this counter before we
3619 **                      slow down.
3620 **              waitnow -- sleep now (in this routine)?
3621 **              cname -- command name for logging.
3622 **              e -- the current envelope.
3623 **
3624 **      Returns:
3625 **              time to wait,
3626 **              STOP_ATTACK if twice as many commands as allowed and
3627 **                      MaxChildren > 0.
3628 **
3629 **      Side Effects:
3630 **              Slows down if we seem to be under attack.
3631 */
3632
3633 static time_t
3634 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
3635         volatile unsigned int *pcounter;
3636         unsigned int maxcount;
3637         bool waitnow;
3638         char *cname;
3639         ENVELOPE *e;
3640 {
3641         if (maxcount <= 0)      /* no limit */
3642                 return (time_t) 0;
3643
3644         if (++(*pcounter) >= maxcount)
3645         {
3646                 unsigned int shift;
3647                 time_t s;
3648
3649                 if (*pcounter == maxcount && LogLevel > 5)
3650                 {
3651                         sm_syslog(LOG_INFO, e->e_id,
3652                                   "%s: possible SMTP attack: command=%.40s, count=%u",
3653                                   CurSmtpClient, cname, *pcounter);
3654                 }
3655                 shift = *pcounter - maxcount;
3656                 s = 1 << shift;
3657                 if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
3658                         s = MAXTIMEOUT;
3659
3660 #define IS_ATTACK(s)    ((MaxChildren > 0 && *pcounter >= maxcount * 2) \
3661                                 ? STOP_ATTACK : (time_t) s)
3662
3663                 /* sleep at least 1 second before returning */
3664                 (void) sleep(*pcounter / maxcount);
3665                 s -= *pcounter / maxcount;
3666                 if (s >= MAXTIMEOUT || s < 0)
3667                         s = MAXTIMEOUT;
3668                 if (waitnow && s > 0)
3669                 {
3670                         (void) sleep(s);
3671                         return IS_ATTACK(0);
3672                 }
3673                 return IS_ATTACK(s);
3674         }
3675         return (time_t) 0;
3676 }
3677 /*
3678 **  SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
3679 **
3680 **      Parameters:
3681 **              none.
3682 **
3683 **      Returns:
3684 **              nothing.
3685 **
3686 **      Side Effects:
3687 **              may change I/O fd.
3688 */
3689
3690 static void
3691 setup_smtpd_io()
3692 {
3693         int inchfd, outchfd, outfd;
3694
3695         inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
3696         outchfd  = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
3697         outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
3698         if (outchfd != outfd)
3699         {
3700                 /* arrange for debugging output to go to remote host */
3701                 (void) dup2(outchfd, outfd);
3702         }
3703
3704         /*
3705         **  if InChannel and OutChannel are stdin/stdout
3706         **  and connected to ttys
3707         **  and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
3708         **  then "chain" them together.
3709         */
3710
3711         if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
3712             isatty(inchfd) && isatty(outchfd))
3713         {
3714                 int inmode, outmode;
3715
3716                 inmode = fcntl(inchfd, F_GETFL, 0);
3717                 if (inmode == -1)
3718                 {
3719                         if (LogLevel > 11)
3720                                 sm_syslog(LOG_INFO, NOQID,
3721                                         "fcntl(inchfd, F_GETFL) failed: %s",
3722                                         sm_errstring(errno));
3723                         return;
3724                 }
3725                 outmode = fcntl(outchfd, F_GETFL, 0);
3726                 if (outmode == -1)
3727                 {
3728                         if (LogLevel > 11)
3729                                 sm_syslog(LOG_INFO, NOQID,
3730                                         "fcntl(outchfd, F_GETFL) failed: %s",
3731                                         sm_errstring(errno));
3732                         return;
3733                 }
3734                 if (bitset(O_NONBLOCK, inmode) ||
3735                     bitset(O_NONBLOCK, outmode) ||
3736                     fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
3737                         return;
3738                 outmode = fcntl(outchfd, F_GETFL, 0);
3739                 if (outmode != -1 && bitset(O_NONBLOCK, outmode))
3740                 {
3741                         /* changing InChannel also changes OutChannel */
3742                         sm_io_automode(OutChannel, InChannel);
3743                         if (tTd(97, 4) && LogLevel > 9)
3744                                 sm_syslog(LOG_INFO, NOQID,
3745                                           "set automode for I (%d)/O (%d) in SMTP server",
3746                                           inchfd, outchfd);
3747                 }
3748
3749                 /* undo change of inchfd */
3750                 (void) fcntl(inchfd, F_SETFL, inmode);
3751         }
3752 }
3753 /*
3754 **  SKIPWORD -- skip a fixed word.
3755 **
3756 **      Parameters:
3757 **              p -- place to start looking.
3758 **              w -- word to skip.
3759 **
3760 **      Returns:
3761 **              p following w.
3762 **              NULL on error.
3763 **
3764 **      Side Effects:
3765 **              clobbers the p data area.
3766 */
3767
3768 static char *
3769 skipword(p, w)
3770         register char *volatile p;
3771         char *w;
3772 {
3773         register char *q;
3774         char *firstp = p;
3775
3776         /* find beginning of word */
3777         SKIP_SPACE(p);
3778         q = p;
3779
3780         /* find end of word */
3781         while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
3782                 p++;
3783         while (isascii(*p) && isspace(*p))
3784                 *p++ = '\0';
3785         if (*p != ':')
3786         {
3787           syntax:
3788                 usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
3789                         shortenstring(firstp, MAXSHORTSTR));
3790                 return NULL;
3791         }
3792         *p++ = '\0';
3793         SKIP_SPACE(p);
3794
3795         if (*p == '\0')
3796                 goto syntax;
3797
3798         /* see if the input word matches desired word */
3799         if (sm_strcasecmp(q, w))
3800                 goto syntax;
3801
3802         return p;
3803 }
3804 /*
3805 **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
3806 **
3807 **      Parameters:
3808 **              kp -- the parameter key.
3809 **              vp -- the value of that parameter.
3810 **              e -- the envelope.
3811 **
3812 **      Returns:
3813 **              none.
3814 */
3815
3816 static void
3817 mail_esmtp_args(kp, vp, e)
3818         char *kp;
3819         char *vp;
3820         ENVELOPE *e;
3821 {
3822         if (sm_strcasecmp(kp, "size") == 0)
3823         {
3824                 if (vp == NULL)
3825                 {
3826                         usrerr("501 5.5.2 SIZE requires a value");
3827                         /* NOTREACHED */
3828                 }
3829                 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
3830                 errno = 0;
3831                 e->e_msgsize = strtol(vp, (char **) NULL, 10);
3832                 if (e->e_msgsize == LONG_MAX && errno == ERANGE)
3833                 {
3834                         usrerr("552 5.2.3 Message size exceeds maximum value");
3835                         /* NOTREACHED */
3836                 }
3837                 if (e->e_msgsize < 0)
3838                 {
3839                         usrerr("552 5.2.3 Message size invalid");
3840                         /* NOTREACHED */
3841                 }
3842         }
3843         else if (sm_strcasecmp(kp, "body") == 0)
3844         {
3845                 if (vp == NULL)
3846                 {
3847                         usrerr("501 5.5.2 BODY requires a value");
3848                         /* NOTREACHED */
3849                 }
3850                 else if (sm_strcasecmp(vp, "8bitmime") == 0)
3851                 {
3852                         SevenBitInput = false;
3853                 }
3854                 else if (sm_strcasecmp(vp, "7bit") == 0)
3855                 {
3856                         SevenBitInput = true;
3857                 }
3858                 else
3859                 {
3860                         usrerr("501 5.5.4 Unknown BODY type %s", vp);
3861                         /* NOTREACHED */
3862                 }
3863                 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
3864         }
3865         else if (sm_strcasecmp(kp, "envid") == 0)
3866         {
3867                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3868                 {
3869                         usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
3870                         /* NOTREACHED */
3871                 }
3872                 if (vp == NULL)
3873                 {
3874                         usrerr("501 5.5.2 ENVID requires a value");
3875                         /* NOTREACHED */
3876                 }
3877                 if (!xtextok(vp))
3878                 {
3879                         usrerr("501 5.5.4 Syntax error in ENVID parameter value");
3880                         /* NOTREACHED */
3881                 }
3882                 if (e->e_envid != NULL)
3883                 {
3884                         usrerr("501 5.5.0 Duplicate ENVID parameter");
3885                         /* NOTREACHED */
3886                 }
3887                 e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
3888                 macdefine(&e->e_macro, A_PERM,
3889                         macid("{dsn_envid}"), e->e_envid);
3890         }
3891         else if (sm_strcasecmp(kp, "ret") == 0)
3892         {
3893                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3894                 {
3895                         usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
3896                         /* NOTREACHED */
3897                 }
3898                 if (vp == NULL)
3899                 {
3900                         usrerr("501 5.5.2 RET requires a value");
3901                         /* NOTREACHED */
3902                 }
3903                 if (bitset(EF_RET_PARAM, e->e_flags))
3904                 {
3905                         usrerr("501 5.5.0 Duplicate RET parameter");
3906                         /* NOTREACHED */
3907                 }
3908                 e->e_flags |= EF_RET_PARAM;
3909                 if (sm_strcasecmp(vp, "hdrs") == 0)
3910                         e->e_flags |= EF_NO_BODY_RETN;
3911                 else if (sm_strcasecmp(vp, "full") != 0)
3912                 {
3913                         usrerr("501 5.5.2 Bad argument \"%s\" to RET", vp);
3914                         /* NOTREACHED */
3915                 }
3916                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
3917         }
3918 #if SASL
3919         else if (sm_strcasecmp(kp, "auth") == 0)
3920         {
3921                 int len;
3922                 char *q;
3923                 char *auth_param;       /* the value of the AUTH=x */
3924                 bool saveQuickAbort = QuickAbort;
3925                 bool saveSuprErrs = SuprErrs;
3926                 bool saveExitStat = ExitStat;
3927
3928                 if (vp == NULL)
3929                 {
3930                         usrerr("501 5.5.2 AUTH= requires a value");
3931                         /* NOTREACHED */
3932                 }
3933                 if (e->e_auth_param != NULL)
3934                 {
3935                         usrerr("501 5.5.0 Duplicate AUTH parameter");
3936                         /* NOTREACHED */
3937                 }
3938                 if ((q = strchr(vp, ' ')) != NULL)
3939                         len = q - vp + 1;
3940                 else
3941                         len = strlen(vp) + 1;
3942                 auth_param = xalloc(len);
3943                 (void) sm_strlcpy(auth_param, vp, len);
3944                 if (!xtextok(auth_param))
3945                 {
3946                         usrerr("501 5.5.4 Syntax error in AUTH parameter value");
3947                         /* just a warning? */
3948                         /* NOTREACHED */
3949                 }
3950
3951                 /* XXX define this always or only if trusted? */
3952                 macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
3953                           auth_param);
3954
3955                 /*
3956                 **  call Strust_auth to find out whether
3957                 **  auth_param is acceptable (trusted)
3958                 **  we shouldn't trust it if not authenticated
3959                 **  (required by RFC, leave it to ruleset?)
3960                 */
3961
3962                 SuprErrs = true;
3963                 QuickAbort = false;
3964                 if (strcmp(auth_param, "<>") != 0 &&
3965                      (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM,
3966                               9, NULL, NOQID) != EX_OK || Errors > 0))
3967                 {
3968                         if (tTd(95, 8))
3969                         {
3970                                 q = e->e_auth_param;
3971                                 sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
3972                                         auth_param, (q == NULL) ? "" : q);
3973                         }
3974
3975                         /* not trusted */
3976                         e->e_auth_param = "<>";
3977 # if _FFR_AUTH_PASSING
3978                         macdefine(&BlankEnvelope.e_macro, A_PERM,
3979                                   macid("{auth_author}"), NULL);
3980 # endif /* _FFR_AUTH_PASSING */
3981                 }
3982                 else
3983                 {
3984                         if (tTd(95, 8))
3985                                 sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
3986                         e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
3987                                                             auth_param);
3988                 }
3989                 sm_free(auth_param); /* XXX */
3990
3991                 /* reset values */
3992                 Errors = 0;
3993                 QuickAbort = saveQuickAbort;
3994                 SuprErrs = saveSuprErrs;
3995                 ExitStat = saveExitStat;
3996         }
3997 #endif /* SASL */
3998 #define PRTCHAR(c)      ((isascii(c) && isprint(c)) ? (c) : '?')
3999
4000         /*
4001         **  "by" is only accepted if DeliverByMin >= 0.
4002         **  We maybe could add this to the list of server_features.
4003         */
4004
4005         else if (sm_strcasecmp(kp, "by") == 0 && DeliverByMin >= 0)
4006         {
4007                 char *s;
4008
4009                 if (vp == NULL)
4010                 {
4011                         usrerr("501 5.5.2 BY= requires a value");
4012                         /* NOTREACHED */
4013                 }
4014                 errno = 0;
4015                 e->e_deliver_by = strtol(vp, &s, 10);
4016                 if (e->e_deliver_by == LONG_MIN ||
4017                     e->e_deliver_by == LONG_MAX ||
4018                     e->e_deliver_by > 999999999l ||
4019                     e->e_deliver_by < -999999999l)
4020                 {
4021                         usrerr("501 5.5.2 BY=%s out of range", vp);
4022                         /* NOTREACHED */
4023                 }
4024                 if (s == NULL || *s != ';')
4025                 {
4026                         usrerr("501 5.5.2 BY= missing ';'");
4027                         /* NOTREACHED */
4028                 }
4029                 e->e_dlvr_flag = 0;
4030                 ++s;    /* XXX: spaces allowed? */
4031                 SKIP_SPACE(s);
4032                 switch (tolower(*s))
4033                 {
4034                   case 'n':
4035                         e->e_dlvr_flag = DLVR_NOTIFY;
4036                         break;
4037                   case 'r':
4038                         e->e_dlvr_flag = DLVR_RETURN;
4039                         if (e->e_deliver_by <= 0)
4040                         {
4041                                 usrerr("501 5.5.4 mode R requires BY time > 0");
4042                                 /* NOTREACHED */
4043                         }
4044                         if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
4045                             e->e_deliver_by < DeliverByMin)
4046                         {
4047                                 usrerr("555 5.5.2 time %ld less than %ld",
4048                                         e->e_deliver_by, (long) DeliverByMin);
4049                                 /* NOTREACHED */
4050                         }
4051                         break;
4052                   default:
4053                         usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
4054                         /* NOTREACHED */
4055                 }
4056                 ++s;    /* XXX: spaces allowed? */
4057                 SKIP_SPACE(s);
4058                 switch (tolower(*s))
4059                 {
4060                   case 't':
4061                         e->e_dlvr_flag |= DLVR_TRACE;
4062                         break;
4063                   case '\0':
4064                         break;
4065                   default:
4066                         usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
4067                         /* NOTREACHED */
4068                 }
4069
4070                 /* XXX: check whether more characters follow? */
4071         }
4072         else
4073         {
4074                 usrerr("555 5.5.4 %s parameter unrecognized", kp);
4075                 /* NOTREACHED */
4076         }
4077 }
4078 /*
4079 **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
4080 **
4081 **      Parameters:
4082 **              a -- the address corresponding to the To: parameter.
4083 **              kp -- the parameter key.
4084 **              vp -- the value of that parameter.
4085 **              e -- the envelope.
4086 **
4087 **      Returns:
4088 **              none.
4089 */
4090
4091 static void
4092 rcpt_esmtp_args(a, kp, vp, e)
4093         ADDRESS *a;
4094         char *kp;
4095         char *vp;
4096         ENVELOPE *e;
4097 {
4098         if (sm_strcasecmp(kp, "notify") == 0)
4099         {
4100                 char *p;
4101
4102                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
4103                 {
4104                         usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
4105                         /* NOTREACHED */
4106                 }
4107                 if (vp == NULL)
4108                 {
4109                         usrerr("501 5.5.2 NOTIFY requires a value");
4110                         /* NOTREACHED */
4111                 }
4112                 a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
4113                 a->q_flags |= QHASNOTIFY;
4114                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
4115
4116                 if (sm_strcasecmp(vp, "never") == 0)
4117                         return;
4118                 for (p = vp; p != NULL; vp = p)
4119                 {
4120                         char *s;
4121
4122                         s = p = strchr(p, ',');
4123                         if (p != NULL)
4124                                 *p++ = '\0';
4125                         if (sm_strcasecmp(vp, "success") == 0)
4126                                 a->q_flags |= QPINGONSUCCESS;
4127                         else if (sm_strcasecmp(vp, "failure") == 0)
4128                                 a->q_flags |= QPINGONFAILURE;
4129                         else if (sm_strcasecmp(vp, "delay") == 0)
4130                                 a->q_flags |= QPINGONDELAY;
4131                         else
4132                         {
4133                                 usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
4134                                         vp);
4135                                 /* NOTREACHED */
4136                         }
4137                         if (s != NULL)
4138                                 *s = ',';
4139                 }
4140         }
4141         else if (sm_strcasecmp(kp, "orcpt") == 0)
4142         {
4143                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
4144                 {
4145                         usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
4146                         /* NOTREACHED */
4147                 }
4148                 if (vp == NULL)
4149                 {
4150                         usrerr("501 5.5.2 ORCPT requires a value");
4151                         /* NOTREACHED */
4152                 }
4153                 if (strchr(vp, ';') == NULL || !xtextok(vp))
4154                 {
4155                         usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
4156                         /* NOTREACHED */
4157                 }
4158                 if (a->q_orcpt != NULL)
4159                 {
4160                         usrerr("501 5.5.0 Duplicate ORCPT parameter");
4161                         /* NOTREACHED */
4162                 }
4163                 a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
4164         }
4165         else
4166         {
4167                 usrerr("555 5.5.4 %s parameter unrecognized", kp);
4168                 /* NOTREACHED */
4169         }
4170 }
4171 /*
4172 **  PRINTVRFYADDR -- print an entry in the verify queue
4173 **
4174 **      Parameters:
4175 **              a -- the address to print.
4176 **              last -- set if this is the last one.
4177 **              vrfy -- set if this is a VRFY command.
4178 **
4179 **      Returns:
4180 **              none.
4181 **
4182 **      Side Effects:
4183 **              Prints the appropriate 250 codes.
4184 */
4185 #define OFFF    (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */
4186
4187 static void
4188 printvrfyaddr(a, last, vrfy)
4189         register ADDRESS *a;
4190         bool last;
4191         bool vrfy;
4192 {
4193         char fmtbuf[30];
4194
4195         if (vrfy && a->q_mailer != NULL &&
4196             !bitnset(M_VRFY250, a->q_mailer->m_flags))
4197                 (void) sm_strlcpy(fmtbuf, "252", sizeof fmtbuf);
4198         else
4199                 (void) sm_strlcpy(fmtbuf, "250", sizeof fmtbuf);
4200         fmtbuf[3] = last ? ' ' : '-';
4201         (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
4202         if (a->q_fullname == NULL)
4203         {
4204                 if ((a->q_mailer == NULL ||
4205                      a->q_mailer->m_addrtype == NULL ||
4206                      sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
4207                     strchr(a->q_user, '@') == NULL)
4208                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
4209                                        sizeof fmtbuf - OFFF);
4210                 else
4211                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
4212                                        sizeof fmtbuf - OFFF);
4213                 message(fmtbuf, a->q_user, MyHostName);
4214         }
4215         else
4216         {
4217                 if ((a->q_mailer == NULL ||
4218                      a->q_mailer->m_addrtype == NULL ||
4219                      sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
4220                     strchr(a->q_user, '@') == NULL)
4221                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
4222                                        sizeof fmtbuf - OFFF);
4223                 else
4224                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
4225                                        sizeof fmtbuf - OFFF);
4226                 message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
4227         }
4228 }
4229
4230 #if SASL
4231 /*
4232 **  SASLMECHS -- get list of possible AUTH mechanisms
4233 **
4234 **      Parameters:
4235 **              conn -- SASL connection info.
4236 **              mechlist -- output parameter for list of mechanisms.
4237 **
4238 **      Returns:
4239 **              number of mechs.
4240 */
4241
4242 static int
4243 saslmechs(conn, mechlist)
4244         sasl_conn_t *conn;
4245         char **mechlist;
4246 {
4247         int len, num, result;
4248
4249         /* "user" is currently unused */
4250 # if SASL >= 20000
4251         result = sasl_listmech(conn, NULL,
4252                                "", " ", "", (const char **) mechlist,
4253                                (unsigned int *)&len, &num);
4254 # else /* SASL >= 20000 */
4255         result = sasl_listmech(conn, "user", /* XXX */
4256                                "", " ", "", mechlist,
4257                                (unsigned int *)&len, (unsigned int *)&num);
4258 # endif /* SASL >= 20000 */
4259         if (result != SASL_OK)
4260         {
4261                 if (LogLevel > 9)
4262                         sm_syslog(LOG_WARNING, NOQID,
4263                                   "AUTH error: listmech=%d, num=%d",
4264                                   result, num);
4265                 num = 0;
4266         }
4267         if (num > 0)
4268         {
4269                 if (LogLevel > 11)
4270                         sm_syslog(LOG_INFO, NOQID,
4271                                   "AUTH: available mech=%s, allowed mech=%s",
4272                                   *mechlist, AuthMechanisms);
4273                 *mechlist = intersect(AuthMechanisms, *mechlist, NULL);
4274         }
4275         else
4276         {
4277                 *mechlist = NULL;       /* be paranoid... */
4278                 if (result == SASL_OK && LogLevel > 9)
4279                         sm_syslog(LOG_WARNING, NOQID,
4280                                   "AUTH warning: no mechanisms");
4281         }
4282         return num;
4283 }
4284
4285 # if SASL >= 20000
4286 /*
4287 **  PROXY_POLICY -- define proxy policy for AUTH
4288 **
4289 **      Parameters:
4290 **              conn -- unused.
4291 **              context -- unused.
4292 **              requested_user -- authorization identity.
4293 **              rlen -- authorization identity length.
4294 **              auth_identity -- authentication identity.
4295 **              alen -- authentication identity length.
4296 **              def_realm -- default user realm.
4297 **              urlen -- user realm length.
4298 **              propctx -- unused.
4299 **
4300 **      Returns:
4301 **              ok?
4302 **
4303 **      Side Effects:
4304 **              sets {auth_authen} macro.
4305 */
4306
4307 int
4308 proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
4309              def_realm, urlen, propctx)
4310         sasl_conn_t *conn;
4311         void *context;
4312         const char *requested_user;
4313         unsigned rlen;
4314         const char *auth_identity;
4315         unsigned alen;
4316         const char *def_realm;
4317         unsigned urlen;
4318         struct propctx *propctx;
4319 {
4320         if (auth_identity == NULL)
4321                 return SASL_FAIL;
4322
4323         macdefine(&BlankEnvelope.e_macro, A_TEMP,
4324                   macid("{auth_authen}"), (char *) auth_identity);
4325
4326         return SASL_OK;
4327 }
4328 # else /* SASL >= 20000 */
4329
4330 /*
4331 **  PROXY_POLICY -- define proxy policy for AUTH
4332 **
4333 **      Parameters:
4334 **              context -- unused.
4335 **              auth_identity -- authentication identity.
4336 **              requested_user -- authorization identity.
4337 **              user -- allowed user (output).
4338 **              errstr -- possible error string (output).
4339 **
4340 **      Returns:
4341 **              ok?
4342 */
4343
4344 int
4345 proxy_policy(context, auth_identity, requested_user, user, errstr)
4346         void *context;
4347         const char *auth_identity;
4348         const char *requested_user;
4349         const char **user;
4350         const char **errstr;
4351 {
4352         if (user == NULL || auth_identity == NULL)
4353                 return SASL_FAIL;
4354         *user = newstr(auth_identity);
4355         return SASL_OK;
4356 }
4357 # endif /* SASL >= 20000 */
4358 #endif /* SASL */
4359
4360 #if STARTTLS
4361 /*
4362 **  INITSRVTLS -- initialize server side TLS
4363 **
4364 **      Parameters:
4365 **              tls_ok -- should tls initialization be done?
4366 **
4367 **      Returns:
4368 **              succeeded?
4369 **
4370 **      Side Effects:
4371 **              sets tls_ok_srv which is a static variable in this module.
4372 **              Do NOT remove assignments to it!
4373 */
4374
4375 bool
4376 initsrvtls(tls_ok)
4377         bool tls_ok;
4378 {
4379         if (!tls_ok)
4380                 return false;
4381
4382         /* do NOT remove assignment */
4383         tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, true, SrvCertFile,
4384                              SrvKeyFile, CACertPath, CACertFile, DHParams);
4385         return tls_ok_srv;
4386 }
4387 #endif /* STARTTLS */
4388 /*
4389 **  SRVFEATURES -- get features for SMTP server
4390 **
4391 **      Parameters:
4392 **              e -- envelope (should be session context).
4393 **              clientname -- name of client.
4394 **              features -- default features for this invocation.
4395 **
4396 **      Returns:
4397 **              server features.
4398 */
4399
4400 /* table with options: it uses just one character, how about strings? */
4401 static struct
4402 {
4403         char            srvf_opt;
4404         unsigned int    srvf_flag;
4405 } srv_feat_table[] =
4406 {
4407         { 'A',  SRV_OFFER_AUTH  },
4408         { 'B',  SRV_OFFER_VERB  },
4409         { 'C',  SRV_REQ_SEC     },
4410         { 'D',  SRV_OFFER_DSN   },
4411         { 'E',  SRV_OFFER_ETRN  },
4412         { 'L',  SRV_REQ_AUTH    },
4413 #if PIPELINING
4414 # if _FFR_NO_PIPE
4415         { 'N',  SRV_NO_PIPE     },
4416 # endif /* _FFR_NO_PIPE */
4417         { 'P',  SRV_OFFER_PIPE  },
4418 #endif /* PIPELINING */
4419         { 'R',  SRV_VRFY_CLT    },      /* same as V; not documented */
4420         { 'S',  SRV_OFFER_TLS   },
4421 /*      { 'T',  SRV_TMP_FAIL    },      */
4422         { 'V',  SRV_VRFY_CLT    },
4423         { 'X',  SRV_OFFER_EXPN  },
4424 /*      { 'Y',  SRV_OFFER_VRFY  },      */
4425         { '\0', SRV_NONE        }
4426 };
4427
4428 static unsigned int
4429 srvfeatures(e, clientname, features)
4430         ENVELOPE *e;
4431         char *clientname;
4432         unsigned int features;
4433 {
4434         int r, i, j;
4435         char **pvp, c, opt;
4436         char pvpbuf[PSBUFSIZE];
4437
4438         pvp = NULL;
4439         r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
4440                   sizeof(pvpbuf));
4441         if (r != EX_OK)
4442                 return features;
4443         if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
4444                 return features;
4445         if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
4446                 return SRV_TMP_FAIL;
4447
4448         /*
4449         **  General rule (see sendmail.h, d_flags):
4450         **  lower case: required/offered, upper case: Not required/available
4451         **
4452         **  Since we can change some features per daemon, we have both
4453         **  cases here: turn on/off a feature.
4454         */
4455
4456         for (i = 1; pvp[i] != NULL; i++)
4457         {
4458                 c = pvp[i][0];
4459                 j = 0;
4460                 for (;;)
4461                 {
4462                         if ((opt = srv_feat_table[j].srvf_opt) == '\0')
4463                         {
4464                                 if (LogLevel > 9)
4465                                         sm_syslog(LOG_WARNING, e->e_id,
4466                                                   "srvfeatures: unknown feature %s",
4467                                                   pvp[i]);
4468                                 break;
4469                         }
4470                         if (c == opt)
4471                         {
4472                                 features &= ~(srv_feat_table[j].srvf_flag);
4473                                 break;
4474                         }
4475                         if (c == tolower(opt))
4476                         {
4477                                 features |= srv_feat_table[j].srvf_flag;
4478                                 break;
4479                         }
4480                         ++j;
4481                 }
4482         }
4483         return features;
4484 }
4485
4486 /*
4487 **  HELP -- implement the HELP command.
4488 **
4489 **      Parameters:
4490 **              topic -- the topic we want help for.
4491 **              e -- envelope.
4492 **
4493 **      Returns:
4494 **              none.
4495 **
4496 **      Side Effects:
4497 **              outputs the help file to message output.
4498 */
4499 #define HELPVSTR        "#vers  "
4500 #define HELPVERSION     2
4501
4502 void
4503 help(topic, e)
4504         char *topic;
4505         ENVELOPE *e;
4506 {
4507         register SM_FILE_T *hf;
4508         register char *p;
4509         int len;
4510         bool noinfo;
4511         bool first = true;
4512         long sff = SFF_OPENASROOT|SFF_REGONLY;
4513         char buf[MAXLINE];
4514         char inp[MAXLINE];
4515         static int foundvers = -1;
4516         extern char Version[];
4517
4518         if (DontLockReadFiles)
4519                 sff |= SFF_NOLOCK;
4520         if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
4521                 sff |= SFF_SAFEDIRPATH;
4522
4523         if (HelpFile == NULL ||
4524             (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
4525         {
4526                 /* no help */
4527                 errno = 0;
4528                 message("502 5.3.0 Sendmail %s -- HELP not implemented",
4529                         Version);
4530                 return;
4531         }
4532
4533         if (topic == NULL || *topic == '\0')
4534         {
4535                 topic = "smtp";
4536                 noinfo = false;
4537         }
4538         else
4539         {
4540                 makelower(topic);
4541                 noinfo = true;
4542         }
4543
4544         len = strlen(topic);
4545
4546         while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
4547         {
4548                 if (buf[0] == '#')
4549                 {
4550                         if (foundvers < 0 &&
4551                             strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
4552                         {
4553                                 int h;
4554
4555                                 if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
4556                                                  &h) == 1)
4557                                         foundvers = h;
4558                         }
4559                         continue;
4560                 }
4561                 if (strncmp(buf, topic, len) == 0)
4562                 {
4563                         if (first)
4564                         {
4565                                 first = false;
4566
4567                                 /* print version if no/old vers# in file */
4568                                 if (foundvers < 2 && !noinfo)
4569                                         message("214-2.0.0 This is Sendmail version %s", Version);
4570                         }
4571                         p = strpbrk(buf, " \t");
4572                         if (p == NULL)
4573                                 p = buf + strlen(buf) - 1;
4574                         else
4575                                 p++;
4576                         fixcrlf(p, true);
4577                         if (foundvers >= 2)
4578                         {
4579                                 translate_dollars(p);
4580                                 expand(p, inp, sizeof inp, e);
4581                                 p = inp;
4582                         }
4583                         message("214-2.0.0 %s", p);
4584                         noinfo = false;
4585                 }
4586         }
4587
4588         if (noinfo)
4589                 message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
4590         else
4591                 message("214 2.0.0 End of HELP info");
4592
4593         if (foundvers != 0 && foundvers < HELPVERSION)
4594         {
4595                 if (LogLevel > 1)
4596                         sm_syslog(LOG_WARNING, e->e_id,
4597                                   "%s too old (require version %d)",
4598                                   HelpFile, HELPVERSION);
4599
4600                 /* avoid log next time */
4601                 foundvers = 0;
4602         }
4603
4604         (void) sm_io_close(hf, SM_TIME_DEFAULT);
4605 }
4606
4607 #if SASL
4608 /*
4609 **  RESET_SASLCONN -- reset SASL connection data
4610 **
4611 **      Parameters:
4612 **              conn -- SASL connection context
4613 **              hostname -- host name
4614 **              various connection data
4615 **
4616 **      Returns:
4617 **              SASL result
4618 */
4619
4620 static int
4621 reset_saslconn(sasl_conn_t **conn, char *hostname,
4622 # if SASL >= 20000
4623                char *remoteip, char *localip,
4624                char *auth_id, sasl_ssf_t * ext_ssf)
4625 # else /* SASL >= 20000 */
4626                struct sockaddr_in *saddr_r, struct sockaddr_in *saddr_l,
4627                sasl_external_properties_t * ext_ssf)
4628 # endif /* SASL >= 20000 */
4629 {
4630         int result;
4631
4632         sasl_dispose(conn);
4633 # if SASL >= 20000
4634         result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
4635                                  NULL, 0, conn);
4636 # elif SASL > 10505
4637         /* use empty realm: only works in SASL > 1.5.5 */
4638         result = sasl_server_new("smtp", hostname, "", NULL, 0, conn);
4639 # else /* SASL >= 20000 */
4640         /* use no realm -> realm is set to hostname by SASL lib */
4641         result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
4642                                  conn);
4643 # endif /* SASL >= 20000 */
4644         if (result != SASL_OK)
4645                 return result;
4646
4647 # if SASL >= 20000
4648 #  if NETINET || NETINET6
4649         if (remoteip != NULL && *remoteip != '\0')
4650                 result = sasl_setprop(*conn, SASL_IPREMOTEPORT, remoteip);
4651         if (result != SASL_OK)
4652                 return result;
4653
4654         if (localip != NULL && *localip != '\0')
4655                 result = sasl_setprop(*conn, SASL_IPLOCALPORT, localip);
4656         if (result != SASL_OK)
4657                 return result;
4658 #  endif /* NETINET || NETINET6 */
4659
4660         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
4661         if (result != SASL_OK)
4662                 return result;
4663
4664         result = sasl_setprop(*conn, SASL_AUTH_EXTERNAL, auth_id);
4665         if (result != SASL_OK)
4666                 return result;
4667 # else /* SASL >= 20000 */
4668 #  if NETINET
4669         if (saddr_r != NULL)
4670                 result = sasl_setprop(*conn, SASL_IP_REMOTE, saddr_r);
4671         if (result != SASL_OK)
4672                 return result;
4673
4674         if (saddr_l != NULL)
4675                 result = sasl_setprop(*conn, SASL_IP_LOCAL, saddr_l);
4676         if (result != SASL_OK)
4677                 return result;
4678 #  endif /* NETINET */
4679
4680         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
4681         if (result != SASL_OK)
4682                 return result;
4683 # endif /* SASL >= 20000 */
4684         return SASL_OK;
4685 }
4686 #endif /* SASL */