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