]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/src/srvrsmtp.c
This commit was generated by cvs2svn to compensate for changes in r141261,
[FreeBSD/FreeBSD.git] / contrib / sendmail / src / srvrsmtp.c
1 /*
2  * Copyright (c) 1998-2004 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.900 2004/07/08 23:29:33 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         result = reset_saslconn(&conn, AuthRealm, remoteip, localip, auth_id, \
84                                 &ext_ssf);      \
85         if (result != SASL_OK)                  \
86         {                                       \
87                 /* This is pretty fatal */      \
88                 goto doquit;                    \
89         }
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         result = reset_saslconn(&conn, AuthRealm, &saddr_r, &saddr_l, &ext_ssf); \
98         if (result != SASL_OK)                  \
99         {                                       \
100                 /* This is pretty fatal */      \
101                 goto doquit;                    \
102         }
103
104 # endif /* SASL >= 20000 */
105 #endif /* SASL */
106
107 extern ENVELOPE BlankEnvelope;
108
109 #define NBADRCPTS                                               \
110         do                                                      \
111         {                                                       \
112                 char buf[16];                                   \
113                 (void) sm_snprintf(buf, sizeof buf, "%d",       \
114                         BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
115                                 ? n_badrcpts - 1 : n_badrcpts); \
116                 macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
117         } while (0)
118
119 #define SKIP_SPACE(s)   while (isascii(*s) && isspace(*s))      \
120                                 (s)++
121
122 /*
123 **  SMTP -- run the SMTP protocol.
124 **
125 **      Parameters:
126 **              nullserver -- if non-NULL, rejection message for
127 **                      (almost) all SMTP commands.
128 **              d_flags -- daemon flags
129 **              e -- the envelope.
130 **
131 **      Returns:
132 **              never.
133 **
134 **      Side Effects:
135 **              Reads commands from the input channel and processes them.
136 */
137
138 /*
139 **  Notice: The smtp server doesn't have a session context like the client
140 **      side has (mci). Therefore some data (session oriented) is allocated
141 **      or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
142 **      This should be fixed in a successor version.
143 */
144
145 struct cmd
146 {
147         char    *cmd_name;      /* command name */
148         int     cmd_code;       /* internal code, see below */
149 };
150
151 /* values for cmd_code */
152 #define CMDERROR        0       /* bad command */
153 #define CMDMAIL 1       /* mail -- designate sender */
154 #define CMDRCPT 2       /* rcpt -- designate recipient */
155 #define CMDDATA 3       /* data -- send message text */
156 #define CMDRSET 4       /* rset -- reset state */
157 #define CMDVRFY 5       /* vrfy -- verify address */
158 #define CMDEXPN 6       /* expn -- expand address */
159 #define CMDNOOP 7       /* noop -- do nothing */
160 #define CMDQUIT 8       /* quit -- close connection and die */
161 #define CMDHELO 9       /* helo -- be polite */
162 #define CMDHELP 10      /* help -- give usage info */
163 #define CMDEHLO 11      /* ehlo -- extended helo (RFC 1425) */
164 #define CMDETRN 12      /* etrn -- flush queue */
165 #if SASL
166 # define CMDAUTH        13      /* auth -- SASL authenticate */
167 #endif /* SASL */
168 #if STARTTLS
169 # define CMDSTLS        14      /* STARTTLS -- start TLS session */
170 #endif /* STARTTLS */
171 /* non-standard commands */
172 #define CMDVERB 17      /* verb -- go into verbose mode */
173 /* unimplemented commands from RFC 821 */
174 #define CMDUNIMPL       19      /* unimplemented rfc821 commands */
175 /* use this to catch and log "door handle" attempts on your system */
176 #define CMDLOGBOGUS     23      /* bogus command that should be logged */
177 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
178 #define CMDDBGQSHOW     24      /* showq -- show send queue */
179 #define CMDDBGDEBUG     25      /* debug -- set debug mode */
180
181 /*
182 **  Note: If you change this list, remember to update 'helpfile'
183 */
184
185 static struct cmd       CmdTab[] =
186 {
187         { "mail",       CMDMAIL         },
188         { "rcpt",       CMDRCPT         },
189         { "data",       CMDDATA         },
190         { "rset",       CMDRSET         },
191         { "vrfy",       CMDVRFY         },
192         { "expn",       CMDEXPN         },
193         { "help",       CMDHELP         },
194         { "noop",       CMDNOOP         },
195         { "quit",       CMDQUIT         },
196         { "helo",       CMDHELO         },
197         { "ehlo",       CMDEHLO         },
198         { "etrn",       CMDETRN         },
199         { "verb",       CMDVERB         },
200         { "send",       CMDUNIMPL       },
201         { "saml",       CMDUNIMPL       },
202         { "soml",       CMDUNIMPL       },
203         { "turn",       CMDUNIMPL       },
204 #if SASL
205         { "auth",       CMDAUTH,        },
206 #endif /* SASL */
207 #if STARTTLS
208         { "starttls",   CMDSTLS,        },
209 #endif /* STARTTLS */
210     /* remaining commands are here only to trap and log attempts to use them */
211         { "showq",      CMDDBGQSHOW     },
212         { "debug",      CMDDBGDEBUG     },
213         { "wiz",        CMDLOGBOGUS     },
214
215         { NULL,         CMDERROR        }
216 };
217
218 static char     *CurSmtpClient;         /* who's at the other end of channel */
219
220 #ifndef MAXBADCOMMANDS
221 # define MAXBADCOMMANDS 25      /* maximum number of bad commands */
222 #endif /* ! MAXBADCOMMANDS */
223 #ifndef MAXNOOPCOMMANDS
224 # define MAXNOOPCOMMANDS 20     /* max "noise" commands before slowdown */
225 #endif /* ! MAXNOOPCOMMANDS */
226 #ifndef MAXHELOCOMMANDS
227 # define MAXHELOCOMMANDS 3      /* max HELO/EHLO commands before slowdown */
228 #endif /* ! MAXHELOCOMMANDS */
229 #ifndef MAXVRFYCOMMANDS
230 # define MAXVRFYCOMMANDS 6      /* max VRFY/EXPN commands before slowdown */
231 #endif /* ! MAXVRFYCOMMANDS */
232 #ifndef MAXETRNCOMMANDS
233 # define MAXETRNCOMMANDS 8      /* max ETRN commands before slowdown */
234 #endif /* ! MAXETRNCOMMANDS */
235 #ifndef MAXTIMEOUT
236 # define MAXTIMEOUT (4 * 60)    /* max timeout for bad commands */
237 #endif /* ! MAXTIMEOUT */
238
239 /*
240 **  Maximum shift value to compute timeout for bad commands.
241 **  This introduces an upper limit of 2^MAXSHIFT for the timeout.
242 */
243
244 #ifndef MAXSHIFT
245 # define MAXSHIFT 8
246 #endif /* ! MAXSHIFT */
247 #if MAXSHIFT > 31
248  ERROR _MAXSHIFT > 31 is invalid
249 #endif /* MAXSHIFT */
250
251
252 #if MAXBADCOMMANDS > 0
253 # define STOP_IF_ATTACK(r)      do              \
254         {                                       \
255                 if ((r) == STOP_ATTACK)         \
256                         goto stopattack;        \
257         } while (0)
258
259 #else /* MAXBADCOMMANDS > 0 */
260 # define STOP_IF_ATTACK(r)      r
261 #endif /* MAXBADCOMMANDS > 0 */
262
263
264 #if SM_HEAP_CHECK
265 static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
266         "@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
267 #endif /* SM_HEAP_CHECK */
268
269 typedef struct
270 {
271         bool    sm_gotmail;     /* mail command received */
272         unsigned int sm_nrcpts; /* number of successful RCPT commands */
273         bool    sm_discard;
274 #if MILTER
275         bool    sm_milterize;
276         bool    sm_milterlist;  /* any filters in the list? */
277 #endif /* MILTER */
278         char    *sm_quarmsg;    /* carry quarantining across messages */
279 } SMTP_T;
280
281 static bool     smtp_data __P((SMTP_T *, ENVELOPE *));
282
283 #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
284
285 #if MILTER
286 # define MILTER_ABORT(e)        milter_abort((e))
287
288 # define MILTER_REPLY(str)                                              \
289         {                                                               \
290                 int savelogusrerrs = LogUsrErrs;                        \
291                                                                         \
292                 switch (state)                                          \
293                 {                                                       \
294                   case SMFIR_REPLYCODE:                                 \
295                         if (MilterLogLevel > 3)                         \
296                         {                                               \
297                                 sm_syslog(LOG_INFO, e->e_id,            \
298                                           "Milter: %s=%s, reject=%s",   \
299                                           str, addr, response);         \
300                                 LogUsrErrs = false;                     \
301                         }                                               \
302                         if (strncmp(response, "421 ", 4) == 0)          \
303                         {                                               \
304                                 bool tsave = QuickAbort;                \
305                                                                         \
306                                 QuickAbort = false;                     \
307                                 usrerr(response);                       \
308                                 QuickAbort = tsave;                     \
309                                 e->e_sendqueue = NULL;                  \
310                                 goto doquit;                            \
311                         }                                               \
312                         else                                            \
313                                 usrerr(response);                       \
314                         break;                                          \
315                                                                         \
316                   case SMFIR_REJECT:                                    \
317                         if (MilterLogLevel > 3)                         \
318                         {                                               \
319                                 sm_syslog(LOG_INFO, e->e_id,            \
320                                           "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
321                                           str, addr);                   \
322                                 LogUsrErrs = false;                     \
323                         }                                               \
324                         usrerr("550 5.7.1 Command rejected");           \
325                         break;                                          \
326                                                                         \
327                   case SMFIR_DISCARD:                                   \
328                         if (MilterLogLevel > 3)                         \
329                                 sm_syslog(LOG_INFO, e->e_id,            \
330                                           "Milter: %s=%s, discard",     \
331                                           str, addr);                   \
332                         e->e_flags |= EF_DISCARD;                       \
333                         break;                                          \
334                                                                         \
335                   case SMFIR_TEMPFAIL:                                  \
336                         if (MilterLogLevel > 3)                         \
337                         {                                               \
338                                 sm_syslog(LOG_INFO, e->e_id,            \
339                                           "Milter: %s=%s, reject=%s",   \
340                                           str, addr, MSG_TEMPFAIL);     \
341                                 LogUsrErrs = false;                     \
342                         }                                               \
343                         usrerr(MSG_TEMPFAIL);                           \
344                         break;                                          \
345                 }                                                       \
346                 LogUsrErrs = savelogusrerrs;                            \
347                 if (response != NULL)                                   \
348                         sm_free(response); /* XXX */                    \
349         }
350
351 #else /* MILTER */
352 # define MILTER_ABORT(e)
353 #endif /* MILTER */
354
355 /* clear all SMTP state (for HELO/EHLO/RSET) */
356 #define CLEAR_STATE(cmd)                                        \
357 do                                                              \
358 {                                                               \
359         /* abort milter filters */                              \
360         MILTER_ABORT(e);                                        \
361                                                                 \
362         if (smtp.sm_nrcpts > 0)                                 \
363         {                                                       \
364                 logundelrcpts(e, cmd, 10, false);               \
365                 smtp.sm_nrcpts = 0;                             \
366                 macdefine(&e->e_macro, A_PERM,                  \
367                           macid("{nrcpts}"), "0");              \
368         }                                                       \
369                                                                 \
370         e->e_sendqueue = NULL;                                  \
371         e->e_flags |= EF_CLRQUEUE;                              \
372                                                                 \
373         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))   \
374                 logsender(e, NULL);                             \
375         e->e_flags &= ~EF_LOGSENDER;                            \
376                                                                 \
377         /* clean up a bit */                                    \
378         smtp.sm_gotmail = false;                                \
379         SuprErrs = true;                                        \
380         dropenvelope(e, true, false);                           \
381         sm_rpool_free(e->e_rpool);                              \
382         e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL));       \
383         CurEnv = e;                                             \
384                                                                 \
385         /* put back discard bit */                              \
386         if (smtp.sm_discard)                                    \
387                 e->e_flags |= EF_DISCARD;                       \
388                                                                 \
389         /* restore connection quarantining */                   \
390         if (smtp.sm_quarmsg == NULL)                            \
391         {                                                       \
392                 e->e_quarmsg = NULL;                            \
393                 macdefine(&e->e_macro, A_PERM,                  \
394                         macid("{quarantine}"), "");             \
395         }                                                       \
396         else                                                    \
397         {                                                       \
398                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool,    \
399                                                 smtp.sm_quarmsg);       \
400                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"),   \
401                           e->e_quarmsg);                        \
402         }                                                       \
403 } while (0)
404
405 /* sleep to flatten out connection load */
406 #define MIN_DELAY_LOG   15      /* wait before logging this again */
407
408 /* is it worth setting the process title for 1s? */
409 #define DELAY_CONN(cmd)                                         \
410         if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA)    \
411         {                                                       \
412                 time_t dnow;                                    \
413                                                                 \
414                 sm_setproctitle(true, e,                        \
415                                 "%s: %s: delaying %s: load average: %d", \
416                                 qid_printname(e), CurSmtpClient,        \
417                                 cmd, DelayLA);  \
418                 if (LogLevel > 8 && (dnow = curtime()) > log_delay)     \
419                 {                                               \
420                         sm_syslog(LOG_INFO, e->e_id,            \
421                                   "delaying=%s, load average=%d >= %d", \
422                                   cmd, CurrentLA, DelayLA);             \
423                         log_delay = dnow + MIN_DELAY_LOG;       \
424                 }                                               \
425                 (void) sleep(1);                                \
426                 sm_setproctitle(true, e, "%s %s: %.80s",        \
427                                 qid_printname(e), CurSmtpClient, inp);  \
428         }
429
430
431 void
432 smtp(nullserver, d_flags, e)
433         char *volatile nullserver;
434         BITMAP256 d_flags;
435         register ENVELOPE *volatile e;
436 {
437         register char *volatile p;
438         register struct cmd *volatile c = NULL;
439         char *cmd;
440         auto ADDRESS *vrfyqueue;
441         ADDRESS *a;
442         volatile bool gothello;         /* helo command received */
443         bool vrfy;                      /* set if this is a vrfy command */
444         char *volatile protocol;        /* sending protocol */
445         char *volatile sendinghost;     /* sending hostname */
446         char *volatile peerhostname;    /* name of SMTP peer or "localhost" */
447         auto char *delimptr;
448         char *id;
449         volatile unsigned int n_badcmds = 0;    /* count of bad commands */
450         volatile unsigned int n_badrcpts = 0;   /* number of rejected RCPT */
451         volatile unsigned int n_verifies = 0;   /* count of VRFY/EXPN */
452         volatile unsigned int n_etrn = 0;       /* count of ETRN */
453         volatile unsigned int n_noop = 0;       /* count of NOOP/VERB/etc */
454         volatile unsigned int n_helo = 0;       /* count of HELO/EHLO */
455         volatile int save_sevenbitinput;
456         bool ok;
457 #if _FFR_BLOCK_PROXIES
458         volatile bool first;
459 #endif /* _FFR_BLOCK_PROXIES */
460         volatile bool tempfail = false;
461         volatile time_t wt;             /* timeout after too many commands */
462         volatile time_t previous;       /* time after checksmtpattack() */
463         volatile bool lognullconnection = true;
464         register char *q;
465         SMTP_T smtp;
466         char *addr;
467         char *greetcode = "220";
468         char *hostname;                 /* my hostname ($j) */
469         QUEUE_CHAR *new;
470         int argno;
471         char *args[MAXSMTPARGS];
472         char inp[MAXLINE];
473         char cmdbuf[MAXLINE];
474 #if SASL
475         sasl_conn_t *conn;
476         volatile bool sasl_ok;
477         volatile unsigned int n_auth = 0;       /* count of AUTH commands */
478         bool ismore;
479         int result;
480         volatile int authenticating;
481         char *user;
482         char *in, *out2;
483 # if SASL >= 20000
484         char *auth_id;
485         const char *out;
486         sasl_ssf_t ext_ssf;
487         char localip[60], remoteip[60];
488 # else /* SASL >= 20000 */
489         char *out;
490         const char *errstr;
491         sasl_external_properties_t ext_ssf;
492         struct sockaddr_in saddr_l;
493         struct sockaddr_in saddr_r;
494 # endif /* SASL >= 20000 */
495         sasl_security_properties_t ssp;
496         sasl_ssf_t *ssf;
497         unsigned int inlen, out2len;
498         unsigned int outlen;
499         char *volatile auth_type;
500         char *mechlist;
501         volatile unsigned int n_mechs;
502         unsigned int len;
503 #endif /* SASL */
504         int r;
505 #if STARTTLS
506         int fdfl;
507         int rfd, wfd;
508         volatile bool tls_active = false;
509         volatile bool smtps = bitnset(D_SMTPS, d_flags);
510         bool saveQuickAbort;
511         bool saveSuprErrs;
512         time_t tlsstart;
513 #endif /* STARTTLS */
514         volatile unsigned int features;
515 #if PIPELINING
516 # if _FFR_NO_PIPE
517         int np_log = 0;
518 # endif /* _FFR_NO_PIPE */
519 #endif /* PIPELINING */
520         volatile time_t log_delay = (time_t) 0;
521
522         save_sevenbitinput = SevenBitInput;
523         smtp.sm_nrcpts = 0;
524 #if MILTER
525         smtp.sm_milterize = (nullserver == NULL);
526         smtp.sm_milterlist = false;
527 #endif /* MILTER */
528
529         /* setup I/O fd correctly for the SMTP server */
530         setup_smtpd_io();
531
532 #if SM_HEAP_CHECK
533         if (sm_debug_active(&DebugLeakSmtp, 1))
534         {
535                 sm_heap_newgroup();
536                 sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
537         }
538 #endif /* SM_HEAP_CHECK */
539
540         /* XXX the rpool should be set when e is initialized in main() */
541         e->e_rpool = sm_rpool_new_x(NULL);
542         e->e_macro.mac_rpool = e->e_rpool;
543
544         settime(e);
545         sm_getla();
546         peerhostname = RealHostName;
547         if (peerhostname == NULL)
548                 peerhostname = "localhost";
549         CurHostName = peerhostname;
550         CurSmtpClient = macvalue('_', e);
551         if (CurSmtpClient == NULL)
552                 CurSmtpClient = CurHostName;
553
554         /* check_relay may have set discard bit, save for later */
555         smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
556
557 #if PIPELINING
558         /* auto-flush output when reading input */
559         (void) sm_io_autoflush(InChannel, OutChannel);
560 #endif /* PIPELINING */
561
562         sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
563
564         /* Set default features for server. */
565         features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
566                      bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
567                 | (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
568                 | (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
569                         : (SRV_OFFER_EXPN
570                           | (bitset(PRIV_NOVERB, PrivacyFlags)
571                              ? SRV_NONE : SRV_OFFER_VERB)))
572                 | (bitset(PRIV_NORECEIPTS, PrivacyFlags) ? SRV_NONE
573                                                          : SRV_OFFER_DSN)
574 #if SASL
575                 | (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
576                 | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
577                                                           : SRV_NONE)
578 #endif /* SASL */
579 #if PIPELINING
580                 | SRV_OFFER_PIPE
581 #endif /* PIPELINING */
582 #if STARTTLS
583                 | (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
584                 | (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
585                                                        : SRV_VRFY_CLT)
586 #endif /* STARTTLS */
587                 ;
588         if (nullserver == NULL)
589         {
590                 features = srvfeatures(e, CurSmtpClient, features);
591                 if (bitset(SRV_TMP_FAIL, features))
592                 {
593                         if (LogLevel > 4)
594                                 sm_syslog(LOG_ERR, NOQID,
595                                           "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
596                                           CurSmtpClient);
597                         nullserver = "450 4.3.0 Please try again later.";
598                 }
599                 else
600                 {
601 #if PIPELINING
602 # if _FFR_NO_PIPE
603                         if (bitset(SRV_NO_PIPE, features))
604                         {
605                                 /* for consistency */
606                                 features &= ~SRV_OFFER_PIPE;
607                         }
608 # endif /* _FFR_NO_PIPE */
609 #endif /* PIPELINING */
610 #if SASL
611                         if (bitset(SRV_REQ_SEC, features))
612                                 SASLOpts |= SASL_SEC_NOPLAINTEXT;
613                         else
614                                 SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
615 #endif /* SASL */
616                 }
617         }
618         else if (strncmp(nullserver, "421 ", 4) == 0)
619         {
620                 message(nullserver);
621                 goto doquit;
622         }
623
624         hostname = macvalue('j', e);
625 #if SASL
626         if (AuthRealm == NULL)
627                 AuthRealm = hostname;
628         sasl_ok = bitset(SRV_OFFER_AUTH, features);
629         n_mechs = 0;
630         authenticating = SASL_NOT_AUTH;
631
632         /* SASL server new connection */
633         if (sasl_ok)
634         {
635 # if SASL >= 20000
636                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
637                                          NULL, 0, &conn);
638 # elif SASL > 10505
639                 /* use empty realm: only works in SASL > 1.5.5 */
640                 result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
641 # else /* SASL >= 20000 */
642                 /* use no realm -> realm is set to hostname by SASL lib */
643                 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
644                                          &conn);
645 # endif /* SASL >= 20000 */
646                 sasl_ok = result == SASL_OK;
647                 if (!sasl_ok)
648                 {
649                         if (LogLevel > 9)
650                                 sm_syslog(LOG_WARNING, NOQID,
651                                           "AUTH error: sasl_server_new failed=%d",
652                                           result);
653                 }
654         }
655         if (sasl_ok)
656         {
657                 /*
658                 **  SASL set properties for sasl
659                 **  set local/remote IP
660                 **  XXX Cyrus SASL v1 only supports IPv4
661                 **
662                 **  XXX where exactly are these used/required?
663                 **  Kerberos_v4
664                 */
665
666 # if SASL >= 20000
667 #  if NETINET || NETINET6
668                 in = macvalue(macid("{daemon_family}"), e);
669                 if (in != NULL && (
670 #   if NETINET6
671                     strcmp(in, "inet6") == 0 ||
672 #   endif /* NETINET6 */
673                     strcmp(in, "inet") == 0))
674                 {
675                         SOCKADDR_LEN_T addrsize;
676                         SOCKADDR saddr_l;
677                         SOCKADDR saddr_r;
678
679                         addrsize = sizeof(saddr_r);
680                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
681                                                       NULL),
682                                         (struct sockaddr *) &saddr_r,
683                                         &addrsize) == 0)
684                         {
685                                 if (iptostring(&saddr_r, addrsize,
686                                                remoteip, sizeof remoteip))
687                                 {
688                                         sasl_setprop(conn, SASL_IPREMOTEPORT,
689                                                      remoteip);
690                                 }
691                                 addrsize = sizeof(saddr_l);
692                                 if (getsockname(sm_io_getinfo(InChannel,
693                                                               SM_IO_WHAT_FD,
694                                                               NULL),
695                                                 (struct sockaddr *) &saddr_l,
696                                                 &addrsize) == 0)
697                                 {
698                                         if (iptostring(&saddr_l, addrsize,
699                                                        localip,
700                                                        sizeof localip))
701                                         {
702                                                 sasl_setprop(conn,
703                                                              SASL_IPLOCALPORT,
704                                                              localip);
705                                         }
706                                 }
707                         }
708                 }
709 #  endif /* NETINET || NETINET6 */
710 # else /* SASL >= 20000 */
711 #  if NETINET
712                 in = macvalue(macid("{daemon_family}"), e);
713                 if (in != NULL && strcmp(in, "inet") == 0)
714                 {
715                         SOCKADDR_LEN_T addrsize;
716
717                         addrsize = sizeof(struct sockaddr_in);
718                         if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
719                                                       NULL),
720                                         (struct sockaddr *)&saddr_r,
721                                         &addrsize) == 0)
722                         {
723                                 sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
724                                 addrsize = sizeof(struct sockaddr_in);
725                                 if (getsockname(sm_io_getinfo(InChannel,
726                                                               SM_IO_WHAT_FD,
727                                                               NULL),
728                                                 (struct sockaddr *)&saddr_l,
729                                                 &addrsize) == 0)
730                                         sasl_setprop(conn, SASL_IP_LOCAL,
731                                                      &saddr_l);
732                         }
733                 }
734 #  endif /* NETINET */
735 # endif /* SASL >= 20000 */
736
737                 auth_type = NULL;
738                 mechlist = NULL;
739                 user = NULL;
740 # if 0
741                 macdefine(&BlankEnvelope.e_macro, A_PERM,
742                         macid("{auth_author}"), NULL);
743 # endif /* 0 */
744
745                 /* set properties */
746                 (void) memset(&ssp, '\0', sizeof ssp);
747
748                 /* XXX should these be options settable via .cf ? */
749                 /* ssp.min_ssf = 0; is default due to memset() */
750 # if STARTTLS
751 # endif /* STARTTLS */
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                                         break;
1970                                 }
1971                                 if (strchr("[].-_#:", *q) == NULL)
1972                                         break;
1973                         }
1974
1975                         if (*q == '\0' && ok)
1976                         {
1977                                 q = "pleased to meet you";
1978                                 sendinghost = sm_strdup_x(p);
1979                         }
1980                         else if (!AllowBogusHELO)
1981                         {
1982                                 usrerr("501 Invalid domain name");
1983                                 if (LogLevel > 9)
1984                                         sm_syslog(LOG_INFO, CurEnv->e_id,
1985                                                   "invalid domain name (%s) from %.100s",
1986                                                   p, CurSmtpClient);
1987                                 break;
1988                         }
1989                         else
1990                         {
1991                                 q = "accepting invalid domain name";
1992                         }
1993
1994                         if (gothello)
1995                         {
1996                                 CLEAR_STATE(cmdbuf);
1997                         }
1998
1999 #if MILTER
2000                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2001                             !bitset(EF_DISCARD, e->e_flags))
2002                         {
2003                                 char state;
2004                                 char *response;
2005
2006                                 response = milter_helo(p, e, &state);
2007                                 switch (state)
2008                                 {
2009                                   case SMFIR_REPLYCODE:
2010                                         if (MilterLogLevel > 3)
2011                                                 sm_syslog(LOG_INFO, e->e_id,
2012                                                           "Milter: helo=%s, reject=%s",
2013                                                           p, response);
2014                                         nullserver = newstr(response);
2015                                         smtp.sm_milterize = false;
2016                                         break;
2017
2018                                   case SMFIR_REJECT:
2019                                         if (MilterLogLevel > 3)
2020                                                 sm_syslog(LOG_INFO, e->e_id,
2021                                                           "Milter: helo=%s, reject=Command rejected",
2022                                                           p);
2023                                         nullserver = "Command rejected";
2024                                         smtp.sm_milterize = false;
2025                                         break;
2026
2027                                   case SMFIR_TEMPFAIL:
2028                                         if (MilterLogLevel > 3)
2029                                                 sm_syslog(LOG_INFO, e->e_id,
2030                                                           "Milter: helo=%s, reject=%s",
2031                                                           p, MSG_TEMPFAIL);
2032                                         tempfail = true;
2033                                         smtp.sm_milterize = false;
2034                                         break;
2035                                 }
2036                                 if (response != NULL)
2037                                         sm_free(response);
2038
2039                                 /*
2040                                 **  If quarantining by a connect/ehlo action,
2041                                 **  save between messages
2042                                 */
2043
2044                                 if (smtp.sm_quarmsg == NULL &&
2045                                     e->e_quarmsg != NULL)
2046                                         smtp.sm_quarmsg = newstr(e->e_quarmsg);
2047                         }
2048 #endif /* MILTER */
2049                         gothello = true;
2050
2051                         /* print HELO response message */
2052                         if (c->cmd_code != CMDEHLO)
2053                         {
2054                                 message("250 %s Hello %s, %s",
2055                                         MyHostName, CurSmtpClient, q);
2056                                 break;
2057                         }
2058
2059                         message("250-%s Hello %s, %s",
2060                                 MyHostName, CurSmtpClient, q);
2061
2062                         /* offer ENHSC even for nullserver */
2063                         if (nullserver != NULL)
2064                         {
2065                                 message("250 ENHANCEDSTATUSCODES");
2066                                 break;
2067                         }
2068
2069                         /*
2070                         **  print EHLO features list
2071                         **
2072                         **  Note: If you change this list,
2073                         **        remember to update 'helpfile'
2074                         */
2075
2076                         message("250-ENHANCEDSTATUSCODES");
2077 #if PIPELINING
2078                         if (bitset(SRV_OFFER_PIPE, features))
2079                                 message("250-PIPELINING");
2080 #endif /* PIPELINING */
2081                         if (bitset(SRV_OFFER_EXPN, features))
2082                         {
2083                                 message("250-EXPN");
2084                                 if (bitset(SRV_OFFER_VERB, features))
2085                                         message("250-VERB");
2086                         }
2087 #if MIME8TO7
2088                         message("250-8BITMIME");
2089 #endif /* MIME8TO7 */
2090                         if (MaxMessageSize > 0)
2091                                 message("250-SIZE %ld", MaxMessageSize);
2092                         else
2093                                 message("250-SIZE");
2094 #if DSN
2095                         if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
2096                                 message("250-DSN");
2097 #endif /* DSN */
2098                         if (bitset(SRV_OFFER_ETRN, features))
2099                                 message("250-ETRN");
2100 #if SASL
2101                         if (sasl_ok && mechlist != NULL && *mechlist != '\0')
2102                                 message("250-AUTH %s", mechlist);
2103 #endif /* SASL */
2104 #if STARTTLS
2105                         if (tls_ok_srv &&
2106                             bitset(SRV_OFFER_TLS, features))
2107                                 message("250-STARTTLS");
2108 #endif /* STARTTLS */
2109                         if (DeliverByMin > 0)
2110                                 message("250-DELIVERBY %ld",
2111                                         (long) DeliverByMin);
2112                         else if (DeliverByMin == 0)
2113                                 message("250-DELIVERBY");
2114
2115                         /* < 0: no deliver-by */
2116
2117                         message("250 HELP");
2118                         break;
2119
2120                   case CMDMAIL:         /* mail -- designate sender */
2121                         SmtpPhase = "server MAIL";
2122                         DELAY_CONN("MAIL");
2123
2124                         /* check for validity of this command */
2125                         if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
2126                         {
2127                                 usrerr("503 5.0.0 Polite people say HELO first");
2128                                 break;
2129                         }
2130                         if (smtp.sm_gotmail)
2131                         {
2132                                 usrerr("503 5.5.0 Sender already specified");
2133                                 break;
2134                         }
2135 #if SASL
2136                         if (bitset(SRV_REQ_AUTH, features) &&
2137                             authenticating != SASL_IS_AUTH)
2138                         {
2139                                 usrerr("530 5.7.0 Authentication required");
2140                                 break;
2141                         }
2142 #endif /* SASL */
2143
2144                         p = skipword(p, "from");
2145                         if (p == NULL)
2146                                 break;
2147                         if (tempfail)
2148                         {
2149                                 if (LogLevel > 9)
2150                                         sm_syslog(LOG_INFO, e->e_id,
2151                                                   "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2152                                                   p, CurSmtpClient);
2153                                 usrerr(MSG_TEMPFAIL);
2154                                 break;
2155                         }
2156
2157                         /* make sure we know who the sending host is */
2158                         if (sendinghost == NULL)
2159                                 sendinghost = peerhostname;
2160
2161
2162 #if SM_HEAP_CHECK
2163                         if (sm_debug_active(&DebugLeakSmtp, 1))
2164                         {
2165                                 sm_heap_newgroup();
2166                                 sm_dprintf("smtp() heap group #%d\n",
2167                                         sm_heap_group());
2168                         }
2169 #endif /* SM_HEAP_CHECK */
2170
2171                         if (Errors > 0)
2172                                 goto undo_no_pm;
2173                         if (!gothello)
2174                         {
2175                                 auth_warning(e, "%s didn't use HELO protocol",
2176                                              CurSmtpClient);
2177                         }
2178 #ifdef PICKY_HELO_CHECK
2179                         if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2180                             (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2181                              sm_strcasecmp(sendinghost, MyHostName) != 0))
2182                         {
2183                                 auth_warning(e, "Host %s claimed to be %s",
2184                                              CurSmtpClient, sendinghost);
2185                         }
2186 #endif /* PICKY_HELO_CHECK */
2187
2188                         if (protocol == NULL)
2189                                 protocol = "SMTP";
2190                         macdefine(&e->e_macro, A_PERM, 'r', protocol);
2191                         macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2192
2193                         if (Errors > 0)
2194                                 goto undo_no_pm;
2195                         smtp.sm_nrcpts = 0;
2196                         n_badrcpts = 0;
2197                         macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2198                         macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2199                         macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
2200                                 "0");
2201                         e->e_flags |= EF_CLRQUEUE;
2202                         sm_setproctitle(true, e, "%s %s: %.80s",
2203                                         qid_printname(e),
2204                                         CurSmtpClient, inp);
2205
2206                         /* do the processing */
2207                     SM_TRY
2208                     {
2209                         extern char *FullName;
2210
2211                         QuickAbort = true;
2212                         SM_FREE_CLR(FullName);
2213
2214                         /* must parse sender first */
2215                         delimptr = NULL;
2216                         setsender(p, e, &delimptr, ' ', false);
2217                         if (delimptr != NULL && *delimptr != '\0')
2218                                 *delimptr++ = '\0';
2219                         if (Errors > 0)
2220                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2221
2222                         /* Successfully set e_from, allow logging */
2223                         e->e_flags |= EF_LOGSENDER;
2224
2225                         /* put resulting triple from parseaddr() into macros */
2226                         if (e->e_from.q_mailer != NULL)
2227                                  macdefine(&e->e_macro, A_PERM,
2228                                         macid("{mail_mailer}"),
2229                                         e->e_from.q_mailer->m_name);
2230                         else
2231                                  macdefine(&e->e_macro, A_PERM,
2232                                         macid("{mail_mailer}"), NULL);
2233                         if (e->e_from.q_host != NULL)
2234                                 macdefine(&e->e_macro, A_PERM,
2235                                         macid("{mail_host}"),
2236                                         e->e_from.q_host);
2237                         else
2238                                 macdefine(&e->e_macro, A_PERM,
2239                                         macid("{mail_host}"), "localhost");
2240                         if (e->e_from.q_user != NULL)
2241                                 macdefine(&e->e_macro, A_PERM,
2242                                         macid("{mail_addr}"),
2243                                         e->e_from.q_user);
2244                         else
2245                                 macdefine(&e->e_macro, A_PERM,
2246                                         macid("{mail_addr}"), NULL);
2247                         if (Errors > 0)
2248                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2249
2250                         /* check for possible spoofing */
2251                         if (RealUid != 0 && OpMode == MD_SMTP &&
2252                             !wordinclass(RealUserName, 't') &&
2253                             (!bitnset(M_LOCALMAILER,
2254                                       e->e_from.q_mailer->m_flags) ||
2255                              strcmp(e->e_from.q_user, RealUserName) != 0))
2256                         {
2257                                 auth_warning(e, "%s owned process doing -bs",
2258                                         RealUserName);
2259                         }
2260
2261                         /* reset to default value */
2262                         SevenBitInput = save_sevenbitinput;
2263
2264                         /* now parse ESMTP arguments */
2265                         e->e_msgsize = 0;
2266                         addr = p;
2267                         argno = 0;
2268                         args[argno++] = p;
2269                         p = delimptr;
2270                         while (p != NULL && *p != '\0')
2271                         {
2272                                 char *kp;
2273                                 char *vp = NULL;
2274                                 char *equal = NULL;
2275
2276                                 /* locate the beginning of the keyword */
2277                                 SKIP_SPACE(p);
2278                                 if (*p == '\0')
2279                                         break;
2280                                 kp = p;
2281
2282                                 /* skip to the value portion */
2283                                 while ((isascii(*p) && isalnum(*p)) || *p == '-')
2284                                         p++;
2285                                 if (*p == '=')
2286                                 {
2287                                         equal = p;
2288                                         *p++ = '\0';
2289                                         vp = p;
2290
2291                                         /* skip to the end of the value */
2292                                         while (*p != '\0' && *p != ' ' &&
2293                                                !(isascii(*p) && iscntrl(*p)) &&
2294                                                *p != '=')
2295                                                 p++;
2296                                 }
2297
2298                                 if (*p != '\0')
2299                                         *p++ = '\0';
2300
2301                                 if (tTd(19, 1))
2302                                         sm_dprintf("MAIL: got arg %s=\"%s\"\n", kp,
2303                                                 vp == NULL ? "<null>" : vp);
2304
2305                                 mail_esmtp_args(kp, vp, e);
2306                                 if (equal != NULL)
2307                                         *equal = '=';
2308                                 args[argno++] = kp;
2309                                 if (argno >= MAXSMTPARGS - 1)
2310                                         usrerr("501 5.5.4 Too many parameters");
2311                                 if (Errors > 0)
2312                                         sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2313                         }
2314                         args[argno] = NULL;
2315                         if (Errors > 0)
2316                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2317
2318 #if SASL
2319 # if _FFR_AUTH_PASSING
2320                         /* set the default AUTH= if the sender didn't */
2321                         if (e->e_auth_param == NULL)
2322                         {
2323                                 /* XXX only do this for an MSA? */
2324                                 e->e_auth_param = macvalue(macid("{auth_authen}"),
2325                                                            e);
2326                                 if (e->e_auth_param == NULL)
2327                                         e->e_auth_param = "<>";
2328
2329                                 /*
2330                                 **  XXX should we invoke Strust_auth now?
2331                                 **  authorizing as the client that just
2332                                 **  authenticated, so we'll trust implicitly
2333                                 */
2334                         }
2335 # endif /* _FFR_AUTH_PASSING */
2336 #endif /* SASL */
2337
2338                         /* do config file checking of the sender */
2339                         macdefine(&e->e_macro, A_PERM,
2340                                 macid("{addr_type}"), "e s");
2341 #if _FFR_MAIL_MACRO
2342                         /* make the "real" sender address available */
2343                         macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
2344                                   e->e_from.q_paddr);
2345 #endif /* _FFR_MAIL_MACRO */
2346                         if (rscheck("check_mail", addr,
2347                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2348                                     NULL, e->e_id) != EX_OK ||
2349                             Errors > 0)
2350                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2351                         macdefine(&e->e_macro, A_PERM,
2352                                   macid("{addr_type}"), NULL);
2353
2354                         if (MaxMessageSize > 0 &&
2355                             (e->e_msgsize > MaxMessageSize ||
2356                              e->e_msgsize < 0))
2357                         {
2358                                 usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
2359                                         MaxMessageSize);
2360                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2361                         }
2362
2363                         /*
2364                         **  XXX always check whether there is at least one fs
2365                         **  with enough space?
2366                         **  However, this may not help much: the queue group
2367                         **  selection may later on select a FS that hasn't
2368                         **  enough space.
2369                         */
2370
2371                         if ((NumFileSys == 1 || NumQueue == 1) &&
2372                             !enoughdiskspace(e->e_msgsize, e)
2373 #if _FFR_ANY_FREE_FS
2374                             && !filesys_free(e->e_msgsize)
2375 #endif /* _FFR_ANY_FREE_FS */
2376                            )
2377                         {
2378                                 /*
2379                                 **  We perform this test again when the
2380                                 **  queue directory is selected, in collect.
2381                                 */
2382
2383                                 usrerr("452 4.4.5 Insufficient disk space; try again later");
2384                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2385                         }
2386                         if (Errors > 0)
2387                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2388
2389                         LogUsrErrs = true;
2390 #if MILTER
2391                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2392                             !bitset(EF_DISCARD, e->e_flags))
2393                         {
2394                                 char state;
2395                                 char *response;
2396
2397                                 response = milter_envfrom(args, e, &state);
2398                                 MILTER_REPLY("from");
2399                         }
2400 #endif /* MILTER */
2401                         if (Errors > 0)
2402                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2403
2404                         message("250 2.1.0 Sender ok");
2405                         smtp.sm_gotmail = true;
2406                     }
2407                     SM_EXCEPT(exc, "[!F]*")
2408                     {
2409                         /*
2410                         **  An error occurred while processing a MAIL command.
2411                         **  Jump to the common error handling code.
2412                         */
2413
2414                         sm_exc_free(exc);
2415                         goto undo_no_pm;
2416                     }
2417                     SM_END_TRY
2418                         break;
2419
2420                   undo_no_pm:
2421                         e->e_flags &= ~EF_PM_NOTIFY;
2422                   undo:
2423                         break;
2424
2425                   case CMDRCPT:         /* rcpt -- designate recipient */
2426                         DELAY_CONN("RCPT");
2427                         if (BadRcptThrottle > 0 &&
2428                             n_badrcpts >= BadRcptThrottle)
2429                         {
2430                                 if (LogLevel > 5 &&
2431                                     n_badrcpts == BadRcptThrottle)
2432                                 {
2433                                         sm_syslog(LOG_INFO, e->e_id,
2434                                                   "%s: Possible SMTP RCPT flood, throttling.",
2435                                                   CurSmtpClient);
2436
2437                                         /* To avoid duplicated message */
2438                                         n_badrcpts++;
2439                                 }
2440                                 NBADRCPTS;
2441
2442                                 /*
2443                                 **  Don't use exponential backoff for now.
2444                                 **  Some servers will open more connections
2445                                 **  and actually overload the receiver even
2446                                 **  more.
2447                                 */
2448
2449                                 (void) sleep(1);
2450                         }
2451                         if (!smtp.sm_gotmail)
2452                         {
2453                                 usrerr("503 5.0.0 Need MAIL before RCPT");
2454                                 break;
2455                         }
2456                         SmtpPhase = "server RCPT";
2457                     SM_TRY
2458                     {
2459                         QuickAbort = true;
2460                         LogUsrErrs = true;
2461
2462                         /* limit flooding of our machine */
2463                         if (MaxRcptPerMsg > 0 &&
2464                             smtp.sm_nrcpts >= MaxRcptPerMsg)
2465                         {
2466                                 /* sleep(1); / * slow down? */
2467                                 usrerr("452 4.5.3 Too many recipients");
2468                                 goto rcpt_done;
2469                         }
2470
2471                         if (e->e_sendmode != SM_DELIVER)
2472                                 e->e_flags |= EF_VRFYONLY;
2473
2474 #if MILTER
2475                         /*
2476                         **  If the filter will be deleting recipients,
2477                         **  don't expand them at RCPT time (in the call
2478                         **  to recipient()).  If they are expanded, it
2479                         **  is impossible for removefromlist() to figure
2480                         **  out the expanded members of the original
2481                         **  recipient and mark them as QS_DONTSEND.
2482                         */
2483
2484                         if (milter_can_delrcpts())
2485                                 e->e_flags |= EF_VRFYONLY;
2486 #endif /* MILTER */
2487
2488                         p = skipword(p, "to");
2489                         if (p == NULL)
2490                                 goto rcpt_done;
2491                         macdefine(&e->e_macro, A_PERM,
2492                                 macid("{addr_type}"), "e r");
2493                         a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
2494                                       e, true);
2495                         macdefine(&e->e_macro, A_PERM,
2496                                 macid("{addr_type}"), NULL);
2497                         if (Errors > 0)
2498                                 goto rcpt_done;
2499                         if (a == NULL)
2500                         {
2501                                 usrerr("501 5.0.0 Missing recipient");
2502                                 goto rcpt_done;
2503                         }
2504
2505                         if (delimptr != NULL && *delimptr != '\0')
2506                                 *delimptr++ = '\0';
2507
2508                         /* put resulting triple from parseaddr() into macros */
2509                         if (a->q_mailer != NULL)
2510                                 macdefine(&e->e_macro, A_PERM,
2511                                         macid("{rcpt_mailer}"),
2512                                         a->q_mailer->m_name);
2513                         else
2514                                 macdefine(&e->e_macro, A_PERM,
2515                                         macid("{rcpt_mailer}"), NULL);
2516                         if (a->q_host != NULL)
2517                                 macdefine(&e->e_macro, A_PERM,
2518                                         macid("{rcpt_host}"), a->q_host);
2519                         else
2520                                 macdefine(&e->e_macro, A_PERM,
2521                                         macid("{rcpt_host}"), "localhost");
2522                         if (a->q_user != NULL)
2523                                 macdefine(&e->e_macro, A_PERM,
2524                                         macid("{rcpt_addr}"), a->q_user);
2525                         else
2526                                 macdefine(&e->e_macro, A_PERM,
2527                                         macid("{rcpt_addr}"), NULL);
2528                         if (Errors > 0)
2529                                 goto rcpt_done;
2530
2531                         /* now parse ESMTP arguments */
2532                         addr = p;
2533                         argno = 0;
2534                         args[argno++] = p;
2535                         p = delimptr;
2536                         while (p != NULL && *p != '\0')
2537                         {
2538                                 char *kp;
2539                                 char *vp = NULL;
2540                                 char *equal = NULL;
2541
2542                                 /* locate the beginning of the keyword */
2543                                 SKIP_SPACE(p);
2544                                 if (*p == '\0')
2545                                         break;
2546                                 kp = p;
2547
2548                                 /* skip to the value portion */
2549                                 while ((isascii(*p) && isalnum(*p)) || *p == '-')
2550                                         p++;
2551                                 if (*p == '=')
2552                                 {
2553                                         equal = p;
2554                                         *p++ = '\0';
2555                                         vp = p;
2556
2557                                         /* skip to the end of the value */
2558                                         while (*p != '\0' && *p != ' ' &&
2559                                                !(isascii(*p) && iscntrl(*p)) &&
2560                                                *p != '=')
2561                                                 p++;
2562                                 }
2563
2564                                 if (*p != '\0')
2565                                         *p++ = '\0';
2566
2567                                 if (tTd(19, 1))
2568                                         sm_dprintf("RCPT: got arg %s=\"%s\"\n", kp,
2569                                                 vp == NULL ? "<null>" : vp);
2570
2571                                 rcpt_esmtp_args(a, kp, vp, e);
2572                                 if (equal != NULL)
2573                                         *equal = '=';
2574                                 args[argno++] = kp;
2575                                 if (argno >= MAXSMTPARGS - 1)
2576                                         usrerr("501 5.5.4 Too many parameters");
2577                                 if (Errors > 0)
2578                                         break;
2579                         }
2580                         args[argno] = NULL;
2581                         if (Errors > 0)
2582                                 goto rcpt_done;
2583
2584                         /* do config file checking of the recipient */
2585                         macdefine(&e->e_macro, A_PERM,
2586                                 macid("{addr_type}"), "e r");
2587                         if (rscheck("check_rcpt", addr,
2588                                     NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
2589                                     NULL, e->e_id) != EX_OK ||
2590                             Errors > 0)
2591                                 goto rcpt_done;
2592                         macdefine(&e->e_macro, A_PERM,
2593                                 macid("{addr_type}"), NULL);
2594
2595                         /* If discarding, don't bother to verify user */
2596                         if (bitset(EF_DISCARD, e->e_flags))
2597                                 a->q_state = QS_VERIFIED;
2598
2599 #if MILTER
2600                         if (smtp.sm_milterlist && smtp.sm_milterize &&
2601                             !bitset(EF_DISCARD, e->e_flags))
2602                         {
2603                                 char state;
2604                                 char *response;
2605
2606                                 response = milter_envrcpt(args, e, &state);
2607                                 MILTER_REPLY("to");
2608                         }
2609 #endif /* MILTER */
2610
2611                         macdefine(&e->e_macro, A_PERM,
2612                                 macid("{rcpt_mailer}"), NULL);
2613                         macdefine(&e->e_macro, A_PERM,
2614                                 macid("{rcpt_host}"), NULL);
2615                         macdefine(&e->e_macro, A_PERM,
2616                                 macid("{rcpt_addr}"), NULL);
2617                         macdefine(&e->e_macro, A_PERM,
2618                                 macid("{dsn_notify}"), NULL);
2619                         if (Errors > 0)
2620                                 goto rcpt_done;
2621
2622                         /* save in recipient list after ESMTP mods */
2623                         a = recipient(a, &e->e_sendqueue, 0, e);
2624                         if (Errors > 0)
2625                                 goto rcpt_done;
2626
2627                         /* no errors during parsing, but might be a duplicate */
2628                         e->e_to = a->q_paddr;
2629                         if (!QS_IS_BADADDR(a->q_state))
2630                         {
2631                                 if (smtp.sm_nrcpts == 0)
2632                                         initsys(e);
2633                                 message("250 2.1.5 Recipient ok%s",
2634                                         QS_IS_QUEUEUP(a->q_state) ?
2635                                                 " (will queue)" : "");
2636                                 smtp.sm_nrcpts++;
2637                         }
2638                         else
2639                         {
2640                                 /* punt -- should keep message in ADDRESS.... */
2641                                 usrerr("550 5.1.1 Addressee unknown");
2642                         }
2643                     rcpt_done:
2644                         if (Errors > 0)
2645                         {
2646                                 ++n_badrcpts;
2647                                 NBADRCPTS;
2648                         }
2649                     }
2650                     SM_EXCEPT(exc, "[!F]*")
2651                     {
2652                         /* An exception occurred while processing RCPT */
2653                         e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
2654                         ++n_badrcpts;
2655                         NBADRCPTS;
2656                     }
2657                     SM_END_TRY
2658                         break;
2659
2660                   case CMDDATA:         /* data -- text of mail */
2661                         DELAY_CONN("DATA");
2662                         if (!smtp_data(&smtp, e))
2663                                 goto doquit;
2664                         break;
2665
2666                   case CMDRSET:         /* rset -- reset state */
2667                         if (tTd(94, 100))
2668                                 message("451 4.0.0 Test failure");
2669                         else
2670                                 message("250 2.0.0 Reset state");
2671                         CLEAR_STATE(cmdbuf);
2672                         break;
2673
2674                   case CMDVRFY:         /* vrfy -- verify address */
2675                   case CMDEXPN:         /* expn -- expand address */
2676                         vrfy = c->cmd_code == CMDVRFY;
2677                         DELAY_CONN(vrfy ? "VRFY" : "EXPN");
2678                         if (tempfail)
2679                         {
2680                                 if (LogLevel > 9)
2681                                         sm_syslog(LOG_INFO, e->e_id,
2682                                                   "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
2683                                                   vrfy ? "VRFY" : "EXPN",
2684                                                   p, CurSmtpClient);
2685
2686                                 /* RFC 821 doesn't allow 4xy reply code */
2687                                 usrerr("550 5.7.1 Please try again later");
2688                                 break;
2689                         }
2690                         wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
2691                                              false, vrfy ? "VRFY" : "EXPN", e);
2692                         STOP_IF_ATTACK(wt);
2693                         previous = curtime();
2694                         if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
2695                             (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
2696                         {
2697                                 if (vrfy)
2698                                         message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
2699                                 else
2700                                         message("502 5.7.0 Sorry, we do not allow this operation");
2701                                 if (LogLevel > 5)
2702                                         sm_syslog(LOG_INFO, e->e_id,
2703                                                   "%s: %s [rejected]",
2704                                                   CurSmtpClient,
2705                                                   shortenstring(inp, MAXSHORTSTR));
2706                                 break;
2707                         }
2708                         else if (!gothello &&
2709                                  bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
2710                                                 PrivacyFlags))
2711                         {
2712                                 usrerr("503 5.0.0 I demand that you introduce yourself first");
2713                                 break;
2714                         }
2715                         if (Errors > 0)
2716                                 break;
2717                         if (LogLevel > 5)
2718                                 sm_syslog(LOG_INFO, e->e_id, "%s: %s",
2719                                           CurSmtpClient,
2720                                           shortenstring(inp, MAXSHORTSTR));
2721                     SM_TRY
2722                     {
2723                         QuickAbort = true;
2724                         vrfyqueue = NULL;
2725                         if (vrfy)
2726                                 e->e_flags |= EF_VRFYONLY;
2727                         while (*p != '\0' && isascii(*p) && isspace(*p))
2728                                 p++;
2729                         if (*p == '\0')
2730                         {
2731                                 usrerr("501 5.5.2 Argument required");
2732                         }
2733                         else
2734                         {
2735                                 /* do config file checking of the address */
2736                                 if (rscheck(vrfy ? "check_vrfy" : "check_expn",
2737                                             p, NULL, e, RSF_RMCOMM,
2738                                             3, NULL, NOQID) != EX_OK ||
2739                                     Errors > 0)
2740                                         sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2741                                 (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
2742                         }
2743                         if (wt > 0)
2744                         {
2745                                 time_t t;
2746
2747                                 t = wt - (curtime() - previous);
2748                                 if (t > 0)
2749                                         (void) sleep(t);
2750                         }
2751                         if (Errors > 0)
2752                                 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2753                         if (vrfyqueue == NULL)
2754                         {
2755                                 usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
2756                         }
2757                         while (vrfyqueue != NULL)
2758                         {
2759                                 if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
2760                                 {
2761                                         vrfyqueue = vrfyqueue->q_next;
2762                                         continue;
2763                                 }
2764
2765                                 /* see if there is more in the vrfy list */
2766                                 a = vrfyqueue;
2767                                 while ((a = a->q_next) != NULL &&
2768                                        (!QS_IS_UNDELIVERED(a->q_state)))
2769                                         continue;
2770                                 printvrfyaddr(vrfyqueue, a == NULL, vrfy);
2771                                 vrfyqueue = a;
2772                         }
2773                     }
2774                     SM_EXCEPT(exc, "[!F]*")
2775                     {
2776                         /*
2777                         **  An exception occurred while processing VRFY/EXPN
2778                         */
2779
2780                         sm_exc_free(exc);
2781                         goto undo;
2782                     }
2783                     SM_END_TRY
2784                         break;
2785
2786                   case CMDETRN:         /* etrn -- force queue flush */
2787                         DELAY_CONN("ETRN");
2788
2789                         /* Don't leak queue information via debug flags */
2790                         if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
2791                             (RealUid != 0 && RealUid != TrustedUid &&
2792                              OpMode == MD_SMTP))
2793                         {
2794                                 /* different message for MSA ? */
2795                                 message("502 5.7.0 Sorry, we do not allow this operation");
2796                                 if (LogLevel > 5)
2797                                         sm_syslog(LOG_INFO, e->e_id,
2798                                                   "%s: %s [rejected]",
2799                                                   CurSmtpClient,
2800                                                   shortenstring(inp, MAXSHORTSTR));
2801                                 break;
2802                         }
2803                         if (tempfail)
2804                         {
2805                                 if (LogLevel > 9)
2806                                         sm_syslog(LOG_INFO, e->e_id,
2807                                                   "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
2808                                                   p, CurSmtpClient);
2809                                 usrerr(MSG_TEMPFAIL);
2810                                 break;
2811                         }
2812
2813                         if (strlen(p) <= 0)
2814                         {
2815                                 usrerr("500 5.5.2 Parameter required");
2816                                 break;
2817                         }
2818
2819                         /* crude way to avoid denial-of-service attacks */
2820                         STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
2821                                                         true, "ETRN", e));
2822
2823                         /*
2824                         **  Do config file checking of the parameter.
2825                         **  Even though we have srv_features now, we still
2826                         **  need this ruleset because the former is called
2827                         **  when the connection has been established, while
2828                         **  this ruleset is called when the command is
2829                         **  actually issued and therefore has all information
2830                         **  available to make a decision.
2831                         */
2832
2833                         if (rscheck("check_etrn", p, NULL, e,
2834                                     RSF_RMCOMM, 3, NULL, NOQID) != EX_OK ||
2835                             Errors > 0)
2836                                 break;
2837
2838                         if (LogLevel > 5)
2839                                 sm_syslog(LOG_INFO, e->e_id,
2840                                           "%s: ETRN %s", CurSmtpClient,
2841                                           shortenstring(p, MAXSHORTSTR));
2842
2843                         id = p;
2844                         if (*id == '#')
2845                         {
2846                                 int i, qgrp;
2847
2848                                 id++;
2849                                 qgrp = name2qid(id);
2850                                 if (!ISVALIDQGRP(qgrp))
2851                                 {
2852                                         usrerr("459 4.5.4 Queue %s unknown",
2853                                                id);
2854                                         break;
2855                                 }
2856                                 for (i = 0; i < NumQueue && Queue[i] != NULL;
2857                                      i++)
2858                                         Queue[i]->qg_nextrun = (time_t) -1;
2859                                 Queue[qgrp]->qg_nextrun = 0;
2860                                 ok = run_work_group(Queue[qgrp]->qg_wgrp,
2861                                                     RWG_FORK|RWG_FORCE);
2862                                 if (ok && Errors == 0)
2863                                         message("250 2.0.0 Queuing for queue group %s started", id);
2864                                 break;
2865                         }
2866
2867                         if (*id == '@')
2868                                 id++;
2869                         else
2870                                 *--id = '@';
2871
2872                         new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
2873                         if (new == NULL)
2874                         {
2875                                 syserr("500 5.5.0 ETRN out of memory");
2876                                 break;
2877                         }
2878                         new->queue_match = id;
2879                         new->queue_negate = false;
2880                         new->queue_next = NULL;
2881                         QueueLimitRecipient = new;
2882                         ok = runqueue(true, false, false, true);
2883                         sm_free(QueueLimitRecipient); /* XXX */
2884                         QueueLimitRecipient = NULL;
2885                         if (ok && Errors == 0)
2886                                 message("250 2.0.0 Queuing for node %s started", p);
2887                         break;
2888
2889                   case CMDHELP:         /* help -- give user info */
2890                         DELAY_CONN("HELP");
2891                         help(p, e);
2892                         break;
2893
2894                   case CMDNOOP:         /* noop -- do nothing */
2895                         DELAY_CONN("NOOP");
2896                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
2897                                                         true, "NOOP", e));
2898                         message("250 2.0.0 OK");
2899                         break;
2900
2901                   case CMDQUIT:         /* quit -- leave mail */
2902                         message("221 2.0.0 %s closing connection", MyHostName);
2903 #if PIPELINING
2904                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2905 #endif /* PIPELINING */
2906
2907                         if (smtp.sm_nrcpts > 0)
2908                                 logundelrcpts(e, "aborted by sender", 9, false);
2909
2910                         /* arrange to ignore any current send list */
2911                         e->e_sendqueue = NULL;
2912
2913 #if STARTTLS
2914                         /* shutdown TLS connection */
2915                         if (tls_active)
2916                         {
2917                                 (void) endtls(srv_ssl, "server");
2918                                 tls_active = false;
2919                         }
2920 #endif /* STARTTLS */
2921 #if SASL
2922                         if (authenticating == SASL_IS_AUTH)
2923                         {
2924                                 sasl_dispose(&conn);
2925                                 authenticating = SASL_NOT_AUTH;
2926                                 /* XXX sasl_done(); this is a child */
2927                         }
2928 #endif /* SASL */
2929
2930 doquit:
2931                         /* avoid future 050 messages */
2932                         disconnect(1, e);
2933
2934 #if MILTER
2935                         /* close out milter filters */
2936                         milter_quit(e);
2937 #endif /* MILTER */
2938
2939                         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
2940                                 logsender(e, NULL);
2941                         e->e_flags &= ~EF_LOGSENDER;
2942
2943                         if (lognullconnection && LogLevel > 5 &&
2944                             nullserver == NULL)
2945                         {
2946                                 char *d;
2947
2948                                 d = macvalue(macid("{daemon_name}"), e);
2949                                 if (d == NULL)
2950                                         d = "stdin";
2951
2952                                 /*
2953                                 **  even though this id is "bogus", it makes
2954                                 **  it simpler to "grep" related events, e.g.,
2955                                 **  timeouts for the same connection.
2956                                 */
2957
2958                                 sm_syslog(LOG_INFO, e->e_id,
2959                                           "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
2960                                           CurSmtpClient, d);
2961                         }
2962                         if (tTd(93, 100))
2963                         {
2964                                 /* return to handle next connection */
2965                                 return;
2966                         }
2967                         finis(true, true, ExitStat);
2968                         /* NOTREACHED */
2969
2970                   case CMDVERB:         /* set verbose mode */
2971                         DELAY_CONN("VERB");
2972                         if (!bitset(SRV_OFFER_EXPN, features) ||
2973                             !bitset(SRV_OFFER_VERB, features))
2974                         {
2975                                 /* this would give out the same info */
2976                                 message("502 5.7.0 Verbose unavailable");
2977                                 break;
2978                         }
2979                         STOP_IF_ATTACK(checksmtpattack(&n_noop, MAXNOOPCOMMANDS,
2980                                                         true, "VERB", e));
2981                         Verbose = 1;
2982                         set_delivery_mode(SM_DELIVER, e);
2983                         message("250 2.0.0 Verbose mode");
2984                         break;
2985
2986 #if SMTPDEBUG
2987                   case CMDDBGQSHOW:     /* show queues */
2988                         (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
2989                                              "Send Queue=");
2990                         printaddr(smioout, e->e_sendqueue, true);
2991                         break;
2992
2993                   case CMDDBGDEBUG:     /* set debug mode */
2994                         tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
2995                         tTflag(p);
2996                         message("200 2.0.0 Debug set");
2997                         break;
2998
2999 #else /* SMTPDEBUG */
3000                   case CMDDBGQSHOW:     /* show queues */
3001                   case CMDDBGDEBUG:     /* set debug mode */
3002 #endif /* SMTPDEBUG */
3003                   case CMDLOGBOGUS:     /* bogus command */
3004                         DELAY_CONN("Bogus");
3005                         if (LogLevel > 0)
3006                                 sm_syslog(LOG_CRIT, e->e_id,
3007                                           "\"%s\" command from %s (%.100s)",
3008                                           c->cmd_name, CurSmtpClient,
3009                                           anynet_ntoa(&RealHostAddr));
3010                         /* FALLTHROUGH */
3011
3012                   case CMDERROR:        /* unknown command */
3013 #if MAXBADCOMMANDS > 0
3014                         if (++n_badcmds > MAXBADCOMMANDS)
3015                         {
3016   stopattack:
3017                                 message("421 4.7.0 %s Too many bad commands; closing connection",
3018                                         MyHostName);
3019
3020                                 /* arrange to ignore any current send list */
3021                                 e->e_sendqueue = NULL;
3022                                 goto doquit;
3023                         }
3024 #endif /* MAXBADCOMMANDS > 0 */
3025
3026 #if MILTER && SMFI_VERSION > 2
3027                         if (smtp.sm_milterlist && smtp.sm_milterize &&
3028                             !bitset(EF_DISCARD, e->e_flags))
3029                         {
3030                                 char state;
3031                                 char *response;
3032
3033                                 if (MilterLogLevel > 9)
3034                                         sm_syslog(LOG_INFO, e->e_id,
3035                                                 "Sending \"%s\" to Milter", inp);
3036                                 response = milter_unknown(inp, e, &state);
3037                                 MILTER_REPLY("unknown");
3038                                 if (state == SMFIR_REPLYCODE ||
3039                                     state == SMFIR_REJECT ||
3040                                     state == SMFIR_TEMPFAIL)
3041                                 {
3042                                         /* MILTER_REPLY already gave an error */
3043                                         break;
3044                                 }
3045                         }
3046 #endif /* MILTER && SMFI_VERSION > 2 */
3047
3048                         usrerr("500 5.5.1 Command unrecognized: \"%s\"",
3049                                shortenstring(inp, MAXSHORTSTR));
3050                         break;
3051
3052                   case CMDUNIMPL:
3053                         DELAY_CONN("Unimpl");
3054                         usrerr("502 5.5.1 Command not implemented: \"%s\"",
3055                                shortenstring(inp, MAXSHORTSTR));
3056                         break;
3057
3058                   default:
3059                         DELAY_CONN("default");
3060                         errno = 0;
3061                         syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
3062                         break;
3063                 }
3064 #if SASL
3065                 }
3066 #endif /* SASL */
3067             }
3068             SM_EXCEPT(exc, "[!F]*")
3069             {
3070                 /*
3071                 **  The only possible exception is "E:mta.quickabort".
3072                 **  There is nothing to do except fall through and loop.
3073                 */
3074             }
3075             SM_END_TRY
3076         }
3077 }
3078 /*
3079 **  SMTP_DATA -- implement the SMTP DATA command.
3080 **
3081 **      Parameters:
3082 **              smtp -- status of SMTP connection.
3083 **              e -- envelope.
3084 **
3085 **      Returns:
3086 **              true iff SMTP session can continue.
3087 **
3088 **      Side Effects:
3089 **              possibly sends message.
3090 */
3091
3092 static bool
3093 smtp_data(smtp, e)
3094         SMTP_T *smtp;
3095         ENVELOPE *e;
3096 {
3097 #if MILTER
3098         bool milteraccept;
3099 #endif /* MILTER */
3100         bool aborting;
3101         bool doublequeue;
3102         ADDRESS *a;
3103         ENVELOPE *ee;
3104         char *id;
3105         char *oldid;
3106         char buf[32];
3107
3108         SmtpPhase = "server DATA";
3109         if (!smtp->sm_gotmail)
3110         {
3111                 usrerr("503 5.0.0 Need MAIL command");
3112                 return true;
3113         }
3114         else if (smtp->sm_nrcpts <= 0)
3115         {
3116                 usrerr("503 5.0.0 Need RCPT (recipient)");
3117                 return true;
3118         }
3119         (void) sm_snprintf(buf, sizeof buf, "%u", smtp->sm_nrcpts);
3120         if (rscheck("check_data", buf, NULL, e,
3121                     RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
3122                     e->e_id) != EX_OK)
3123                 return true;
3124
3125 #if MILTER && SMFI_VERSION > 3
3126         if (smtp->sm_milterlist && smtp->sm_milterize &&
3127             !bitset(EF_DISCARD, e->e_flags))
3128         {
3129                 char state;
3130                 char *response;
3131                 int savelogusrerrs = LogUsrErrs;
3132
3133                 response = milter_data_cmd(e, &state);
3134                 switch (state)
3135                 {
3136                   case SMFIR_REPLYCODE:
3137                         if (MilterLogLevel > 3)
3138                         {
3139                                 sm_syslog(LOG_INFO, e->e_id,
3140                                           "Milter: cmd=data, reject=%s",
3141                                           response);
3142                                 LogUsrErrs = false;
3143                         }
3144                         usrerr(response);
3145                         if (strncmp(response, "421 ", 4) == 0)
3146                         {
3147                                 e->e_sendqueue = NULL;
3148                                 return false;
3149                         }
3150                         return true;
3151
3152                   case SMFIR_REJECT:
3153                         if (MilterLogLevel > 3)
3154                         {
3155                                 sm_syslog(LOG_INFO, e->e_id,
3156                                           "Milter: cmd=data, reject=550 5.7.1 Command rejected");
3157                                 LogUsrErrs = false;
3158                         }
3159                         usrerr("550 5.7.1 Command rejected");
3160                         return true;
3161
3162                   case SMFIR_DISCARD:
3163                         if (MilterLogLevel > 3)
3164                                 sm_syslog(LOG_INFO, e->e_id,
3165                                           "Milter: cmd=data, discard");
3166                         e->e_flags |= EF_DISCARD;
3167                         break;
3168
3169                   case SMFIR_TEMPFAIL:
3170                         if (MilterLogLevel > 3)
3171                         {
3172                                 sm_syslog(LOG_INFO, e->e_id,
3173                                           "Milter: cmd=data, reject=%s",
3174                                           MSG_TEMPFAIL);
3175                                 LogUsrErrs = false;
3176                         }
3177                         usrerr(MSG_TEMPFAIL);
3178                         return true;
3179                 }
3180                 LogUsrErrs = savelogusrerrs;
3181                 if (response != NULL)
3182                         sm_free(response); /* XXX */
3183         }
3184 #endif /* MILTER && SMFI_VERSION > 3 */
3185
3186         /* put back discard bit */
3187         if (smtp->sm_discard)
3188                 e->e_flags |= EF_DISCARD;
3189
3190         /* check to see if we need to re-expand aliases */
3191         /* also reset QS_BADADDR on already-diagnosted addrs */
3192         doublequeue = false;
3193         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
3194         {
3195                 if (QS_IS_VERIFIED(a->q_state) &&
3196                     !bitset(EF_DISCARD, e->e_flags))
3197                 {
3198                         /* need to re-expand aliases */
3199                         doublequeue = true;
3200                 }
3201                 if (QS_IS_BADADDR(a->q_state))
3202                 {
3203                         /* make this "go away" */
3204                         a->q_state = QS_DONTSEND;
3205                 }
3206         }
3207
3208         /* collect the text of the message */
3209         SmtpPhase = "collect";
3210         buffer_errors();
3211
3212         collect(InChannel, true, NULL, e, true);
3213
3214         /* redefine message size */
3215         (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3216         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3217
3218 #if _FFR_CHECK_EOM
3219         /* rscheck() will set Errors or EF_DISCARD if it trips */
3220         (void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
3221                        3, NULL, e->e_id);
3222 #endif /* _FFR_CHECK_EOM */
3223
3224 #if MILTER
3225         milteraccept = true;
3226         if (smtp->sm_milterlist && smtp->sm_milterize &&
3227             Errors <= 0 &&
3228             !bitset(EF_DISCARD, e->e_flags))
3229         {
3230                 char state;
3231                 char *response;
3232
3233                 response = milter_data(e, &state);
3234                 switch (state)
3235                 {
3236                   case SMFIR_REPLYCODE:
3237                         if (MilterLogLevel > 3)
3238                                 sm_syslog(LOG_INFO, e->e_id,
3239                                           "Milter: data, reject=%s",
3240                                           response);
3241                         milteraccept = false;
3242                         usrerr(response);
3243                         break;
3244
3245                   case SMFIR_REJECT:
3246                         milteraccept = false;
3247                         if (MilterLogLevel > 3)
3248                                 sm_syslog(LOG_INFO, e->e_id,
3249                                           "Milter: data, reject=554 5.7.1 Command rejected");
3250                         usrerr("554 5.7.1 Command rejected");
3251                         break;
3252
3253                   case SMFIR_DISCARD:
3254                         if (MilterLogLevel > 3)
3255                                 sm_syslog(LOG_INFO, e->e_id,
3256                                           "Milter: data, discard");
3257                         milteraccept = false;
3258                         e->e_flags |= EF_DISCARD;
3259                         break;
3260
3261                   case SMFIR_TEMPFAIL:
3262                         if (MilterLogLevel > 3)
3263                                 sm_syslog(LOG_INFO, e->e_id,
3264                                           "Milter: data, reject=%s",
3265                                           MSG_TEMPFAIL);
3266                         milteraccept = false;
3267                         usrerr(MSG_TEMPFAIL);
3268                         break;
3269                 }
3270                 if (response != NULL)
3271                         sm_free(response);
3272         }
3273
3274         /* Milter may have changed message size */
3275         (void) sm_snprintf(buf, sizeof buf, "%ld", e->e_msgsize);
3276         macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
3277
3278         /* abort message filters that didn't get the body & log msg is OK */
3279         if (smtp->sm_milterlist && smtp->sm_milterize)
3280         {
3281                 milter_abort(e);
3282                 if (milteraccept && MilterLogLevel > 9)
3283                         sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
3284         }
3285
3286         /*
3287         **  If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
3288         **  milter accepted message, sync it now
3289         **
3290         **  XXX This is almost a copy of the code in collect(): put it into
3291         **      a function that is called from both places?
3292         */
3293
3294         if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
3295         {
3296                 int afd;
3297                 SM_FILE_T *volatile df;
3298                 char *dfname;
3299
3300                 df = e->e_dfp;
3301                 dfname = queuename(e, DATAFL_LETTER);
3302                 if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
3303                     && errno != EINVAL)
3304                 {
3305                         int save_errno;
3306
3307                         save_errno = errno;
3308                         if (save_errno == EEXIST)
3309                         {
3310                                 struct stat st;
3311                                 int dfd;
3312
3313                                 if (stat(dfname, &st) < 0)
3314                                         st.st_size = -1;
3315                                 errno = EEXIST;
3316                                 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
3317                                        dfname, (long) st.st_size);
3318                                 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
3319                                 if (dfd >= 0)
3320                                         dumpfd(dfd, true, true);
3321                         }
3322                         errno = save_errno;
3323                         dferror(df, "bfcommit", e);
3324                         flush_errors(true);
3325                         finis(save_errno != EEXIST, true, ExitStat);
3326                 }
3327                 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
3328                 {
3329                         dferror(df, "sm_io_getinfo", e);
3330                         flush_errors(true);
3331                         finis(true, true, ExitStat);
3332                         /* NOTREACHED */
3333                 }
3334                 else if (fsync(afd) < 0)
3335                 {
3336                         dferror(df, "fsync", e);
3337                         flush_errors(true);
3338                         finis(true, true, ExitStat);
3339                         /* NOTREACHED */
3340                 }
3341                 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
3342                 {
3343                         dferror(df, "sm_io_close", e);
3344                         flush_errors(true);
3345                         finis(true, true, ExitStat);
3346                         /* NOTREACHED */
3347                 }
3348
3349                 /* Now reopen the df file */
3350                 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
3351                                         SM_IO_RDONLY, NULL);
3352                 if (e->e_dfp == NULL)
3353                 {
3354                         /* we haven't acked receipt yet, so just chuck this */
3355                         syserr("@Cannot reopen %s", dfname);
3356                         finis(true, true, ExitStat);
3357                         /* NOTREACHED */
3358                 }
3359         }
3360 #endif /* MILTER */
3361
3362         /* Check if quarantining stats should be updated */
3363         if (e->e_quarmsg != NULL)
3364                 markstats(e, NULL, STATS_QUARANTINE);
3365
3366         /*
3367         **  If a header/body check (header checks or milter)
3368         **  set EF_DISCARD, don't queueup the message --
3369         **  that would lose the EF_DISCARD bit and deliver
3370         **  the message.
3371         */
3372
3373         if (bitset(EF_DISCARD, e->e_flags))
3374                 doublequeue = false;
3375
3376         aborting = Errors > 0;
3377         if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
3378             (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
3379             !split_by_recipient(e))
3380                 aborting = bitset(EF_FATALERRS, e->e_flags);
3381
3382         if (aborting)
3383         {
3384                 /* Log who the mail would have gone to */
3385                 logundelrcpts(e, e->e_message, 8, false);
3386                 flush_errors(true);
3387                 buffer_errors();
3388                 goto abortmessage;
3389         }
3390
3391         /* from now on, we have to operate silently */
3392         buffer_errors();
3393
3394 #if 0
3395         /*
3396         **  Clear message, it may contain an error from the SMTP dialogue.
3397         **  This error must not show up in the queue.
3398         **      Some error message should show up, e.g., alias database
3399         **      not available, but others shouldn't, e.g., from check_rcpt.
3400         */
3401
3402         e->e_message = NULL;
3403 #endif /* 0 */
3404
3405         /*
3406         **  Arrange to send to everyone.
3407         **      If sending to multiple people, mail back
3408         **              errors rather than reporting directly.
3409         **      In any case, don't mail back errors for
3410         **              anything that has happened up to
3411         **              now (the other end will do this).
3412         **      Truncate our transcript -- the mail has gotten
3413         **              to us successfully, and if we have
3414         **              to mail this back, it will be easier
3415         **              on the reader.
3416         **      Then send to everyone.
3417         **      Finally give a reply code.  If an error has
3418         **              already been given, don't mail a
3419         **              message back.
3420         **      We goose error returns by clearing error bit.
3421         */
3422
3423         SmtpPhase = "delivery";
3424         (void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
3425         id = e->e_id;
3426
3427 #if NAMED_BIND
3428         _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
3429         _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
3430 #endif /* NAMED_BIND */
3431
3432         for (ee = e; ee != NULL; ee = ee->e_sibling)
3433         {
3434                 /* make sure we actually do delivery */
3435                 ee->e_flags &= ~EF_CLRQUEUE;
3436
3437                 /* from now on, operate silently */
3438                 ee->e_errormode = EM_MAIL;
3439
3440                 if (doublequeue)
3441                 {
3442                         /* make sure it is in the queue */
3443                         queueup(ee, false, true);
3444                 }
3445                 else
3446                 {
3447                         /* send to all recipients */
3448                         sendall(ee, SM_DEFAULT);
3449                 }
3450                 ee->e_to = NULL;
3451         }
3452
3453         /* put back id for SMTP logging in putoutmsg() */
3454         oldid = CurEnv->e_id;
3455         CurEnv->e_id = id;
3456
3457         /* issue success message */
3458         message("250 2.0.0 %s Message accepted for delivery", id);
3459         CurEnv->e_id = oldid;
3460
3461         /* if we just queued, poke it */
3462         if (doublequeue)
3463         {
3464                 bool anything_to_send = false;
3465
3466                 sm_getla();
3467                 for (ee = e; ee != NULL; ee = ee->e_sibling)
3468                 {
3469                         if (WILL_BE_QUEUED(ee->e_sendmode))
3470                                 continue;
3471                         if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
3472                         {
3473                                 ee->e_sendmode = SM_QUEUE;
3474                                 continue;
3475                         }
3476                         else if (QueueMode != QM_QUARANTINE &&
3477                                  ee->e_quarmsg != NULL)
3478                         {
3479                                 ee->e_sendmode = SM_QUEUE;
3480                                 continue;
3481                         }
3482                         anything_to_send = true;
3483
3484                         /* close all the queue files */
3485                         closexscript(ee);
3486                         if (ee->e_dfp != NULL)
3487                         {
3488                                 (void) sm_io_close(ee->e_dfp, SM_TIME_DEFAULT);
3489                                 ee->e_dfp = NULL;
3490                         }
3491                         unlockqueue(ee);
3492                 }
3493                 if (anything_to_send)
3494                 {
3495 #if PIPELINING
3496                         /*
3497                         **  XXX if we don't do this, we get 250 twice
3498                         **      because it is also flushed in the child.
3499                         */
3500
3501                         (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3502 #endif /* PIPELINING */
3503                         (void) doworklist(e, true, true);
3504                 }
3505         }
3506
3507   abortmessage:
3508         if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3509                 logsender(e, NULL);
3510         e->e_flags &= ~EF_LOGSENDER;
3511
3512         /* clean up a bit */
3513         smtp->sm_gotmail = false;
3514
3515         /*
3516         **  Call dropenvelope if and only if the envelope is *not*
3517         **  being processed by the child process forked by doworklist().
3518         */
3519
3520         if (aborting || bitset(EF_DISCARD, e->e_flags))
3521                 dropenvelope(e, true, false);
3522         else
3523         {
3524                 for (ee = e; ee != NULL; ee = ee->e_sibling)
3525                 {
3526                         if (!doublequeue &&
3527                             QueueMode != QM_QUARANTINE &&
3528                             ee->e_quarmsg != NULL)
3529                         {
3530                                 dropenvelope(ee, true, false);
3531                                 continue;
3532                         }
3533                         if (WILL_BE_QUEUED(ee->e_sendmode))
3534                                 dropenvelope(ee, true, false);
3535                 }
3536         }
3537         sm_rpool_free(e->e_rpool);
3538
3539         /*
3540         **  At this point, e == &MainEnvelope, but if we did splitting,
3541         **  then CurEnv may point to an envelope structure that was just
3542         **  freed with the rpool.  So reset CurEnv *before* calling
3543         **  newenvelope.
3544         */
3545
3546         CurEnv = e;
3547         newenvelope(e, e, sm_rpool_new_x(NULL));
3548         e->e_flags = BlankEnvelope.e_flags;
3549
3550         /* restore connection quarantining */
3551         if (smtp->sm_quarmsg == NULL)
3552         {
3553                 e->e_quarmsg = NULL;
3554                 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
3555         }
3556         else
3557         {
3558                 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
3559                 macdefine(&e->e_macro, A_PERM,
3560                           macid("{quarantine}"), e->e_quarmsg);
3561         }
3562         return true;
3563 }
3564 /*
3565 **  LOGUNDELRCPTS -- log undelivered (or all) recipients.
3566 **
3567 **      Parameters:
3568 **              e -- envelope.
3569 **              msg -- message for Stat=
3570 **              level -- log level.
3571 **              all -- log all recipients.
3572 **
3573 **      Returns:
3574 **              none.
3575 **
3576 **      Side Effects:
3577 **              logs undelivered (or all) recipients
3578 */
3579
3580 void
3581 logundelrcpts(e, msg, level, all)
3582         ENVELOPE *e;
3583         char *msg;
3584         int level;
3585         bool all;
3586 {
3587         ADDRESS *a;
3588
3589         if (LogLevel <= level || msg == NULL || *msg == '\0')
3590                 return;
3591
3592         /* Clear $h so relay= doesn't get mislogged by logdelivery() */
3593         macdefine(&e->e_macro, A_PERM, 'h', NULL);
3594
3595         /* Log who the mail would have gone to */
3596         for (a = e->e_sendqueue; a != NULL; a = a->q_next)
3597         {
3598                 if (!QS_IS_UNDELIVERED(a->q_state) && !all)
3599                         continue;
3600                 e->e_to = a->q_paddr;
3601                 logdelivery(NULL, NULL, a->q_status, msg, NULL,
3602                             (time_t) 0, e);
3603         }
3604         e->e_to = NULL;
3605 }
3606 /*
3607 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
3608 **
3609 **      Parameters:
3610 **              pcounter -- pointer to a counter for this command.
3611 **              maxcount -- maximum value for this counter before we
3612 **                      slow down.
3613 **              waitnow -- sleep now (in this routine)?
3614 **              cname -- command name for logging.
3615 **              e -- the current envelope.
3616 **
3617 **      Returns:
3618 **              time to wait,
3619 **              STOP_ATTACK if twice as many commands as allowed and
3620 **                      MaxChildren > 0.
3621 **
3622 **      Side Effects:
3623 **              Slows down if we seem to be under attack.
3624 */
3625
3626 static time_t
3627 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
3628         volatile unsigned int *pcounter;
3629         unsigned int maxcount;
3630         bool waitnow;
3631         char *cname;
3632         ENVELOPE *e;
3633 {
3634         if (maxcount <= 0)      /* no limit */
3635                 return (time_t) 0;
3636
3637         if (++(*pcounter) >= maxcount)
3638         {
3639                 unsigned int shift;
3640                 time_t s;
3641
3642                 if (*pcounter == maxcount && LogLevel > 5)
3643                 {
3644                         sm_syslog(LOG_INFO, e->e_id,
3645                                   "%s: possible SMTP attack: command=%.40s, count=%u",
3646                                   CurSmtpClient, cname, *pcounter);
3647                 }
3648                 shift = *pcounter - maxcount;
3649                 s = 1 << shift;
3650                 if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
3651                         s = MAXTIMEOUT;
3652
3653 #define IS_ATTACK(s)    ((MaxChildren > 0 && *pcounter >= maxcount * 2) \
3654                                 ? STOP_ATTACK : (time_t) s)
3655
3656                 /* sleep at least 1 second before returning */
3657                 (void) sleep(*pcounter / maxcount);
3658                 s -= *pcounter / maxcount;
3659                 if (s >= MAXTIMEOUT || s < 0)
3660                         s = MAXTIMEOUT;
3661                 if (waitnow && s > 0)
3662                 {
3663                         (void) sleep(s);
3664                         return IS_ATTACK(0);
3665                 }
3666                 return IS_ATTACK(s);
3667         }
3668         return (time_t) 0;
3669 }
3670 /*
3671 **  SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
3672 **
3673 **      Parameters:
3674 **              none.
3675 **
3676 **      Returns:
3677 **              nothing.
3678 **
3679 **      Side Effects:
3680 **              may change I/O fd.
3681 */
3682
3683 static void
3684 setup_smtpd_io()
3685 {
3686         int inchfd, outchfd, outfd;
3687
3688         inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
3689         outchfd  = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
3690         outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
3691         if (outchfd != outfd)
3692         {
3693                 /* arrange for debugging output to go to remote host */
3694                 (void) dup2(outchfd, outfd);
3695         }
3696
3697         /*
3698         **  if InChannel and OutChannel are stdin/stdout
3699         **  and connected to ttys
3700         **  and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
3701         **  then "chain" them together.
3702         */
3703
3704         if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
3705             isatty(inchfd) && isatty(outchfd))
3706         {
3707                 int inmode, outmode;
3708
3709                 inmode = fcntl(inchfd, F_GETFL, 0);
3710                 if (inmode == -1)
3711                 {
3712                         if (LogLevel > 11)
3713                                 sm_syslog(LOG_INFO, NOQID,
3714                                         "fcntl(inchfd, F_GETFL) failed: %s",
3715                                         sm_errstring(errno));
3716                         return;
3717                 }
3718                 outmode = fcntl(outchfd, F_GETFL, 0);
3719                 if (outmode == -1)
3720                 {
3721                         if (LogLevel > 11)
3722                                 sm_syslog(LOG_INFO, NOQID,
3723                                         "fcntl(outchfd, F_GETFL) failed: %s",
3724                                         sm_errstring(errno));
3725                         return;
3726                 }
3727                 if (bitset(O_NONBLOCK, inmode) ||
3728                     bitset(O_NONBLOCK, outmode) ||
3729                     fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
3730                         return;
3731                 outmode = fcntl(outchfd, F_GETFL, 0);
3732                 if (outmode != -1 && bitset(O_NONBLOCK, outmode))
3733                 {
3734                         /* changing InChannel also changes OutChannel */
3735                         sm_io_automode(OutChannel, InChannel);
3736                         if (tTd(97, 4) && LogLevel > 9)
3737                                 sm_syslog(LOG_INFO, NOQID,
3738                                           "set automode for I (%d)/O (%d) in SMTP server",
3739                                           inchfd, outchfd);
3740                 }
3741
3742                 /* undo change of inchfd */
3743                 (void) fcntl(inchfd, F_SETFL, inmode);
3744         }
3745 }
3746 /*
3747 **  SKIPWORD -- skip a fixed word.
3748 **
3749 **      Parameters:
3750 **              p -- place to start looking.
3751 **              w -- word to skip.
3752 **
3753 **      Returns:
3754 **              p following w.
3755 **              NULL on error.
3756 **
3757 **      Side Effects:
3758 **              clobbers the p data area.
3759 */
3760
3761 static char *
3762 skipword(p, w)
3763         register char *volatile p;
3764         char *w;
3765 {
3766         register char *q;
3767         char *firstp = p;
3768
3769         /* find beginning of word */
3770         SKIP_SPACE(p);
3771         q = p;
3772
3773         /* find end of word */
3774         while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
3775                 p++;
3776         while (isascii(*p) && isspace(*p))
3777                 *p++ = '\0';
3778         if (*p != ':')
3779         {
3780           syntax:
3781                 usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
3782                         shortenstring(firstp, MAXSHORTSTR));
3783                 return NULL;
3784         }
3785         *p++ = '\0';
3786         SKIP_SPACE(p);
3787
3788         if (*p == '\0')
3789                 goto syntax;
3790
3791         /* see if the input word matches desired word */
3792         if (sm_strcasecmp(q, w))
3793                 goto syntax;
3794
3795         return p;
3796 }
3797 /*
3798 **  MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
3799 **
3800 **      Parameters:
3801 **              kp -- the parameter key.
3802 **              vp -- the value of that parameter.
3803 **              e -- the envelope.
3804 **
3805 **      Returns:
3806 **              none.
3807 */
3808
3809 static void
3810 mail_esmtp_args(kp, vp, e)
3811         char *kp;
3812         char *vp;
3813         ENVELOPE *e;
3814 {
3815         if (sm_strcasecmp(kp, "size") == 0)
3816         {
3817                 if (vp == NULL)
3818                 {
3819                         usrerr("501 5.5.2 SIZE requires a value");
3820                         /* NOTREACHED */
3821                 }
3822                 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
3823                 errno = 0;
3824                 e->e_msgsize = strtol(vp, (char **) NULL, 10);
3825                 if (e->e_msgsize == LONG_MAX && errno == ERANGE)
3826                 {
3827                         usrerr("552 5.2.3 Message size exceeds maximum value");
3828                         /* NOTREACHED */
3829                 }
3830                 if (e->e_msgsize < 0)
3831                 {
3832                         usrerr("552 5.2.3 Message size invalid");
3833                         /* NOTREACHED */
3834                 }
3835         }
3836         else if (sm_strcasecmp(kp, "body") == 0)
3837         {
3838                 if (vp == NULL)
3839                 {
3840                         usrerr("501 5.5.2 BODY requires a value");
3841                         /* NOTREACHED */
3842                 }
3843                 else if (sm_strcasecmp(vp, "8bitmime") == 0)
3844                 {
3845                         SevenBitInput = false;
3846                 }
3847                 else if (sm_strcasecmp(vp, "7bit") == 0)
3848                 {
3849                         SevenBitInput = true;
3850                 }
3851                 else
3852                 {
3853                         usrerr("501 5.5.4 Unknown BODY type %s", vp);
3854                         /* NOTREACHED */
3855                 }
3856                 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
3857         }
3858         else if (sm_strcasecmp(kp, "envid") == 0)
3859         {
3860                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3861                 {
3862                         usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
3863                         /* NOTREACHED */
3864                 }
3865                 if (vp == NULL)
3866                 {
3867                         usrerr("501 5.5.2 ENVID requires a value");
3868                         /* NOTREACHED */
3869                 }
3870                 if (!xtextok(vp))
3871                 {
3872                         usrerr("501 5.5.4 Syntax error in ENVID parameter value");
3873                         /* NOTREACHED */
3874                 }
3875                 if (e->e_envid != NULL)
3876                 {
3877                         usrerr("501 5.5.0 Duplicate ENVID parameter");
3878                         /* NOTREACHED */
3879                 }
3880                 e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
3881                 macdefine(&e->e_macro, A_PERM,
3882                         macid("{dsn_envid}"), e->e_envid);
3883         }
3884         else if (sm_strcasecmp(kp, "ret") == 0)
3885         {
3886                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
3887                 {
3888                         usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
3889                         /* NOTREACHED */
3890                 }
3891                 if (vp == NULL)
3892                 {
3893                         usrerr("501 5.5.2 RET requires a value");
3894                         /* NOTREACHED */
3895                 }
3896                 if (bitset(EF_RET_PARAM, e->e_flags))
3897                 {
3898                         usrerr("501 5.5.0 Duplicate RET parameter");
3899                         /* NOTREACHED */
3900                 }
3901                 e->e_flags |= EF_RET_PARAM;
3902                 if (sm_strcasecmp(vp, "hdrs") == 0)
3903                         e->e_flags |= EF_NO_BODY_RETN;
3904                 else if (sm_strcasecmp(vp, "full") != 0)
3905                 {
3906                         usrerr("501 5.5.2 Bad argument \"%s\" to RET", vp);
3907                         /* NOTREACHED */
3908                 }
3909                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
3910         }
3911 #if SASL
3912         else if (sm_strcasecmp(kp, "auth") == 0)
3913         {
3914                 int len;
3915                 char *q;
3916                 char *auth_param;       /* the value of the AUTH=x */
3917                 bool saveQuickAbort = QuickAbort;
3918                 bool saveSuprErrs = SuprErrs;
3919                 bool saveExitStat = ExitStat;
3920
3921                 if (vp == NULL)
3922                 {
3923                         usrerr("501 5.5.2 AUTH= requires a value");
3924                         /* NOTREACHED */
3925                 }
3926                 if (e->e_auth_param != NULL)
3927                 {
3928                         usrerr("501 5.5.0 Duplicate AUTH parameter");
3929                         /* NOTREACHED */
3930                 }
3931                 if ((q = strchr(vp, ' ')) != NULL)
3932                         len = q - vp + 1;
3933                 else
3934                         len = strlen(vp) + 1;
3935                 auth_param = xalloc(len);
3936                 (void) sm_strlcpy(auth_param, vp, len);
3937                 if (!xtextok(auth_param))
3938                 {
3939                         usrerr("501 5.5.4 Syntax error in AUTH parameter value");
3940                         /* just a warning? */
3941                         /* NOTREACHED */
3942                 }
3943
3944                 /* XXX define this always or only if trusted? */
3945                 macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
3946                           auth_param);
3947
3948                 /*
3949                 **  call Strust_auth to find out whether
3950                 **  auth_param is acceptable (trusted)
3951                 **  we shouldn't trust it if not authenticated
3952                 **  (required by RFC, leave it to ruleset?)
3953                 */
3954
3955                 SuprErrs = true;
3956                 QuickAbort = false;
3957                 if (strcmp(auth_param, "<>") != 0 &&
3958                      (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM,
3959                               9, NULL, NOQID) != EX_OK || Errors > 0))
3960                 {
3961                         if (tTd(95, 8))
3962                         {
3963                                 q = e->e_auth_param;
3964                                 sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
3965                                         auth_param, (q == NULL) ? "" : q);
3966                         }
3967
3968                         /* not trusted */
3969                         e->e_auth_param = "<>";
3970 # if _FFR_AUTH_PASSING
3971                         macdefine(&BlankEnvelope.e_macro, A_PERM,
3972                                   macid("{auth_author}"), NULL);
3973 # endif /* _FFR_AUTH_PASSING */
3974                 }
3975                 else
3976                 {
3977                         if (tTd(95, 8))
3978                                 sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
3979                         e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
3980                                                             auth_param);
3981                 }
3982                 sm_free(auth_param); /* XXX */
3983
3984                 /* reset values */
3985                 Errors = 0;
3986                 QuickAbort = saveQuickAbort;
3987                 SuprErrs = saveSuprErrs;
3988                 ExitStat = saveExitStat;
3989         }
3990 #endif /* SASL */
3991 #define PRTCHAR(c)      ((isascii(c) && isprint(c)) ? (c) : '?')
3992
3993         /*
3994         **  "by" is only accepted if DeliverByMin >= 0.
3995         **  We maybe could add this to the list of server_features.
3996         */
3997
3998         else if (sm_strcasecmp(kp, "by") == 0 && DeliverByMin >= 0)
3999         {
4000                 char *s;
4001
4002                 if (vp == NULL)
4003                 {
4004                         usrerr("501 5.5.2 BY= requires a value");
4005                         /* NOTREACHED */
4006                 }
4007                 errno = 0;
4008                 e->e_deliver_by = strtol(vp, &s, 10);
4009                 if (e->e_deliver_by == LONG_MIN ||
4010                     e->e_deliver_by == LONG_MAX ||
4011                     e->e_deliver_by > 999999999l ||
4012                     e->e_deliver_by < -999999999l)
4013                 {
4014                         usrerr("501 5.5.2 BY=%s out of range", vp);
4015                         /* NOTREACHED */
4016                 }
4017                 if (s == NULL || *s != ';')
4018                 {
4019                         usrerr("501 5.5.2 BY= missing ';'");
4020                         /* NOTREACHED */
4021                 }
4022                 e->e_dlvr_flag = 0;
4023                 ++s;    /* XXX: spaces allowed? */
4024                 SKIP_SPACE(s);
4025                 switch (tolower(*s))
4026                 {
4027                   case 'n':
4028                         e->e_dlvr_flag = DLVR_NOTIFY;
4029                         break;
4030                   case 'r':
4031                         e->e_dlvr_flag = DLVR_RETURN;
4032                         if (e->e_deliver_by <= 0)
4033                         {
4034                                 usrerr("501 5.5.4 mode R requires BY time > 0");
4035                                 /* NOTREACHED */
4036                         }
4037                         if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
4038                             e->e_deliver_by < DeliverByMin)
4039                         {
4040                                 usrerr("555 5.5.2 time %ld less than %ld",
4041                                         e->e_deliver_by, (long) DeliverByMin);
4042                                 /* NOTREACHED */
4043                         }
4044                         break;
4045                   default:
4046                         usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
4047                         /* NOTREACHED */
4048                 }
4049                 ++s;    /* XXX: spaces allowed? */
4050                 SKIP_SPACE(s);
4051                 switch (tolower(*s))
4052                 {
4053                   case 't':
4054                         e->e_dlvr_flag |= DLVR_TRACE;
4055                         break;
4056                   case '\0':
4057                         break;
4058                   default:
4059                         usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
4060                         /* NOTREACHED */
4061                 }
4062
4063                 /* XXX: check whether more characters follow? */
4064         }
4065         else
4066         {
4067                 usrerr("555 5.5.4 %s parameter unrecognized", kp);
4068                 /* NOTREACHED */
4069         }
4070 }
4071 /*
4072 **  RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
4073 **
4074 **      Parameters:
4075 **              a -- the address corresponding to the To: parameter.
4076 **              kp -- the parameter key.
4077 **              vp -- the value of that parameter.
4078 **              e -- the envelope.
4079 **
4080 **      Returns:
4081 **              none.
4082 */
4083
4084 static void
4085 rcpt_esmtp_args(a, kp, vp, e)
4086         ADDRESS *a;
4087         char *kp;
4088         char *vp;
4089         ENVELOPE *e;
4090 {
4091         if (sm_strcasecmp(kp, "notify") == 0)
4092         {
4093                 char *p;
4094
4095                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
4096                 {
4097                         usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
4098                         /* NOTREACHED */
4099                 }
4100                 if (vp == NULL)
4101                 {
4102                         usrerr("501 5.5.2 NOTIFY requires a value");
4103                         /* NOTREACHED */
4104                 }
4105                 a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
4106                 a->q_flags |= QHASNOTIFY;
4107                 macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
4108
4109                 if (sm_strcasecmp(vp, "never") == 0)
4110                         return;
4111                 for (p = vp; p != NULL; vp = p)
4112                 {
4113                         p = strchr(p, ',');
4114                         if (p != NULL)
4115                                 *p++ = '\0';
4116                         if (sm_strcasecmp(vp, "success") == 0)
4117                                 a->q_flags |= QPINGONSUCCESS;
4118                         else if (sm_strcasecmp(vp, "failure") == 0)
4119                                 a->q_flags |= QPINGONFAILURE;
4120                         else if (sm_strcasecmp(vp, "delay") == 0)
4121                                 a->q_flags |= QPINGONDELAY;
4122                         else
4123                         {
4124                                 usrerr("501 5.5.4 Bad argument \"%s\"  to NOTIFY",
4125                                         vp);
4126                                 /* NOTREACHED */
4127                         }
4128                 }
4129         }
4130         else if (sm_strcasecmp(kp, "orcpt") == 0)
4131         {
4132                 if (bitset(PRIV_NORECEIPTS, PrivacyFlags))
4133                 {
4134                         usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
4135                         /* NOTREACHED */
4136                 }
4137                 if (vp == NULL)
4138                 {
4139                         usrerr("501 5.5.2 ORCPT requires a value");
4140                         /* NOTREACHED */
4141                 }
4142                 if (strchr(vp, ';') == NULL || !xtextok(vp))
4143                 {
4144                         usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
4145                         /* NOTREACHED */
4146                 }
4147                 if (a->q_orcpt != NULL)
4148                 {
4149                         usrerr("501 5.5.0 Duplicate ORCPT parameter");
4150                         /* NOTREACHED */
4151                 }
4152                 a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
4153         }
4154         else
4155         {
4156                 usrerr("555 5.5.4 %s parameter unrecognized", kp);
4157                 /* NOTREACHED */
4158         }
4159 }
4160 /*
4161 **  PRINTVRFYADDR -- print an entry in the verify queue
4162 **
4163 **      Parameters:
4164 **              a -- the address to print.
4165 **              last -- set if this is the last one.
4166 **              vrfy -- set if this is a VRFY command.
4167 **
4168 **      Returns:
4169 **              none.
4170 **
4171 **      Side Effects:
4172 **              Prints the appropriate 250 codes.
4173 */
4174 #define OFFF    (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */
4175
4176 static void
4177 printvrfyaddr(a, last, vrfy)
4178         register ADDRESS *a;
4179         bool last;
4180         bool vrfy;
4181 {
4182         char fmtbuf[30];
4183
4184         if (vrfy && a->q_mailer != NULL &&
4185             !bitnset(M_VRFY250, a->q_mailer->m_flags))
4186                 (void) sm_strlcpy(fmtbuf, "252", sizeof fmtbuf);
4187         else
4188                 (void) sm_strlcpy(fmtbuf, "250", sizeof fmtbuf);
4189         fmtbuf[3] = last ? ' ' : '-';
4190         (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4);
4191         if (a->q_fullname == NULL)
4192         {
4193                 if ((a->q_mailer == NULL ||
4194                      a->q_mailer->m_addrtype == NULL ||
4195                      sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
4196                     strchr(a->q_user, '@') == NULL)
4197                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
4198                                        sizeof fmtbuf - OFFF);
4199                 else
4200                         (void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
4201                                        sizeof fmtbuf - OFFF);
4202                 message(fmtbuf, a->q_user, MyHostName);
4203         }
4204         else
4205         {
4206                 if ((a->q_mailer == NULL ||
4207                      a->q_mailer->m_addrtype == NULL ||
4208                      sm_strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) &&
4209                     strchr(a->q_user, '@') == NULL)
4210                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
4211                                        sizeof fmtbuf - OFFF);
4212                 else
4213                         (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
4214                                        sizeof fmtbuf - OFFF);
4215                 message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
4216         }
4217 }
4218
4219 #if SASL
4220 /*
4221 **  SASLMECHS -- get list of possible AUTH mechanisms
4222 **
4223 **      Parameters:
4224 **              conn -- SASL connection info.
4225 **              mechlist -- output parameter for list of mechanisms.
4226 **
4227 **      Returns:
4228 **              number of mechs.
4229 */
4230
4231 static int
4232 saslmechs(conn, mechlist)
4233         sasl_conn_t *conn;
4234         char **mechlist;
4235 {
4236         int len, num, result;
4237
4238         /* "user" is currently unused */
4239 # if SASL >= 20000
4240         result = sasl_listmech(conn, NULL,
4241                                "", " ", "", (const char **) mechlist,
4242                                (unsigned int *)&len, &num);
4243 # else /* SASL >= 20000 */
4244         result = sasl_listmech(conn, "user", /* XXX */
4245                                "", " ", "", mechlist,
4246                                (unsigned int *)&len, (unsigned int *)&num);
4247 # endif /* SASL >= 20000 */
4248         if (result != SASL_OK)
4249         {
4250                 if (LogLevel > 9)
4251                         sm_syslog(LOG_WARNING, NOQID,
4252                                   "AUTH error: listmech=%d, num=%d",
4253                                   result, num);
4254                 num = 0;
4255         }
4256         if (num > 0)
4257         {
4258                 if (LogLevel > 11)
4259                         sm_syslog(LOG_INFO, NOQID,
4260                                   "AUTH: available mech=%s, allowed mech=%s",
4261                                   *mechlist, AuthMechanisms);
4262                 *mechlist = intersect(AuthMechanisms, *mechlist, NULL);
4263         }
4264         else
4265         {
4266                 *mechlist = NULL;       /* be paranoid... */
4267                 if (result == SASL_OK && LogLevel > 9)
4268                         sm_syslog(LOG_WARNING, NOQID,
4269                                   "AUTH warning: no mechanisms");
4270         }
4271         return num;
4272 }
4273
4274 # if SASL >= 20000
4275 /*
4276 **  PROXY_POLICY -- define proxy policy for AUTH
4277 **
4278 **      Parameters:
4279 **              conn -- unused.
4280 **              context -- unused.
4281 **              requested_user -- authorization identity.
4282 **              rlen -- authorization identity length.
4283 **              auth_identity -- authentication identity.
4284 **              alen -- authentication identity length.
4285 **              def_realm -- default user realm.
4286 **              urlen -- user realm length.
4287 **              propctx -- unused.
4288 **
4289 **      Returns:
4290 **              ok?
4291 **
4292 **      Side Effects:
4293 **              sets {auth_authen} macro.
4294 */
4295
4296 int
4297 proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
4298              def_realm, urlen, propctx)
4299         sasl_conn_t *conn;
4300         void *context;
4301         const char *requested_user;
4302         unsigned rlen;
4303         const char *auth_identity;
4304         unsigned alen;
4305         const char *def_realm;
4306         unsigned urlen;
4307         struct propctx *propctx;
4308 {
4309         if (auth_identity == NULL)
4310                 return SASL_FAIL;
4311
4312         macdefine(&BlankEnvelope.e_macro, A_TEMP,
4313                   macid("{auth_authen}"), (char *) auth_identity);
4314
4315         return SASL_OK;
4316 }
4317 # else /* SASL >= 20000 */
4318
4319 /*
4320 **  PROXY_POLICY -- define proxy policy for AUTH
4321 **
4322 **      Parameters:
4323 **              context -- unused.
4324 **              auth_identity -- authentication identity.
4325 **              requested_user -- authorization identity.
4326 **              user -- allowed user (output).
4327 **              errstr -- possible error string (output).
4328 **
4329 **      Returns:
4330 **              ok?
4331 */
4332
4333 int
4334 proxy_policy(context, auth_identity, requested_user, user, errstr)
4335         void *context;
4336         const char *auth_identity;
4337         const char *requested_user;
4338         const char **user;
4339         const char **errstr;
4340 {
4341         if (user == NULL || auth_identity == NULL)
4342                 return SASL_FAIL;
4343         *user = newstr(auth_identity);
4344         return SASL_OK;
4345 }
4346 # endif /* SASL >= 20000 */
4347 #endif /* SASL */
4348
4349 #if STARTTLS
4350 /*
4351 **  INITSRVTLS -- initialize server side TLS
4352 **
4353 **      Parameters:
4354 **              tls_ok -- should tls initialization be done?
4355 **
4356 **      Returns:
4357 **              succeeded?
4358 **
4359 **      Side Effects:
4360 **              sets tls_ok_srv which is a static variable in this module.
4361 **              Do NOT remove assignments to it!
4362 */
4363
4364 bool
4365 initsrvtls(tls_ok)
4366         bool tls_ok;
4367 {
4368         if (!tls_ok)
4369                 return false;
4370
4371         /* do NOT remove assignment */
4372         tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, true, SrvCertFile,
4373                              SrvKeyFile, CACertPath, CACertFile, DHParams);
4374         return tls_ok_srv;
4375 }
4376 #endif /* STARTTLS */
4377 /*
4378 **  SRVFEATURES -- get features for SMTP server
4379 **
4380 **      Parameters:
4381 **              e -- envelope (should be session context).
4382 **              clientname -- name of client.
4383 **              features -- default features for this invocation.
4384 **
4385 **      Returns:
4386 **              server features.
4387 */
4388
4389 /* table with options: it uses just one character, how about strings? */
4390 static struct
4391 {
4392         char            srvf_opt;
4393         unsigned int    srvf_flag;
4394 } srv_feat_table[] =
4395 {
4396         { 'A',  SRV_OFFER_AUTH  },
4397         { 'B',  SRV_OFFER_VERB  },
4398         { 'C',  SRV_REQ_SEC     },
4399         { 'D',  SRV_OFFER_DSN   },
4400         { 'E',  SRV_OFFER_ETRN  },
4401         { 'L',  SRV_REQ_AUTH    },
4402 #if PIPELINING
4403 # if _FFR_NO_PIPE
4404         { 'N',  SRV_NO_PIPE     },
4405 # endif /* _FFR_NO_PIPE */
4406         { 'P',  SRV_OFFER_PIPE  },
4407 #endif /* PIPELINING */
4408         { 'R',  SRV_VRFY_CLT    },      /* same as V; not documented */
4409         { 'S',  SRV_OFFER_TLS   },
4410 /*      { 'T',  SRV_TMP_FAIL    },      */
4411         { 'V',  SRV_VRFY_CLT    },
4412         { 'X',  SRV_OFFER_EXPN  },
4413 /*      { 'Y',  SRV_OFFER_VRFY  },      */
4414         { '\0', SRV_NONE        }
4415 };
4416
4417 static unsigned int
4418 srvfeatures(e, clientname, features)
4419         ENVELOPE *e;
4420         char *clientname;
4421         unsigned int features;
4422 {
4423         int r, i, j;
4424         char **pvp, c, opt;
4425         char pvpbuf[PSBUFSIZE];
4426
4427         pvp = NULL;
4428         r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
4429                   sizeof(pvpbuf));
4430         if (r != EX_OK)
4431                 return features;
4432         if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
4433                 return features;
4434         if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
4435                 return SRV_TMP_FAIL;
4436
4437         /*
4438         **  General rule (see sendmail.h, d_flags):
4439         **  lower case: required/offered, upper case: Not required/available
4440         **
4441         **  Since we can change some features per daemon, we have both
4442         **  cases here: turn on/off a feature.
4443         */
4444
4445         for (i = 1; pvp[i] != NULL; i++)
4446         {
4447                 c = pvp[i][0];
4448                 j = 0;
4449                 for (;;)
4450                 {
4451                         if ((opt = srv_feat_table[j].srvf_opt) == '\0')
4452                         {
4453                                 if (LogLevel > 9)
4454                                         sm_syslog(LOG_WARNING, e->e_id,
4455                                                   "srvfeatures: unknown feature %s",
4456                                                   pvp[i]);
4457                                 break;
4458                         }
4459                         if (c == opt)
4460                         {
4461                                 features &= ~(srv_feat_table[j].srvf_flag);
4462                                 break;
4463                         }
4464                         if (c == tolower(opt))
4465                         {
4466                                 features |= srv_feat_table[j].srvf_flag;
4467                                 break;
4468                         }
4469                         ++j;
4470                 }
4471         }
4472         return features;
4473 }
4474
4475 /*
4476 **  HELP -- implement the HELP command.
4477 **
4478 **      Parameters:
4479 **              topic -- the topic we want help for.
4480 **              e -- envelope.
4481 **
4482 **      Returns:
4483 **              none.
4484 **
4485 **      Side Effects:
4486 **              outputs the help file to message output.
4487 */
4488 #define HELPVSTR        "#vers  "
4489 #define HELPVERSION     2
4490
4491 void
4492 help(topic, e)
4493         char *topic;
4494         ENVELOPE *e;
4495 {
4496         register SM_FILE_T *hf;
4497         register char *p;
4498         int len;
4499         bool noinfo;
4500         bool first = true;
4501         long sff = SFF_OPENASROOT|SFF_REGONLY;
4502         char buf[MAXLINE];
4503         char inp[MAXLINE];
4504         static int foundvers = -1;
4505         extern char Version[];
4506
4507         if (DontLockReadFiles)
4508                 sff |= SFF_NOLOCK;
4509         if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
4510                 sff |= SFF_SAFEDIRPATH;
4511
4512         if (HelpFile == NULL ||
4513             (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
4514         {
4515                 /* no help */
4516                 errno = 0;
4517                 message("502 5.3.0 Sendmail %s -- HELP not implemented",
4518                         Version);
4519                 return;
4520         }
4521
4522         if (topic == NULL || *topic == '\0')
4523         {
4524                 topic = "smtp";
4525                 noinfo = false;
4526         }
4527         else
4528         {
4529                 makelower(topic);
4530                 noinfo = true;
4531         }
4532
4533         len = strlen(topic);
4534
4535         while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof buf) != NULL)
4536         {
4537                 if (buf[0] == '#')
4538                 {
4539                         if (foundvers < 0 &&
4540                             strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
4541                         {
4542                                 int h;
4543
4544                                 if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
4545                                                  &h) == 1)
4546                                         foundvers = h;
4547                         }
4548                         continue;
4549                 }
4550                 if (strncmp(buf, topic, len) == 0)
4551                 {
4552                         if (first)
4553                         {
4554                                 first = false;
4555
4556                                 /* print version if no/old vers# in file */
4557                                 if (foundvers < 2 && !noinfo)
4558                                         message("214-2.0.0 This is Sendmail version %s", Version);
4559                         }
4560                         p = strpbrk(buf, " \t");
4561                         if (p == NULL)
4562                                 p = buf + strlen(buf) - 1;
4563                         else
4564                                 p++;
4565                         fixcrlf(p, true);
4566                         if (foundvers >= 2)
4567                         {
4568                                 translate_dollars(p);
4569                                 expand(p, inp, sizeof inp, e);
4570                                 p = inp;
4571                         }
4572                         message("214-2.0.0 %s", p);
4573                         noinfo = false;
4574                 }
4575         }
4576
4577         if (noinfo)
4578                 message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
4579         else
4580                 message("214 2.0.0 End of HELP info");
4581
4582         if (foundvers != 0 && foundvers < HELPVERSION)
4583         {
4584                 if (LogLevel > 1)
4585                         sm_syslog(LOG_WARNING, e->e_id,
4586                                   "%s too old (require version %d)",
4587                                   HelpFile, HELPVERSION);
4588
4589                 /* avoid log next time */
4590                 foundvers = 0;
4591         }
4592
4593         (void) sm_io_close(hf, SM_TIME_DEFAULT);
4594 }
4595
4596 #if SASL
4597 /*
4598 **  RESET_SASLCONN -- reset SASL connection data
4599 **
4600 **      Parameters:
4601 **              conn -- SASL connection context
4602 **              hostname -- host name
4603 **              various connection data
4604 **
4605 **      Returns:
4606 **              SASL result
4607 */
4608
4609 static int
4610 reset_saslconn(sasl_conn_t ** conn, char *hostname,
4611 # if SASL >= 20000
4612                char *remoteip, char *localip,
4613                char *auth_id, sasl_ssf_t * ext_ssf)
4614 # else /* SASL >= 20000 */
4615                struct sockaddr_in * saddr_r, struct sockaddr_in * saddr_l,
4616                sasl_external_properties_t * ext_ssf)
4617 # endif /* SASL >= 20000 */
4618 {
4619         int result;
4620
4621         sasl_dispose(conn);
4622 # if SASL >= 20000
4623         result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
4624                                  NULL, 0, conn);
4625 # elif SASL > 10505
4626         /* use empty realm: only works in SASL > 1.5.5 */
4627         result = sasl_server_new("smtp", hostname, "", NULL, 0, conn);
4628 # else /* SASL >= 20000 */
4629         /* use no realm -> realm is set to hostname by SASL lib */
4630         result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
4631                                  conn);
4632 # endif /* SASL >= 20000 */
4633         if (result != SASL_OK)
4634                 return result;
4635
4636 # if SASL >= 20000
4637 #  if NETINET || NETINET6
4638         if (remoteip != NULL)
4639                 result = sasl_setprop(*conn, SASL_IPREMOTEPORT, remoteip);
4640         if (result != SASL_OK)
4641                 return result;
4642
4643         if (localip != NULL)
4644                 result = sasl_setprop(*conn, SASL_IPLOCALPORT, localip);
4645         if (result != SASL_OK)
4646                 return result;
4647 #  endif /* NETINET || NETINET6 */
4648
4649         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
4650         if (result != SASL_OK)
4651                 return result;
4652
4653         result = sasl_setprop(*conn, SASL_AUTH_EXTERNAL, auth_id);
4654         if (result != SASL_OK)
4655                 return result;
4656 # else /* SASL >= 20000 */
4657 #  if NETINET
4658         if (saddr_r != NULL)
4659                 result = sasl_setprop(*conn, SASL_IP_REMOTE, saddr_r);
4660         if (result != SASL_OK)
4661                 return result;
4662
4663         if (saddr_l != NULL)
4664                 result = sasl_setprop(*conn, SASL_IP_LOCAL, saddr_l);
4665         if (result != SASL_OK)
4666                 return result;
4667 #  endif /* NETINET */
4668
4669         result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
4670         if (result != SASL_OK)
4671                 return result;
4672 # endif /* SASL >= 20000 */
4673         return SASL_OK;
4674 }
4675 #endif /* SASL */