2 * Copyright (c) 1998-2010, 2012-2014,2021-2024 Proofpoint, Inc. and its suppliers.
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.
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.
16 # include <libmilter/mfapi.h>
17 # include <libmilter/mfdef.h>
20 SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.1016 2013-11-22 20:51:56 ca Exp $")
22 #include <sm/sendmail.h>
24 # include <sm/ixlen.h>
34 # define ENC64LEN(l) (((l) + 2) * 4 / 3 + 1)
35 static int saslmechs __P((sasl_conn_t *, char **));
38 # include <openssl/err.h>
40 static SSL_CTX *srv_ctx = NULL; /* TLS server context */
41 static SSL *srv_ssl = NULL; /* per connection context */
42 static tlsi_ctx_T tlsi_ctx; /* TLS information context */
44 static bool tls_ok_srv = false;
46 # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
47 bitset(SRV_VRFY_CLT, features))
51 static bool NotFirstDelivery = false;
55 #define SRV_NONE 0x00000000 /* none... */
56 #define SRV_OFFER_TLS 0x00000001 /* offer STARTTLS */
57 #define SRV_VRFY_CLT 0x00000002 /* request a cert */
58 #define SRV_OFFER_AUTH 0x00000004 /* offer AUTH */
59 #define SRV_OFFER_ETRN 0x00000008 /* offer ETRN */
60 #define SRV_OFFER_VRFY 0x00000010 /* offer VRFY (not yet used) */
61 #define SRV_OFFER_EXPN 0x00000020 /* offer EXPN */
62 #define SRV_OFFER_VERB 0x00000040 /* offer VERB */
63 #define SRV_OFFER_DSN 0x00000080 /* offer DSN */
65 # define SRV_OFFER_PIPE 0x00000100 /* offer PIPELINING */
67 # define SRV_NO_PIPE 0x00000200 /* disable PIPELINING, sleep if used */
69 #endif /* PIPELINING */
70 #define SRV_REQ_AUTH 0x00000400 /* require AUTH */
71 #define SRV_REQ_SEC 0x00000800 /* require security - equiv to AuthOptions=p */
72 #define SRV_TMP_FAIL 0x00001000 /* ruleset caused a temporary failure */
74 # define SRV_OFFER_EAI 0x00002000 /* offer SMTPUTF8 */
76 #define SRV_NO_HTTP_CMD 0x00004000 /* always reject HTTP commands */
77 #define SRV_BAD_PIPELINE 0x00008000 /* reject bad pipelining (see comment below) */
78 #define SRV_REQ_CRLF 0x00010000 /* require CRLF as EOL */
79 #define SRV_BARE_LF_421 0x00020000 /* bare LF - drop connection */
80 #define SRV_BARE_CR_421 0x00040000 /* bare CR - drop connection */
81 #define SRV_BARE_LF_SP 0x00080000
82 #define SRV_BARE_CR_SP 0x00100000
84 static unsigned long srvfeatures __P((ENVELOPE *, char *, unsigned long));
86 #define STOP_ATTACK ((time_t) -1)
87 static time_t checksmtpattack __P((volatile unsigned int *, unsigned int,
88 bool, char *, ENVELOPE *));
89 static void printvrfyaddr __P((ADDRESS *, bool, bool));
90 static char *skipword __P((char *volatile, char *));
91 static void setup_smtpd_io __P((void));
92 static struct timeval *channel_readable __P((SM_FILE_T *, int));
95 # ifndef MAX_AUTH_USER_LEN
96 # define MAX_AUTH_USER_LEN 256
98 # ifndef MAX_AUTH_LOG_LEN
99 # define MAX_AUTH_LOG_LEN 64
101 static void get_sasl_user __P((char *, unsigned int, const char *, char *out, size_t));
102 # define RESET_AUTH_FAIL_LOG_USER \
105 (void) memset(auth_user, 0, sizeof(auth_user)); \
106 (void) memset(auth_user_tmp, 0, sizeof(auth_user_tmp)); \
109 # define SET_AUTH_USER_TMP(s, len) \
112 auth_user_len = SM_MIN(len, MAX_AUTH_USER_LEN-1); \
113 (void) memcpy(auth_user_tmp, s, auth_user_len); \
115 # define SET_AUTH_USER \
116 get_sasl_user(auth_user_tmp, auth_user_len, auth_type, auth_user, sizeof(auth_user))
117 # define SET_AUTH_USER_CONDITIONALLY \
118 if ('\0' == auth_user[0]) \
120 # define LOG_AUTH_FAIL_USER ", user=", (int)MAX_AUTH_LOG_LEN, auth_user
122 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
123 char *_remoteip, char *_localip,
124 char *_auth_id, sasl_ssf_t *_ext_ssf));
126 # define RESET_SASLCONN \
129 RESET_AUTH_FAIL_LOG_USER; \
130 result = reset_saslconn(&conn, AuthRealm, remoteip, \
131 localip, auth_id, &ext_ssf); \
132 if (result != SASL_OK) \
136 # else /* SASL >= 20000 */
137 static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname,
138 struct sockaddr_in *_saddr_r,
139 struct sockaddr_in *_saddr_l,
140 sasl_external_properties_t *_ext_ssf));
141 # define RESET_SASLCONN \
144 RESET_AUTH_FAIL_LOG_USER; \
145 result = reset_saslconn(&conn, AuthRealm, &saddr_r, \
146 &saddr_l, &ext_ssf); \
147 if (result != SASL_OK) \
151 # endif /* SASL >= 20000 */
154 #if !defined(RESET_AUTH_FAIL_LOG_USER)
155 # define RESET_AUTH_FAIL_LOG_USER
158 extern ENVELOPE BlankEnvelope;
164 (void) sm_snprintf(buf, sizeof(buf), "%d", \
165 BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \
166 ? n_badrcpts - 1 : n_badrcpts); \
167 macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \
170 #define SKIP_SPACE(s) while (SM_ISSPACE(*s)) \
175 ** ADDR_IS_ASCII -- check whether a string (address) is ASCII
181 ** TRUE iff str is non-NULL and points to only ASCII
188 while (str != NULL && *str != '\0' && isascii((unsigned char)*str))
190 return (str != NULL && *str == '\0');
194 ** STR_IS_PRINT -- check whether a string is printable ASCII
200 ** TRUE iff str is non-NULL and points to only printable ASCII
207 while (str != NULL && *str != '\0' && *str >= ' ' && (unsigned char)*str < 127)
209 return (str != NULL && *str == '\0');
213 # define CHECK_UTF8_ADDR(a, q) \
217 if (addr_is_ascii(a)) \
221 if (!e->e_smtputf8) \
222 q = "553 5.6.7 Address requires SMTPUTF8"; \
226 dequote_internal_chars(a, str, sizeof(str)); \
227 if (!utf8_valid(str, strlen(str)) && SMTP_UTF8 <= 1) \
228 q = "553 5.6.7 Address not valid UTF8"; \
234 ** PARSE_ESMTP_ARGS -- parse ESMTP arguments (for MAIL, RCPT)
238 ** addr_st -- address (RCPT only)
240 ** delimptr -- current position in read buffer
241 ** which -- MAIL/RCPT
242 ** args -- arguments (output)
243 ** esmtp_args -- function to process a single ESMTP argument
250 parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args)
257 esmtp_args_F esmtp_args;
265 while (p != NULL && *p != '\0')
271 /* locate the beginning of the keyword */
277 /* skip to the value portion */
278 while ((isascii(*p) && isalnum(*p)) || *p == '-')
286 /* skip to the end of the value */
287 while (*p != '\0' && *p != ' ' &&
288 !(isascii(*p) && iscntrl(*p)) &&
297 sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp,
298 vp == NULL ? "<null>" : vp);
300 esmtp_args(addr_st, kp, vp, e);
306 if (argno >= MAXSMTPARGS - 1)
307 usrerr("501 5.5.4 Too many parameters");
318 ** ADDRCPT -- Add a rcpt to sendq list
322 ** sendq -- a pointer to the head of a queue to put
323 ** these people into.
324 ** e -- the envelope in which to add these recipients.
327 ** The number of addresses added to the list.
331 addrcpt(rcpt, sendq, e)
340 SM_REQUIRE(rcpt != NULL);
341 SM_REQUIRE(sendq != NULL);
342 SM_REQUIRE(e != NULL);
345 sm_dprintf("addrcpt: rcpt=%s\n", rcpt);
350 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), "e b");
351 /* XXX rcpt must be [i] */
352 a = parseaddr(rcpt, NULLADDR, RF_COPYALL, ' ', NULL, e, true);
356 a->q_flags &= ~Q_PINGFLAGS;
357 a->q_flags |= QINTBCC;
360 /* disable alias expansion? */
361 a = recipient(a, sendq, 0, e);
366 macdefine(&e->e_macro, A_PERM, macid("{addr_type}"), NULL);
370 sm_dprintf("addrcpt: rcpt=%s, flags=%#lx\n", rcpt,
371 a != NULL ? a->q_flags : 0);
377 ** ADDBCC -- Maybe create a copy of an e-mail
381 ** e -- the envelope.
387 ** rscheck() can trigger an "exception"
396 char *newrcpt, empty[1];
405 nobcc = rscheck("bcc", a->q_paddr, NULL, e, RSF_ADDR, 12, NULL, NOQID,
408 sm_dprintf("addbcc: nobcc=%d, Errors=%d, newrcpt=<%s>\n", nobcc, Errors, newrcpt);
409 if (nobcc != EX_OK || Errors > 0 || *newrcpt == '\0')
412 (void) addrcpt(newrcpt, &e->e_sendqueue, e);
415 #else /* _FFR_ADD_BCC */
416 # define addbcc(a, e)
417 #endif /* _FFR_ADD_BCC */
421 ** RCPTMODS -- Perform rcpt modifications if requested
424 ** rcpt -- current RCPT
425 ** e -- the envelope.
438 SM_REQUIRE(rcpt != NULL);
439 SM_REQUIRE(e != NULL);
441 fl = macvalue(macid("{rcpt_flags}"), e);
445 sm_dprintf("rcptmods: rcpt=%s, flags=%s\n", rcpt->q_paddr, fl);
448 for ( ; *fl != '\0'; ++fl)
453 rcpt->q_flags &= ~Q_PINGFLAGS;
454 rcpt->q_flags |= QINTBCC;
455 rcpt->q_owner = "<>";
459 rcpt->q_flags &= ~Q_PINGFLAGS;
460 rcpt->q_owner = "<>";
464 rcpt->q_flags |= QDYNMAILER;
465 newmodmailer(rcpt, *fl);
469 sm_syslog(LOG_INFO, e->e_id,
470 "rcpt=%s, rcpt_flags=%s, status=unknown",
476 /* reset macro to avoid confusion later on */
477 macdefine(&e->e_macro, A_PERM, macid("{rcpt_flags}"), NULL);
480 #else /* _FFR_RCPTFLAGS */
481 # define rcptmods(a, e)
482 #endif /* _FFR_RCPTFLAGS */
487 ** SEP_ARGS -- separate address and argument string for MAIL/RCPT command
490 ** args -- arguments (converted to and from internal format)
491 ** orig -- string after command (original data)
492 ** id -- envelope id (for logging only)
493 ** addr -- for logging only: address (original data)
499 static void sep_args __P((char *, char *, const char *, const char *));
502 sep_args(args, orig, id, addr)
515 sm_syslog(LOG_ERR, id,
516 "ERROR=ARGS_NOT_FOUND, address='%s', rest='%s', orig='%s', strlen(rest)=%d, strlen(orig)=%d",
517 addr, args, orig, lr, lo);
521 q = orig + (lo - lr);
522 if (!(q > orig && *--q == ' '))
524 sm_syslog(LOG_INFO, id,
525 "ERROR=ARGS_DO_NOT_MATCH, address='%s', rest='%s', orig='%s', q='%s', strlen(rest)=%d, strlen(orig)=%d, cmp=%d",
526 addr, args, orig, q, lr, lo, strcmp(args, q));
530 for (; q > orig && *q == ' '; q--)
533 #endif /* _FFR_8BITENVADDR */
536 ** CHANNEL_READBLE -- determine if data is readable from the SMTP channel
539 ** channel -- connect channel for reading
540 ** timeout -- how long to pause for data in milliseconds
543 ** timeval contained how long we waited if data detected,
547 static struct timeval *
548 channel_readable(channel, timeout)
552 struct timeval bp, ep; /* {begin,end} pause */
553 static struct timeval tp; /* total pause */
556 /* check if data is on the channel during the pause */
557 gettimeofday(&bp, NULL);
558 if ((eoftest = sm_io_getc(channel, timeout)) != SM_IO_EOF)
560 gettimeofday(&ep, NULL);
561 sm_io_ungetc(channel, SM_TIME_DEFAULT, eoftest);
562 timersub(&ep, &bp, &tp);
569 ** SMTP -- run the SMTP protocol.
572 ** nullserver -- if non-NULL, rejection message for
573 ** (almost) all SMTP commands.
574 ** d_flags -- daemon flags
575 ** e -- the envelope.
581 ** Reads commands from the input channel and processes them.
585 ** Notice: The smtp server doesn't have a session context like the client
586 ** side has (mci). Therefore some data (session oriented) is allocated
587 ** or assigned to the "wrong" structure (esp. STARTTLS, AUTH).
588 ** This should be fixed in a successor version.
593 char *cmd_name; /* command name */
594 int cmd_code; /* internal code, see below */
597 /* values for cmd_code */
598 #define CMDERROR 0 /* bad command */
599 #define CMDMAIL 1 /* mail -- designate sender */
600 #define CMDRCPT 2 /* rcpt -- designate recipient */
601 #define CMDDATA 3 /* data -- send message text */
602 #define CMDRSET 4 /* rset -- reset state */
603 #define CMDVRFY 5 /* vrfy -- verify address */
604 #define CMDEXPN 6 /* expn -- expand address */
605 #define CMDNOOP 7 /* noop -- do nothing */
606 #define CMDQUIT 8 /* quit -- close connection and die */
607 #define CMDHELO 9 /* helo -- be polite */
608 #define CMDHELP 10 /* help -- give usage info */
609 #define CMDEHLO 11 /* ehlo -- extended helo (RFC 1425) */
610 #define CMDETRN 12 /* etrn -- flush queue */
612 # define CMDAUTH 13 /* auth -- SASL authenticate */
615 # define CMDSTLS 14 /* STARTTLS -- start TLS session */
617 /* non-standard commands */
618 #define CMDVERB 17 /* verb -- go into verbose mode */
619 /* unimplemented commands from RFC 821 */
620 #define CMDUNIMPL 19 /* unimplemented rfc821 commands */
621 /* use this to catch and log "door handle" attempts on your system */
622 #define CMDLOGBOGUS 23 /* bogus command that should be logged */
623 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
624 #define CMDDBGQSHOW 24 /* showq -- show send queue */
625 #define CMDDBGDEBUG 25 /* debug -- set debug mode */
628 ** Note: If you change this list, remember to update 'helpfile'
631 static struct cmd CmdTab[] =
646 { "send", CMDUNIMPL },
647 { "saml", CMDUNIMPL },
648 { "soml", CMDUNIMPL },
649 { "turn", CMDUNIMPL },
651 { "auth", CMDAUTH, },
654 { "starttls", CMDSTLS, },
656 /* remaining commands are here only to trap and log attempts to use them */
657 { "showq", CMDDBGQSHOW },
658 { "debug", CMDDBGDEBUG },
659 { "wiz", CMDLOGBOGUS },
664 static char *CurSmtpClient; /* who's at the other end of channel */
666 #ifndef MAXBADCOMMANDS
667 # define MAXBADCOMMANDS 25 /* maximum number of bad commands */
669 #ifndef MAXHELOCOMMANDS
670 # define MAXHELOCOMMANDS 3 /* max HELO/EHLO commands before slowdown */
672 #ifndef MAXVRFYCOMMANDS
673 # define MAXVRFYCOMMANDS 6 /* max VRFY/EXPN commands before slowdown */
675 #ifndef MAXETRNCOMMANDS
676 # define MAXETRNCOMMANDS 8 /* max ETRN commands before slowdown */
679 # define MAXTIMEOUT (4 * 60) /* max timeout for bad commands */
683 ** Maximum shift value to compute timeout for bad commands.
684 ** This introduces an upper limit of 2^MAXSHIFT for the timeout.
691 # error "MAXSHIFT > 31 is invalid"
695 #if MAXBADCOMMANDS > 0
696 # define STOP_IF_ATTACK(r) do \
698 if ((r) == STOP_ATTACK) \
702 #else /* MAXBADCOMMANDS > 0 */
703 # define STOP_IF_ATTACK(r) r
704 #endif /* MAXBADCOMMANDS > 0 */
708 static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp",
709 "@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $");
714 bool sm_gotmail; /* mail command received */
715 unsigned int sm_nrcpts; /* number of successful RCPT commands */
719 bool sm_milterlist; /* any filters in the list? */
720 milters_T sm_milters;
722 /* e_nrcpts from envelope before recipient() call */
723 unsigned int sm_e_nrcpts_orig;
725 char *sm_quarmsg; /* carry quarantining across messages */
728 static bool smtp_data __P((SMTP_T *, ENVELOPE *, bool));
730 #define MSG_TEMPFAIL "451 4.3.2 Please try again later"
733 # define MILTER_ABORT(e) milter_abort((e))
735 # define MILTER_REPLY(str) \
737 int savelogusrerrs = LogUsrErrs; \
739 milter_cmd_fail = true; \
742 case SMFIR_SHUTDOWN: \
743 if (MilterLogLevel > 3) \
745 sm_syslog(LOG_INFO, e->e_id, \
746 "Milter: %s=%s, reject=421, errormode=4", \
748 LogUsrErrs = false; \
751 bool tsave = QuickAbort; \
753 QuickAbort = false; \
754 usrerr("421 4.3.0 closing connection"); \
755 QuickAbort = tsave; \
756 e->e_sendqueue = NULL; \
760 case SMFIR_REPLYCODE: \
761 if (MilterLogLevel > 3) \
763 sm_syslog(LOG_INFO, e->e_id, \
764 "Milter: %s=%s, reject=%s", \
765 str, addr, response); \
766 LogUsrErrs = false; \
768 if (strncmp(response, "421 ", 4) == 0 \
769 || strncmp(response, "421-", 4) == 0) \
771 bool tsave = QuickAbort; \
773 QuickAbort = false; \
775 QuickAbort = tsave; \
776 e->e_sendqueue = NULL; \
784 if (MilterLogLevel > 3) \
786 sm_syslog(LOG_INFO, e->e_id, \
787 "Milter: %s=%s, reject=550 5.7.1 Command rejected", \
789 LogUsrErrs = false; \
791 usrerr("550 5.7.1 Command rejected"); \
794 case SMFIR_DISCARD: \
795 if (MilterLogLevel > 3) \
796 sm_syslog(LOG_INFO, e->e_id, \
797 "Milter: %s=%s, discard", \
799 e->e_flags |= EF_DISCARD; \
800 milter_cmd_fail = false; \
803 case SMFIR_TEMPFAIL: \
804 if (MilterLogLevel > 3) \
806 sm_syslog(LOG_INFO, e->e_id, \
807 "Milter: %s=%s, reject=%s", \
808 str, addr, MSG_TEMPFAIL); \
809 LogUsrErrs = false; \
811 usrerr(MSG_TEMPFAIL); \
814 milter_cmd_fail = false; \
817 LogUsrErrs = savelogusrerrs; \
818 if (response != NULL) \
819 sm_free(response); /* XXX */ \
823 # define MILTER_ABORT(e)
826 /* clear all SMTP state (for HELO/EHLO/RSET) */
827 #define CLEAR_STATE(cmd) \
830 /* abort milter filters */ \
833 if (smtp.sm_nrcpts > 0) \
835 logundelrcpts(e, cmd, 10, false); \
836 smtp.sm_nrcpts = 0; \
837 macdefine(&e->e_macro, A_PERM, \
838 macid("{nrcpts}"), "0"); \
841 e->e_sendqueue = NULL; \
842 e->e_flags |= EF_CLRQUEUE; \
845 sm_dprintf("CLEAR_STATE: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",\
846 e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);\
847 if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) \
848 logsender(e, NULL); \
849 e->e_flags &= ~EF_LOGSENDER; \
851 /* clean up a bit */ \
852 smtp.sm_gotmail = false; \
854 (void) dropenvelope(e, true, false); \
855 sm_rpool_free(e->e_rpool); \
856 e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL)); \
858 e->e_features = features; \
860 /* put back discard bit */ \
861 if (smtp.sm_discard) \
862 e->e_flags |= EF_DISCARD; \
864 /* restore connection quarantining */ \
865 if (smtp.sm_quarmsg == NULL) \
867 e->e_quarmsg = NULL; \
868 macdefine(&e->e_macro, A_PERM, \
869 macid("{quarantine}"), ""); \
873 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, \
875 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), \
880 /* sleep to flatten out connection load */
881 #define MIN_DELAY_LOG 15 /* wait before logging this again */
883 /* is it worth setting the process title for 1s? */
884 #define DELAY_CONN(cmd) \
885 if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA) \
889 sm_setproctitle(true, e, \
890 "%s: %s: delaying %s: load average: %d", \
891 qid_printname(e), CurSmtpClient, \
893 if (LogLevel > 8 && (dnow = curtime()) > log_delay) \
895 sm_syslog(LOG_INFO, e->e_id, \
896 "delaying=%s, load average=%d >= %d", \
897 cmd, CurrentLA, DelayLA); \
898 log_delay = dnow + MIN_DELAY_LOG; \
901 sm_setproctitle(true, e, "%s %s: %.80s", \
902 qid_printname(e), CurSmtpClient, inp); \
906 ** Determine the correct protocol keyword to use in the
907 ** Received: header, following RFC 3848.
911 # define tls_active false
914 # define auth_active (authenticating == SASL_IS_AUTH)
916 # define auth_active false
919 #define GET_PROTOCOL() \
922 ? (tls_active ? "UTF8SMTPSA" : "UTF8SMTPA") \
923 : (tls_active ? "UTF8SMTPS" : "UTF8SMTP")) \
925 ? (tls_active ? "ESMTPSA" : "ESMTPA") \
926 : (tls_active ? "ESMTPS" : "ESMTP")))
928 #define GET_PROTOCOL() \
930 ? (tls_active ? "ESMTPSA" : "ESMTPA") \
931 : (tls_active ? "ESMTPS" : "ESMTP"))
935 # define SHOWCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
936 "(suppressed)" : inp)
937 # define SHOWSHRTCMDINREPLY(inp) (bitset(PRIV_NOREFLECTION, PrivacyFlags) ? \
938 "(suppressed)" : shortenstring(inp, MAXSHORTSTR))
940 # define SHOWCMDINREPLY(inp) inp
941 # define SHOWSHRTCMDINREPLY(inp) shortenstring(inp, MAXSHORTSTR)
945 smtp(nullserver, d_flags, e)
946 char *volatile nullserver;
948 register ENVELOPE *volatile e;
950 register char *volatile p;
951 register struct cmd *volatile c = NULL;
953 auto ADDRESS *vrfyqueue;
955 volatile bool gothello; /* helo command received */
956 bool vrfy; /* set if this is a vrfy command */
957 char *volatile protocol; /* sending protocol */
958 char *volatile sendinghost; /* sending hostname */
959 char *volatile peerhostname; /* name of SMTP peer or "localhost" */
962 volatile unsigned int n_badcmds = 0; /* count of bad commands */
963 volatile unsigned int n_badrcpts = 0; /* number of rejected RCPT */
964 volatile unsigned int n_verifies = 0; /* count of VRFY/EXPN */
965 volatile unsigned int n_etrn = 0; /* count of ETRN */
966 volatile unsigned int n_noop = 0; /* count of NOOP/VERB/etc */
967 volatile unsigned int n_helo = 0; /* count of HELO/EHLO */
970 volatile bool tempfail = false;
971 volatile time_t wt; /* timeout after too many commands */
972 volatile time_t previous; /* time after checksmtpattack() */
973 volatile bool lognullconnection = true;
977 char *greetcode = "220";
978 const char *greetmsg = "not accepting messages";
979 char *hostname; /* my hostname ($j) */
981 char *args[MAXSMTPARGS];
982 char inp[MAXINPLINE];
983 #if MAXINPLINE < MAXLINE
984 # error "MAXINPLINE must NOT be less than MAXLINE"
986 char cmdbuf[MAXLINE];
989 volatile bool sasl_ok;
990 volatile unsigned int n_auth = 0; /* count of AUTH commands */
993 volatile int authenticating;
996 char auth_user[MAX_AUTH_USER_LEN], auth_user_tmp[MAX_AUTH_USER_LEN];
997 unsigned int auth_user_len;
999 char *auth_id = NULL;
1002 char localip[60], remoteip[60];
1003 # else /* SASL >= 20000 */
1006 sasl_external_properties_t ext_ssf;
1007 struct sockaddr_in saddr_l;
1008 struct sockaddr_in saddr_r;
1009 # endif /* SASL >= 20000 */
1010 sasl_security_properties_t ssp;
1012 unsigned int inlen, out2len;
1013 unsigned int outlen;
1014 char *volatile auth_type;
1016 volatile unsigned int n_mechs;
1022 volatile bool tls_active = false;
1023 volatile bool smtps = bitnset(D_SMTPS, d_flags);
1024 bool gotostarttls = false;
1025 bool saveQuickAbort;
1028 int ssl_err, tlsret;
1030 extern int TLSsslidx;
1031 #endif /* STARTTLS */
1032 volatile unsigned long features;
1033 #if PIPELINING && _FFR_NO_PIPE
1036 volatile time_t log_delay = (time_t) 0;
1038 volatile bool milter_cmd_done, milter_cmd_safe;
1039 volatile bool milter_rcpt_added, milter_cmd_fail;
1041 # define p_addr_st &addr_st
1043 # define p_addr_st NULL
1046 #if _FFR_BADRCPT_SHUTDOWN
1049 bool gotodoquit = false;
1051 RESET_AUTH_FAIL_LOG_USER;
1054 smtp.sm_milterize = (nullserver == NULL);
1055 smtp.sm_milterlist = false;
1059 /* setup I/O fd correctly for the SMTP server */
1063 if (sm_debug_active(&DebugLeakSmtp, 1))
1066 sm_dprintf("smtp() heap group #%d\n", sm_heap_group());
1068 #endif /* SM_HEAP_CHECK */
1070 /* XXX the rpool should be set when e is initialized in main() */
1071 e->e_rpool = sm_rpool_new_x(NULL);
1072 e->e_macro.mac_rpool = e->e_rpool;
1076 peerhostname = RealHostName;
1077 if (peerhostname == NULL)
1078 peerhostname = "localhost";
1079 CurHostName = peerhostname;
1080 CurSmtpClient = macvalue('_', e);
1081 if (CurSmtpClient == NULL)
1082 CurSmtpClient = CurHostName;
1084 /* check_relay may have set discard bit, save for later */
1085 smtp.sm_discard = bitset(EF_DISCARD, e->e_flags);
1088 /* auto-flush output when reading input */
1089 (void) sm_io_autoflush(InChannel, OutChannel);
1092 sm_setproctitle(true, e, "server %s startup", CurSmtpClient);
1094 maps_reset_chged("server:smtp");
1097 ** Set default features for server.
1099 ** Changing SRV_BARE_LF_421 | SRV_BARE_CR_421 below also
1100 ** requires changing srvfeatures() variant code.
1103 features = ((bitset(PRIV_NOETRN, PrivacyFlags) ||
1104 bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN)
1105 | (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE)
1106 | (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE
1108 | (bitset(PRIV_NOVERB, PrivacyFlags)
1109 ? SRV_NONE : SRV_OFFER_VERB)))
1110 | ((bitset(PRIV_NORECEIPTS, PrivacyFlags) || !SendMIMEErrors)
1111 ? SRV_NONE : SRV_OFFER_DSN)
1113 | (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH)
1114 | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC
1122 | (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS)
1123 | (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE
1127 | (SMTP_UTF8 ? SRV_OFFER_EAI : 0)
1129 | SRV_REQ_CRLF | SRV_BARE_LF_421 | SRV_BARE_CR_421
1131 if (nullserver == NULL)
1133 features = srvfeatures(e, CurSmtpClient, features);
1134 if (bitset(SRV_TMP_FAIL, features))
1137 sm_syslog(LOG_ERR, NOQID,
1138 "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled",
1140 nullserver = "450 4.3.0 Please try again later.";
1144 #if PIPELINING && _FFR_NO_PIPE
1145 if (bitset(SRV_NO_PIPE, features))
1147 /* for consistency */
1148 features &= ~SRV_OFFER_PIPE;
1150 #endif /* PIPELINING && _FFR_NO_PIPE */
1152 if (bitset(SRV_REQ_SEC, features))
1153 SASLOpts |= SASL_SEC_NOPLAINTEXT;
1155 SASLOpts &= ~SASL_SEC_NOPLAINTEXT;
1159 else if (strncmp(nullserver, "421 ", 4) == 0)
1161 /* Can't use ("%s", ...) due to message() requirements */
1162 message(nullserver);
1167 e->e_features = features;
1168 hostname = macvalue('j', e);
1170 if (AuthRealm == NULL)
1171 AuthRealm = hostname;
1172 sasl_ok = bitset(SRV_OFFER_AUTH, features);
1174 authenticating = SASL_NOT_AUTH;
1176 /* SASL server new connection */
1180 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL,
1183 /* use empty realm: only works in SASL > 1.5.5 */
1184 result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn);
1185 # else /* SASL >= 20000 */
1186 /* use no realm -> realm is set to hostname by SASL lib */
1187 result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0,
1189 # endif /* SASL >= 20000 */
1190 sasl_ok = result == SASL_OK;
1194 sm_syslog(LOG_WARNING, NOQID,
1195 "AUTH error: sasl_server_new failed=%d",
1202 ** SASL set properties for sasl
1203 ** set local/remote IP
1204 ** XXX Cyrus SASL v1 only supports IPv4
1206 ** XXX where exactly are these used/required?
1211 localip[0] = remoteip[0] = '\0';
1212 # if NETINET || NETINET6
1213 in = macvalue(macid("{daemon_family}"), e);
1216 strcmp(in, "inet6") == 0 ||
1218 strcmp(in, "inet") == 0))
1220 SOCKADDR_LEN_T addrsize;
1224 addrsize = sizeof(saddr_r);
1225 if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1227 (struct sockaddr *) &saddr_r,
1230 if (iptostring(&saddr_r, addrsize,
1231 remoteip, sizeof(remoteip)))
1233 sasl_setprop(conn, SASL_IPREMOTEPORT,
1236 addrsize = sizeof(saddr_l);
1237 if (getsockname(sm_io_getinfo(InChannel,
1240 (struct sockaddr *) &saddr_l,
1243 if (iptostring(&saddr_l, addrsize,
1254 # endif /* NETINET || NETINET6 */
1255 # else /* SASL >= 20000 */
1257 in = macvalue(macid("{daemon_family}"), e);
1258 if (in != NULL && strcmp(in, "inet") == 0)
1260 SOCKADDR_LEN_T addrsize;
1262 addrsize = sizeof(struct sockaddr_in);
1263 if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD,
1265 (struct sockaddr *)&saddr_r,
1268 sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r);
1269 addrsize = sizeof(struct sockaddr_in);
1270 if (getsockname(sm_io_getinfo(InChannel,
1273 (struct sockaddr *)&saddr_l,
1275 sasl_setprop(conn, SASL_IP_LOCAL,
1279 # endif /* NETINET */
1280 # endif /* SASL >= 20000 */
1286 macdefine(&BlankEnvelope.e_macro, A_PERM,
1287 macid("{auth_author}"), NULL);
1290 /* set properties */
1291 (void) memset(&ssp, '\0', sizeof(ssp));
1293 /* XXX should these be options settable via .cf ? */
1294 /* ssp.min_ssf = 0; is default due to memset() */
1295 ssp.max_ssf = MaxSLBits;
1296 ssp.maxbufsize = MAXOUTLEN;
1297 ssp.security_flags = SASLOpts & SASL_SEC_MASK;
1298 sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK;
1303 ** external security strength factor;
1304 ** currently we have none so zero
1310 sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL,
1311 &ext_ssf) == SASL_OK) &&
1312 (sasl_setprop(conn, SASL_AUTH_EXTERNAL,
1313 auth_id) == SASL_OK));
1314 # else /* SASL >= 20000 */
1316 ext_ssf.auth_id = NULL;
1317 sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL,
1318 &ext_ssf) == SASL_OK;
1319 # endif /* SASL >= 20000 */
1322 n_mechs = saslmechs(conn, &mechlist);
1326 (void) set_tls_rd_tmo(TimeOuts.to_nextcommand);
1329 if (smtp.sm_milterize)
1333 /* initialize mail filter connection */
1334 smtp.sm_milterlist = milter_init(e, &state, &smtp.sm_milters);
1338 if (MilterLogLevel > 3)
1339 sm_syslog(LOG_INFO, e->e_id,
1340 "Milter: initialization failed, rejecting commands");
1342 nullserver = "Command rejected";
1343 smtp.sm_milterize = false;
1346 case SMFIR_TEMPFAIL:
1347 if (MilterLogLevel > 3)
1348 sm_syslog(LOG_INFO, e->e_id,
1349 "Milter: initialization failed, temp failing commands");
1351 smtp.sm_milterize = false;
1354 case SMFIR_SHUTDOWN:
1355 if (MilterLogLevel > 3)
1356 sm_syslog(LOG_INFO, e->e_id,
1357 "Milter: initialization failed, closing connection");
1359 smtp.sm_milterize = false;
1360 message("421 4.7.0 %s closing connection",
1363 /* arrange to ignore send list */
1364 e->e_sendqueue = NULL;
1365 lognullconnection = false;
1371 if (smtp.sm_milterlist && smtp.sm_milterize &&
1372 !bitset(EF_DISCARD, e->e_flags))
1377 q = macvalue(macid("{client_name}"), e);
1378 SM_ASSERT(q != NULL || OpMode == MD_SMTP);
1381 response = milter_connect(q, RealHostAddr, e, &state);
1384 # if _FFR_MILTER_CONNECT_REPLYCODE
1385 case SMFIR_REPLYCODE:
1386 if (*response == '5')
1388 if (MilterLogLevel > 3)
1389 sm_syslog(LOG_INFO, e->e_id,
1390 "Milter: connect: host=%s, addr=%s, reject=%s",
1392 anynet_ntoa(&RealHostAddr),
1394 greetcode = "554"; /* Required by 2821 3.1 */
1395 nullserver = newstr(response);
1396 if (strlen(nullserver) > 4)
1400 greetmsg = nullserver + 4;
1402 /* skip over enhanced status code */
1403 skip = isenhsc(greetmsg, ' ');
1405 greetmsg += skip + 1;
1407 smtp.sm_milterize = false;
1410 else if (strncmp(response, "421 ", 4) == 0)
1413 const char *msg = response + 4;
1415 if (MilterLogLevel > 3)
1416 sm_syslog(LOG_INFO, e->e_id,
1417 "Milter: connect: host=%s, addr=%s, shutdown=%s",
1419 anynet_ntoa(&RealHostAddr),
1422 smtp.sm_milterize = false;
1424 /* skip over enhanced status code */
1425 skip = isenhsc(msg, ' ');
1428 message("421 %s %s", MyHostName, msg);
1430 /* arrange to ignore send list */
1431 e->e_sendqueue = NULL;
1437 if (MilterLogLevel > 3)
1438 sm_syslog(LOG_INFO, e->e_id,
1439 "Milter: connect: host=%s, addr=%s, temp failing commands=%s",
1441 anynet_ntoa(&RealHostAddr),
1443 /*tempfail = true;*/
1444 smtp.sm_milterize = false;
1445 nullserver = newstr(response);
1449 # else /* _FFR_MILTER_CONNECT_REPLYCODE */
1450 case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */
1451 # endif /* _FFR_MILTER_CONNECT_REPLYCODE */
1453 if (MilterLogLevel > 3)
1454 sm_syslog(LOG_INFO, e->e_id,
1455 "Milter: connect: host=%s, addr=%s, rejecting commands",
1457 anynet_ntoa(&RealHostAddr));
1459 nullserver = "Command rejected";
1460 smtp.sm_milterize = false;
1463 case SMFIR_TEMPFAIL:
1464 if (MilterLogLevel > 3)
1465 sm_syslog(LOG_INFO, e->e_id,
1466 "Milter: connect: host=%s, addr=%s, temp failing commands",
1468 anynet_ntoa(&RealHostAddr));
1470 smtp.sm_milterize = false;
1473 case SMFIR_SHUTDOWN:
1474 if (MilterLogLevel > 3)
1475 sm_syslog(LOG_INFO, e->e_id,
1476 "Milter: connect: host=%s, addr=%s, shutdown",
1478 anynet_ntoa(&RealHostAddr));
1480 smtp.sm_milterize = false;
1481 message("421 4.7.0 %s closing connection",
1484 /* arrange to ignore send list */
1485 e->e_sendqueue = NULL;
1489 if (response != NULL)
1495 ** Broken proxies and SMTP slammers
1496 ** push data without waiting, catch them
1503 *greetcode == '2' && nullserver == NULL)
1507 char pvpbuf[PSBUFSIZE];
1509 /* Ask the rulesets how long to pause */
1511 r = rscap("greet_pause", peerhostname,
1512 anynet_ntoa(&RealHostAddr), e,
1513 &pvp, pvpbuf, sizeof(pvpbuf));
1514 if (r == EX_OK && pvp != NULL && pvp[0] != NULL &&
1515 (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL)
1517 msecs = strtol(pvp[1], NULL, 10);
1522 struct timeval *tp; /* total pause */
1524 /* Obey RFC 2821: 4.5.3.2: 220 timeout of 5 minutes (300 seconds) */
1525 if (msecs >= 300000)
1528 /* check if data is on the socket during the pause */
1529 if ((tp = channel_readable(InChannel, msecs)) != NULL)
1532 nullserver = "Command rejected";
1533 sm_syslog(LOG_INFO, e->e_id,
1534 "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds",
1536 anynet_ntoa(&RealHostAddr),
1538 (tp->tv_usec >= 500000 ? 1 : 0)
1545 /* If this an smtps connection, start TLS now */
1548 if (!tls_ok_srv || srv_ctx == NULL)
1550 sm_syslog(LOG_ERR, e->e_id,
1551 "smtps: TLS not available, exiting");
1557 smtp.sm_gotmail = false;
1558 gotostarttls = true;
1564 #endif /* STARTTLS */
1566 /* output the first line, inserting "ESMTP" as second word */
1567 if (*greetcode == '5')
1568 (void) sm_snprintf(inp, sizeof(inp), "%s %s", hostname,
1571 expand(SmtpGreeting, inp, sizeof(inp), e);
1573 p = strchr(inp, '\n');
1576 id = strchr(inp, ' ');
1578 id = &inp[strlen(inp)];
1580 (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1581 "%s %%.*s ESMTP%%s", greetcode);
1583 (void) sm_snprintf(cmdbuf, sizeof(cmdbuf),
1584 "%s-%%.*s ESMTP%%s", greetcode);
1585 message(cmdbuf, (int) (id - inp), inp, id);
1587 /* output remaining lines */
1588 while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
1591 if (SM_ISSPACE(*id))
1593 (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s");
1594 message(cmdbuf, id);
1598 if (SM_ISSPACE(*id))
1600 (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s");
1601 message(cmdbuf, id);
1605 sendinghost = macvalue('s', e);
1607 /* If quarantining by a connect/ehlo action, save between messages */
1608 if (e->e_quarmsg == NULL)
1609 smtp.sm_quarmsg = NULL;
1611 smtp.sm_quarmsg = newstr(e->e_quarmsg);
1613 /* sendinghost's storage must outlive the current envelope */
1614 if (sendinghost != NULL)
1615 sendinghost = sm_strdup_x(sendinghost);
1618 smtp.sm_gotmail = false;
1629 OnlyOneError = true;
1630 e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
1632 milter_cmd_fail = false;
1635 /* setup for the read */
1639 (void) sm_io_flush(smioout, SM_TIME_DEFAULT);
1649 gotostarttls = false;
1654 /* read the input line */
1655 SmtpPhase = "server cmd read";
1656 sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient);
1659 if (sm_io_error(OutChannel) ||
1660 (p = sfgets(inp, sizeof(inp), InChannel,
1661 TimeOuts.to_nextcommand, SmtpPhase)) == NULL)
1665 d = macvalue(macid("{daemon_name}"), e);
1668 /* end of file, just die */
1672 /* close out milter filters */
1676 message("421 4.4.1 %s Lost input channel from %s",
1677 MyHostName, CurSmtpClient);
1678 if (LogLevel > (smtp.sm_gotmail ? 1 : 19))
1679 sm_syslog(LOG_NOTICE, e->e_id,
1680 "lost input channel from %s to %s after %s",
1682 (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name);
1684 ** If have not accepted mail (DATA), do not bounce
1685 ** bad addresses back to sender.
1688 if (bitset(EF_CLRQUEUE, e->e_flags))
1689 e->e_sendqueue = NULL;
1693 /* also used by "proxy" check below */
1694 inplen = strlen(inp);
1697 ** SMTP AUTH requires accepting any length,
1698 ** at least for challenge/response. However, not imposing
1699 ** a limit is a bad idea (denial of service).
1702 if (authenticating != SASL_PROC_AUTH
1703 && sm_strncasecmp(inp, "AUTH ", 5) != 0
1704 && inplen > MAXLINE)
1706 message("421 4.7.0 %s Command too long, possible attack %s",
1707 MyHostName, CurSmtpClient);
1708 sm_syslog(LOG_INFO, e->e_id,
1709 "%s: SMTP violation, input too long: %lu",
1710 CurSmtpClient, (unsigned long) inplen);
1715 if (first || bitset(SRV_NO_HTTP_CMD, features))
1720 static char *http_cmds[] = { "GET", "POST",
1721 "CONNECT", "USER", NULL };
1723 for (idx = 0; (http_cmd = http_cmds[idx]) != NULL;
1726 cmdlen = strlen(http_cmd);
1727 if (cmdlen < inplen &&
1728 sm_strncasecmp(inp, http_cmd, cmdlen) == 0 &&
1729 SM_ISSPACE(inp[cmdlen]))
1731 /* Open proxy, drop it */
1732 message("421 4.7.0 %s %s %s",
1734 first ? "Rejecting open proxy"
1737 sm_syslog(LOG_INFO, e->e_id,
1738 "%s: probable open proxy: command=%.40s",
1739 CurSmtpClient, inp);
1746 /* clean up end of line */
1749 #if PIPELINING && _FFR_NO_PIPE
1751 ** if there is more input and pipelining is disabled:
1752 ** delay ... (and maybe discard the input?)
1755 if (bitset(SRV_NO_PIPE, features) &&
1756 sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
1759 sm_syslog(LOG_INFO, NOQID,
1760 "unauthorized PIPELINING, sleeping, relay=%.100s",
1764 #endif /* PIPELINING && _FFR_NO_PIPE */
1767 if (authenticating == SASL_PROC_AUTH)
1772 authenticating = SASL_NOT_AUTH;
1773 message("501 5.5.2 missing input");
1778 if (*inp == '*' && *(inp + 1) == '\0')
1780 authenticating = SASL_NOT_AUTH;
1783 message("501 5.0.0 AUTH aborted");
1788 /* could this be shorter? XXX */
1790 in = xalloc(strlen(inp) + 1);
1791 result = sasl_decode64(inp, strlen(inp), in,
1792 strlen(inp), &inlen);
1793 # else /* SASL >= 20000 */
1794 out = xalloc(strlen(inp));
1795 result = sasl_decode64(inp, strlen(inp), out, &outlen);
1796 # endif /* SASL >= 20000 */
1797 if (result != SASL_OK)
1799 authenticating = SASL_NOT_AUTH;
1802 message("501 5.5.4 cannot decode AUTH parameter %s",
1812 SET_AUTH_USER_TMP(in, inlen);
1813 result = sasl_server_step(conn, in, inlen,
1816 # else /* SASL >= 20000 */
1817 SET_AUTH_USER_TMP(out, outlen);
1818 result = sasl_server_step(conn, out, outlen,
1819 &out, &outlen, &errstr);
1820 # endif /* SASL >= 20000 */
1822 /* get an OK if we're done */
1823 if (result == SASL_OK)
1826 message("235 2.0.0 OK Authenticated");
1827 authenticating = SASL_IS_AUTH;
1828 macdefine(&BlankEnvelope.e_macro, A_TEMP,
1829 macid("{auth_type}"), auth_type);
1832 user = macvalue(macid("{auth_authen}"), e);
1834 /* get security strength (features) */
1835 result = sasl_getprop(conn, SASL_SSF,
1836 (const void **) &ssf);
1837 # else /* SASL >= 20000 */
1838 result = sasl_getprop(conn, SASL_USERNAME,
1840 if (result != SASL_OK)
1843 macdefine(&BlankEnvelope.e_macro,
1845 macid("{auth_authen}"), NULL);
1849 macdefine(&BlankEnvelope.e_macro,
1851 macid("{auth_authen}"),
1852 xtextify(user, "<>\")"));
1857 sasl_getprop(conn, SASL_REALM, (void **) &data);
1860 /* get security strength (features) */
1861 result = sasl_getprop(conn, SASL_SSF,
1863 # endif /* SASL >= 20000 */
1864 if (result != SASL_OK)
1866 macdefine(&BlankEnvelope.e_macro,
1868 macid("{auth_ssf}"), "0");
1875 (void) sm_snprintf(pbuf, sizeof(pbuf),
1877 macdefine(&BlankEnvelope.e_macro,
1879 macid("{auth_ssf}"), pbuf);
1881 sm_dprintf("AUTH auth_ssf: %u\n",
1885 protocol = GET_PROTOCOL();
1888 ** Only switch to encrypted connection
1889 ** if a security layer has been negotiated
1892 if (ssf != NULL && *ssf > 0)
1897 ** Convert I/O layer to use SASL.
1898 ** If the call fails, the connection
1902 tmo = TimeOuts.to_datablock * 1000;
1903 if (sfdcsasl(&InChannel, &OutChannel,
1906 /* restart dialogue */
1909 (void) sm_io_autoflush(InChannel,
1911 # endif /* PIPELINING */
1914 syserr("503 5.3.3 SASL TLS failed");
1917 /* NULL pointer ok since it's our function */
1919 sm_syslog(LOG_INFO, NOQID,
1920 "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d",
1922 shortenstring(user, 128),
1925 else if (result == SASL_CONTINUE)
1929 len = ENC64LEN(outlen);
1931 result = sasl_encode64(out, outlen, out2, len,
1933 if (result != SASL_OK)
1935 /* correct code? XXX */
1936 /* 454 Temp. authentication failure */
1937 message("454 4.5.4 Internal error: unable to encode64");
1939 sm_syslog(LOG_WARNING, e->e_id,
1940 "AUTH encode64 error [%d for \"%s\"], relay=%.100s",
1944 authenticating = SASL_NOT_AUTH;
1948 message("334 %s", out2);
1950 sm_dprintf("AUTH continue: msg='%s' len=%u\n",
1961 # define SASLERR sasl_errdetail(conn)
1963 # define SASLERR errstr == NULL ? "" : errstr
1965 #define LOGAUTHFAIL \
1968 SET_AUTH_USER_CONDITIONALLY \
1969 message("535 5.7.0 authentication failed"); \
1970 if (LogLevel >= 9) \
1971 sm_syslog(LOG_WARNING, e->e_id, \
1972 "AUTH failure (%s): %s (%d) %s%s%.*s, relay=%.100s", \
1973 (auth_type != NULL) ? auth_type : "unknown", \
1974 sasl_errstring(result, NULL, NULL), \
1977 LOG_AUTH_FAIL_USER, \
1984 authenticating = SASL_NOT_AUTH;
1989 /* don't want to do any of this if authenticating */
1992 /* echo command to transcript */
1993 if (e->e_xfp != NULL)
1994 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
1998 sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp);
2000 /* break off command */
2001 for (p = inp; SM_ISSPACE(*p); p++)
2004 while (*p != '\0' &&
2005 !(SM_ISSPACE(*p)) &&
2006 cmd < &cmdbuf[sizeof(cmdbuf) - 2])
2010 /* throw away leading whitespace */
2013 /* decode command */
2014 for (c = CmdTab; c->cmd_name != NULL; c++)
2016 if (SM_STRCASEEQ(c->cmd_name, cmdbuf))
2023 /* check whether a "non-null" command has been used */
2024 switch (c->cmd_code)
2028 /* avoid information leak; take first two words? */
2037 lognullconnection = false;
2044 if (e->e_id == NULL)
2045 sm_setproctitle(true, e, "%s: %.80s",
2048 sm_setproctitle(true, e, "%s %s: %.80s",
2055 ** If we are running as a null server, return 550
2056 ** to almost everything.
2059 if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags))
2061 switch (c->cmd_code)
2069 /* process normally */
2073 if (bitnset(D_ETRNONLY, d_flags) &&
2080 #if MAXBADCOMMANDS > 0
2081 /* theoretically this could overflow */
2082 if (nullserver != NULL &&
2083 ++n_badcmds > MAXBADCOMMANDS)
2085 message("421 4.7.0 %s Too many bad commands; closing connection",
2088 /* arrange to ignore send list */
2089 e->e_sendqueue = NULL;
2092 #endif /* MAXBADCOMMANDS > 0 */
2093 if (nullserver != NULL)
2095 if (ISSMTPREPLY(nullserver))
2097 /* Can't use ("%s", ...) due to usrerr() requirements */
2102 usrerr("550 5.0.0 %s",
2107 usrerr("452 4.4.5 Insufficient disk space; try again later");
2112 switch (c->cmd_code)
2115 case CMDAUTH: /* sasl */
2117 if (!sasl_ok || n_mechs <= 0)
2119 message("503 5.3.3 AUTH not available");
2124 message("503 5.5.0 Already Authenticated");
2127 if (smtp.sm_gotmail)
2129 message("503 5.5.0 AUTH not permitted during a mail transaction");
2135 sm_syslog(LOG_INFO, e->e_id,
2136 "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)",
2138 usrerr("454 4.3.0 Please try again later");
2144 /* crude way to avoid crack attempts */
2145 STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1,
2148 /* make sure mechanism (p) is a valid string */
2149 for (q = p; *q != '\0' && isascii(*q); q++)
2154 while (*++q != '\0' && SM_ISSPACE(*q))
2157 ismore = (*q != '\0');
2164 message("501 5.5.2 AUTH mechanism must be specified");
2168 /* check whether mechanism is available */
2169 if (iteminlist(p, mechlist, " ") == NULL)
2171 message("504 5.3.3 AUTH mechanism %.32s not available",
2178 ** Unlike a zero-length client answer to a
2179 ** 334 reply, a zero- length initial response
2180 ** is sent as a single equals sign ("=").
2183 if (ismore && *q == '=' && *(q + 1) == '\0')
2185 /* will be free()d, don't use in=""; */
2192 /* could this be shorter? XXX */
2194 in = xalloc(strlen(q) + 1);
2195 result = sasl_decode64(q, strlen(q), in,
2197 # else /* SASL >= 20000 */
2198 in = sm_rpool_malloc(e->e_rpool, strlen(q));
2199 result = sasl_decode64(q, strlen(q), in,
2201 # endif /* SASL >= 20000 */
2203 if (result != SASL_OK)
2205 message("501 5.5.4 cannot BASE64 decode '%s'",
2208 sm_syslog(LOG_WARNING, e->e_id,
2209 "AUTH decode64 error [%d for \"%s\"], relay=%.100s",
2213 authenticating = SASL_NOT_AUTH;
2221 SET_AUTH_USER_TMP(in, inlen);
2229 /* see if that auth type exists */
2231 result = sasl_server_start(conn, p, in, inlen,
2234 # else /* SASL >= 20000 */
2235 result = sasl_server_start(conn, p, in, inlen,
2236 &out, &outlen, &errstr);
2237 # endif /* SASL >= 20000 */
2240 auth_type = newstr(p);
2241 if (result != SASL_OK && result != SASL_CONTINUE)
2247 if (result == SASL_OK)
2249 /* ugly, but same code */
2251 /* authenticated by the initial response */
2256 /* len is at least 2 */
2257 len = ENC64LEN(outlen);
2259 result = sasl_encode64(out, outlen, out2, len,
2262 if (result != SASL_OK)
2264 message("454 4.5.4 Temporary authentication failure");
2266 sm_syslog(LOG_WARNING, e->e_id,
2267 "AUTH encode64 error [%d for \"%s\"]",
2271 authenticating = SASL_NOT_AUTH;
2276 message("334 %s", out2);
2277 authenticating = SASL_PROC_AUTH;
2286 case CMDSTLS: /* starttls */
2287 DELAY_CONN("STARTTLS");
2290 message("501 5.5.2 Syntax error (no parameters allowed)");
2293 if (!bitset(SRV_OFFER_TLS, features))
2295 message("503 5.5.0 TLS not available");
2301 message("454 4.3.3 TLS not available after start");
2304 if (smtp.sm_gotmail)
2306 message("503 5.5.0 TLS not permitted during a mail transaction");
2312 sm_syslog(LOG_INFO, e->e_id,
2313 "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)",
2315 usrerr("454 4.7.0 Please try again later");
2318 if (!TLS_set_engine(SSLEngine, false))
2320 sm_syslog(LOG_ERR, NOQID,
2321 "STARTTLS=server, engine=%s, TLS_set_engine=failed",
2324 message("454 4.3.3 TLS not available right now");
2329 ** XXX do we need a temp key ?
2333 # if TLS_VRFY_PER_CTX
2335 ** Note: this sets the verification globally
2337 ** it's ok since it applies only to one transaction
2340 TLS_VERIFY_CLIENT();
2341 # endif /* TLS_VRFY_PER_CTX */
2343 #define SMTLSFAILED \
2345 SM_SSL_FREE(srv_ssl); \
2349 if (srv_ssl != NULL)
2351 else if ((srv_ssl = SSL_new(srv_ctx)) == NULL)
2353 message("454 4.3.3 TLS not available: error generating SSL handle");
2354 tlslogerr(LOG_WARNING, 8, "server");
2358 tlsi_ctx.tlsi_dvc.dane_vrfy_dane_enabled = false;
2359 tlsi_ctx.tlsi_dvc.dane_vrfy_chk = DANE_NEVER;
2361 if (get_tls_se_features(e, srv_ssl, &tlsi_ctx, true)
2364 /* do not offer too much info to client */
2365 message("454 4.3.3 TLS currently not available");
2368 r = SSL_set_ex_data(srv_ssl, TLSsslidx, &tlsi_ctx);
2373 sm_syslog(LOG_ERR, NOQID,
2374 "STARTTLS=server, error: SSL_set_ex_data failed=%d, TLSsslidx=%d",
2376 tlslogerr(LOG_WARNING, 9, "server");
2381 # if !TLS_VRFY_PER_CTX
2383 ** this could be used if it were possible to set
2384 ** verification per SSL (connection)
2385 ** not just per SSL_CTX (global)
2388 TLS_VERIFY_CLIENT();
2389 # endif /* !TLS_VRFY_PER_CTX */
2391 rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
2392 wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
2394 if (rfd < 0 || wfd < 0 ||
2395 SSL_set_rfd(srv_ssl, rfd) <= 0 ||
2396 SSL_set_wfd(srv_ssl, wfd) <= 0)
2398 message("454 4.3.3 TLS not available: error set fd");
2402 message("220 2.0.0 Ready to start TLS");
2404 (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
2407 SSL_set_accept_state(srv_ssl);
2409 tlsstart = curtime();
2411 ssl_err = SSL_ERROR_WANT_READ;
2415 tlsret = tls_retry(srv_ssl, rfd, wfd, tlsstart,
2416 TimeOuts.to_starttls, ssl_err,
2425 l = ERR_peek_error();
2426 sr = ERR_reason_error_string(l);
2428 sm_syslog(LOG_WARNING, NOQID,
2429 "STARTTLS=server, error: accept failed=%d, reason=%s, SSL_error=%d, errno=%d, retry=%d, relay=%.100s",
2430 r, sr == NULL ? "unknown"
2432 ssl_err, save_errno,
2433 tlsret, CurSmtpClient);
2434 tlslogerr(LOG_WARNING, 9, "server");
2437 SM_SSL_FREE(srv_ssl);
2440 ** according to the next draft of
2441 ** RFC 2487 the connection should
2444 ** arrange to ignore any current
2448 e->e_sendqueue = NULL;
2452 r = SSL_accept(srv_ssl);
2455 ssl_err = SSL_get_error(srv_ssl, r);
2458 /* ignore return code for now, it's in {verify} */
2459 (void) tls_get_info(srv_ssl, true,
2461 &BlankEnvelope.e_macro,
2462 bitset(SRV_VRFY_CLT, features));
2465 ** call Stls_client to find out whether
2466 ** to accept the connection from the client
2469 saveQuickAbort = QuickAbort;
2470 saveSuprErrs = SuprErrs;
2473 if (rscheck("tls_client",
2474 macvalue(macid("{verify}"), e),
2476 RSF_RMCOMM|RSF_COUNT,
2477 5, NULL, NOQID, NULL, NULL) != EX_OK ||
2480 extern char MsgBuf[];
2482 if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf))
2483 nullserver = newstr(MsgBuf);
2485 nullserver = "503 5.7.0 Authentication required.";
2487 QuickAbort = saveQuickAbort;
2488 SuprErrs = saveSuprErrs;
2490 tls_ok_srv = false; /* don't offer STARTTLS again */
2500 s = macvalue(macid("{cipher_bits}"), e);
2501 v = macvalue(macid("{verify}"), e);
2502 c = macvalue(macid("{cert_subject}"), e);
2503 verified = (v != NULL && strcmp(v, "OK") == 0);
2504 if (s != NULL && (cipher_bits = atoi(s)) > 0)
2507 ext_ssf = cipher_bits;
2508 auth_id = verified ? c : NULL;
2509 sasl_ok = ((sasl_setprop(conn,
2511 &ext_ssf) == SASL_OK) &&
2514 auth_id) == SASL_OK));
2515 # else /* SASL >= 20000 */
2516 ext_ssf.ssf = cipher_bits;
2517 ext_ssf.auth_id = verified ? c : NULL;
2518 sasl_ok = sasl_setprop(conn,
2520 &ext_ssf) == SASL_OK;
2521 # endif /* SASL >= 20000 */
2524 n_mechs = saslmechs(conn,
2530 /* switch to secure connection */
2531 if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0)
2535 (void) sm_io_autoflush(InChannel, OutChannel);
2541 ** XXX this is an internal error
2542 ** how to deal with it?
2543 ** we can't generate an error message
2544 ** since the other side switched to an
2545 ** encrypted layer, but we could not...
2549 nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer";
2550 syserr("STARTTLS: can't switch to encrypted layer");
2561 #endif /* STARTTLS */
2563 case CMDHELO: /* hello -- introduce yourself */
2564 case CMDEHLO: /* extended hello */
2566 if (c->cmd_code == CMDEHLO)
2568 protocol = GET_PROTOCOL();
2569 SmtpPhase = "server EHLO";
2574 SmtpPhase = "server HELO";
2577 /* avoid denial-of-service */
2578 STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS,
2579 true, "HELO/EHLO", e));
2582 ** Despite the fact that the name indicates this
2583 ** a PIPELINE related feature, do not enclose
2584 ** it in #if PIPELINING so we can protect SMTP
2585 ** servers not compiled with PIPELINE support
2586 ** from transaction stuffing.
2589 /* check if data is on the socket before the EHLO reply */
2590 if (bitset(SRV_BAD_PIPELINE, features) &&
2591 sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
2593 sm_syslog(LOG_INFO, e->e_id,
2594 "rejecting %s from %s [%s] due to traffic before response",
2595 SmtpPhase, CurHostName,
2596 anynet_ntoa(&RealHostAddr));
2597 usrerr("554 5.5.0 SMTP protocol error");
2598 nullserver = "Command rejected";
2600 smtp.sm_milterize = false;
2606 /* RFC2821 4.1.4 allows duplicate HELO/EHLO */
2607 /* check for duplicate HELO/EHLO per RFC 1651 4.2 */
2610 usrerr("503 %s Duplicate HELO/EHLO",
2616 /* check for valid domain name (re 1123 5.2.5) */
2617 if (*p == '\0' && !AllowBogusHELO)
2619 usrerr("501 %s requires domain address",
2624 /* check for long domain name (hides Received: info) */
2625 if (strlen(p) > MAXNAME) /* EAI:ok:EHLO name must be ASCII */
2627 usrerr("501 Invalid domain name");
2629 sm_syslog(LOG_INFO, CurEnv->e_id,
2630 "invalid domain name (too long) from %s",
2636 for (q = p; *q != '\0'; q++)
2646 /* only complain if strict check */
2647 ok = AllowBogusHELO;
2649 /* allow trailing whitespace */
2650 while (!ok && *++q != '\0' &&
2657 if (strchr("[].-_#:", *q) == NULL)
2661 if (*q == '\0' && ok)
2663 q = "pleased to meet you";
2664 sendinghost = sm_strdup_x(p);
2666 else if (!AllowBogusHELO)
2668 usrerr("501 Invalid domain name");
2670 sm_syslog(LOG_INFO, CurEnv->e_id,
2671 "invalid domain name (%s) from %.100s",
2677 q = "accepting invalid domain name";
2680 if (gothello || smtp.sm_gotmail)
2681 CLEAR_STATE(cmdbuf);
2684 if (smtp.sm_milterlist && smtp.sm_milterize &&
2685 !bitset(EF_DISCARD, e->e_flags))
2690 response = milter_helo(p, e, &state);
2694 if (MilterLogLevel > 3)
2695 sm_syslog(LOG_INFO, e->e_id,
2696 "Milter: helo=%s, reject=Command rejected",
2698 nullserver = "Command rejected";
2699 smtp.sm_milterize = false;
2702 case SMFIR_TEMPFAIL:
2703 if (MilterLogLevel > 3)
2704 sm_syslog(LOG_INFO, e->e_id,
2705 "Milter: helo=%s, reject=%s",
2708 smtp.sm_milterize = false;
2711 case SMFIR_REPLYCODE:
2712 if (MilterLogLevel > 3)
2713 sm_syslog(LOG_INFO, e->e_id,
2714 "Milter: helo=%s, reject=%s",
2716 if (strncmp(response, "421 ", 4) != 0
2717 && strncmp(response, "421-", 4) != 0)
2719 nullserver = newstr(response);
2720 smtp.sm_milterize = false;
2725 case SMFIR_SHUTDOWN:
2726 if (MilterLogLevel > 3 &&
2728 sm_syslog(LOG_INFO, e->e_id,
2729 "Milter: helo=%s, reject=421 4.7.0 %s closing connection",
2732 smtp.sm_milterize = false;
2733 if (response != NULL)
2735 /* Can't use ("%s", ...) due to usrerr() requirements */
2740 message("421 4.7.0 %s closing connection",
2743 /* arrange to ignore send list */
2744 e->e_sendqueue = NULL;
2745 lognullconnection = false;
2748 if (response != NULL)
2752 ** If quarantining by a connect/ehlo action,
2753 ** save between messages
2756 if (smtp.sm_quarmsg == NULL &&
2757 e->e_quarmsg != NULL)
2758 smtp.sm_quarmsg = newstr(e->e_quarmsg);
2763 /* print HELO response message */
2764 if (c->cmd_code != CMDEHLO)
2766 message("250 %s Hello %s, %s",
2767 MyHostName, CurSmtpClient, q);
2771 message("250-%s Hello %s, %s",
2772 MyHostName, CurSmtpClient, q);
2774 /* offer ENHSC even for nullserver */
2775 if (nullserver != NULL)
2777 message("250 ENHANCEDSTATUSCODES");
2782 ** print EHLO features list
2784 ** Note: If you change this list,
2785 ** remember to update 'helpfile'
2788 message("250-ENHANCEDSTATUSCODES");
2790 if (bitset(SRV_OFFER_PIPE, features))
2791 message("250-PIPELINING");
2793 if (bitset(SRV_OFFER_EXPN, features))
2795 message("250-EXPN");
2796 if (bitset(SRV_OFFER_VERB, features))
2797 message("250-VERB");
2800 message("250-8BITMIME");
2802 if (MaxMessageSize > 0)
2803 message("250-SIZE %ld", MaxMessageSize);
2805 message("250-SIZE");
2807 if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features))
2811 if (bitset(SRV_OFFER_EAI, features))
2812 message("250-SMTPUTF8");
2814 if (bitset(SRV_OFFER_ETRN, features))
2815 message("250-ETRN");
2817 if (sasl_ok && mechlist != NULL && *mechlist != '\0')
2818 message("250-AUTH %s", mechlist);
2821 if (tls_ok_srv && bitset(SRV_OFFER_TLS, features))
2822 message("250-STARTTLS");
2824 if (DeliverByMin > 0)
2825 message("250-DELIVERBY %ld",
2826 (long) DeliverByMin);
2827 else if (DeliverByMin == 0)
2828 message("250-DELIVERBY");
2830 /* < 0: no deliver-by */
2832 message("250 HELP");
2835 case CMDMAIL: /* mail -- designate sender */
2836 SmtpPhase = "server MAIL";
2839 /* check for validity of this command */
2840 if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
2842 usrerr("503 5.0.0 Polite people say HELO first");
2845 if (smtp.sm_gotmail)
2847 usrerr("503 5.5.0 Sender already specified");
2851 if (bitset(SRV_REQ_AUTH, features) &&
2852 authenticating != SASL_IS_AUTH)
2854 usrerr("530 5.7.0 Authentication required");
2859 p = skipword(p, "from");
2862 maps_reset_chged("server:MAIL");
2866 sm_syslog(LOG_INFO, e->e_id,
2867 "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)",
2869 /* Can't use ("%s", ...) due to usrerr() requirements */
2870 usrerr(MSG_TEMPFAIL);
2874 /* make sure we know who the sending host is */
2875 if (sendinghost == NULL)
2876 sendinghost = peerhostname;
2880 if (sm_debug_active(&DebugLeakSmtp, 1))
2883 sm_dprintf("smtp() heap group #%d\n",
2886 #endif /* SM_HEAP_CHECK */
2892 auth_warning(e, "%s didn't use HELO protocol",
2895 #ifdef PICKY_HELO_CHECK
2896 if (sm_strcasecmp(sendinghost, peerhostname) != 0 &&
2897 (sm_strcasecmp(peerhostname, "localhost") != 0 ||
2898 sm_strcasecmp(sendinghost, MyHostName) != 0))
2900 auth_warning(e, "Host %s claimed to be %s",
2901 CurSmtpClient, sendinghost);
2903 #endif /* PICKY_HELO_CHECK */
2905 if (protocol == NULL)
2907 macdefine(&e->e_macro, A_PERM, 'r', protocol);
2908 macdefine(&e->e_macro, A_PERM, 's', sendinghost);
2914 macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0");
2915 macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0");
2916 macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"),
2918 e->e_flags |= EF_CLRQUEUE;
2919 sm_setproctitle(true, e, "%s %s: %.80s",
2921 CurSmtpClient, inp);
2923 /* do the processing */
2926 extern char *FullName;
2927 #if _FFR_8BITENVADDR
2929 char iaddr[MAXLINE * 2];
2937 #if _FFR_8BITENVADDR
2938 len = sizeof(iaddr);
2941 /* HACK!!!! p is more than the address! */
2942 p = quote_internal_chars(p, iaddr, &len, NULL);
2945 /* must parse sender first */
2947 setsender(p, e, &delimptr, ' ', false);
2948 if (delimptr != NULL && *delimptr != '\0')
2951 #if _FFR_8BITENVADDR
2952 len = sizeof(iaddr) - (delimptr - iaddr);
2953 (void) dequote_internal_chars(delimptr, delimptr, len);
2954 sep_args(delimptr, origp, e->e_id, p);
2958 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2960 /* Successfully set e_from, allow logging */
2961 e->e_flags |= EF_LOGSENDER;
2963 /* put resulting triple from parseaddr() into macros */
2964 if (e->e_from.q_mailer != NULL)
2965 macdefine(&e->e_macro, A_PERM,
2966 macid("{mail_mailer}"),
2967 e->e_from.q_mailer->m_name);
2969 macdefine(&e->e_macro, A_PERM,
2970 macid("{mail_mailer}"), NULL);
2971 if (e->e_from.q_host != NULL)
2972 macdefine(&e->e_macro, A_PERM,
2973 macid("{mail_host}"),
2976 macdefine(&e->e_macro, A_PERM,
2977 macid("{mail_host}"), "localhost");
2978 if (e->e_from.q_user != NULL)
2979 macdefine(&e->e_macro, A_PERM,
2980 macid("{mail_addr}"),
2983 macdefine(&e->e_macro, A_PERM,
2984 macid("{mail_addr}"), NULL);
2986 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
2988 /* check for possible spoofing */
2989 if (RealUid != 0 && OpMode == MD_SMTP &&
2990 !wordinclass(RealUserName, 't') &&
2991 (!bitnset(M_LOCALMAILER,
2992 e->e_from.q_mailer->m_flags) ||
2993 strcmp(e->e_from.q_user, RealUserName) != 0))
2995 auth_warning(e, "%s owned process doing -bs",
2999 /* reset to default value */
3000 e->e_flags &= ~EF_7BITBODY;
3002 /* now parse ESMTP arguments */
3005 parse_esmtp_args(e, NULL, origp, delimptr, "MAIL", args,
3008 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3013 protocol = GET_PROTOCOL();
3014 macdefine(&e->e_macro, A_PERM, 'r', protocol);
3017 /* UTF8 addresses are only legal with SMTPUTF8 */
3018 /* XXX different error if SMTPUTF8 is not enabled? */
3019 CHECK_UTF8_ADDR(e->e_from.q_paddr, q);
3023 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3028 # if _FFR_AUTH_PASSING
3029 /* set the default AUTH= if the sender didn't */
3030 if (e->e_auth_param == NULL)
3032 /* XXX only do this for an MSA? */
3033 e->e_auth_param = macvalue(macid("{auth_authen}"),
3035 if (e->e_auth_param == NULL)
3036 e->e_auth_param = "<>";
3039 ** XXX should we invoke Strust_auth now?
3040 ** authorizing as the client that just
3041 ** authenticated, so we'll trust implicitly
3044 # endif /* _FFR_AUTH_PASSING */
3047 /* do config file checking of the sender */
3048 macdefine(&e->e_macro, A_PERM,
3049 macid("{addr_type}"), "e s");
3051 /* make the "real" sender address available */
3052 macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"),
3055 if (rscheck("check_mail", addr,
3056 NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
3057 NULL, e->e_id, NULL, NULL) != EX_OK ||
3059 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3060 macdefine(&e->e_macro, A_PERM,
3061 macid("{addr_type}"), NULL);
3063 if (MaxMessageSize > 0 &&
3064 (e->e_msgsize > MaxMessageSize ||
3067 usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)",
3069 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3073 ** XXX always check whether there is at least one fs
3074 ** with enough space?
3075 ** However, this may not help much: the queue group
3076 ** selection may later on select a FS that hasn't
3080 if ((NumFileSys == 1 || NumQueue == 1) &&
3081 !enoughdiskspace(e->e_msgsize, e)
3082 #if _FFR_ANY_FREE_FS
3083 && !filesys_free(e->e_msgsize)
3088 ** We perform this test again when the
3089 ** queue directory is selected, in collect.
3092 usrerr("452 4.4.5 Insufficient disk space; try again later");
3093 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3096 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3100 if (smtp.sm_milterlist && smtp.sm_milterize &&
3101 !bitset(EF_DISCARD, e->e_flags))
3106 response = milter_envfrom(args, e, &state);
3107 MILTER_REPLY("from");
3111 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3113 message("250 2.1.0 Sender ok");
3114 smtp.sm_gotmail = true;
3116 SM_EXCEPT(exc, "[!F]*")
3119 ** An error occurred while processing a MAIL command.
3120 ** Jump to the common error handling code.
3130 e->e_flags &= ~EF_PM_NOTIFY;
3134 case CMDRCPT: /* rcpt -- designate recipient */
3136 macdefine(&e->e_macro, A_PERM,
3137 macid("{rcpt_mailer}"), NULL);
3138 macdefine(&e->e_macro, A_PERM,
3139 macid("{rcpt_host}"), NULL);
3140 macdefine(&e->e_macro, A_PERM,
3141 macid("{rcpt_addr}"), NULL);
3143 (void) memset(&addr_st, '\0', sizeof(addr_st));
3145 milter_rcpt_added = false;
3146 smtp.sm_e_nrcpts_orig = e->e_nrcpts;
3148 #if _FFR_BADRCPT_SHUTDOWN
3150 ** hack to deal with hack, see below:
3151 ** n_badrcpts is increased if limit is reached.
3154 n_badrcpts_adj = (BadRcptThrottle > 0 &&
3155 n_badrcpts > BadRcptThrottle &&
3157 ? n_badrcpts - 1 : n_badrcpts;
3158 if (BadRcptShutdown > 0 &&
3159 n_badrcpts_adj >= BadRcptShutdown &&
3160 (BadRcptShutdownGood == 0 ||
3161 smtp.sm_nrcpts == 0 ||
3162 (n_badrcpts_adj * 100 /
3163 (smtp.sm_nrcpts + n_badrcpts) >=
3164 BadRcptShutdownGood)))
3167 sm_syslog(LOG_INFO, e->e_id,
3168 "%s: Possible SMTP RCPT flood, shutting down connection.",
3170 message("421 4.7.0 %s Too many bad recipients; closing connection",
3173 /* arrange to ignore any current send list */
3174 e->e_sendqueue = NULL;
3177 #endif /* _FFR_BADRCPT_SHUTDOWN */
3178 if (BadRcptThrottle > 0 &&
3179 n_badrcpts >= BadRcptThrottle)
3182 n_badrcpts == BadRcptThrottle)
3184 sm_syslog(LOG_INFO, e->e_id,
3185 "%s: Possible SMTP RCPT flood, throttling.",
3188 /* To avoid duplicated message */
3194 ** Don't use exponential backoff for now.
3195 ** Some systems will open more connections
3196 ** and actually overload the receiver even
3200 (void) sleep(BadRcptThrottleDelay);
3202 if (!smtp.sm_gotmail)
3204 usrerr("503 5.0.0 Need MAIL before RCPT");
3207 SmtpPhase = "server RCPT";
3210 #if _FFR_8BITENVADDR
3211 char iaddr[MAXLINE * 2];
3219 /* limit flooding of our machine */
3220 if (MaxRcptPerMsg > 0 &&
3221 smtp.sm_nrcpts >= MaxRcptPerMsg)
3223 /* sleep(1); / * slow down? */
3224 usrerr("452 4.5.3 Too many recipients");
3228 if (!SM_IS_INTERACTIVE(e->e_sendmode)
3230 && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode)
3233 e->e_flags |= EF_VRFYONLY;
3237 ** Do not expand recipients at RCPT time (in the call
3238 ** to recipient()) if a milter can delete or reject
3239 ** a RCPT. If they are expanded, it is impossible
3240 ** for removefromlist() to figure out the expanded
3241 ** members of the original recipient and mark them
3245 if (smtp.sm_milterlist && smtp.sm_milterize &&
3246 !bitset(EF_DISCARD, e->e_flags) &&
3247 (smtp.sm_milters.mis_flags &
3248 (MIS_FL_DEL_RCPT|MIS_FL_REJ_RCPT)) != 0)
3249 e->e_flags |= EF_VRFYONLY;
3250 milter_cmd_done = false;
3251 milter_cmd_safe = false;
3254 p = skipword(p, "to");
3257 macdefine(&e->e_macro, A_PERM,
3258 macid("{addr_type}"), "e r");
3259 #if _FFR_8BITENVADDR
3260 len = sizeof(iaddr);
3263 /* HACK!!!! p is more than the address! */
3264 p = quote_internal_chars(p, iaddr, &len, NULL);
3266 a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr,
3268 macdefine(&e->e_macro, A_PERM,
3269 macid("{addr_type}"), NULL);
3274 usrerr("501 5.0.0 Missing recipient");
3278 CHECK_UTF8_ADDR(a->q_paddr, q);
3286 if (delimptr != NULL && *delimptr != '\0')
3289 #if _FFR_8BITENVADDR
3290 len = sizeof(iaddr) - (delimptr - iaddr);
3291 (void) dequote_internal_chars(delimptr, delimptr, len);
3292 sep_args(delimptr, origp, e->e_id, p);
3296 /* put resulting triple from parseaddr() into macros */
3297 if (a->q_mailer != NULL)
3298 macdefine(&e->e_macro, A_PERM,
3299 macid("{rcpt_mailer}"),
3300 a->q_mailer->m_name);
3302 macdefine(&e->e_macro, A_PERM,
3303 macid("{rcpt_mailer}"), NULL);
3304 if (a->q_host != NULL)
3305 macdefine(&e->e_macro, A_PERM,
3306 macid("{rcpt_host}"), a->q_host);
3308 macdefine(&e->e_macro, A_PERM,
3309 macid("{rcpt_host}"), "localhost");
3310 if (a->q_user != NULL)
3311 macdefine(&e->e_macro, A_PERM,
3312 macid("{rcpt_addr}"), a->q_user);
3314 macdefine(&e->e_macro, A_PERM,
3315 macid("{rcpt_addr}"), NULL);
3319 /* now parse ESMTP arguments */
3320 addr = sm_rpool_strdup_x(e->e_rpool, p);
3321 parse_esmtp_args(e, a, origp, delimptr, "RCPT", args,
3328 ** rscheck() can trigger an "exception"
3329 ** in which case the execution continues at
3330 ** SM_EXCEPT(exc, "[!F]*")
3331 ** This means milter_cmd_safe is not set
3332 ** and hence milter is not invoked.
3333 ** Would it be "safe" to change that, i.e., use
3334 ** milter_cmd_safe = true;
3335 ** here so a milter is informed (if requested)
3336 ** about RCPTs that are rejected by check_rcpt?
3338 # if _FFR_MILTER_CHECK_REJECTIONS_TOO
3339 milter_cmd_safe = true;
3343 /* do config file checking of the recipient */
3344 macdefine(&e->e_macro, A_PERM,
3345 macid("{addr_type}"), "e r");
3346 if (rscheck("check_rcpt", addr,
3347 NULL, e, RSF_RMCOMM|RSF_COUNT, 3,
3348 NULL, e->e_id, p_addr_st, NULL) != EX_OK ||
3351 macdefine(&e->e_macro, A_PERM,
3352 macid("{addr_type}"), NULL);
3354 /* If discarding, don't bother to verify user */
3355 if (bitset(EF_DISCARD, e->e_flags))
3356 a->q_state = QS_VERIFIED;
3358 milter_cmd_safe = true;
3364 /* save in recipient list after ESMTP mods */
3365 a = recipient(a, &e->e_sendqueue, 0, e);
3366 /* may trigger exception... */
3369 milter_rcpt_added = true;
3372 if(!(Errors > 0) && QS_IS_BADADDR(a->q_state))
3374 /* punt -- should keep message in ADDRESS.... */
3375 usrerr("550 5.1.1 Addressee unknown");
3380 if (smtp.sm_milterlist && smtp.sm_milterize &&
3381 !bitset(EF_DISCARD, e->e_flags))
3386 /* how to get the error codes? */
3389 macdefine(&e->e_macro, A_PERM,
3390 macid("{rcpt_mailer}"),
3393 a->q_status != NULL &&
3394 a->q_rstatus != NULL)
3396 macdefine(&e->e_macro, A_PERM,
3397 macid("{rcpt_host}"),
3399 macdefine(&e->e_macro, A_PERM,
3400 macid("{rcpt_addr}"),
3405 if (addr_st.q_host != NULL)
3406 macdefine(&e->e_macro,
3408 macid("{rcpt_host}"),
3410 if (addr_st.q_user != NULL)
3411 macdefine(&e->e_macro,
3413 macid("{rcpt_addr}"),
3418 response = milter_envrcpt(args, e, &state,
3420 milter_cmd_done = true;
3425 /* no errors during parsing, but might be a duplicate */
3426 e->e_to = a->q_paddr;
3427 if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state))
3429 if (smtp.sm_nrcpts == 0)
3431 message("250 2.1.5 Recipient ok%s",
3432 QS_IS_QUEUEUP(a->q_state) ?
3433 " (will queue)" : "");
3437 /* Is this needed? */
3442 macdefine(&e->e_macro, A_PERM,
3443 macid("{rcpt_mailer}"), NULL);
3444 macdefine(&e->e_macro, A_PERM,
3445 macid("{rcpt_host}"), NULL);
3446 macdefine(&e->e_macro, A_PERM,
3447 macid("{rcpt_addr}"), NULL);
3448 macdefine(&e->e_macro, A_PERM,
3449 macid("{dsn_notify}"), NULL);
3457 SM_EXCEPT(exc, "[!F]*")
3459 /* An exception occurred while processing RCPT */
3460 e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY);
3464 if (smtp.sm_milterlist && smtp.sm_milterize &&
3465 !bitset(EF_DISCARD, e->e_flags) &&
3466 !milter_cmd_done && milter_cmd_safe)
3471 macdefine(&e->e_macro, A_PERM,
3472 macid("{rcpt_mailer}"), "error");
3474 /* how to get the error codes? */
3475 if (addr_st.q_host != NULL)
3476 macdefine(&e->e_macro, A_PERM,
3477 macid("{rcpt_host}"),
3479 else if (a != NULL && a->q_status != NULL)
3480 macdefine(&e->e_macro, A_PERM,
3481 macid("{rcpt_host}"),
3484 if (addr_st.q_user != NULL)
3485 macdefine(&e->e_macro, A_PERM,
3486 macid("{rcpt_addr}"),
3488 else if (a != NULL && a->q_rstatus != NULL)
3489 macdefine(&e->e_macro, A_PERM,
3490 macid("{rcpt_addr}"),
3493 response = milter_envrcpt(args, e, &state,
3495 milter_cmd_done = true;
3497 macdefine(&e->e_macro, A_PERM,
3498 macid("{rcpt_mailer}"), NULL);
3499 macdefine(&e->e_macro, A_PERM,
3500 macid("{rcpt_host}"), NULL);
3501 macdefine(&e->e_macro, A_PERM,
3502 macid("{rcpt_addr}"), NULL);
3504 if (smtp.sm_milterlist && smtp.sm_milterize &&
3505 milter_rcpt_added && milter_cmd_done &&
3508 (void) removefromlist(addr, &e->e_sendqueue, e);
3509 milter_cmd_fail = false;
3510 if (smtp.sm_e_nrcpts_orig < e->e_nrcpts)
3511 e->e_nrcpts = smtp.sm_e_nrcpts_orig;
3518 case CMDDATA: /* data -- text of mail */
3520 if (!smtp_data(&smtp, e,
3521 bitset(SRV_BAD_PIPELINE, features)))
3525 case CMDRSET: /* rset -- reset state */
3527 message("451 4.0.0 Test failure");
3529 message("250 2.0.0 Reset state");
3530 CLEAR_STATE(cmdbuf);
3533 case CMDVRFY: /* vrfy -- verify address */
3534 case CMDEXPN: /* expn -- expand address */
3535 vrfy = c->cmd_code == CMDVRFY;
3536 DELAY_CONN(vrfy ? "VRFY" : "EXPN");
3540 sm_syslog(LOG_INFO, e->e_id,
3541 "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)",
3542 vrfy ? "VRFY" : "EXPN",
3545 /* RFC 821 doesn't allow 4xy reply code */
3546 usrerr("550 5.7.1 Please try again later");
3549 wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS,
3550 false, vrfy ? "VRFY" : "EXPN", e);
3552 previous = curtime();
3553 if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) ||
3554 (!vrfy && !bitset(SRV_OFFER_EXPN, features)))
3557 message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
3559 message("502 5.7.0 Sorry, we do not allow this operation");
3561 sm_syslog(LOG_INFO, e->e_id,
3562 "%s: %s [rejected]",
3564 shortenstring(inp, MAXSHORTSTR));
3567 else if (!gothello &&
3568 bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
3571 usrerr("503 5.0.0 I demand that you introduce yourself first");
3577 sm_syslog(LOG_INFO, e->e_id, "%s: %s",
3579 shortenstring(inp, MAXSHORTSTR));
3585 e->e_flags |= EF_VRFYONLY;
3586 while (*p != '\0' && SM_ISSPACE(*p))
3590 usrerr("501 5.5.2 Argument required");
3594 /* do config file checking of the address */
3595 if (rscheck(vrfy ? "check_vrfy" : "check_expn",
3596 p, NULL, e, RSF_RMCOMM, 3, NULL,
3597 NOQID, NULL, NULL) != EX_OK ||
3599 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3600 (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e);
3606 t = wt - (curtime() - previous);
3611 sm_exc_raisenew_x(&EtypeQuickAbort, 1);
3612 if (vrfyqueue == NULL)
3614 usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN");
3616 while (vrfyqueue != NULL)
3618 if (!QS_IS_UNDELIVERED(vrfyqueue->q_state))
3620 vrfyqueue = vrfyqueue->q_next;
3624 /* see if there is more in the vrfy list */
3626 while ((a = a->q_next) != NULL &&
3627 (!QS_IS_UNDELIVERED(a->q_state)))
3629 printvrfyaddr(vrfyqueue, a == NULL, vrfy);
3633 SM_EXCEPT(exc, "[!F]*")
3636 ** An exception occurred while processing VRFY/EXPN
3645 case CMDETRN: /* etrn -- force queue flush */
3648 /* Don't leak queue information via debug flags */
3649 if (!bitset(SRV_OFFER_ETRN, features) || UseMSP ||
3650 (RealUid != 0 && RealUid != TrustedUid &&
3653 /* different message for MSA ? */
3654 message("502 5.7.0 Sorry, we do not allow this operation");
3656 sm_syslog(LOG_INFO, e->e_id,
3657 "%s: %s [rejected]",
3659 shortenstring(inp, MAXSHORTSTR));
3665 sm_syslog(LOG_INFO, e->e_id,
3666 "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)",
3668 /* Can't use ("%s", ...) due to usrerr() requirements */
3669 usrerr(MSG_TEMPFAIL);
3675 usrerr("500 5.5.2 Parameter required");
3679 /* crude way to avoid denial-of-service attacks */
3680 STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS,
3684 ** Do config file checking of the parameter.
3685 ** Even though we have srv_features now, we still
3686 ** need this ruleset because the former is called
3687 ** when the connection has been established, while
3688 ** this ruleset is called when the command is
3689 ** actually issued and therefore has all information
3690 ** available to make a decision.
3693 if (rscheck("check_etrn", p, NULL, e, RSF_RMCOMM, 3,
3694 NULL, NOQID, NULL, NULL) != EX_OK ||
3699 sm_syslog(LOG_INFO, e->e_id,
3700 "%s: ETRN %s", CurSmtpClient,
3701 shortenstring(p, MAXSHORTSTR));
3709 qgrp = name2qid(id);
3710 if (!ISVALIDQGRP(qgrp))
3712 usrerr("459 4.5.4 Queue %s unknown",
3716 for (i = 0; i < NumQueue && Queue[i] != NULL;
3718 Queue[i]->qg_nextrun = (time_t) -1;
3719 Queue[qgrp]->qg_nextrun = 0;
3720 ok = run_work_group(Queue[qgrp]->qg_wgrp,
3721 RWG_FORK|RWG_FORCE);
3722 if (ok && Errors == 0)
3723 message("250 2.0.0 Queuing for queue group %s started", id);
3732 new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR));
3735 syserr("500 5.5.0 ETRN out of memory");
3738 new->queue_match = id;
3739 new->queue_negate = false;
3740 new->queue_next = NULL;
3741 QueueLimitRecipient = new;
3742 ok = runqueue(true, false, false, true);
3743 sm_free(QueueLimitRecipient); /* XXX */
3744 QueueLimitRecipient = NULL;
3745 if (ok && Errors == 0)
3746 message("250 2.0.0 Queuing for node %s started", p);
3749 case CMDHELP: /* help -- give user info */
3754 #define CHECK_OTHER(type) do \
3756 bool saveQuickAbort = QuickAbort; \
3757 extern char MsgBuf[]; \
3759 QuickAbort = false; \
3760 if ((rsc = rscheck("check_other", inp, type, e, \
3761 RSF_UNSTRUCTURED, 3, NULL, NOQID, NULL, NULL)) \
3765 if (strncmp(MsgBuf, "421 ", 4) == 0) \
3767 e->e_sendqueue = NULL; \
3771 QuickAbort = saveQuickAbort; \
3774 case CMDNOOP: /* noop -- do nothing */
3776 STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3779 message("250 2.0.0 OK");
3782 case CMDQUIT: /* quit -- leave mail */
3783 message("221 2.0.0 %s closing connection", MyHostName);
3785 (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
3788 if (smtp.sm_nrcpts > 0)
3789 logundelrcpts(e, "aborted by sender", 9, false);
3791 /* arrange to ignore any current send list */
3792 e->e_sendqueue = NULL;
3795 /* shutdown TLS connection */
3798 (void) endtls(&srv_ssl, "server");
3801 #endif /* STARTTLS */
3805 sasl_dispose(&conn);
3806 authenticating = SASL_NOT_AUTH;
3807 /* XXX sasl_done(); this is a child */
3812 /* avoid future 050 messages */
3816 /* close out milter filters */
3821 sm_dprintf("QUIT: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
3823 bitset(EF_LOGSENDER, e->e_flags),
3825 if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
3827 e->e_flags &= ~EF_LOGSENDER;
3829 if (lognullconnection && LogLevel > 5 &&
3834 d = macvalue(macid("{daemon_name}"), e);
3839 ** even though this id is "bogus", it makes
3840 ** it simpler to "grep" related events, e.g.,
3841 ** timeouts for the same connection.
3844 sm_syslog(LOG_INFO, e->e_id,
3845 "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s",
3850 /* return to handle next connection */
3852 # define SM_HC_TRIGGER "heapdump"
3853 if (sm_debug_active(&SmHeapCheck, 2)
3854 && access(SM_HC_TRIGGER, F_OK) == 0
3859 remove(SM_HC_TRIGGER);
3860 out = sm_io_open(SmFtStdio,
3861 SM_TIME_DEFAULT, SM_HC_TRIGGER ".heap",
3862 SM_IO_APPEND, NULL);
3865 (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "----------------------\n");
3867 sm_debug_level(&SmHeapCheck) - 1);
3868 (void) sm_io_close(out, SM_TIME_DEFAULT);
3871 #endif /* SM_HEAP_CHECK */
3874 finis(true, true, ExitStat);
3877 /* just to avoid bogus warning from some compilers */
3880 case CMDVERB: /* set verbose mode */
3882 if (!bitset(SRV_OFFER_EXPN, features) ||
3883 !bitset(SRV_OFFER_VERB, features))
3885 /* this would give out the same info */
3886 message("502 5.7.0 Verbose unavailable");
3889 STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands,
3893 set_delivery_mode(SM_DELIVER, e);
3894 message("250 2.0.0 Verbose mode");
3898 case CMDDBGQSHOW: /* show queues */
3900 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
3902 printaddr(smioout, e->e_sendqueue, true);
3905 case CMDDBGDEBUG: /* set debug mode */
3907 tTsetup(tTdvect, sizeof(tTdvect), "0-99.1");
3909 message("200 2.0.0 Debug set");
3912 #else /* SMTPDEBUG */
3913 case CMDDBGQSHOW: /* show queues */
3914 case CMDDBGDEBUG: /* set debug mode */
3915 #endif /* SMTPDEBUG */
3916 case CMDLOGBOGUS: /* bogus command */
3917 DELAY_CONN("Bogus");
3919 sm_syslog(LOG_CRIT, e->e_id,
3920 "\"%s\" command from %s (%.100s)",
3921 c->cmd_name, CurSmtpClient,
3922 anynet_ntoa(&RealHostAddr));
3925 case CMDERROR: /* unknown command */
3926 #if MAXBADCOMMANDS > 0
3927 if (++n_badcmds > MAXBADCOMMANDS)
3930 message("421 4.7.0 %s Too many bad commands; closing connection",
3933 /* arrange to ignore any current send list */
3934 e->e_sendqueue = NULL;
3937 #endif /* MAXBADCOMMANDS > 0 */
3939 #if MILTER && SMFI_VERSION > 2
3940 if (smtp.sm_milterlist && smtp.sm_milterize &&
3941 !bitset(EF_DISCARD, e->e_flags))
3946 if (MilterLogLevel > 9)
3947 sm_syslog(LOG_INFO, e->e_id,
3948 "Sending \"%s\" to Milter", inp);
3949 response = milter_unknown(inp, e, &state);
3950 MILTER_REPLY("unknown");
3951 if (state == SMFIR_REPLYCODE ||
3952 state == SMFIR_REJECT ||
3953 state == SMFIR_TEMPFAIL ||
3954 state == SMFIR_SHUTDOWN)
3956 /* MILTER_REPLY already gave an error */
3960 #endif /* MILTER && SMFI_VERSION > 2 */
3963 usrerr("500 5.5.1 Command unrecognized: \"%s\"",
3964 SHOWSHRTCMDINREPLY(inp));
3968 DELAY_CONN("Unimpl");
3970 usrerr("502 5.5.1 Command not implemented: \"%s\"",
3971 SHOWSHRTCMDINREPLY(inp));
3975 DELAY_CONN("default");
3978 syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code);
3985 SM_EXCEPT(exc, "[!F]*")
3988 ** The only possible exception is "E:mta.quickabort".
3989 ** There is nothing to do except fall through and loop.
3996 ** SMTP_DATA -- implement the SMTP DATA command.
3999 ** smtp -- status of SMTP connection.
4001 ** check_stuffing -- check for transaction stuffing.
4004 ** true iff SMTP session can continue.
4007 ** possibly sends message.
4011 smtp_data(smtp, e, check_stuffing)
4014 bool check_stuffing;
4026 unsigned long features;
4029 SmtpPhase = "server DATA";
4030 if (!smtp->sm_gotmail)
4032 usrerr("503 5.0.0 Need MAIL command");
4035 else if (smtp->sm_nrcpts <= 0)
4037 usrerr("503 5.0.0 Need RCPT (recipient)");
4041 /* check if data is on the socket before the DATA reply */
4042 if (check_stuffing &&
4043 sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0)
4045 sm_syslog(LOG_INFO, e->e_id,
4046 "rejecting %s from %s [%s] due to traffic before response",
4047 SmtpPhase, CurHostName, anynet_ntoa(&RealHostAddr));
4048 usrerr("554 5.5.0 SMTP protocol error");
4052 (void) sm_snprintf(buf, sizeof(buf), "%u", smtp->sm_nrcpts);
4053 if (rscheck("check_data", buf, NULL, e,
4054 RSF_RMCOMM|RSF_UNSTRUCTURED|RSF_COUNT, 3, NULL,
4055 e->e_id, NULL, NULL) != EX_OK)
4058 #if MILTER && SMFI_VERSION > 3
4059 if (smtp->sm_milterlist && smtp->sm_milterize &&
4060 !bitset(EF_DISCARD, e->e_flags))
4064 int savelogusrerrs = LogUsrErrs;
4066 response = milter_data_cmd(e, &state);
4069 case SMFIR_REPLYCODE:
4070 if (MilterLogLevel > 3)
4072 sm_syslog(LOG_INFO, e->e_id,
4073 "Milter: cmd=data, reject=%s",
4077 # if _FFR_MILTER_ENHSC
4078 if (ISSMTPCODE(response))
4079 (void) extenhsc(response + 4, ' ', e->e_enhsc);
4082 /* Can't use ("%s", ...) due to usrerr() requirements */
4084 if (strncmp(response, "421 ", 4) == 0
4085 || strncmp(response, "421-", 4) == 0)
4087 e->e_sendqueue = NULL;
4093 if (MilterLogLevel > 3)
4095 sm_syslog(LOG_INFO, e->e_id,
4096 "Milter: cmd=data, reject=550 5.7.1 Command rejected");
4099 # if _FFR_MILTER_ENHSC
4100 (void) sm_strlcpy(e->e_enhsc, "5.7.1",
4101 sizeof(e->e_enhsc));
4103 usrerr("550 5.7.1 Command rejected");
4107 if (MilterLogLevel > 3)
4108 sm_syslog(LOG_INFO, e->e_id,
4109 "Milter: cmd=data, discard");
4110 e->e_flags |= EF_DISCARD;
4113 case SMFIR_TEMPFAIL:
4114 if (MilterLogLevel > 3)
4116 sm_syslog(LOG_INFO, e->e_id,
4117 "Milter: cmd=data, reject=%s",
4121 # if _FFR_MILTER_ENHSC
4122 (void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
4124 /* Can't use ("%s", ...) due to usrerr() requirements */
4125 usrerr(MSG_TEMPFAIL);
4128 case SMFIR_SHUTDOWN:
4129 if (MilterLogLevel > 3)
4131 sm_syslog(LOG_INFO, e->e_id,
4132 "Milter: cmd=data, reject=421 4.7.0 %s closing connection",
4136 usrerr("421 4.7.0 %s closing connection", MyHostName);
4137 e->e_sendqueue = NULL;
4140 LogUsrErrs = savelogusrerrs;
4141 if (response != NULL)
4142 sm_free(response); /* XXX */
4144 #endif /* MILTER && SMFI_VERSION > 3 */
4146 /* put back discard bit */
4147 if (smtp->sm_discard)
4148 e->e_flags |= EF_DISCARD;
4150 /* check to see if we need to re-expand aliases */
4151 /* also reset QS_BADADDR on already-diagnosted addrs */
4152 doublequeue = false;
4153 for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4155 if (QS_IS_VERIFIED(a->q_state) &&
4156 !bitset(EF_DISCARD, e->e_flags))
4158 /* need to re-expand aliases */
4161 if (QS_IS_BADADDR(a->q_state))
4163 /* make this "go away" */
4164 a->q_state = QS_DONTSEND;
4168 /* collect the text of the message */
4169 SmtpPhase = "collect";
4172 collect(InChannel, SMTPMODE_LAX
4173 | (bitset(SRV_BARE_LF_421, e->e_features) ? SMTPMODE_LF_421 : 0)
4174 | (bitset(SRV_BARE_CR_421, e->e_features) ? SMTPMODE_CR_421 : 0)
4175 | (bitset(SRV_BARE_LF_SP, e->e_features) ? SMTPMODE_LF_SP : 0)
4176 | (bitset(SRV_BARE_CR_SP, e->e_features) ? SMTPMODE_CR_SP : 0)
4177 | (bitset(SRV_REQ_CRLF, e->e_features) ? SMTPMODE_CRLF : 0),
4180 /* redefine message size */
4181 (void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4182 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4184 /* rscheck() will set Errors or EF_DISCARD if it trips */
4185 (void) rscheck("check_eom", buf, NULL, e, RSF_UNSTRUCTURED|RSF_COUNT,
4186 3, NULL, e->e_id, NULL, NULL);
4189 milteraccept = true;
4190 if (smtp->sm_milterlist && smtp->sm_milterize &&
4192 !bitset(EF_DISCARD, e->e_flags))
4197 response = milter_data(e, &state);
4200 case SMFIR_REPLYCODE:
4201 if (MilterLogLevel > 3)
4202 sm_syslog(LOG_INFO, e->e_id,
4203 "Milter: data, reject=%s",
4205 milteraccept = false;
4206 # if _FFR_MILTER_ENHSC
4207 if (ISSMTPCODE(response))
4208 (void) extenhsc(response + 4, ' ', e->e_enhsc);
4210 /* Can't use ("%s", ...) due to usrerr() requirements */
4212 if (strncmp(response, "421 ", 4) == 0
4213 || strncmp(response, "421-", 4) == 0)
4218 milteraccept = false;
4219 if (MilterLogLevel > 3)
4220 sm_syslog(LOG_INFO, e->e_id,
4221 "Milter: data, reject=554 5.7.1 Command rejected");
4222 usrerr("554 5.7.1 Command rejected");
4226 if (MilterLogLevel > 3)
4227 sm_syslog(LOG_INFO, e->e_id,
4228 "Milter: data, discard");
4229 milteraccept = false;
4230 e->e_flags |= EF_DISCARD;
4233 case SMFIR_TEMPFAIL:
4234 if (MilterLogLevel > 3)
4235 sm_syslog(LOG_INFO, e->e_id,
4236 "Milter: data, reject=%s",
4238 milteraccept = false;
4239 # if _FFR_MILTER_ENHSC
4240 (void) extenhsc(MSG_TEMPFAIL + 4, ' ', e->e_enhsc);
4242 /* Can't use ("%s", ...) due to usrerr() requirements */
4243 usrerr(MSG_TEMPFAIL);
4246 case SMFIR_SHUTDOWN:
4247 if (MilterLogLevel > 3)
4248 sm_syslog(LOG_INFO, e->e_id,
4249 "Milter: data, reject=421 4.7.0 %s closing connection",
4251 milteraccept = false;
4252 usrerr("421 4.7.0 %s closing connection", MyHostName);
4256 if (response != NULL)
4260 /* Milter may have changed message size */
4261 (void) sm_snprintf(buf, sizeof(buf), "%ld", PRT_NONNEGL(e->e_msgsize));
4262 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), buf);
4264 /* abort message filters that didn't get the body & log msg is OK */
4265 if (smtp->sm_milterlist && smtp->sm_milterize)
4268 if (milteraccept && MilterLogLevel > 9)
4269 sm_syslog(LOG_INFO, e->e_id, "Milter accept: message");
4273 ** If SuperSafe is SAFE_REALLY_POSTMILTER, and we don't have milter or
4274 ** milter accepted message, sync it now
4276 ** XXX This is almost a copy of the code in collect(): put it into
4277 ** a function that is called from both places?
4280 if (milteraccept && SuperSafe == SAFE_REALLY_POSTMILTER)
4283 SM_FILE_T *volatile df;
4287 dfname = queuename(e, DATAFL_LETTER);
4288 if (sm_io_setinfo(df, SM_BF_COMMIT, NULL) < 0
4294 if (save_errno == EEXIST)
4299 if (stat(dfname, &st) < 0)
4302 syserr("@collect: bfcommit(%s): already on disk, size=%ld",
4303 dfname, (long) st.st_size);
4304 dfd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL);
4306 dumpfd(dfd, true, true);
4309 dferror(df, "bfcommit", e);
4311 finis(save_errno != EEXIST, true, ExitStat);
4313 else if ((afd = sm_io_getinfo(df, SM_IO_WHAT_FD, NULL)) < 0)
4315 dferror(df, "sm_io_getinfo", e);
4317 finis(true, true, ExitStat);
4320 else if (fsync(afd) < 0)
4322 dferror(df, "fsync", e);
4324 finis(true, true, ExitStat);
4327 else if (sm_io_close(df, SM_TIME_DEFAULT) < 0)
4329 dferror(df, "sm_io_close", e);
4331 finis(true, true, ExitStat);
4335 /* Now reopen the df file */
4336 e->e_dfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, dfname,
4337 SM_IO_RDONLY, NULL);
4338 if (e->e_dfp == NULL)
4340 /* we haven't acked receipt yet, so just chuck this */
4341 syserr("@Cannot reopen %s", dfname);
4342 finis(true, true, ExitStat);
4348 /* Check if quarantining stats should be updated */
4349 if (e->e_quarmsg != NULL)
4350 markstats(e, NULL, STATS_QUARANTINE);
4353 ** If a header/body check (header checks or milter)
4354 ** set EF_DISCARD, don't queueup the message --
4355 ** that would lose the EF_DISCARD bit and deliver
4359 if (bitset(EF_DISCARD, e->e_flags))
4360 doublequeue = false;
4362 aborting = Errors > 0;
4363 if (!(aborting || bitset(EF_DISCARD, e->e_flags)) &&
4364 (QueueMode == QM_QUARANTINE || e->e_quarmsg == NULL) &&
4365 !split_by_recipient(e))
4366 aborting = bitset(EF_FATALERRS, e->e_flags);
4372 /* Log who the mail would have gone to */
4373 logundelrcpts(e, e->e_message, 8, false);
4376 ** If something above refused the message, we still haven't
4377 ** accepted responsibility for it. Don't send DSNs.
4380 for (q = e->e_sendqueue; q != NULL; q = q->q_next)
4381 q->q_flags &= ~Q_PINGFLAGS;
4388 /* from now on, we have to operate silently */
4393 ** Clear message, it may contain an error from the SMTP dialogue.
4394 ** This error must not show up in the queue.
4395 ** Some error message should show up, e.g., alias database
4396 ** not available, but others shouldn't, e.g., from check_rcpt.
4399 e->e_message = NULL;
4403 ** Arrange to send to everyone.
4404 ** If sending to multiple people, mail back
4405 ** errors rather than reporting directly.
4406 ** In any case, don't mail back errors for
4407 ** anything that has happened up to
4408 ** now (the other end will do this).
4409 ** Truncate our transcript -- the mail has gotten
4410 ** to us successfully, and if we have
4411 ** to mail this back, it will be easier
4413 ** Then send to everyone.
4414 ** Finally give a reply code. If an error has
4415 ** already been given, don't mail a
4417 ** We goose error returns by clearing error bit.
4420 SmtpPhase = "delivery";
4421 (void) sm_io_setinfo(e->e_xfp, SM_BF_TRUNCATE, NULL);
4425 _res.retry = TimeOuts.res_retry[RES_TO_FIRST];
4426 _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST];
4430 if (SM_PROXY_REQ == e->e_sendmode)
4432 /* is proxy mode possible? */
4433 if (e->e_sibling == NULL && e->e_nrcpts == 1
4434 && smtp->sm_nrcpts == 1
4435 && (a = e->e_sendqueue) != NULL && a->q_next == NULL)
4437 a->q_flags &= ~(QPINGONFAILURE|QPINGONSUCCESS|
4439 e->e_errormode = EM_QUIET;
4440 e->e_sendmode = SM_PROXY;
4447 sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, sm_nrcpts=%d, sendqueue=%p, next=%p\n",
4448 e->e_sendmode, e, e->e_sibling, e->e_nrcpts,
4450 (a == NULL) ? (void *)0 : a->q_next);
4453 /* switch to interactive mode */
4454 e->e_sendmode = SM_DELIVER;
4456 sm_syslog(LOG_DEBUG, e->e_id,
4457 "proxy mode requested but not possible");
4460 #endif /* _FFR_PROXY */
4463 if (SM_TRIGGER == e->e_sendmode)
4466 for (ee = e; ee != NULL; ee = ee->e_sibling)
4468 /* make sure we actually do delivery */
4469 ee->e_flags &= ~EF_CLRQUEUE;
4471 /* from now on, operate silently */
4472 ee->e_errormode = EM_MAIL;
4476 unsigned int qup_flags;
4478 qup_flags = QUP_FL_MSYNC;
4480 if (IS_SM_TRIGGER(ee->e_sendmode))
4481 qup_flags |= QUP_FL_UNLOCK;
4483 /* make sure it is in the queue */
4484 queueup(ee, qup_flags);
4490 /* send to all recipients */
4493 if (SM_DM_ONE == e->e_sendmode)
4495 if (NotFirstDelivery)
4498 e->e_sendmode = SM_QUEUE;
4503 NotFirstDelivery = true;
4506 #endif /* _FFR_DM_ONE */
4512 /* put back id for SMTP logging in putoutmsg() */
4513 oldid = CurEnv->e_id;
4520 sm_dprintf("srv: mode=%c, e=%p, sibling=%p, nrcpts=%d, msg=%s, sendqueue=%p, next=%p, state=%d, SmtpError=%s, rcode=%d, renhsc=%s, text=%s\n",
4521 e->e_sendmode, e, e->e_sibling, e->e_nrcpts, e->e_message, a,
4522 (a == NULL) ? (void *)0 : a->q_next,
4523 (a == NULL) ? -1 : a->q_state, SmtpError, e->e_rcode,
4524 e->e_renhsc, e->e_text);
4527 if (SM_PROXY == e->e_sendmode && a->q_state != QS_SENT &&
4528 a->q_state != QS_VERIFIED) /* discarded! */
4535 #define NN_MSG(e) (((e)->e_message != NULL) ? (e)->e_message : "")
4537 #define SM_MSG_DEFERRED "Deferred: "
4538 if (m != NULL && strncmp(SM_MSG_DEFERRED, m,
4539 sizeof(SM_MSG_DEFERRED) - 1) == 0)
4540 m += sizeof(SM_MSG_DEFERRED) - 1;
4541 offset = extsc(m, ' ', replycode, enhsc);
4545 sm_dprintf("srv: SmtpError=%s, rcode=%d, renhsc=%s, replycode=%s, enhsc=%s, offset=%d\n",
4546 SmtpError, e->e_rcode, e->e_renhsc,
4547 replycode, enhsc, offset);
4550 #define DIG2CHAR(d) ((d) + '0')
4551 if (e->e_rcode != 0 && (replycode[0] == '\0' ||
4552 replycode[0] == DIG2CHAR(REPLYTYPE(e->e_rcode))))
4554 replycode[0] = DIG2CHAR(REPLYTYPE(e->e_rcode));
4555 replycode[1] = DIG2CHAR(REPLYCLASS(e->e_rcode));
4556 replycode[2] = DIG2CHAR(REPLYMINOR(e->e_rcode));
4557 replycode[3] = '\0';
4558 if (e->e_renhsc[0] == replycode[0])
4559 sm_strlcpy(enhsc, e->e_renhsc, sizeof(enhsc));
4563 if (e->e_text != NULL)
4565 (void) strreplnonprt(e->e_text, '_');
4566 errtext = e->e_text;
4569 errtext = m + offset;
4571 if (replycode[0] != '\0' && enhsc[0] != '\0')
4572 emessage(replycode, enhsc, "%s", errtext);
4573 else if (replycode[0] != '\0')
4574 emessage(replycode, smtptodsn(atoi(replycode)),
4576 else if (QS_IS_TEMPFAIL(a->q_state))
4579 message("450 4.5.1 %s", m);
4581 message("450 4.5.1 Temporary error");
4586 message("550 5.5.1 %s", m);
4588 message("550 5.0.0 Permanent error");
4593 #endif /* _FFR_PROXY */
4594 /* issue success message */
4596 if (MessageAccept != NULL && *MessageAccept != '\0')
4600 expand(MessageAccept, msg, sizeof(msg), e);
4601 message("250 2.0.0 %s", msg);
4604 #endif /* _FFR_MSG_ACCEPT */
4605 /* "else" in #if code above */
4606 message("250 2.0.0 %s Message accepted for delivery", id);
4610 CurEnv->e_id = oldid;
4612 /* if we just queued, poke it */
4615 bool anything_to_send = false;
4618 for (ee = e; ee != NULL; ee = ee->e_sibling)
4621 if (SM_TRIGGER == ee->e_sendmode)
4623 sm_syslog(LOG_DEBUG, ee->e_id,
4624 "smtp: doublequeue, mode=%c", ee->e_sendmode);
4625 ee->e_sendmode = SM_DELIVER;
4627 /* close all the queue files */
4628 /* almost the same as below */
4630 SM_CLOSE_FP(ee->e_dfp);
4633 #endif /* _FFR_DMTRIGGER */
4634 if (WILL_BE_QUEUED(ee->e_sendmode))
4636 if (shouldqueue(ee->e_msgpriority, ee->e_ctime))
4638 ee->e_sendmode = SM_QUEUE;
4641 else if (QueueMode != QM_QUARANTINE &&
4642 ee->e_quarmsg != NULL)
4644 ee->e_sendmode = SM_QUEUE;
4647 anything_to_send = true;
4649 /* close all the queue files */
4651 SM_CLOSE_FP(ee->e_dfp);
4654 if (anything_to_send)
4658 ** XXX if we don't do this, we get 250 twice
4659 ** because it is also flushed in the child.
4662 (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT);
4663 #endif /* PIPELINING */
4665 sm_syslog(LOG_DEBUG, e->e_id, "smtp: doublequeue=send");
4667 (void) doworklist(e, true, true);
4673 sm_dprintf("abortmessage: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
4674 e->e_id, bitset(EF_LOGSENDER, e->e_flags), LogLevel);
4675 if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
4677 e->e_flags &= ~EF_LOGSENDER;
4679 /* clean up a bit */
4680 smtp->sm_gotmail = false;
4683 ** Call dropenvelope if and only if the envelope is *not*
4684 ** being processed by the child process forked by doworklist().
4687 if (aborting || bitset(EF_DISCARD, e->e_flags))
4688 (void) dropenvelope(e, true, false);
4691 for (ee = e; ee != NULL; ee = ee->e_sibling)
4694 QueueMode != QM_QUARANTINE &&
4695 ee->e_quarmsg != NULL)
4697 (void) dropenvelope(ee, true, false);
4700 if (WILL_BE_QUEUED(ee->e_sendmode))
4701 (void) dropenvelope(ee, true, false);
4706 features = e->e_features;
4707 sm_rpool_free(e->e_rpool);
4708 newenvelope(e, e, sm_rpool_new_x(NULL));
4709 e->e_flags = BlankEnvelope.e_flags;
4710 e->e_features = features;
4712 /* restore connection quarantining */
4713 if (smtp->sm_quarmsg == NULL)
4715 e->e_quarmsg = NULL;
4716 macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), "");
4720 e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, smtp->sm_quarmsg);
4721 macdefine(&e->e_macro, A_PERM,
4722 macid("{quarantine}"), e->e_quarmsg);
4727 ** LOGUNDELRCPTS -- log undelivered (or all) recipients.
4731 ** msg -- message for Stat=
4732 ** level -- log level.
4733 ** all -- log all recipients.
4739 ** logs undelivered (or all) recipients
4743 logundelrcpts(e, msg, level, all)
4751 if (LogLevel <= level || msg == NULL || *msg == '\0')
4754 /* Clear $h so relay= doesn't get mislogged by logdelivery() */
4755 macdefine(&e->e_macro, A_PERM, 'h', NULL);
4757 /* Log who the mail would have gone to */
4758 for (a = e->e_sendqueue; a != NULL; a = a->q_next)
4760 if (!QS_IS_UNDELIVERED(a->q_state) && !all)
4762 e->e_to = a->q_paddr;
4763 logdelivery(NULL, NULL,
4764 #if _FFR_MILTER_ENHSC
4765 (a->q_status == NULL && e->e_enhsc[0] != '\0')
4768 /* not yet documented or tested */
4769 #if _FFR_USE_E_STATUS
4770 (NULL == a->q_status) ? e->e_status :
4773 msg, NULL, (time_t) 0, e, a, EX_OK /* ??? */);
4778 ** CHECKSMTPATTACK -- check for denial-of-service attack by repetition
4781 ** pcounter -- pointer to a counter for this command.
4782 ** maxcount -- maximum value for this counter before we
4784 ** waitnow -- sleep now (in this routine)?
4785 ** cname -- command name for logging.
4786 ** e -- the current envelope.
4790 ** STOP_ATTACK if twice as many commands as allowed and
4794 ** Slows down if we seem to be under attack.
4798 checksmtpattack(pcounter, maxcount, waitnow, cname, e)
4799 volatile unsigned int *pcounter;
4800 unsigned int maxcount;
4805 if (maxcount <= 0) /* no limit */
4808 if (++(*pcounter) >= maxcount)
4813 if (*pcounter == maxcount && LogLevel > 5)
4815 sm_syslog(LOG_INFO, e->e_id,
4816 "%s: possible SMTP attack: command=%.40s, count=%u",
4817 CurSmtpClient, cname, *pcounter);
4819 shift = *pcounter - maxcount;
4821 if (shift > MAXSHIFT || s >= MAXTIMEOUT || s <= 0)
4824 #define IS_ATTACK(s) ((MaxChildren > 0 && *pcounter >= maxcount * 2) \
4825 ? STOP_ATTACK : (time_t) s)
4827 /* sleep at least 1 second before returning */
4828 (void) sleep(*pcounter / maxcount);
4829 s -= *pcounter / maxcount;
4830 if (s >= MAXTIMEOUT || s < 0)
4832 if (waitnow && s > 0)
4835 return IS_ATTACK(0);
4837 return IS_ATTACK(s);
4842 ** SETUP_SMTPD_IO -- setup I/O fd correctly for the SMTP server
4851 ** may change I/O fd.
4857 int inchfd, outchfd, outfd;
4859 inchfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL);
4860 outchfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL);
4861 outfd = sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL);
4862 if (outchfd != outfd)
4864 /* arrange for debugging output to go to remote host */
4865 (void) dup2(outchfd, outfd);
4869 ** if InChannel and OutChannel are stdin/stdout
4870 ** and connected to ttys
4871 ** and fcntl(STDIN, F_SETFL, O_NONBLOCKING) also changes STDOUT,
4872 ** then "chain" them together.
4875 if (inchfd == STDIN_FILENO && outchfd == STDOUT_FILENO &&
4876 isatty(inchfd) && isatty(outchfd))
4878 int inmode, outmode;
4880 inmode = fcntl(inchfd, F_GETFL, 0);
4884 sm_syslog(LOG_INFO, NOQID,
4885 "fcntl(inchfd, F_GETFL) failed: %s",
4886 sm_errstring(errno));
4889 outmode = fcntl(outchfd, F_GETFL, 0);
4893 sm_syslog(LOG_INFO, NOQID,
4894 "fcntl(outchfd, F_GETFL) failed: %s",
4895 sm_errstring(errno));
4898 if (bitset(O_NONBLOCK, inmode) ||
4899 bitset(O_NONBLOCK, outmode) ||
4900 fcntl(inchfd, F_SETFL, inmode | O_NONBLOCK) == -1)
4902 outmode = fcntl(outchfd, F_GETFL, 0);
4903 if (outmode != -1 && bitset(O_NONBLOCK, outmode))
4905 /* changing InChannel also changes OutChannel */
4906 sm_io_automode(OutChannel, InChannel);
4907 if (tTd(97, 4) && LogLevel > 9)
4908 sm_syslog(LOG_INFO, NOQID,
4909 "set automode for I (%d)/O (%d) in SMTP server",
4913 /* undo change of inchfd */
4914 (void) fcntl(inchfd, F_SETFL, inmode);
4918 ** SKIPWORD -- skip a fixed word.
4921 ** p -- place to start looking.
4922 ** w -- word to skip.
4929 ** clobbers the p data area.
4934 register char *volatile p;
4940 /* find beginning of word */
4944 /* find end of word */
4945 while (*p != '\0' && *p != ':' && !(SM_ISSPACE(*p)))
4947 while (SM_ISSPACE(*p))
4952 usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"",
4953 SHOWSHRTCMDINREPLY(firstp));
4962 /* see if the input word matches desired word */
4963 if (sm_strcasecmp(q, w))
4970 ** RESET_MAIL_ESMTP_ARGS -- reset ESMTP arguments for MAIL
4973 ** e -- the envelope.
4980 reset_mail_esmtp_args(e)
4983 /* "size": no reset */
4986 e->e_flags &= ~EF_7BITBODY;
4987 e->e_bodytype = NULL;
4991 macdefine(&e->e_macro, A_PERM, macid("{dsn_envid}"), NULL);
4994 e->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
4995 macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), NULL);
4999 macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"), NULL);
5000 e->e_auth_param = "";
5001 # if _FFR_AUTH_PASSING
5002 macdefine(&BlankEnvelope.e_macro, A_PERM,
5003 macid("{auth_author}"), NULL);
5008 e->e_deliver_by = 0;
5013 ** MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
5016 ** a -- address (unused, for compatibility with rcpt_esmtp_args)
5017 ** kp -- the parameter key.
5018 ** vp -- the value of that parameter.
5019 ** e -- the envelope.
5026 mail_esmtp_args(a, kp, vp, e)
5032 if (SM_STRCASEEQ(kp, "size"))
5036 usrerr("501 5.5.2 SIZE requires a value");
5039 macdefine(&e->e_macro, A_TEMP, macid("{msg_size}"), vp);
5041 e->e_msgsize = strtol(vp, (char **) NULL, 10);
5042 if (e->e_msgsize == LONG_MAX && errno == ERANGE)
5044 usrerr("552 5.2.3 Message size exceeds maximum value");
5047 if (e->e_msgsize < 0)
5049 usrerr("552 5.2.3 Message size invalid");
5053 else if (SM_STRCASEEQ(kp, "body"))
5057 usrerr("501 5.5.2 BODY requires a value");
5060 else if (SM_STRCASEEQ(vp, "8bitmime"))
5062 else if (SM_STRCASEEQ(vp, "7bit"))
5063 e->e_flags |= EF_7BITBODY;
5066 usrerr("501 5.5.4 Unknown BODY type %s",
5067 SHOWCMDINREPLY(vp));
5070 e->e_bodytype = sm_rpool_strdup_x(e->e_rpool, vp);
5072 else if (SM_STRCASEEQ(kp, "envid"))
5074 if (!bitset(SRV_OFFER_DSN, e->e_features))
5076 usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN");
5081 usrerr("501 5.5.2 ENVID requires a value");
5086 usrerr("501 5.5.4 Syntax error in ENVID parameter value");
5089 if (e->e_envid != NULL)
5091 usrerr("501 5.5.0 Duplicate ENVID parameter");
5094 e->e_envid = sm_rpool_strdup_x(e->e_rpool, vp);
5095 macdefine(&e->e_macro, A_PERM,
5096 macid("{dsn_envid}"), e->e_envid);
5098 else if (SM_STRCASEEQ(kp, "ret"))
5100 if (!bitset(SRV_OFFER_DSN, e->e_features))
5102 usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN");
5107 usrerr("501 5.5.2 RET requires a value");
5110 if (bitset(EF_RET_PARAM, e->e_flags))
5112 usrerr("501 5.5.0 Duplicate RET parameter");
5115 e->e_flags |= EF_RET_PARAM;
5116 if (SM_STRCASEEQ(vp, "hdrs"))
5117 e->e_flags |= EF_NO_BODY_RETN;
5118 else if (sm_strcasecmp(vp, "full") != 0)
5120 usrerr("501 5.5.2 Bad argument \"%s\" to RET",
5121 SHOWCMDINREPLY(vp));
5124 macdefine(&e->e_macro, A_TEMP, macid("{dsn_ret}"), vp);
5127 else if (SM_STRCASEEQ(kp, "auth"))
5131 char *auth_param; /* the value of the AUTH=x */
5132 bool saveQuickAbort = QuickAbort;
5133 bool saveSuprErrs = SuprErrs;
5134 bool saveExitStat = ExitStat;
5138 usrerr("501 5.5.2 AUTH= requires a value");
5141 if (e->e_auth_param != NULL)
5143 usrerr("501 5.5.0 Duplicate AUTH parameter");
5146 if ((q = strchr(vp, ' ')) != NULL)
5149 len = strlen(vp) + 1;
5150 auth_param = xalloc(len);
5151 (void) sm_strlcpy(auth_param, vp, len);
5152 if (!xtextok(auth_param))
5154 usrerr("501 5.5.4 Syntax error in AUTH parameter value");
5155 /* just a warning? */
5159 /* XXX define this always or only if trusted? */
5160 macdefine(&e->e_macro, A_TEMP, macid("{auth_author}"),
5164 ** call Strust_auth to find out whether
5165 ** auth_param is acceptable (trusted)
5166 ** we shouldn't trust it if not authenticated
5167 ** (required by RFC, leave it to ruleset?)
5172 if (strcmp(auth_param, "<>") != 0 &&
5173 (rscheck("trust_auth", auth_param, NULL, e, RSF_RMCOMM, 9,
5174 NULL, NOQID, NULL, NULL) != EX_OK || Errors > 0))
5178 q = e->e_auth_param;
5179 sm_dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n",
5180 auth_param, (q == NULL) ? "" : q);
5184 e->e_auth_param = "<>";
5185 # if _FFR_AUTH_PASSING
5186 macdefine(&BlankEnvelope.e_macro, A_PERM,
5187 macid("{auth_author}"), NULL);
5193 sm_dprintf("auth=\"%.100s\" trusted\n", auth_param);
5194 e->e_auth_param = sm_rpool_strdup_x(e->e_rpool,
5197 sm_free(auth_param); /* XXX */
5201 QuickAbort = saveQuickAbort;
5202 SuprErrs = saveSuprErrs;
5203 ExitStat = saveExitStat;
5206 #define PRTCHAR(c) ((isascii(c) && isprint(c)) ? (c) : '?')
5209 ** "by" is only accepted if DeliverByMin >= 0.
5210 ** We maybe could add this to the list of server_features.
5213 else if (SM_STRCASEEQ(kp, "by") && DeliverByMin >= 0)
5219 usrerr("501 5.5.2 BY= requires a value");
5223 e->e_deliver_by = strtol(vp, &s, 10);
5224 if (e->e_deliver_by == LONG_MIN ||
5225 e->e_deliver_by == LONG_MAX ||
5226 e->e_deliver_by > 999999999l ||
5227 e->e_deliver_by < -999999999l)
5229 usrerr("501 5.5.2 BY=%s out of range",
5230 SHOWCMDINREPLY(vp));
5233 if (s == NULL || *s != ';')
5235 usrerr("501 5.5.2 BY= missing ';'");
5239 ++s; /* XXX: spaces allowed? */
5241 switch (tolower(*s))
5244 e->e_dlvr_flag = DLVR_NOTIFY;
5247 e->e_dlvr_flag = DLVR_RETURN;
5248 if (e->e_deliver_by <= 0)
5250 usrerr("501 5.5.4 mode R requires BY time > 0");
5253 if (DeliverByMin > 0 && e->e_deliver_by > 0 &&
5254 e->e_deliver_by < DeliverByMin)
5256 usrerr("555 5.5.2 time %ld less than %ld",
5257 e->e_deliver_by, (long) DeliverByMin);
5262 usrerr("501 5.5.2 illegal by-mode '%c'", PRTCHAR(*s));
5265 ++s; /* XXX: spaces allowed? */
5267 switch (tolower(*s))
5270 e->e_dlvr_flag |= DLVR_TRACE;
5275 usrerr("501 5.5.2 illegal by-trace '%c'", PRTCHAR(*s));
5279 /* XXX: check whether more characters follow? */
5282 else if (SM_STRCASEEQ(kp, "smtputf8"))
5284 if (!bitset(SRV_OFFER_EAI, e->e_features))
5286 usrerr("504 5.7.0 Sorry, SMTPUTF8 not supported");
5289 e->e_smtputf8 = true;
5294 usrerr("555 5.5.4 %s parameter unrecognized",
5295 SHOWCMDINREPLY(kp));
5301 ** RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
5304 ** a -- the address corresponding to the To: parameter.
5305 ** kp -- the parameter key.
5306 ** vp -- the value of that parameter.
5307 ** e -- the envelope.
5314 rcpt_esmtp_args(a, kp, vp, e)
5320 if (SM_STRCASEEQ(kp, "notify"))
5324 if (!bitset(SRV_OFFER_DSN, e->e_features))
5326 usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN");
5331 usrerr("501 5.5.2 NOTIFY requires a value");
5334 a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
5335 a->q_flags |= QHASNOTIFY;
5336 macdefine(&e->e_macro, A_TEMP, macid("{dsn_notify}"), vp);
5338 if (SM_STRCASEEQ(vp, "never"))
5340 for (p = vp; p != NULL; vp = p)
5344 s = p = strchr(p, ',');
5347 if (SM_STRCASEEQ(vp, "success"))
5348 a->q_flags |= QPINGONSUCCESS;
5349 else if (SM_STRCASEEQ(vp, "failure"))
5350 a->q_flags |= QPINGONFAILURE;
5351 else if (SM_STRCASEEQ(vp, "delay"))
5352 a->q_flags |= QPINGONDELAY;
5355 usrerr("501 5.5.4 Bad argument \"%s\" to NOTIFY",
5356 SHOWCMDINREPLY(vp));
5363 else if (SM_STRCASEEQ(kp, "orcpt"))
5367 if (!bitset(SRV_OFFER_DSN, e->e_features))
5369 usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN");
5374 usrerr("501 5.5.2 ORCPT requires a value");
5377 if (a->q_orcpt != NULL)
5379 usrerr("501 5.5.0 Duplicate ORCPT parameter");
5382 p = strchr(vp, ';');
5385 usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5390 if (SM_STRCASEEQ(vp, "utf-8"))
5392 /* XXX check syntax of p+1 ! */
5393 if (!xtextok(p + 1) &&
5394 uxtext_unquote(p + 1, NULL, MAXNAME_I) <= 0)
5397 usrerr("501 5.5.4 Syntax error in UTF-8 ORCPT parameter value");
5401 complicated... see grammar!
5402 RFC 6533 Internationalized Delivery Status and Disposition Notifications
5403 utf-8-enc-addr = utf-8-addr-xtext / utf-8-addr-unitext / utf-8-address
5407 #endif /* USE_EAI */
5408 /* "else" in #if code above */
5409 if (!isatom(vp) || !xtextok(p + 1))
5412 usrerr("501 5.5.4 Syntax error in ORCPT parameter value");
5416 a->q_orcpt = sm_rpool_strdup_x(e->e_rpool, vp);
5420 usrerr("555 5.5.4 %s parameter unrecognized",
5421 SHOWCMDINREPLY(kp));
5426 ** PRINTVRFYADDR -- print an entry in the verify queue
5429 ** a -- the address to print.
5430 ** last -- set if this is the last one.
5431 ** vrfy -- set if this is a VRFY command.
5437 ** Prints the appropriate 250 codes.
5439 #define OFFF (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */
5442 printvrfyaddr(a, last, vrfy)
5443 register ADDRESS *a;
5449 if (vrfy && a->q_mailer != NULL &&
5450 !bitnset(M_VRFY250, a->q_mailer->m_flags))
5451 (void) sm_strlcpy(fmtbuf, "252", sizeof(fmtbuf));
5453 (void) sm_strlcpy(fmtbuf, "250", sizeof(fmtbuf));
5454 fmtbuf[3] = last ? ' ' : '-';
5455 (void) sm_strlcpy(&fmtbuf[4], "2.1.5 ", sizeof(fmtbuf) - 4);
5456 if (a->q_fullname == NULL)
5458 if ((a->q_mailer == NULL ||
5459 a->q_mailer->m_addrtype == NULL ||
5460 SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5461 strchr(a->q_user, '@') == NULL)
5462 (void) sm_strlcpy(&fmtbuf[OFFF], "<%s@%s>",
5463 sizeof(fmtbuf) - OFFF);
5465 (void) sm_strlcpy(&fmtbuf[OFFF], "<%s>",
5466 sizeof(fmtbuf) - OFFF);
5467 message(fmtbuf, a->q_user, MyHostName);
5471 if ((a->q_mailer == NULL ||
5472 a->q_mailer->m_addrtype == NULL ||
5473 SM_STRCASEEQ(a->q_mailer->m_addrtype, "rfc822")) &&
5474 strchr(a->q_user, '@') == NULL)
5475 (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s@%s>",
5476 sizeof(fmtbuf) - OFFF);
5478 (void) sm_strlcpy(&fmtbuf[OFFF], "%s <%s>",
5479 sizeof(fmtbuf) - OFFF);
5480 message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
5486 ** SASLMECHS -- get list of possible AUTH mechanisms
5489 ** conn -- SASL connection info.
5490 ** mechlist -- output parameter for list of mechanisms.
5497 saslmechs(conn, mechlist)
5501 int len, num, result;
5503 /* "user" is currently unused */
5505 result = sasl_listmech(conn, NULL,
5506 "", " ", "", (const char **) mechlist,
5507 (unsigned int *)&len, &num);
5508 # else /* SASL >= 20000 */
5509 result = sasl_listmech(conn, "user", /* XXX */
5510 "", " ", "", mechlist,
5511 (unsigned int *)&len, (unsigned int *)&num);
5512 # endif /* SASL >= 20000 */
5513 if (result != SASL_OK)
5516 sm_syslog(LOG_WARNING, NOQID,
5517 "AUTH error: listmech=%d, num=%d",
5524 sm_syslog(LOG_INFO, NOQID,
5525 "AUTH: available mech=%s, allowed mech=%s",
5526 *mechlist, AuthMechanisms);
5527 *mechlist = intersect(AuthMechanisms, *mechlist, NULL);
5531 *mechlist = NULL; /* be paranoid... */
5532 if (result == SASL_OK && LogLevel > 9)
5533 sm_syslog(LOG_WARNING, NOQID,
5534 "AUTH warning: no mechanisms");
5541 ** PROXY_POLICY -- define proxy policy for AUTH
5545 ** context -- unused.
5546 ** requested_user -- authorization identity.
5547 ** rlen -- authorization identity length.
5548 ** auth_identity -- authentication identity.
5549 ** alen -- authentication identity length.
5550 ** def_realm -- default user realm.
5551 ** urlen -- user realm length.
5552 ** propctx -- unused.
5558 ** sets {auth_authen} macro.
5562 proxy_policy(conn, context, requested_user, rlen, auth_identity, alen,
5563 def_realm, urlen, propctx)
5566 const char *requested_user;
5568 const char *auth_identity;
5570 const char *def_realm;
5572 struct propctx *propctx;
5574 if (auth_identity == NULL)
5577 macdefine(&BlankEnvelope.e_macro, A_TEMP,
5578 macid("{auth_authen}"),
5579 xtextify((char *) auth_identity, "=<>\")"));
5583 # else /* SASL >= 20000 */
5586 ** PROXY_POLICY -- define proxy policy for AUTH
5589 ** context -- unused.
5590 ** auth_identity -- authentication identity.
5591 ** requested_user -- authorization identity.
5592 ** user -- allowed user (output).
5593 ** errstr -- possible error string (output).
5600 proxy_policy(context, auth_identity, requested_user, user, errstr)
5602 const char *auth_identity;
5603 const char *requested_user;
5605 const char **errstr;
5607 if (user == NULL || auth_identity == NULL)
5609 *user = newstr(auth_identity);
5612 # endif /* SASL >= 20000 */
5617 ** INITSRVTLS -- initialize server side TLS
5620 ** tls_ok -- should tls initialization be done?
5626 ** sets tls_ok_srv which is a static variable in this module.
5627 ** Do NOT remove assignments to it!
5637 /* do NOT remove assignment */
5638 tls_ok_srv = inittls(&srv_ctx, TLS_Srv_Opts, Srv_SSL_Options, true,
5639 SrvCertFile, SrvKeyFile,
5640 CACertPath, CACertFile, DHParams);
5643 #endif /* STARTTLS */
5645 ** SRVFEATURES -- get features for SMTP server
5648 ** e -- envelope (should be session context).
5649 ** clientname -- name of client.
5650 ** features -- default features for this invocation.
5656 /* table with options: it uses just one character, how about strings? */
5660 unsigned long srvf_flag;
5661 unsigned long srvf_flag2;
5662 } srv_feat_table[] =
5664 { 'A', SRV_OFFER_AUTH , 0 },
5665 { 'B', SRV_OFFER_VERB , 0 },
5666 { 'C', SRV_REQ_SEC , 0 },
5667 { 'D', SRV_OFFER_DSN , 0 },
5668 { 'E', SRV_OFFER_ETRN , 0 },
5669 { 'F', SRV_BAD_PIPELINE , 0 },
5670 { 'G', SRV_BARE_LF_421 , SRV_BARE_LF_SP },
5671 { 'H', SRV_NO_HTTP_CMD , 0 },
5673 { 'I', SRV_OFFER_EAI , 0 },
5675 /* { 'J', 0 , 0 }, */
5676 /* { 'K', 0 , 0 }, */
5677 { 'L', SRV_REQ_AUTH , 0 },
5678 /* { 'M', 0 , 0 }, */
5679 #if PIPELINING && _FFR_NO_PIPE
5680 { 'N', SRV_NO_PIPE , 0 },
5682 { 'O', SRV_REQ_CRLF , 0 }, /* eOl */
5684 { 'P', SRV_OFFER_PIPE , 0 },
5686 /* { 'Q', 0 , 0 }, */
5687 { 'R', SRV_VRFY_CLT , 0 }, /* same as V; not documented */
5688 { 'S', SRV_OFFER_TLS , 0 },
5689 /* { 'T', SRV_TMP_FAIL , 0 }, */
5690 { 'U', SRV_BARE_CR_421 , SRV_BARE_CR_SP },
5691 { 'V', SRV_VRFY_CLT , 0 },
5692 /* { 'W', 0 , 0 }, */
5693 { 'X', SRV_OFFER_EXPN , 0 },
5694 /* { 'Y', SRV_OFFER_VRFY , 0 }, */
5695 /* { 'Z', 0 , 0 }, */
5696 { '\0', SRV_NONE , 0 }
5699 static unsigned long
5700 srvfeatures(e, clientname, features)
5703 unsigned long features;
5707 char pvpbuf[PSBUFSIZE];
5710 r = rscap("srv_features", clientname, "", e, &pvp, pvpbuf,
5714 if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
5716 if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0)
5717 return SRV_TMP_FAIL;
5720 ** General rule (see sendmail.h, d_flags):
5721 ** lower case: required/offered, upper case: Not required/available
5723 ** Since we can change some features per daemon, we have both
5724 ** cases here: turn on/off a feature.
5727 for (i = 1; pvp[i] != NULL; i++)
5733 if ((opt = srv_feat_table[j].srvf_opt) == '\0')
5736 sm_syslog(LOG_WARNING, e->e_id,
5737 "srv_features: unknown feature %s",
5743 features &= ~(srv_feat_table[j].srvf_flag);
5748 ** Note: the "noflag" code below works ONLY for
5749 ** the current situation:
5750 ** - _flag itself is set by default
5751 ** (drop session if bare CR or LF is found)
5752 ** - _flag2 is only "effective" if _flag is not set,
5753 ** hence using it turns off _flag.
5754 ** If that situation changes, the code must be changed!
5757 if (c == tolower(opt))
5759 unsigned long flag, noflag;
5765 flag = srv_feat_table[j].srvf_flag2;
5766 noflag = srv_feat_table[j].srvf_flag;
5769 flag = srv_feat_table[j].srvf_flag;
5774 features &= ~noflag;
5776 else if (LogLevel > 9)
5777 sm_syslog(LOG_WARNING, e->e_id,
5778 "srv_features: unknown variant %s",
5789 ** HELP -- implement the HELP command.
5792 ** topic -- the topic we want help for.
5799 ** outputs the help file to message output.
5801 #define HELPVSTR "#vers "
5802 #define HELPVERSION 2
5809 register SM_FILE_T *hf;
5815 long sff = SFF_OPENASROOT|SFF_REGONLY;
5818 static int foundvers = -1;
5819 extern char Version[];
5821 if (DontLockReadFiles)
5823 if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail))
5824 sff |= SFF_SAFEDIRPATH;
5826 if (HelpFile == NULL ||
5827 (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL)
5831 message("502 5.3.0 Sendmail %s -- HELP not implemented",
5837 if (SM_IS_EMPTY(topic))
5845 lstr = makelower_a(&topic, NULL);
5853 len = strlen(topic);
5855 while (sm_io_fgets(hf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
5859 if (foundvers < 0 &&
5860 strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0)
5864 if (sm_io_sscanf(buf + strlen(HELPVSTR), "%d",
5870 if (strncmp(buf, topic, len) == 0)
5876 /* print version if no/old vers# in file */
5877 if (foundvers < 2 && !noinfo)
5878 message("214-2.0.0 This is Sendmail version %s", Version);
5880 p = strpbrk(buf, " \t");
5882 p = buf + strlen(buf) - 1;
5889 int lbs = sizeof(buf) - (p - buf);
5891 lbp = translate_dollars(p, p, &lbs);
5892 expand(lbp, inp, sizeof(inp), e);
5897 message("214-2.0.0 %s", p);
5903 message("504 5.3.0 HELP topic \"%.10s\" unknown", topic);
5905 message("214 2.0.0 End of HELP info");
5907 if (foundvers != 0 && foundvers < HELPVERSION)
5910 sm_syslog(LOG_WARNING, e->e_id,
5911 "%s too old (require version %d)",
5912 HelpFile, HELPVERSION);
5914 /* avoid log next time */
5918 (void) sm_io_close(hf, SM_TIME_DEFAULT);
5924 ** RESET_SASLCONN -- reset SASL connection data
5927 ** conn -- SASL connection context
5928 ** hostname -- host name
5929 ** various connection data
5937 reset_saslconn(sasl_conn_t **conn, char *hostname,
5939 char *remoteip, char *localip,
5940 char *auth_id, sasl_ssf_t * ext_ssf)
5941 # else /* SASL >= 20000 */
5942 struct sockaddr_in *saddr_r, struct sockaddr_in *saddr_l,
5943 sasl_external_properties_t * ext_ssf)
5944 # endif /* SASL >= 20000 */
5945 #else /* __STDC__ */
5946 # error "SASL requires __STDC__"
5947 #endif /* __STDC__ */
5953 result = sasl_server_new("smtp", hostname, NULL, NULL, NULL,
5956 /* use empty realm: only works in SASL > 1.5.5 */
5957 result = sasl_server_new("smtp", hostname, "", NULL, 0, conn);
5958 # else /* SASL >= 20000 */
5959 /* use no realm -> realm is set to hostname by SASL lib */
5960 result = sasl_server_new("smtp", hostname, NULL, NULL, 0,
5962 # endif /* SASL >= 20000 */
5963 if (result != SASL_OK)
5967 # if NETINET || NETINET6
5968 if (remoteip != NULL && *remoteip != '\0')
5969 result = sasl_setprop(*conn, SASL_IPREMOTEPORT, remoteip);
5970 if (result != SASL_OK)
5973 if (localip != NULL && *localip != '\0')
5974 result = sasl_setprop(*conn, SASL_IPLOCALPORT, localip);
5975 if (result != SASL_OK)
5977 # endif /* NETINET || NETINET6 */
5979 result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
5980 if (result != SASL_OK)
5983 result = sasl_setprop(*conn, SASL_AUTH_EXTERNAL, auth_id);
5984 if (result != SASL_OK)
5986 # else /* SASL >= 20000 */
5988 if (saddr_r != NULL)
5989 result = sasl_setprop(*conn, SASL_IP_REMOTE, saddr_r);
5990 if (result != SASL_OK)
5993 if (saddr_l != NULL)
5994 result = sasl_setprop(*conn, SASL_IP_LOCAL, saddr_l);
5995 if (result != SASL_OK)
5997 # endif /* NETINET */
5999 result = sasl_setprop(*conn, SASL_SSF_EXTERNAL, ext_ssf);
6000 if (result != SASL_OK)
6002 # endif /* SASL >= 20000 */
6007 ** GET_SASL_USER -- extract user part from SASL reply
6010 ** val -- sasl reply (may contain NUL)
6011 ** len -- length of val
6012 ** auth_type -- auth_type (can be NULL)
6013 ** user -- output buffer for extract user
6014 ** user_len -- length of output buffer (user)
6019 ** Note: val is supplied by the client and hence may contain "bad"
6020 ** (non-printable) characters, but the returned value (user)
6021 ** is only used for logging which converts those characters.
6025 get_sasl_user(val, len, auth_type, user, user_len)
6028 const char *auth_type;
6034 SM_ASSERT(val != NULL);
6035 SM_ASSERT(user != NULL);
6036 SM_ASSERT(user_len > 0);
6039 if (SM_IS_EMPTY(auth_type))
6044 # define DIGMD5U "username=\""
6045 # define DIGMD5U_L (sizeof(DIGMD5U) - 1)
6046 if (SM_STRCASEEQ(auth_type, "digest-md5") &&
6047 strncmp(val, DIGMD5U, DIGMD5U_L) == 0)
6052 if (len <= DIGMD5U_L)
6056 /* format? could there be a quoted '"'? */
6057 for (s = val, u = 0; *s != '\0' && u < len; s++)
6072 else if (SM_STRCASEEQ(auth_type, "cram-md5"))
6076 for (s = val, u = 0; *s != '\0' && u < len; s++)
6086 else if (SM_STRCASEEQ(auth_type, "plain") ||
6087 SM_STRCASEEQ(auth_type, "login"))
6090 ** RFC 4616: The PLAIN Simple Authentication and
6091 ** Security Layer (SASL) Mechanism
6092 ** message = [authzid] UTF8NUL authcid UTF8NUL passwd
6093 ** each part: 1*SAFE ; MUST accept up to 255 octets
6094 ** UTF8NUL = %x00 ; UTF-8 encoded NUL character
6096 ** draft-murchison-sasl-login: it's just username by its own
6099 for (u = 0; u < len; u++)
6104 (void) sm_strlcpy(user,
6105 val + ((0 == u) ? 1 : 0),
6114 ** Extracting the "user" from other mechanisms
6115 ** is currently not supported.
6122 ** Does the input buffer has an NUL in it so it can be treated
6126 /* SM_ASSERT(len > 0); see above */
6130 for (u = 0; u < len; u++)
6137 user_len = SM_MIN(len, user_len);
6139 (void) sm_strlcpy(user, val, user_len);