source: trunk/third/sendmail/sendmail/srvrsmtp.c @ 22421

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