Postfix3.3.1
postscreen_smtpd.c
[詳解]
1 /*++
2 /* NAME
3 /* postscreen_smtpd 3
4 /* SUMMARY
5 /* postscreen built-in SMTP server engine
6 /* SYNOPSIS
7 /* #include <postscreen.h>
8 /*
9 /* void psc_smtpd_pre_jail_init(void)
10 /*
11 /* void psc_smtpd_init(void)
12 /*
13 /* void psc_smtpd_tests(state)
14 /* PSC_STATE *state;
15 /*
16 /* void PSC_SMTPD_X21(state, final_reply)
17 /* PSC_STATE *state;
18 /* const char *final_reply;
19 /* DESCRIPTION
20 /* psc_smtpd_pre_jail_init() performs one-time per-process
21 /* initialization during the "before chroot" execution phase.
22 /*
23 /* psc_smtpd_init() performs one-time per-process initialization.
24 /*
25 /* psc_smtpd_tests() starts up an SMTP server engine for deep
26 /* protocol tests and for collecting helo/sender/recipient
27 /* information.
28 /*
29 /* PSC_SMTPD_X21() redirects the SMTP client to an SMTP server
30 /* engine, which sends the specified final reply at the first
31 /* legitimate opportunity without doing any protocol tests.
32 /*
33 /* Unlike the Postfix SMTP server, this engine does not announce
34 /* PIPELINING support. This exposes spambots that pipeline
35 /* their commands anyway. Like the Postfix SMTP server, this
36 /* engine will accept input with bare newline characters. To
37 /* pass the "pipelining" and "bare newline" test, the client
38 /* has to properly speak SMTP all the way to the RCPT TO
39 /* command. These tests fail if the client violates the protocol
40 /* at any stage.
41 /*
42 /* No support is announced for AUTH, XCLIENT or XFORWARD.
43 /* Clients that need this should be whitelisted or should talk
44 /* directly to the submission service.
45 /*
46 /* The engine rejects RCPT TO and VRFY commands with the
47 /* state->rcpt_reply response which depends on program history,
48 /* rejects ETRN with a generic response, and closes the
49 /* connection after QUIT.
50 /*
51 /* Since this engine defers or rejects all non-junk commands,
52 /* there is no point maintaining separate counters for "error"
53 /* commands and "junk" commands. Instead, the engine maintains
54 /* a per-session command counter, and terminates the session
55 /* with a 421 reply when the command count exceeds the limit.
56 /*
57 /* We limit the command count, as well as the total time to
58 /* receive a command. This limits the time per client more
59 /* effectively than would be possible with read() timeouts.
60 /*
61 /* There is no concern about getting blocked on output. The
62 /* psc_send() routine uses non-blocking output, and discards
63 /* output that the client is not willing to receive.
64 /* PROTOCOL INSPECTION VERSUS CONTENT INSPECTION
65 /* The goal of postscreen is to keep spambots away from Postfix.
66 /* To recognize spambots, postscreen measures properties of
67 /* the client IP address and of the client SMTP protocol
68 /* implementation. These client properties don't change with
69 /* each delivery attempt. Therefore it is possible to make a
70 /* long-term decision after a single measurement. For example,
71 /* allow a good client to skip the DNSBL test for 24 hours,
72 /* or to skip the pipelining test for one week.
73 /*
74 /* If postscreen were to measure properties of message content
75 /* (MIME compliance, etc.) then it would measure properties
76 /* that may change with each delivery attempt. Here, it would
77 /* be wrong to make a long-term decision after a single
78 /* measurement. Instead, postscreen would need to develop a
79 /* ranking based on the content of multiple messages from the
80 /* same client.
81 /*
82 /* Many spambots avoid spamming the same site repeatedly.
83 /* Thus, postscreen must make decisions after a single
84 /* measurement. Message content is not a good indicator for
85 /* making long-term decisions after single measurements, and
86 /* that is why postscreen does not inspect message content.
87 /* REJECTING RCPT TO VERSUS SENDING LIVE SOCKETS TO SMTPD(8)
88 /* When post-handshake protocol tests are enabled, postscreen
89 /* rejects the RCPT TO command from a good client, and forces
90 /* it to deliver mail in a later session. This is why
91 /* post-handshake protocol tests have a longer expiration time
92 /* than pre-handshake tests.
93 /*
94 /* Instead, postscreen could send the network socket to smtpd(8)
95 /* and ship the session history (including TLS and other SMTP
96 /* or non-SMTP attributes) as auxiliary data. The Postfix SMTP
97 /* server would then use new code to replay the session history,
98 /* and would use existing code to validate the client, helo,
99 /* sender and recipient address.
100 /*
101 /* Such an approach would increase the implementation and
102 /* maintenance effort, because:
103 /*
104 /* 1) New replay code would be needed in smtpd(8), such that
105 /* the HELO, EHLO, and MAIL command handlers can delay their
106 /* error responses until the RCPT TO reply.
107 /*
108 /* 2) postscreen(8) would have to implement more of smtpd(8)'s
109 /* syntax checks, to avoid confusing delayed "syntax error"
110 /* and other error responses syntax error responses while
111 /* replaying history.
112 /*
113 /* 3) New code would be needed in postscreen(8) and smtpd(8)
114 /* to send and receive the session history (including TLS and
115 /* other SMTP or non-SMTP attributes) as auxiliary data while
116 /* sending the network socket from postscreen(8) to smtpd(8).
117 /* REJECTING RCPT TO VERSUS PROXYING LIVE SESSIONS TO SMTPD(8)
118 /* An alternative would be to proxy the session history to a
119 /* real Postfix SMTP process, presumably passing TLS and other
120 /* attributes via an extended XCLIENT implementation. That
121 /* would require all the work described in 2) above, plus
122 /* duplication of all the features of the smtpd(8) TLS engine,
123 /* plus additional XCLIENT support for a lot more attributes.
124 /* LICENSE
125 /* .ad
126 /* .fi
127 /* The Secure Mailer license must be distributed with this software.
128 /* AUTHOR(S)
129 /* Wietse Venema
130 /* IBM T.J. Watson Research
131 /* P.O. Box 704
132 /* Yorktown Heights, NY 10598, USA
133 /*
134 /* Wietse Venema
135 /* Google, Inc.
136 /* 111 8th Avenue
137 /* New York, NY 10011, USA
138 /*--*/
139 
140 /* System library. */
141 
142 #include <sys_defs.h>
143 #include <string.h>
144 #include <ctype.h>
145 
146 #ifdef STRCASECMP_IN_STRINGS_H
147 #include <strings.h>
148 #endif
149 
150 /* Utility library. */
151 
152 #include <msg.h>
153 #include <stringops.h>
154 #include <mymalloc.h>
155 #include <iostuff.h>
156 #include <vstring.h>
157 
158 /* Global library. */
159 
160 #include <mail_params.h>
161 #include <mail_proto.h>
162 #include <is_header.h>
163 #include <string_list.h>
164 #include <maps.h>
165 #include <ehlo_mask.h>
166 #include <lex_822.h>
167 
168 /* TLS library. */
169 
170 #include <tls.h>
171 
172 /* Application-specific. */
173 
174 #include <postscreen.h>
175 
176  /*
177  * Plan for future body processing. See smtp-sink.c. For now, we have no
178  * per-session push-back except for the single-character push-back that
179  * VSTREAM guarantees after we read one character.
180  */
181 #define PSC_SMTPD_HAVE_PUSH_BACK(state) (0)
182 #define PSC_SMTPD_PUSH_BACK_CHAR(state, ch) \
183  vstream_ungetc((state)->smtp_client_stream, (ch))
184 #define PSC_SMTPD_NEXT_CHAR(state) \
185  VSTREAM_GETC((state)->smtp_client_stream)
186 
187 #define PSC_SMTPD_BUFFER_EMPTY(state) \
188  (!PSC_SMTPD_HAVE_PUSH_BACK(state) \
189  && vstream_peek((state)->smtp_client_stream) <= 0)
190 
191 #define PSC_SMTPD_PEEK_DATA(state) \
192  vstream_peek_data((state)->smtp_client_stream)
193 #define PSC_SMTPD_PEEK_LEN(state) \
194  vstream_peek((state)->smtp_client_stream)
195 
196  /*
197  * Dynamic reply strings. To minimize overhead we format these once.
198  */
199 static char *psc_smtpd_greeting; /* smtp banner */
200 static char *psc_smtpd_helo_reply; /* helo reply */
201 static char *psc_smtpd_ehlo_reply_plain;/* multi-line ehlo reply, non-TLS */
202 static char *psc_smtpd_ehlo_reply_tls; /* multi-line ehlo reply, with TLS */
203 static char *psc_smtpd_timeout_reply; /* timeout reply */
204 static char *psc_smtpd_421_reply; /* generic final_reply value */
205 
206  /*
207  * Forward declaration, needed by PSC_CLEAR_EVENT_REQUEST.
208  */
209 static void psc_smtpd_time_event(int, void *);
210 static void psc_smtpd_read_event(int, void *);
211 
212  /*
213  * Encapsulation. The STARTTLS, EHLO and AUTH command handlers temporarily
214  * suspend SMTP command events, send an asynchronous proxy request, and
215  * resume SMTP command events after receiving the asynchrounous proxy
216  * response (the EHLO handler must asynchronously talk to the auth server
217  * before it can announce the SASL mechanism list; the list can depend on
218  * the client IP address and on the presence on TLS encryption).
219  */
220 #define PSC_RESUME_SMTP_CMD_EVENTS(state) do { \
221  PSC_READ_EVENT_REQUEST2(vstream_fileno((state)->smtp_client_stream), \
222  psc_smtpd_read_event, psc_smtpd_time_event, \
223  (void *) (state), PSC_EFF_CMD_TIME_LIMIT); \
224  if (!PSC_SMTPD_BUFFER_EMPTY(state)) \
225  psc_smtpd_read_event(EVENT_READ, (void *) state); \
226  } while (0)
227 
228 #define PSC_SUSPEND_SMTP_CMD_EVENTS(state) \
229  PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
230  psc_smtpd_time_event, (void *) (state));
231 
232  /*
233  * Make control characters and other non-text visible.
234  */
235 #define PSC_SMTPD_ESCAPE_TEXT(dest, src, src_len, max_len) do { \
236  ssize_t _s_len = (src_len); \
237  ssize_t _m_len = (max_len); \
238  (void) escape((dest), (src), _s_len < _m_len ? _s_len : _m_len); \
239  } while (0)
240 
241  /*
242  * Command parser support.
243  */
244 #define PSC_SMTPD_NEXT_TOKEN(ptr) mystrtok(&(ptr), " ")
245 
246  /*
247  * EHLO keyword filter
248  */
249 static MAPS *psc_ehlo_discard_maps;
250 static int psc_ehlo_discard_mask;
251 
252  /*
253  * Command editing filter.
254  */
255 static DICT *psc_cmd_filter;
256 
257  /*
258  * Encapsulation. We must not forget turn off input/timer events when we
259  * terminate the SMTP protocol engine.
260  *
261  * It would be safer to turn off input/timer events after each event, and to
262  * turn on input/timer events again when we want more input. But experience
263  * with the Postfix smtp-source and smtp-sink tools shows that this would
264  * noticeably increase the run-time cost.
265  */
266 #define PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, event, reply) do { \
267  PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
268  (event), (void *) (state)); \
269  PSC_DROP_SESSION_STATE((state), (reply)); \
270  } while (0);
271 
272 #define PSC_CLEAR_EVENT_HANGUP(state, event) do { \
273  PSC_CLEAR_EVENT_REQUEST(vstream_fileno((state)->smtp_client_stream), \
274  (event), (void *) (state)); \
275  psc_hangup_event(state); \
276  } while (0);
277 
278 /* psc_helo_cmd - record HELO and respond */
279 
280 static int psc_helo_cmd(PSC_STATE *state, char *args)
281 {
282  char *helo_name = PSC_SMTPD_NEXT_TOKEN(args);
283 
284  /*
285  * smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them.
286  */
287  if (helo_name == 0)
288  return (PSC_SEND_REPLY(state, "501 Syntax: HELO hostname\r\n"));
289 
290  PSC_STRING_UPDATE(state->helo_name, helo_name);
291  PSC_STRING_RESET(state->sender);
292  /* Don't downgrade state->protocol, in case some test depends on this. */
293  return (PSC_SEND_REPLY(state, psc_smtpd_helo_reply));
294 }
295 
296 /* psc_smtpd_format_ehlo_reply - format EHLO response */
297 
298 static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask
299  /* , const char *sasl_mechanism_list */ )
300 {
301  const char *myname = "psc_smtpd_format_ehlo_reply";
302  int saved_len = 0;
303 
304  if (msg_verbose)
305  msg_info("%s: discard_mask %s", myname, str_ehlo_mask(discard_mask));
306 
307 #define PSC_EHLO_APPEND(save, buf, fmt) do { \
308  (save) = LEN(buf); \
309  vstring_sprintf_append((buf), (fmt)); \
310  } while (0)
311 
312 #define PSC_EHLO_APPEND1(save, buf, fmt, arg1) do { \
313  (save) = LEN(buf); \
314  vstring_sprintf_append((buf), (fmt), (arg1)); \
315  } while (0)
316 
317  vstring_sprintf(psc_temp, "250-%s\r\n", var_myhostname);
318  if ((discard_mask & EHLO_MASK_SIZE) == 0) {
319  if (var_message_limit)
320  PSC_EHLO_APPEND1(saved_len, psc_temp, "250-SIZE %lu\r\n",
321  (unsigned long) var_message_limit);
322  else
323  PSC_EHLO_APPEND(saved_len, psc_temp, "250-SIZE\r\n");
324  }
325  if ((discard_mask & EHLO_MASK_VRFY) == 0 && var_disable_vrfy_cmd == 0)
326  PSC_EHLO_APPEND(saved_len, psc_temp, "250-VRFY\r\n");
327  if ((discard_mask & EHLO_MASK_ETRN) == 0)
328  PSC_EHLO_APPEND(saved_len, psc_temp, "250-ETRN\r\n");
329  if ((discard_mask & EHLO_MASK_STARTTLS) == 0 && var_psc_use_tls)
330  PSC_EHLO_APPEND(saved_len, psc_temp, "250-STARTTLS\r\n");
331 #ifdef TODO_SASL_AUTH
332  if ((discard_mask & EHLO_MASK_AUTH) == 0 && sasl_mechanism_list
333  && (!var_psc_tls_auth_only || (discard_mask & EHLO_MASK_STARTTLS))) {
334  PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH %s", sasl_mechanism_list);
336  PSC_EHLO_APPEND1(saved_len, psc_temp, "AUTH=%s", sasl_mechanism_list);
337  }
338 #endif
339  if ((discard_mask & EHLO_MASK_ENHANCEDSTATUSCODES) == 0)
340  PSC_EHLO_APPEND(saved_len, psc_temp, "250-ENHANCEDSTATUSCODES\r\n");
341  if ((discard_mask & EHLO_MASK_8BITMIME) == 0)
342  PSC_EHLO_APPEND(saved_len, psc_temp, "250-8BITMIME\r\n");
343  if ((discard_mask & EHLO_MASK_DSN) == 0)
344  PSC_EHLO_APPEND(saved_len, psc_temp, "250-DSN\r\n");
345  /* Fix 20140708: announce SMTPUTF8. */
346  if (var_smtputf8_enable && (discard_mask & EHLO_MASK_SMTPUTF8) == 0)
347  PSC_EHLO_APPEND(saved_len, psc_temp, "250-SMTPUTF8\r\n");
348  STR(psc_temp)[saved_len + 3] = ' ';
349 }
350 
351 /* psc_ehlo_cmd - record EHLO and respond */
352 
353 static int psc_ehlo_cmd(PSC_STATE *state, char *args)
354 {
355  char *helo_name = PSC_SMTPD_NEXT_TOKEN(args);
356  const char *ehlo_words;
357  int discard_mask;
358  char *reply;
359 
360  /*
361  * smtpd(8) incompatibility: we ignore extra words; smtpd(8) saves them.
362  */
363  if (helo_name == 0)
364  return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
365 
366  PSC_STRING_UPDATE(state->helo_name, helo_name);
367  PSC_STRING_RESET(state->sender);
368  state->protocol = MAIL_PROTO_ESMTP;
369 
370  /*
371  * smtpd(8) compatibility: dynamic reply filtering.
372  */
373  if (psc_ehlo_discard_maps != 0
374  && (ehlo_words = psc_maps_find(psc_ehlo_discard_maps,
375  state->smtp_client_addr, 0)) != 0
376  && (discard_mask = ehlo_mask(ehlo_words)) != psc_ehlo_discard_mask) {
377  if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
378  msg_info("[%s]%s: discarding EHLO keywords: %s",
379  PSC_CLIENT_ADDR_PORT(state), str_ehlo_mask(discard_mask));
380  if (state->flags & PSC_STATE_FLAG_USING_TLS)
381  discard_mask |= EHLO_MASK_STARTTLS;
382  psc_smtpd_format_ehlo_reply(psc_temp, discard_mask);
383  reply = STR(psc_temp);
384  state->ehlo_discard_mask = discard_mask;
385  } else if (psc_ehlo_discard_maps && psc_ehlo_discard_maps->error) {
386  msg_fatal("%s lookup error for %s",
387  psc_ehlo_discard_maps->title, state->smtp_client_addr);
388  } else if (state->flags & PSC_STATE_FLAG_USING_TLS) {
389  reply = psc_smtpd_ehlo_reply_tls;
390  state->ehlo_discard_mask = psc_ehlo_discard_mask | EHLO_MASK_STARTTLS;
391  } else {
392  reply = psc_smtpd_ehlo_reply_plain;
393  state->ehlo_discard_mask = psc_ehlo_discard_mask;
394  }
395  return (PSC_SEND_REPLY(state, reply));
396 }
397 
398 /* psc_starttls_resume - resume the SMTP protocol after tlsproxy activation */
399 
400 static void psc_starttls_resume(int unused_event, void *context)
401 {
402  const char *myname = "psc_starttls_resume";
403  PSC_STATE *state = (PSC_STATE *) context;
404 
405  /*
406  * Reset SMTP server state if STARTTLS was successful.
407  */
408  if (state->flags & PSC_STATE_FLAG_USING_TLS) {
409  /* Purge the push-back buffer, when implemented. */
410  PSC_STRING_RESET(state->helo_name);
411  PSC_STRING_RESET(state->sender);
412 #ifdef TODO_SASL_AUTH
413  /* Reset SASL AUTH state. Dovecot responses may change. */
414 #endif
415  }
416 
417  /*
418  * Resume read/timeout events. If we still have unread input, resume the
419  * command processor immediately.
420  */
422 }
423 
424 /* psc_starttls_cmd - activate the tlsproxy server */
425 
426 static int psc_starttls_cmd(PSC_STATE *state, char *args)
427 {
428  const char *myname = "psc_starttls_cmd";
429 
430  /*
431  * smtpd(8) incompatibility: we can't send a 4XX reply that TLS is
432  * unavailable when tlsproxy(8) detects the problem too late.
433  */
434  if (PSC_SMTPD_NEXT_TOKEN(args) != 0)
435  return (PSC_SEND_REPLY(state, "501 Syntax: EHLO hostname\r\n"));
436  if (state->flags & PSC_STATE_FLAG_USING_TLS)
437  return (PSC_SEND_REPLY(state,
438  "554 5.5.1 Error: TLS already active\r\n"));
439  if (var_psc_use_tls == 0 || (state->ehlo_discard_mask & EHLO_MASK_STARTTLS))
440  return (PSC_SEND_REPLY(state,
441  "502 5.5.1 Error: command not implemented\r\n"));
442 
443  /*
444  * Suspend the SMTP protocol until psc_starttls_resume() is called.
445  */
447  psc_starttls_open(state, psc_starttls_resume);
448  return (0);
449 }
450 
451 /* psc_extract_addr - extract MAIL/RCPT address, unquoted form */
452 
453 static char *psc_extract_addr(VSTRING *result, const char *string)
454 {
455  const unsigned char *cp = (const unsigned char *) string;
456  char *addr;
457  char *colon;
458  int stop_at;
459  int inquote = 0;
460 
461  /*
462  * smtpd(8) incompatibility: we allow more invalid address forms, and we
463  * don't validate recipients. We are not going to deliver them so we
464  * won't have to worry about deliverability. This may have to change when
465  * we pass the socket to a real SMTP server and replay message envelope
466  * commands.
467  */
468 
469  /* Skip SP characters. */
470  while (*cp && *cp == ' ')
471  cp++;
472 
473  /* Choose the terminator for <addr> or bare addr. */
474  if (*cp == '<') {
475  cp++;
476  stop_at = '>';
477  } else {
478  stop_at = ' ';
479  }
480 
481  /* Skip to terminator or end. */
482  VSTRING_RESET(result);
483  for ( /* void */ ; *cp; cp++) {
484  if (!inquote && *cp == stop_at)
485  break;
486  if (*cp == '"') {
487  inquote = !inquote;
488  } else {
489  if (*cp == '\\' && *++cp == 0)
490  break;
491  VSTRING_ADDCH(result, *cp);
492  }
493  }
494  VSTRING_TERMINATE(result);
495 
496  /*
497  * smtpd(8) compatibility: truncate deprecated route address form. This
498  * is primarily to simplify logfile analysis.
499  */
500  addr = STR(result);
501  if (*addr == '@' && (colon = strchr(addr, ':')) != 0)
502  addr = colon + 1;
503  return (addr);
504 }
505 
506 /* psc_mail_cmd - record MAIL and respond */
507 
508 static int psc_mail_cmd(PSC_STATE *state, char *args)
509 {
510  char *colon;
511  char *addr;
512 
513  /*
514  * smtpd(8) incompatibility: we never reject the sender, and we ignore
515  * additional arguments.
516  */
517  if (var_psc_helo_required && state->helo_name == 0)
518  return (PSC_SEND_REPLY(state,
519  "503 5.5.1 Error: send HELO/EHLO first\r\n"));
520  if (state->sender != 0)
521  return (PSC_SEND_REPLY(state,
522  "503 5.5.1 Error: nested MAIL command\r\n"));
523  if (args == 0 || (colon = strchr(args, ':')) == 0)
524  return (PSC_SEND_REPLY(state,
525  "501 5.5.4 Syntax: MAIL FROM:<address>\r\n"));
526  if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0)
527  return (PSC_SEND_REPLY(state,
528  "501 5.1.7 Bad sender address syntax\r\n"));
529  PSC_STRING_UPDATE(state->sender, addr);
530  return (PSC_SEND_REPLY(state, "250 2.1.0 Ok\r\n"));
531 }
532 
533 /* psc_soften_reply - copy and soft-bounce a reply */
534 
535 static char *psc_soften_reply(const char *reply)
536 {
537  static VSTRING *buf = 0;
538 
539  if (buf == 0)
540  buf = vstring_alloc(100);
541  vstring_strcpy(buf, reply);
542  if (reply[0] == '5')
543  STR(buf)[0] = '4';
544  if (reply[4] == '5')
545  STR(buf)[4] = '4';
546  return (STR(buf));
547 }
548 
549 /* psc_rcpt_cmd record RCPT and respond */
550 
551 static int psc_rcpt_cmd(PSC_STATE *state, char *args)
552 {
553  char *colon;
554  char *addr;
555 
556  /*
557  * smtpd(8) incompatibility: we reject all recipients, and ignore
558  * additional arguments.
559  */
560  if (state->sender == 0)
561  return (PSC_SEND_REPLY(state,
562  "503 5.5.1 Error: need MAIL command\r\n"));
563  if (args == 0 || (colon = strchr(args, ':')) == 0)
564  return (PSC_SEND_REPLY(state,
565  "501 5.5.4 Syntax: RCPT TO:<address>\r\n"));
566  if ((addr = psc_extract_addr(psc_temp, colon + 1)) == 0)
567  return (PSC_SEND_REPLY(state,
568  "501 5.1.3 Bad recipient address syntax\r\n"));
569  msg_info("NOQUEUE: reject: RCPT from [%s]:%s: %.*s; "
570  "from=<%s>, to=<%s>, proto=%s, helo=<%s>",
571  PSC_CLIENT_ADDR_PORT(state),
572  (int) strlen(state->rcpt_reply) - 2,
573  var_soft_bounce == 0 ? state->rcpt_reply :
574  psc_soften_reply(state->rcpt_reply),
575  state->sender, addr, state->protocol,
576  state->helo_name ? state->helo_name : "");
577  return (PSC_SEND_REPLY(state, state->rcpt_reply));
578 }
579 
580 /* psc_data_cmd - respond to DATA and disconnect */
581 
582 static int psc_data_cmd(PSC_STATE *state, char *args)
583 {
584 
585  /*
586  * smtpd(8) incompatibility: we reject all requests.
587  */
588  if (PSC_SMTPD_NEXT_TOKEN(args) != 0)
589  return (PSC_SEND_REPLY(state,
590  "501 5.5.4 Syntax: DATA\r\n"));
591  if (state->sender == 0)
592  return (PSC_SEND_REPLY(state,
593  "503 5.5.1 Error: need RCPT command\r\n"));
594 
595  /*
596  * We really would like to hang up the connection as early as possible,
597  * so that we dont't have to deal with broken zombies that fall silent at
598  * the first reject response. For now we rely on stress-dependent command
599  * read timeouts.
600  *
601  * If we proceed into the data phase, enforce over-all DATA time limit.
602  */
603  return (PSC_SEND_REPLY(state,
604  "554 5.5.1 Error: no valid recipients\r\n"));
605 }
606 
607 /* psc_rset_cmd - reset, send 250 OK */
608 
609 static int psc_rset_cmd(PSC_STATE *state, char *unused_args)
610 {
611  PSC_STRING_RESET(state->sender);
612  return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
613 }
614 
615 /* psc_noop_cmd - respond to something */
616 
617 static int psc_noop_cmd(PSC_STATE *state, char *unused_args)
618 {
619  return (PSC_SEND_REPLY(state, "250 2.0.0 Ok\r\n"));
620 }
621 
622 /* psc_vrfy_cmd - respond to VRFY */
623 
624 static int psc_vrfy_cmd(PSC_STATE *state, char *args)
625 {
626 
627  /*
628  * smtpd(8) incompatibility: we reject all requests, and ignore
629  * additional arguments.
630  */
631  if (PSC_SMTPD_NEXT_TOKEN(args) == 0)
632  return (PSC_SEND_REPLY(state,
633  "501 5.5.4 Syntax: VRFY address\r\n"));
635  return (PSC_SEND_REPLY(state,
636  "502 5.5.1 VRFY command is disabled\r\n"));
637  return (PSC_SEND_REPLY(state, state->rcpt_reply));
638 }
639 
640 /* psc_etrn_cmd - reset, send 250 OK */
641 
642 static int psc_etrn_cmd(PSC_STATE *state, char *args)
643 {
644 
645  /*
646  * smtpd(8) incompatibility: we reject all requests, and ignore
647  * additional arguments.
648  */
649  if (var_psc_helo_required && state->helo_name == 0)
650  return (PSC_SEND_REPLY(state,
651  "503 5.5.1 Error: send HELO/EHLO first\r\n"));
652  if (PSC_SMTPD_NEXT_TOKEN(args) == 0)
653  return (PSC_SEND_REPLY(state,
654  "500 Syntax: ETRN domain\r\n"));
655  return (PSC_SEND_REPLY(state, "458 Unable to queue messages\r\n"));
656 }
657 
658 /* psc_quit_cmd - respond to QUIT and disconnect */
659 
660 static int psc_quit_cmd(PSC_STATE *state, char *unused_args)
661 {
662  const char *myname = "psc_quit_cmd";
663 
664  PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
665  "221 2.0.0 Bye\r\n");
666  /* Caution: state is now a dangling pointer. */
667  return (0);
668 }
669 
670 /* psc_smtpd_time_event - handle per-session time limit */
671 
672 static void psc_smtpd_time_event(int event, void *context)
673 {
674  const char *myname = "psc_smtpd_time_event";
675  PSC_STATE *state = (PSC_STATE *) context;
676 
677  if (msg_verbose > 1)
678  msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
680  event, vstream_fileno(state->smtp_client_stream),
681  state->smtp_client_addr, state->smtp_client_port,
682  psc_print_state_flags(state->flags, myname));
683 
684  msg_info("COMMAND TIME LIMIT from [%s]:%s after %s",
685  PSC_CLIENT_ADDR_PORT(state), state->where);
686  PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
687  psc_smtpd_timeout_reply);
688 }
689 
690  /*
691  * The table of all SMTP commands that we know.
692  */
693 typedef struct {
694  const char *name;
695  int (*action) (PSC_STATE *, char *);
696  int flags; /* see below */
698 
699 #define PSC_SMTPD_CMD_FLAG_NONE (0) /* no flags (i.e. disabled) */
700 #define PSC_SMTPD_CMD_FLAG_ENABLE (1<<0) /* command is enabled */
701 #define PSC_SMTPD_CMD_FLAG_DESTROY (1<<1) /* dangling pointer alert */
702 #define PSC_SMTPD_CMD_FLAG_PRE_TLS (1<<2) /* allowed with mandatory TLS */
703 #define PSC_SMTPD_CMD_FLAG_SUSPEND (1<<3) /* suspend command engine */
704 
705 static const PSC_SMTPD_COMMAND command_table[] = {
709  "XCLIENT", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
710  "XFORWARD", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
711  "AUTH", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_NONE,
712  "MAIL", psc_mail_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
713  "RCPT", psc_rcpt_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
714  "DATA", psc_data_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
715  /* ".", psc_dot_cmd, PSC_SMTPD_CMD_FLAG_NONE, */
716  "RSET", psc_rset_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
717  "NOOP", psc_noop_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_PRE_TLS,
718  "VRFY", psc_vrfy_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
719  "ETRN", psc_etrn_cmd, PSC_SMTPD_CMD_FLAG_ENABLE,
720  "QUIT", psc_quit_cmd, PSC_SMTPD_CMD_FLAG_ENABLE | PSC_SMTPD_CMD_FLAG_DESTROY | PSC_SMTPD_CMD_FLAG_PRE_TLS,
721  0,
722 };
723 
724 /* psc_smtpd_read_event - pseudo responder */
725 
726 static void psc_smtpd_read_event(int event, void *context)
727 {
728  const char *myname = "psc_smtpd_read_event";
729  PSC_STATE *state = (PSC_STATE *) context;
730  time_t *expire_time = state->client_info->expire_time;
731  int ch;
732  struct cmd_trans {
733  int state;
734  int want;
735  int next_state;
736  };
737  const char *saved_where;
738 
739 #define PSC_SMTPD_CMD_ST_ANY 0
740 #define PSC_SMTPD_CMD_ST_CR 1
741 #define PSC_SMTPD_CMD_ST_CR_LF 2
742 
743  static const struct cmd_trans cmd_trans[] = {
746  0, 0, 0,
747  };
748  const struct cmd_trans *transp;
749  char *cmd_buffer_ptr;
750  char *command;
751  const PSC_SMTPD_COMMAND *cmdp;
752  int write_stat;
753 
754  if (msg_verbose > 1)
755  msg_info("%s: sq=%d cq=%d event %d on smtp socket %d from [%s]:%s flags=%s",
757  event, vstream_fileno(state->smtp_client_stream),
758  state->smtp_client_addr, state->smtp_client_port,
759  psc_print_state_flags(state->flags, myname));
760 
761  /*
762  * Basic liveness requirements.
763  *
764  * Drain all input in the VSTREAM buffer, otherwise this socket will not
765  * receive further read event notification until the client disconnects!
766  *
767  * To suspend this loop temporarily before the buffer is drained, use the
768  * PSC_SUSPEND_SMTP_CMD_EVENTS() and PSC_RESUME_SMTP_CMD_EVENTS() macros,
769  * and set the PSC_SMTPD_CMD_FLAG_SUSPEND flag in the command table.
770  *
771  * Don't try to read input before it has arrived, otherwise we would starve
772  * the pseudo threads of other sessions. Get out of here as soon as the
773  * VSTREAM read buffer dries up. Do not look for more input in kernel
774  * buffers. That input wasn't likely there when psc_smtpd_read_event()
775  * was called. Also, yielding the pseudo thread will improve fairness for
776  * other pseudo threads.
777  */
778 
779  /*
780  * Note: on entry into this function the VSTREAM buffer may or may not be
781  * empty, so we test the "no more input" condition at the bottom of the
782  * loops.
783  */
784  for (;;) {
785 
786  /*
787  * Read one command line, possibly one fragment at a time.
788  */
789  for (;;) {
790 
791  if ((ch = PSC_SMTPD_NEXT_CHAR(state)) == VSTREAM_EOF) {
792  PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event);
793  return;
794  }
795 
796  /*
797  * Sanity check. We don't want to store infinitely long commands.
798  */
799  if (state->read_state == PSC_SMTPD_CMD_ST_ANY
800  && VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
801  msg_info("COMMAND LENGTH LIMIT from [%s]:%s after %s",
802  PSC_CLIENT_ADDR_PORT(state), state->where);
803  PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
804  psc_smtpd_421_reply);
805  return;
806  }
807  VSTRING_ADDCH(state->cmd_buffer, ch);
808 
809  /*
810  * Try to match the current character desired by the state
811  * machine. If that fails, try to restart the machine with a
812  * match for its first state. Like smtpd(8), we understand lines
813  * ending in <CR><LF> and bare <LF>. Unlike smtpd(8), we may
814  * treat lines ending in bare <LF> as an offense.
815  */
816  for (transp = cmd_trans; transp->state != state->read_state; transp++)
817  if (transp->want == 0)
818  msg_panic("%s: command_read: unknown state: %d",
819  myname, state->read_state);
820  if (ch == transp->want)
821  state->read_state = transp->next_state;
822  else if (ch == cmd_trans[0].want)
823  state->read_state = cmd_trans[0].next_state;
824  else
826  if (state->read_state == PSC_SMTPD_CMD_ST_CR_LF) {
828  VSTRING_LEN(state->cmd_buffer) - 2);
829  break;
830  }
831 
832  /*
833  * Bare newline test.
834  */
835  if (ch == '\n') {
839  VSTRING_LEN(state->cmd_buffer) - 1, 100);
840  msg_info("BARE NEWLINE from [%s]:%s after %s",
844  expire_time[PSC_TINDX_BARLF] = PSC_TIME_STAMP_DISABLED; /* XXX */
845  /* Skip this test for the remainder of this session. */
846  PSC_SKIP_SESSION_STATE(state, "bare newline test",
848  switch (psc_barlf_action) {
849  case PSC_ACT_DROP:
851  psc_smtpd_time_event,
852  "521 5.5.1 Protocol error\r\n");
853  return;
854  case PSC_ACT_ENFORCE:
856  "550 5.5.1 Protocol error\r\n");
857  break;
858  case PSC_ACT_IGNORE:
861  /* Temporarily whitelist until something expires. */
862  PSC_PASS_SESSION_STATE(state, "bare newline test",
864  expire_time[PSC_TINDX_BARLF] = event_time() + psc_min_ttl;
865  break;
866  default:
867  msg_panic("%s: unknown bare_newline action value %d",
868  myname, psc_barlf_action);
869  }
870  }
872  VSTRING_LEN(state->cmd_buffer) - 1);
873  break;
874  }
875 
876  /*
877  * Yield this pseudo thread when the VSTREAM buffer is empty in
878  * the middle of a command.
879  *
880  * XXX Do not reset the read timeout. The entire command must be
881  * received within the time limit.
882  */
883  if (PSC_SMTPD_BUFFER_EMPTY(state))
884  return;
885  }
886 
887  /*
888  * Terminate the command buffer, and apply the last-resort command
889  * editing workaround.
890  */
892  if (psc_cmd_filter != 0) {
893  const char *cp;
894 
895  for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++)
896  /* void */ ;
897  if ((cp = psc_dict_get(psc_cmd_filter, cp)) != 0) {
898  msg_info("[%s]:%s: replacing command \"%.100s\" with \"%.100s\"",
899  state->smtp_client_addr, state->smtp_client_port,
900  STR(state->cmd_buffer), cp);
901  vstring_strcpy(state->cmd_buffer, cp);
902  } else if (psc_cmd_filter->error != 0) {
903  msg_fatal("%s:%s lookup error for \"%.100s\"",
904  psc_cmd_filter->type, psc_cmd_filter->name, cp);
905  }
906  }
907 
908  /*
909  * Reset the command buffer write pointer and state machine in
910  * preparation for the next command. For this to work as expected,
911  * VSTRING_RESET() must be non-destructive. We just can't ask for the
912  * VSTRING_LEN() and vstring_end() results.
913  */
915  VSTRING_RESET(state->cmd_buffer);
916 
917  /*
918  * Process the command line.
919  *
920  * Caution: some command handlers terminate the session and destroy the
921  * session state structure. When this happens we must leave the SMTP
922  * engine to avoid a dangling pointer problem.
923  */
924  cmd_buffer_ptr = STR(state->cmd_buffer);
925  if (msg_verbose)
926  msg_info("< [%s]:%s: %s", state->smtp_client_addr,
927  state->smtp_client_port, cmd_buffer_ptr);
928 
929  /* Parse the command name. */
930  if ((command = PSC_SMTPD_NEXT_TOKEN(cmd_buffer_ptr)) == 0)
931  command = "";
932 
933  /*
934  * The non-SMTP, PIPELINING and command COUNT tests depend on the
935  * client command handler.
936  *
937  * Caution: cmdp->name and cmdp->action may be null on loop exit.
938  */
939  saved_where = state->where;
940  state->where = PSC_SMTPD_CMD_UNIMPL;
941  for (cmdp = command_table; cmdp->name != 0; cmdp++) {
942  if (strcasecmp(command, cmdp->name) == 0) {
943  state->where = cmdp->name;
944  break;
945  }
946  }
947 
948  if ((state->flags & PSC_STATE_FLAG_SMTPD_X21)
949  && cmdp->action != psc_quit_cmd) {
950  PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
951  state->final_reply);
952  return;
953  }
954  /* Non-SMTP command test. */
956  == PSC_STATE_FLAG_NSMTP_TODO && cmdp->name == 0
957  && (is_header(command)
958  /* Ignore forbid_cmds lookup errors. Non-critical feature. */
960  && string_list_match(psc_forbid_cmds, command)))) {
961  printable(command, '?');
962  PSC_SMTPD_ESCAPE_TEXT(psc_temp, cmd_buffer_ptr,
963  strlen(cmd_buffer_ptr), 100);
964  msg_info("NON-SMTP COMMAND from [%s]:%s after %s: %.100s %s",
965  PSC_CLIENT_ADDR_PORT(state), saved_where,
966  command, STR(psc_temp));
969  expire_time[PSC_TINDX_NSMTP] = PSC_TIME_STAMP_DISABLED; /* XXX */
970  /* Skip this test for the remainder of this SMTP session. */
971  PSC_SKIP_SESSION_STATE(state, "non-smtp test",
973  switch (psc_nsmtp_action) {
974  case PSC_ACT_DROP:
976  psc_smtpd_time_event,
977  "521 5.7.0 Error: I can break rules, too. Goodbye.\r\n");
978  return;
979  case PSC_ACT_ENFORCE:
981  "550 5.5.1 Protocol error\r\n");
982  break;
983  case PSC_ACT_IGNORE:
986  /* Temporarily whitelist until something else expires. */
987  PSC_PASS_SESSION_STATE(state, "non-smtp test",
989  expire_time[PSC_TINDX_NSMTP] = event_time() + psc_min_ttl;
990  break;
991  default:
992  msg_panic("%s: unknown non_smtp_command action value %d",
993  myname, psc_nsmtp_action);
994  }
995  }
996  /* Command PIPELINING test. */
999  printable(command, '?');
1001  PSC_SMTPD_PEEK_LEN(state), 100);
1002  msg_info("COMMAND PIPELINING from [%s]:%s after %.100s: %s",
1003  PSC_CLIENT_ADDR_PORT(state), command, STR(psc_temp));
1006  expire_time[PSC_TINDX_PIPEL] = PSC_TIME_STAMP_DISABLED; /* XXX */
1007  /* Skip this test for the remainder of this SMTP session. */
1008  PSC_SKIP_SESSION_STATE(state, "pipelining test",
1010  switch (psc_pipel_action) {
1011  case PSC_ACT_DROP:
1013  psc_smtpd_time_event,
1014  "521 5.5.1 Protocol error\r\n");
1015  return;
1016  case PSC_ACT_ENFORCE:
1018  "550 5.5.1 Protocol error\r\n");
1019  break;
1020  case PSC_ACT_IGNORE:
1023  /* Temporarily whitelist until something else expires. */
1024  PSC_PASS_SESSION_STATE(state, "pipelining test",
1026  expire_time[PSC_TINDX_PIPEL] = event_time() + psc_min_ttl;
1027  break;
1028  default:
1029  msg_panic("%s: unknown pipelining action value %d",
1030  myname, psc_pipel_action);
1031  }
1032  }
1033 
1034  /*
1035  * The following tests don't pass until the client gets all the way
1036  * to the RCPT TO command. However, the client can still fail these
1037  * tests with some later command.
1038  */
1039  if (cmdp->action == psc_rcpt_cmd) {
1042  PSC_PASS_SESSION_STATE(state, "bare newline test",
1044  /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
1045  expire_time[PSC_TINDX_BARLF] = event_time() + var_psc_barlf_ttl;
1046  }
1049  PSC_PASS_SESSION_STATE(state, "non-smtp test",
1051  /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
1052  expire_time[PSC_TINDX_NSMTP] = event_time() + var_psc_nsmtp_ttl;
1053  }
1056  PSC_PASS_SESSION_STATE(state, "pipelining test",
1058  /* XXX Reset to PSC_TIME_STAMP_DISABLED on failure. */
1059  expire_time[PSC_TINDX_PIPEL] = event_time() + var_psc_pipel_ttl;
1060  }
1061  }
1062  /* Command COUNT limit test. */
1063  if (++state->command_count > var_psc_cmd_count
1064  && cmdp->action != psc_quit_cmd) {
1065  msg_info("COMMAND COUNT LIMIT from [%s]:%s after %s",
1066  PSC_CLIENT_ADDR_PORT(state), saved_where);
1067  PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
1068  psc_smtpd_421_reply);
1069  return;
1070  }
1071  /* Finally, execute the command. */
1072  if (cmdp->name == 0 || (cmdp->flags & PSC_SMTPD_CMD_FLAG_ENABLE) == 0) {
1073  write_stat = PSC_SEND_REPLY(state,
1074  "502 5.5.2 Error: command not recognized\r\n");
1075  } else if (var_psc_enforce_tls
1076  && (state->flags & PSC_STATE_FLAG_USING_TLS) == 0
1077  && (cmdp->flags & PSC_SMTPD_CMD_FLAG_PRE_TLS) == 0) {
1078  write_stat = PSC_SEND_REPLY(state,
1079  "530 5.7.0 Must issue a STARTTLS command first\r\n");
1080  } else {
1081  write_stat = cmdp->action(state, cmd_buffer_ptr);
1082  if (cmdp->flags & PSC_SMTPD_CMD_FLAG_DESTROY)
1083  return;
1084  }
1085 
1086  /*
1087  * Terminate the session after a write error.
1088  */
1089  if (write_stat < 0) {
1090  PSC_CLEAR_EVENT_HANGUP(state, psc_smtpd_time_event);
1091  return;
1092  }
1093 
1094  /*
1095  * We're suspended, waiting for some external event to happen.
1096  * Hopefully, someone will call us back to process the remainder of
1097  * the pending input, otherwise we could hang.
1098  */
1099  if (cmdp->flags & PSC_SMTPD_CMD_FLAG_SUSPEND)
1100  return;
1101 
1102  /*
1103  * Reset the command read timeout before reading the next command.
1104  */
1105  event_request_timer(psc_smtpd_time_event, (void *) state,
1107 
1108  /*
1109  * Yield this pseudo thread when the VSTREAM buffer is empty.
1110  */
1111  if (PSC_SMTPD_BUFFER_EMPTY(state))
1112  return;
1113  }
1114 }
1115 
1116 /* psc_smtpd_tests - per-session deep protocol test initialization */
1117 
1119 {
1120  static char *myname = "psc_smtpd_tests";
1121 
1122  /*
1123  * Report errors and progress in the context of this test.
1124  */
1125  PSC_BEGIN_TESTS(state, "tests after SMTP handshake");
1126 
1127  /*
1128  * Initialize per-session state that is used only by the dummy engine:
1129  * the command read buffer and the command read state machine.
1130  */
1131  state->cmd_buffer = vstring_alloc(100);
1133 
1134  /*
1135  * Opportunistically make postscreen more useful by turning on the
1136  * pipelining and non-SMTP command tests when a pre-handshake test
1137  * failed, or when some deep test is configured as enabled.
1138  *
1139  * XXX Make "opportunistically" configurable for each test.
1140  */
1141  if ((state->flags & PSC_STATE_FLAG_SMTPD_X21) == 0) {
1142  state->flags |= PSC_STATE_MASK_SMTPD_TODO;
1143  } else {
1144  state->flags &= ~PSC_STATE_MASK_SMTPD_TODO;
1145  }
1146 
1147  /*
1148  * Send no SMTP banner to pregreeting clients. This eliminates a lot of
1149  * "NON-SMTP COMMAND" events, and improves sender/recipient logging.
1150  */
1151  if ((state->flags & PSC_STATE_FLAG_PREGR_FAIL) == 0
1152  && PSC_SEND_REPLY(state, psc_smtpd_greeting) != 0) {
1153  psc_hangup_event(state);
1154  return;
1155  }
1156 
1157  /*
1158  * Wait for the client to respond.
1159  */
1161  psc_smtpd_read_event, psc_smtpd_time_event,
1162  (void *) state, PSC_EFF_CMD_TIME_LIMIT);
1163 }
1164 
1165 /* psc_smtpd_init - per-process deep protocol test initialization */
1166 
1167 void psc_smtpd_init(void)
1168 {
1169 
1170  /*
1171  * Initialize the server banner.
1172  */
1173  vstring_sprintf(psc_temp, "220 %s\r\n", var_smtpd_banner);
1174  psc_smtpd_greeting = mystrdup(STR(psc_temp));
1175 
1176  /*
1177  * Initialize the HELO reply.
1178  */
1179  vstring_sprintf(psc_temp, "250 %s\r\n", var_myhostname);
1180  psc_smtpd_helo_reply = mystrdup(STR(psc_temp));
1181 
1182  /*
1183  * STARTTLS support. Note the complete absence of #ifdef USE_TLS
1184  * throughout the postscreen(8) source code. If Postfix is built without
1185  * TLS support, then the TLS proxy will simply report that TLS is not
1186  * available, and conventional error handling will take care of the
1187  * issue.
1188  *
1189  * Legacy code copied from smtpd(8). The pre-fabricated EHLO reply depends
1190  * on this.
1191  */
1192  if (*var_psc_tls_level) {
1194  default:
1195  msg_fatal("Invalid TLS level \"%s\"", var_psc_tls_level);
1196  /* NOTREACHED */
1197  break;
1198  case TLS_LEV_SECURE:
1199  case TLS_LEV_VERIFY:
1200  case TLS_LEV_FPRINT:
1201  msg_warn("%s: unsupported TLS level \"%s\", using \"encrypt\"",
1203  /* FALLTHROUGH */
1204  case TLS_LEV_ENCRYPT:
1206  break;
1207  case TLS_LEV_MAY:
1208  var_psc_enforce_tls = 0;
1209  var_psc_use_tls = 1;
1210  break;
1211  case TLS_LEV_NONE:
1213  break;
1214  }
1215  }
1217 #ifdef TODO_SASL_AUTH
1218  var_psc_tls_auth_only = var_psc_tls_auth_only || var_psc_enforce_tls;
1219 #endif
1220 
1221  /*
1222  * Initialize the EHLO reply. Once for plaintext sessions, and once for
1223  * TLS sessions.
1224  */
1225  psc_smtpd_format_ehlo_reply(psc_temp, psc_ehlo_discard_mask);
1226  psc_smtpd_ehlo_reply_plain = mystrdup(STR(psc_temp));
1227 
1228  psc_smtpd_format_ehlo_reply(psc_temp,
1229  psc_ehlo_discard_mask | EHLO_MASK_STARTTLS);
1230  psc_smtpd_ehlo_reply_tls = mystrdup(STR(psc_temp));
1231 
1232  /*
1233  * Initialize the 421 timeout reply.
1234  */
1235  vstring_sprintf(psc_temp, "421 4.4.2 %s Error: timeout exceeded\r\n",
1236  var_myhostname);
1237  psc_smtpd_timeout_reply = mystrdup(STR(psc_temp));
1238 
1239  /*
1240  * Initialize the generic 421 reply.
1241  */
1242  vstring_sprintf(psc_temp, "421 %s Service unavailable - try again later\r\n",
1243  var_myhostname);
1244  psc_smtpd_421_reply = mystrdup(STR(psc_temp));
1245 
1246  /*
1247  * Initialize the reply footer.
1248  */
1249  if (*var_psc_rej_footer)
1250  psc_expand_init();
1251 }
1252 
1253 /* psc_smtpd_pre_jail_init - per-process deep protocol test initialization */
1254 
1256 {
1257 
1258  /*
1259  * Determine what server ESMTP features to suppress, typically to avoid
1260  * inter-operability problems. We do the default filter here, and
1261  * determine client-dependent filtering on the fly.
1262  *
1263  * XXX Bugger. This means we have to restart when the table changes!
1264  */
1265  if (*var_psc_ehlo_dis_maps)
1266  psc_ehlo_discard_maps = maps_create(VAR_PSC_EHLO_DIS_MAPS,
1268  DICT_FLAG_LOCK);
1269  psc_ehlo_discard_mask = ehlo_mask(var_psc_ehlo_dis_words);
1270 
1271  /*
1272  * Last-resort command editing support.
1273  */
1274  if (*var_psc_cmd_filter)
1275  psc_cmd_filter = dict_open(var_psc_cmd_filter, O_RDONLY,
1277 }
int msg_verbose
Definition: msg.c:177
PSC_CLIENT_INFO * client_info
Definition: postscreen.h:83
#define IS_SPACE_TAB(ch)
Definition: lex_822.h:17
VSTRING * cmd_buffer
Definition: postscreen.h:94
int var_psc_barlf_ttl
Definition: postscreen.c:503
#define VSTREAM_EOF
Definition: vstream.h:110
#define MAIL_PROTO_ESMTP
Definition: mail_proto.h:31
#define PSC_SMTPD_CMD_UNIMPL
Definition: postscreen.h:291
#define PSC_RESUME_SMTP_CMD_EVENTS(state)
int command_count
Definition: postscreen.h:90
#define PSC_EHLO_APPEND1(save, buf, fmt, arg1)
#define PSC_SMTPD_CMD_ST_CR
const char * rcpt_reply
Definition: postscreen.h:89
#define PSC_STATE_FLAG_NSMTP_TODO
Definition: postscreen.h:203
char * mystrdup(const char *str)
Definition: mymalloc.c:225
char * helo_name
Definition: postscreen.h:92
#define EHLO_MASK_STARTTLS
Definition: ehlo_mask.h:24
time_t expire_time[PSC_TINDX_COUNT]
Definition: postscreen.h:63
int psc_pipel_action
Definition: postscreen.c:534
#define EHLO_MASK_SMTPUTF8
Definition: ehlo_mask.h:30
#define PSC_FAIL_SESSION_STATE(state, bits)
Definition: postscreen.h:422
int ehlo_discard_mask
Definition: postscreen.h:97
int var_soft_bounce
Definition: mail_params.c:281
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
bool var_disable_vrfy_cmd
Definition: postscreen.c:443
char * sender
Definition: postscreen.h:93
bool var_psc_helo_required
Definition: postscreen.c:465
bool var_psc_enforce_tls
Definition: postscreen.c:462
char * name
Definition: dict.h:80
#define PSC_STATE_FLAG_PIPEL_SKIP
Definition: postscreen.h:199
#define PSC_STATE_MASK_BARLF_TODO_PASS_FAIL
Definition: postscreen.h:241
char * smtp_client_port
Definition: postscreen.h:75
STRING_LIST * psc_forbid_cmds
Definition: postscreen.c:538
#define PSC_SUSPEND_SMTP_CMD_EVENTS(state)
#define PSC_STATE_FLAG_PIPEL_PASS
Definition: postscreen.h:197
Definition: maps.h:22
int var_psc_pipel_ttl
Definition: postscreen.c:495
#define PSC_STATE_MASK_NSMTP_TODO_SKIP
Definition: postscreen.h:229
#define EHLO_MASK_8BITMIME
Definition: ehlo_mask.h:17
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
#define TLS_LEV_VERIFY
Definition: tls.h:50
#define EHLO_MASK_DSN
Definition: ehlo_mask.h:29
#define PSC_STATE_MASK_PIPEL_TODO_PASS_FAIL
Definition: postscreen.h:237
#define TLS_LEV_NONE
Definition: tls.h:43
DICT * dict_open(const char *, int, int)
Definition: dict_open.c:421
#define PSC_TIME_STAMP_DISABLED
Definition: postscreen.h:106
int var_smtputf8_enable
Definition: mail_params.c:343
void psc_starttls_open(PSC_STATE *, EVENT_NOTIFY_FN)
void psc_expand_init(void)
int psc_check_queue_length
Definition: postscreen.c:527
void psc_smtpd_init(void)
#define PSC_UNFAIL_SESSION_STATE(state, bits)
Definition: postscreen.h:450
int flags
Definition: postscreen.h:70
#define VSTRING_LEN(vp)
Definition: vstring.h:72
#define PSC_SMTPD_CMD_FLAG_DESTROY
#define DICT_FLAG_FOLD_FIX
Definition: dict.h:124
#define PSC_UNPASS_SESSION_STATE(state, bits)
Definition: postscreen.h:445
int psc_barlf_action
Definition: postscreen.c:536
char * var_psc_cmd_filter
Definition: postscreen.c:447
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
long var_message_limit
Definition: mail_params.c:265
#define PSC_SMTPD_CMD_FLAG_ENABLE
const char * str_ehlo_mask(int mask_bits)
Definition: ehlo_mask.c:100
#define TLS_LEV_SECURE
Definition: tls.h:51
Definition: dict.h:78
#define PSC_EFF_CMD_TIME_LIMIT
Definition: postscreen.h:387
#define PSC_STATE_FLAG_SMTPD_X21
Definition: postscreen.h:118
#define string_list_match
Definition: string_list.h:26
#define is_header(str)
Definition: is_header.h:17
char * type
Definition: dict.h:79
char * var_psc_tls_level
Definition: postscreen.c:460
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define PSC_BEGIN_TESTS(state, name)
Definition: postscreen.h:498
#define PSC_STRING_UPDATE(str, text)
Definition: postscreen.h:393
void psc_smtpd_tests(PSC_STATE *state)
const char * final_reply
Definition: postscreen.h:78
bool var_broken_auth_clients
Definition: smtpd.c:1284
#define PSC_CLIENT_ADDR_PORT(state)
Definition: postscreen.h:414
const char * where
Definition: postscreen.h:99
#define PSC_STATE_MASK_SMTPD_TODO
Definition: postscreen.h:256
const char * psc_maps_find(MAPS *, const char *, int)
char * smtp_client_addr
Definition: postscreen.h:74
#define EHLO_MASK_SIZE
Definition: ehlo_mask.h:19
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
Definition: maps.c:112
#define PSC_ENFORCE_SESSION_STATE(state, reply)
Definition: postscreen.h:439
#define PSC_SMTPD_BUFFER_EMPTY(state)
#define PSC_TINDX_BARLF
Definition: postscreen.h:46
#define PSC_CLEAR_EVENT_HANGUP(state, event)
#define EHLO_MASK_SILENT
Definition: ehlo_mask.h:31
char * title
Definition: maps.h:23
#define VSTRING_RESET(vp)
Definition: vstring.h:77
#define DICT_FLAG_LOCK
Definition: dict.h:116
#define STR(x)
Definition: anvil.c:518
#define PSC_STATE_FLAG_NSMTP_PASS
Definition: postscreen.h:202
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
void psc_hangup_event(PSC_STATE *)
bool var_psc_use_tls
Definition: postscreen.c:461
#define PSC_SKIP_SESSION_STATE(state, what, bits)
Definition: postscreen.h:427
#define PSC_STATE_FLAG_BARLF_SKIP
Definition: postscreen.h:209
#define PSC_SMTPD_CMD_FLAG_SUSPEND
#define PSC_SMTPD_PEEK_DATA(state)
#define PSC_SMTPD_CMD_ST_CR_LF
void psc_smtpd_pre_jail_init(void)
#define TLS_LEV_ENCRYPT
Definition: tls.h:45
#define PSC_ACT_ENFORCE
Definition: postscreen.h:357
int error
Definition: dict.h:94
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
int var_psc_nsmtp_ttl
Definition: postscreen.c:499
char * var_psc_ehlo_dis_maps
Definition: postscreen.c:455
#define PSC_ACT_IGNORE
Definition: postscreen.h:358
#define PSC_SMTPD_NEXT_TOKEN(ptr)
#define PSC_SMTPD_NEXT_CHAR(state)
int psc_nsmtp_action
Definition: postscreen.c:535
int var_line_limit
Definition: mail_params.c:263
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define TLS_LEV_FPRINT
Definition: tls.h:46
#define PSC_STATE_MASK_PIPEL_TODO_SKIP
Definition: postscreen.h:227
VSTRING * psc_temp
Definition: postscreen.c:530
int(* action)(PSC_STATE *, char *)
char * var_psc_ehlo_dis_words
Definition: postscreen.c:454
time_t event_time(void)
Definition: events.c:647
int error
Definition: maps.h:25
#define PSC_STATE_FLAG_BARLF_FAIL
Definition: postscreen.h:206
int tls_level_lookup(const char *)
Definition: tls_level.c:85
#define PSC_STATE_MASK_BARLF_TODO_SKIP
Definition: postscreen.h:231
#define PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, event, reply)
char * var_psc_rej_footer
Definition: postscreen.c:512
#define VAR_PSC_TLS_LEVEL
Definition: mail_params.h:3732
#define PSC_SMTPD_CMD_FLAG_NONE
int int
Definition: smtpd_proxy.h:21
char * var_psc_forbid_cmds
Definition: postscreen.c:450
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:41
#define PSC_STATE_FLAG_USING_TLS
Definition: postscreen.h:113
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
Definition: events.c:894
#define PSC_TINDX_PIPEL
Definition: postscreen.h:44
#define VAR_PSC_EHLO_DIS_MAPS
Definition: mail_params.h:3728
#define PSC_STATE_FLAG_PREGR_FAIL
Definition: postscreen.h:186
#define PSC_SMTPD_ESCAPE_TEXT(dest, src, src_len, max_len)
const char * protocol
Definition: postscreen.h:91
#define PSC_PASS_SESSION_STATE(state, what, bits)
Definition: postscreen.h:417
#define vstream_fileno(vp)
Definition: vstream.h:115
#define PSC_STRING_RESET(str)
Definition: postscreen.h:398
#define TLS_LEV_MAY
Definition: tls.h:44
#define PSC_STATE_FLAG_BARLF_PASS
Definition: postscreen.h:207
#define PSC_SMTPD_PEEK_LEN(state)
#define EHLO_MASK_ENHANCEDSTATUSCODES
Definition: ehlo_mask.h:28
#define PSC_READ_EVENT_REQUEST2(fd, read_act, time_act, context, timeout)
Definition: postscreen.h:332
#define PSC_STATE_FLAG_PIPEL_TODO
Definition: postscreen.h:198
int psc_min_ttl
Definition: postscreen.c:537
char * var_myhostname
Definition: mail_params.c:223
#define PSC_STATE_FLAG_PIPEL_FAIL
Definition: postscreen.h:196
char * printable(char *string, int replacement)
Definition: printable.c:49
#define EHLO_MASK_VRFY
Definition: ehlo_mask.h:20
#define PSC_STATE_FLAG_NSMTP_SKIP
Definition: postscreen.h:204
#define EHLO_MASK_AUTH
Definition: ehlo_mask.h:22
#define EHLO_MASK_ETRN
Definition: ehlo_mask.h:21
char * var_smtpd_banner
Definition: postscreen.c:442
#define PSC_SEND_REPLY
Definition: postscreen.h:542
int psc_post_queue_length
Definition: postscreen.c:528
#define PSC_EHLO_APPEND(save, buf, fmt)
bool var_psc_disable_vrfy
Definition: postscreen.c:464
int read_state
Definition: postscreen.h:95
const char * psc_dict_get(DICT *, const char *)
#define PSC_STATE_FLAG_BARLF_TODO
Definition: postscreen.h:208
#define PSC_STATE_MASK_NSMTP_TODO_PASS_FAIL
Definition: postscreen.h:239
const char * psc_print_state_flags(int, const char *)
int var_psc_cmd_count
Definition: postscreen.c:505
#define PSC_SMTPD_CMD_ST_ANY
VSTREAM * smtp_client_stream
Definition: postscreen.h:72
#define PSC_ACT_DROP
Definition: postscreen.h:356
#define PSC_SMTPD_CMD_FLAG_PRE_TLS
#define PSC_STATE_FLAG_NSMTP_FAIL
Definition: postscreen.h:201
int ehlo_mask(const char *mask_str)
Definition: ehlo_mask.c:86
#define PSC_TINDX_NSMTP
Definition: postscreen.h:45
void msg_info(const char *fmt,...)
Definition: msg.c:199