Postfix3.3.1
smtpd_check.c
[詳解]
1 /*++
2 /* NAME
3 /* smtpd_check 3
4 /* SUMMARY
5 /* SMTP client request filtering
6 /* SYNOPSIS
7 /* #include "smtpd.h"
8 /* #include "smtpd_check.h"
9 /*
10 /* void smtpd_check_init()
11 /*
12 /* int smtpd_check_addr(sender, address, smtputf8)
13 /* const char *sender;
14 /* const char *address;
15 /* int smtputf8;
16 /*
17 /* char *smtpd_check_rewrite(state)
18 /* SMTPD_STATE *state;
19 /*
20 /* char *smtpd_check_client(state)
21 /* SMTPD_STATE *state;
22 /*
23 /* char *smtpd_check_helo(state, helohost)
24 /* SMTPD_STATE *state;
25 /* char *helohost;
26 /*
27 /* char *smtpd_check_mail(state, sender)
28 /* SMTPD_STATE *state;
29 /* char *sender;
30 /*
31 /* char *smtpd_check_rcpt(state, recipient)
32 /* SMTPD_STATE *state;
33 /* char *recipient;
34 /*
35 /* char *smtpd_check_etrn(state, destination)
36 /* SMTPD_STATE *state;
37 /* char *destination;
38 /*
39 /* char *smtpd_check_data(state)
40 /* SMTPD_STATE *state;
41 /*
42 /* char *smtpd_check_eod(state)
43 /* SMTPD_STATE *state;
44 /*
45 /* char *smtpd_check_size(state, size)
46 /* SMTPD_STATE *state;
47 /* off_t size;
48 /*
49 /* char *smtpd_check_queue(state)
50 /* SMTPD_STATE *state;
51 /* DESCRIPTION
52 /* This module implements additional checks on SMTP client requests.
53 /* A client request is validated in the context of the session state.
54 /* The result is either an error response (including the numerical
55 /* code) or the result is a null pointer in case of success.
56 /*
57 /* smtpd_check_init() initializes. This function should be called
58 /* once during the process life time.
59 /*
60 /* smtpd_check_addr() sanity checks an email address and returns
61 /* non-zero in case of badness. The sender argument provides sender
62 /* context for address resolution and caching, or a null pointer
63 /* if information is unavailable.
64 /*
65 /* smtpd_check_rewrite() should be called before opening a queue
66 /* file or proxy connection, in order to establish the proper
67 /* header address rewriting context.
68 /*
69 /* Each of the following routines scrutinizes the argument passed to
70 /* an SMTP command such as HELO, MAIL FROM, RCPT TO, or scrutinizes
71 /* the initial client connection request. The administrator can
72 /* specify what restrictions apply.
73 /*
74 /* Restrictions are specified via configuration parameters named
75 /* \fIsmtpd_{client,helo,sender,recipient}_restrictions.\fR Each
76 /* configuration parameter specifies a list of zero or more
77 /* restrictions that are applied in the order as specified.
78 /* .PP
79 /* smtpd_check_client() validates the client host name or address.
80 /* Relevant configuration parameters:
81 /* .IP smtpd_client_restrictions
82 /* Restrictions on the names or addresses of clients that may connect
83 /* to this SMTP server.
84 /* .PP
85 /* smtpd_check_helo() validates the hostname provided with the
86 /* HELO/EHLO commands. Relevant configuration parameters:
87 /* .IP smtpd_helo_restrictions
88 /* Restrictions on the hostname that is sent with the HELO/EHLO
89 /* command.
90 /* .PP
91 /* smtpd_check_mail() validates the sender address provided with
92 /* a MAIL FROM request. Relevant configuration parameters:
93 /* .IP smtpd_sender_restrictions
94 /* Restrictions on the sender address that is sent with the MAIL FROM
95 /* command.
96 /* .PP
97 /* smtpd_check_rcpt() validates the recipient address provided
98 /* with an RCPT TO request. Relevant configuration parameters:
99 /* .IP smtpd_recipient_restrictions
100 /* Restrictions on the recipient address that is sent with the RCPT
101 /* TO command.
102 /* .IP local_recipient_maps
103 /* Tables of user names (not addresses) that exist in $mydestination.
104 /* Mail for local users not in these tables is rejected.
105 /* .PP
106 /* smtpd_check_etrn() validates the domain name provided with the
107 /* ETRN command, and other client-provided information. Relevant
108 /* configuration parameters:
109 /* .IP smtpd_etrn_restrictions
110 /* Restrictions on the hostname that is sent with the HELO/EHLO
111 /* command.
112 /* .PP
113 /* smtpd_check_size() checks if a message with the given size can
114 /* be received (zero means that the message size is unknown). The
115 /* message is rejected when
116 /* the message size exceeds the non-zero bound specified with the
117 /* \fImessage_size_limit\fR configuration parameter. This is a
118 /* permanent error.
119 /*
120 /* smtpd_check_queue() checks the available queue file system
121 /* space. The message is rejected when:
122 /* .IP \(bu
123 /* The available queue file system space is less than the amount
124 /* specified with the \fImin_queue_free\fR configuration parameter.
125 /* This is a temporary error.
126 /* .IP \(bu
127 /* The available queue file system space is less than twice the
128 /* message size limit. This is a temporary error.
129 /* .PP
130 /* smtpd_check_data() enforces generic restrictions after the
131 /* client has sent the DATA command.
132 /*
133 /* smtpd_check_eod() enforces generic restrictions after the
134 /* client has sent the END-OF-DATA command.
135 /*
136 /* Arguments:
137 /* .IP name
138 /* The client hostname, or \fIunknown\fR.
139 /* .IP addr
140 /* The client address.
141 /* .IP helohost
142 /* The hostname given with the HELO command.
143 /* .IP sender
144 /* The sender address given with the MAIL FROM command.
145 /* .IP recipient
146 /* The recipient address given with the RCPT TO or VRFY command.
147 /* .IP size
148 /* The message size given with the MAIL FROM command (zero if unknown).
149 /* BUGS
150 /* Policies like these should not be hard-coded in C, but should
151 /* be user-programmable instead.
152 /* SEE ALSO
153 /* namadr_list(3) host access control
154 /* domain_list(3) domain access control
155 /* fsspace(3) free file system space
156 /* LICENSE
157 /* .ad
158 /* .fi
159 /* The Secure Mailer license must be distributed with this software.
160 /* AUTHOR(S)
161 /* Wietse Venema
162 /* IBM T.J. Watson Research
163 /* P.O. Box 704
164 /* Yorktown Heights, NY 10598, USA
165 /*
166 /* Wietse Venema
167 /* Google, Inc.
168 /* 111 8th Avenue
169 /* New York, NY 10011, USA
170 /*
171 /* TLS support originally by:
172 /* Lutz Jaenicke
173 /* BTU Cottbus
174 /* Allgemeine Elektrotechnik
175 /* Universitaetsplatz 3-4
176 /* D-03044 Cottbus, Germany
177 /*--*/
178 
179 /* System library. */
180 
181 #include <sys_defs.h>
182 #include <sys/socket.h>
183 #include <netinet/in.h>
184 #include <arpa/inet.h>
185 #include <string.h>
186 #include <ctype.h>
187 #include <stdarg.h>
188 #include <netdb.h>
189 #include <setjmp.h>
190 #include <stdlib.h>
191 #include <unistd.h>
192 #include <errno.h>
193 
194 #ifdef STRCASECMP_IN_STRINGS_H
195 #include <strings.h>
196 #endif
197 
198 /* Utility library. */
199 
200 #include <msg.h>
201 #include <vstring.h>
202 #include <split_at.h>
203 #include <fsspace.h>
204 #include <stringops.h>
205 #include <valid_hostname.h>
206 #include <argv.h>
207 #include <mymalloc.h>
208 #include <dict.h>
209 #include <htable.h>
210 #include <ctable.h>
211 #include <mac_expand.h>
212 #include <attr_clnt.h>
213 #include <myaddrinfo.h>
214 #include <inet_proto.h>
215 #include <ip_match.h>
216 #include <valid_utf8_hostname.h>
217 #include <midna_domain.h>
218 #include <mynetworks.h>
219 
220 /* DNS library. */
221 
222 #include <dns.h>
223 
224 /* Global library. */
225 
226 #include <string_list.h>
227 #include <namadr_list.h>
228 #include <domain_list.h>
229 #include <mail_params.h>
230 #include <resolve_clnt.h>
231 #include <mail_error.h>
232 #include <resolve_local.h>
233 #include <own_inet_addr.h>
234 #include <mail_conf.h>
235 #include <maps.h>
236 #include <mail_addr_find.h>
237 #include <match_parent_style.h>
238 #include <strip_addr.h>
239 #include <cleanup_user.h>
240 #include <record.h>
241 #include <rec_type.h>
242 #include <mail_proto.h>
243 #include <mail_addr.h>
244 #include <verify_clnt.h>
245 #include <input_transp.h>
246 #include <is_header.h>
247 #include <valid_mailhost_addr.h>
248 #include <dsn_util.h>
249 #include <conv_time.h>
250 #include <xtext.h>
251 #include <smtp_stream.h>
252 #include <attr_override.h>
253 
254 /* Application-specific. */
255 
256 #include "smtpd.h"
257 #include "smtpd_sasl_glue.h"
258 #include "smtpd_check.h"
259 #include "smtpd_dsn_fix.h"
260 #include "smtpd_resolve.h"
261 #include "smtpd_expand.h"
262 
263  /*
264  * Eject seat in case of parsing problems.
265  */
266 static jmp_buf smtpd_check_buf;
267 
268  /*
269  * Results of restrictions. Errors are negative; see dict.h.
270  */
271 #define SMTPD_CHECK_DUNNO 0 /* indifferent */
272 #define SMTPD_CHECK_OK 1 /* explicitly permit */
273 #define SMTPD_CHECK_REJECT 2 /* explicitly reject */
274 
275  /*
276  * Intermediate results. These are static to avoid unnecessary stress on the
277  * memory manager routines.
278  */
279 static VSTRING *error_text;
280 static CTABLE *smtpd_rbl_cache;
281 static CTABLE *smtpd_rbl_byte_cache;
282 
283  /*
284  * Pre-opened SMTP recipient maps so we can reject mail for unknown users.
285  * XXX This does not belong here and will eventually become part of the
286  * trivial-rewrite resolver.
287  */
288 static MAPS *local_rcpt_maps;
289 static MAPS *send_canon_maps;
290 static MAPS *rcpt_canon_maps;
291 static MAPS *canonical_maps;
292 static MAPS *virt_alias_maps;
293 static MAPS *virt_mailbox_maps;
294 static MAPS *relay_rcpt_maps;
295 
296 #ifdef TEST
297 
298 static STRING_LIST *virt_alias_doms;
299 static STRING_LIST *virt_mailbox_doms;
300 
301 #endif
302 
303  /*
304  * Response templates for various rbl domains.
305  */
306 static MAPS *rbl_reply_maps;
307 
308  /*
309  * Pre-opened sender to login name mapping.
310  */
311 static MAPS *smtpd_sender_login_maps;
312 
313  /*
314  * Pre-opened access control lists.
315  */
316 static DOMAIN_LIST *relay_domains;
317 static NAMADR_LIST *mynetworks_curr;
318 static NAMADR_LIST *mynetworks_new;
319 static NAMADR_LIST *perm_mx_networks;
320 
321 #ifdef USE_TLS
322 static MAPS *relay_ccerts;
323 
324 #endif
325 
326  /*
327  * How to do parent domain wildcard matching, if any.
328  */
329 static int access_parent_style;
330 
331  /*
332  * Pre-parsed restriction lists.
333  */
334 static ARGV *client_restrctions;
335 static ARGV *helo_restrctions;
336 static ARGV *mail_restrctions;
337 static ARGV *relay_restrctions;
338 static ARGV *fake_relay_restrctions;
339 static ARGV *rcpt_restrctions;
340 static ARGV *etrn_restrctions;
341 static ARGV *data_restrctions;
342 static ARGV *eod_restrictions;
343 
344 static HTABLE *smtpd_rest_classes;
345 static HTABLE *policy_clnt_table;
346 static HTABLE *map_command_table;
347 
348 static ARGV *local_rewrite_clients;
349 
350  /*
351  * The routine that recursively applies restrictions.
352  */
353 static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, const char *);
354 
355  /*
356  * Recipient table check.
357  */
358 static int check_sender_rcpt_maps(SMTPD_STATE *, const char *);
359 static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *);
360 static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *,
361  const char *);
362 
363  /*
364  * Tempfail actions;
365  */
366 static int unk_name_tf_act;
367 static int unk_addr_tf_act;
368 static int unv_rcpt_tf_act;
369 static int unv_from_tf_act;
370 
371  /*
372  * Optional permit logging.
373  */
374 static STRING_LIST *smtpd_acl_perm_log;
375 
376  /*
377  * YASLM.
378  */
379 #define STR vstring_str
380 #define CONST_STR(x) ((const char *) vstring_str(x))
381 #define UPDATE_STRING(ptr,val) { if (ptr) myfree(ptr); ptr = mystrdup(val); }
382 
383  /*
384  * If some decision can't be made due to a temporary error, then change
385  * other decisions into deferrals.
386  *
387  * XXX Deferrals can be postponed only with restrictions that are based on
388  * client-specified information: this restricts their use to parameters
389  * given in HELO, MAIL FROM, RCPT TO commands.
390  *
391  * XXX Deferrals must not be postponed after client hostname lookup failure.
392  * The reason is that the effect of access tables may depend on whether a
393  * client hostname is available or not. Thus, the reject_unknown_client
394  * restriction must defer immediately when lookup fails, otherwise incorrect
395  * results happen with:
396  *
397  * reject_unknown_client, hostname-based white-list, reject
398  *
399  * XXX With warn_if_reject, don't raise the defer_if_permit flag when a
400  * reject-style restriction fails. Instead, log the warning for the
401  * resulting defer message.
402  *
403  * XXX With warn_if_reject, do raise the defer_if_reject flag when a
404  * permit-style restriction fails. Otherwise, we could reject legitimate
405  * mail.
406  */
407 static int PRINTFLIKE(5, 6) defer_if(SMTPD_DEFER *, int, int, const char *, const char *,...);
408 static int PRINTFLIKE(5, 6) smtpd_check_reject(SMTPD_STATE *, int, int, const char *, const char *,...);
409 
410 #define DEFER_IF_REJECT2(state, class, code, dsn, fmt, a1, a2) \
411  defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2))
412 #define DEFER_IF_REJECT3(state, class, code, dsn, fmt, a1, a2, a3) \
413  defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2), (a3))
414 #define DEFER_IF_REJECT4(state, class, code, dsn, fmt, a1, a2, a3, a4) \
415  defer_if(&(state)->defer_if_reject, (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4))
416 
417  /*
418  * The following choose between DEFER_IF_PERMIT (only if warn_if_reject is
419  * turned off) and plain DEFER. See tempfail_actions[] below for the mapping
420  * from names to numeric action code.
421  */
422 #define DEFER_ALL_ACT 0
423 #define DEFER_IF_PERMIT_ACT 1
424 
425 #define DEFER_IF_PERMIT2(type, state, class, code, dsn, fmt, a1, a2) \
426  (((state)->warn_if_reject == 0 && (type) != 0) ? \
427  defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2)) \
428  : \
429  smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2)))
430 #define DEFER_IF_PERMIT3(type, state, class, code, dsn, fmt, a1, a2, a3) \
431  (((state)->warn_if_reject == 0 && (type) != 0) ? \
432  defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2), (a3)) \
433  : \
434  smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2), (a3)))
435 #define DEFER_IF_PERMIT4(type, state, class, code, dsn, fmt, a1, a2, a3, a4) \
436  (((state)->warn_if_reject == 0 && (type) != 0) ? \
437  defer_if(&(state)->defer_if_permit, (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4)) \
438  : \
439  smtpd_check_reject((state), (class), (code), (dsn), (fmt), (a1), (a2), (a3), (a4)))
440 
441  /*
442  * Cached RBL lookup state.
443  */
444 typedef struct {
445  char *txt; /* TXT content or NULL */
446  DNS_RR *a; /* A records */
448 
449 static void *rbl_pagein(const char *, void *);
450 static void rbl_pageout(void *, void *);
451 static void *rbl_byte_pagein(const char *, void *);
452 static void rbl_byte_pageout(void *, void *);
453 
454  /*
455  * Context for RBL $name expansion.
456  */
457 typedef struct {
458  SMTPD_STATE *state; /* general state */
459  char *domain; /* query domain */
460  const char *what; /* rejected value */
461  const char *class; /* name of rejected value */
462  const char *txt; /* randomly selected trimmed TXT rr */
464 
465  /*
466  * Multiplication factor for free space check. Free space must be at least
467  * smtpd_space_multf * message_size_limit.
468  */
469 double smtpd_space_multf = 1.5;
470 
471  /*
472  * SMTPD policy client. Most attributes are ATTR_CLNT attributes.
473  */
474 typedef struct {
475  ATTR_CLNT *client; /* client handle */
476  char *def_action; /* default action */
477  char *policy_context; /* context of policy request */
479 
480  /*
481  * Table-driven parsing of main.cf parameter overrides for specific policy
482  * clients. We derive the override names from the corresponding main.cf
483  * parameter names by skipping the redundant "smtpd_policy_service_" prefix.
484  */
485 static ATTR_OVER_TIME time_table[] = {
490  0,
491 };
492 static ATTR_OVER_INT int_table[] = {
493  21 + VAR_SMTPD_POLICY_REQ_LIMIT, 0, 0, 0,
494  21 + VAR_SMTPD_POLICY_TRY_LIMIT, 0, 1, 0,
495  0,
496 };
497 static ATTR_OVER_STR str_table[] = {
498  21 + VAR_SMTPD_POLICY_DEF_ACTION, 0, 1, 0,
499  21 + VAR_SMTPD_POLICY_CONTEXT, 0, 1, 0,
500  0,
501 };
502 
503 #define link_override_table_to_variable(table, var) \
504  do { table[var##_offset].target = &var; } while (0)
505 
506 #define smtpd_policy_tmout_offset 0
507 #define smtpd_policy_idle_offset 1
508 #define smtpd_policy_ttl_offset 2
509 #define smtpd_policy_try_delay_offset 3
510 
511 #define smtpd_policy_req_limit_offset 0
512 #define smtpd_policy_try_limit_offset 1
513 
514 #define smtpd_policy_def_action_offset 0
515 #define smtpd_policy_context_offset 1
516 
517 /* policy_client_register - register policy service endpoint */
518 
519 static void policy_client_register(const char *name)
520 {
521  static const char myname[] = "policy_client_register";
522  SMTPD_POLICY_CLNT *policy_client;
523  char *saved_name = 0;
524  const char *policy_name = 0;
525  char *cp;
526  const char *sep = CHARS_COMMA_SP;
527  const char *parens = CHARS_BRACE;
528  char *err;
529 
530  if (policy_clnt_table == 0)
531  policy_clnt_table = htable_create(1);
532 
533  if (htable_find(policy_clnt_table, name) == 0) {
534 
535  /*
536  * Allow per-service overrides for main.cf global settings.
537  */
538  int smtpd_policy_tmout = var_smtpd_policy_tmout;
539  int smtpd_policy_idle = var_smtpd_policy_idle;
540  int smtpd_policy_ttl = var_smtpd_policy_ttl;
541  int smtpd_policy_try_delay = var_smtpd_policy_try_delay;
542  int smtpd_policy_req_limit = var_smtpd_policy_req_limit;
543  int smtpd_policy_try_limit = var_smtpd_policy_try_limit;
544  const char *smtpd_policy_def_action = var_smtpd_policy_def_action;
545  const char *smtpd_policy_context = var_smtpd_policy_context;
546 
547  link_override_table_to_variable(time_table, smtpd_policy_tmout);
548  link_override_table_to_variable(time_table, smtpd_policy_idle);
549  link_override_table_to_variable(time_table, smtpd_policy_ttl);
550  link_override_table_to_variable(time_table, smtpd_policy_try_delay);
551  link_override_table_to_variable(int_table, smtpd_policy_req_limit);
552  link_override_table_to_variable(int_table, smtpd_policy_try_limit);
553  link_override_table_to_variable(str_table, smtpd_policy_def_action);
554  link_override_table_to_variable(str_table, smtpd_policy_context);
555 
556  if (*name == parens[0]) {
557  cp = saved_name = mystrdup(name);
558  if ((err = extpar(&cp, parens, EXTPAR_FLAG_NONE)) != 0)
559  msg_fatal("policy service syntax error: %s", cp);
560  if ((policy_name = mystrtok(&cp, sep)) == 0)
561  msg_fatal("empty policy service: \"%s\"", name);
562  attr_override(cp, sep, parens,
563  CA_ATTR_OVER_TIME_TABLE(time_table),
564  CA_ATTR_OVER_INT_TABLE(int_table),
565  CA_ATTR_OVER_STR_TABLE(str_table),
567  } else {
568  policy_name = name;
569  }
570  if (msg_verbose)
571  msg_info("%s: name=\"%s\" default_action=\"%s\" max_idle=%d "
572  "max_ttl=%d request_limit=%d retry_delay=%d "
573  "timeout=%d try_limit=%d policy_context=\"%s\"",
574  myname, policy_name, smtpd_policy_def_action,
575  smtpd_policy_idle, smtpd_policy_ttl,
576  smtpd_policy_req_limit, smtpd_policy_try_delay,
577  smtpd_policy_tmout, smtpd_policy_try_limit,
578  smtpd_policy_context);
579 
580  /*
581  * Create the client.
582  */
583  policy_client = (SMTPD_POLICY_CLNT *) mymalloc(sizeof(*policy_client));
584  policy_client->client = attr_clnt_create(policy_name,
585  smtpd_policy_tmout,
586  smtpd_policy_idle,
587  smtpd_policy_ttl);
588 
589  attr_clnt_control(policy_client->client,
590  ATTR_CLNT_CTL_REQ_LIMIT, smtpd_policy_req_limit,
591  ATTR_CLNT_CTL_TRY_LIMIT, smtpd_policy_try_limit,
592  ATTR_CLNT_CTL_TRY_DELAY, smtpd_policy_try_delay,
594  policy_client->def_action = mystrdup(smtpd_policy_def_action);
595  policy_client->policy_context = mystrdup(smtpd_policy_context);
596  htable_enter(policy_clnt_table, name, (void *) policy_client);
597  if (saved_name)
598  myfree(saved_name);
599  }
600 }
601 
602 /* command_map_register - register access table for maps lookup */
603 
604 static void command_map_register(const char *name)
605 {
606  MAPS *maps;
607 
608  if (map_command_table == 0)
609  map_command_table = htable_create(1);
610 
611  if (htable_find(map_command_table, name) == 0) {
612  maps = maps_create(name, name, DICT_FLAG_LOCK
615  (void) htable_enter(map_command_table, name, (void *) maps);
616  }
617 }
618 
619 /* smtpd_check_parse - pre-parse restrictions */
620 
621 static ARGV *smtpd_check_parse(int flags, const char *checks)
622 {
623  char *saved_checks = mystrdup(checks);
624  ARGV *argv = argv_alloc(1);
625  char *bp = saved_checks;
626  char *name;
627  char *last = 0;
628 
629  /*
630  * Pre-parse the restriction list, and open any dictionaries that we
631  * encounter. Dictionaries must be opened before entering the chroot
632  * jail.
633  */
634 #define SMTPD_CHECK_PARSE_POLICY (1<<0)
635 #define SMTPD_CHECK_PARSE_MAPS (1<<1)
636 #define SMTPD_CHECK_PARSE_ALL (~0)
637 
638  while ((name = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
639  argv_add(argv, name, (char *) 0);
640  if ((flags & SMTPD_CHECK_PARSE_POLICY)
641  && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
642  policy_client_register(name);
643  else if ((flags & SMTPD_CHECK_PARSE_MAPS) && strchr(name, ':') != 0) {
644  command_map_register(name);
645  }
646  last = name;
647  }
648  argv_terminate(argv);
649 
650  /*
651  * Cleanup.
652  */
653  myfree(saved_checks);
654  return (argv);
655 }
656 
657 #ifndef TEST
658 
659 /* has_required - make sure required restriction is present */
660 
661 static int has_required(ARGV *restrictions, const char **required)
662 {
663  char **rest;
664  const char **reqd;
665  ARGV *expansion;
666 
667  /*
668  * Recursively check list membership.
669  */
670  for (rest = restrictions->argv; *rest; rest++) {
671  if (strcasecmp(*rest, WARN_IF_REJECT) == 0 && rest[1] != 0) {
672  rest += 1;
673  continue;
674  }
675  if (strcasecmp(*rest, PERMIT_ALL) == 0) {
676  if (rest[1] != 0)
677  msg_warn("restriction `%s' after `%s' is ignored",
678  rest[1], rest[0]);
679  return (0);
680  }
681  for (reqd = required; *reqd; reqd++)
682  if (strcasecmp(*rest, *reqd) == 0)
683  return (1);
684  /* XXX This lookup operation should not be case-sensitive. */
685  if ((expansion = (ARGV *) htable_find(smtpd_rest_classes, *rest)) != 0)
686  if (has_required(expansion, required))
687  return (1);
688  }
689  return (0);
690 }
691 
692 /* fail_required - handle failure to use required restriction */
693 
694 static void fail_required(const char *name, const char **required)
695 {
696  const char *myname = "fail_required";
697  const char **reqd;
698  VSTRING *example;
699 
700  /*
701  * Sanity check.
702  */
703  if (required[0] == 0)
704  msg_panic("%s: null required list", myname);
705 
706  /*
707  * Go bust.
708  */
709  example = vstring_alloc(10);
710  for (reqd = required; *reqd; reqd++)
711  vstring_sprintf_append(example, "%s%s", *reqd,
712  reqd[1] == 0 ? "" : reqd[2] == 0 ? " or " : ", ");
713  msg_fatal("in parameter %s, specify at least one working instance of: %s",
714  name, STR(example));
715 }
716 
717 #endif
718 
719 /* smtpd_check_init - initialize once during process lifetime */
720 
722 {
723  char *saved_classes;
724  const char *name;
725  const char *value;
726  char *cp;
727 
728 #ifndef TEST
729  static const char *rcpt_required[] = {
732  REJECT_ALL,
733  DEFER_ALL,
736  0,
737  };
738 
739 #endif
740  static NAME_CODE tempfail_actions[] = {
743  0, -1,
744  };
745 
746  /*
747  * Pre-open access control lists before going to jail.
748  */
749  mynetworks_curr =
752  mynetworks_new =
755  relay_domains =
759  perm_mx_networks =
763 #ifdef USE_TLS
766 #endif
767 
768  /*
769  * Pre-parse and pre-open the recipient maps.
770  */
786  virt_mailbox_maps = maps_create(VAR_VIRT_MAILBOX_MAPS,
793 
794 #ifdef TEST
799 #endif
800 
801  access_parent_style = match_parent_style(SMTPD_ACCESS_MAPS);
802 
803  /*
804  * Templates for RBL rejection replies.
805  */
809 
810  /*
811  * Sender to login name mapping.
812  */
813  smtpd_sender_login_maps = maps_create(VAR_SMTPD_SND_AUTH_MAPS,
817 
818  /*
819  * error_text is used for returning error responses.
820  */
821  error_text = vstring_alloc(10);
822 
823  /*
824  * Initialize the resolved address cache. Note: the cache persists across
825  * SMTP sessions so we cannot make it dependent on session state.
826  */
827  smtpd_resolve_init(100);
828 
829  /*
830  * Initialize the RBL lookup cache. Note: the cache persists across SMTP
831  * sessions so we cannot make it dependent on session state.
832  */
833  smtpd_rbl_cache = ctable_create(100, rbl_pagein, rbl_pageout, (void *) 0);
834  smtpd_rbl_byte_cache = ctable_create(1000, rbl_byte_pagein,
835  rbl_byte_pageout, (void *) 0);
836 
837  /*
838  * Pre-parse the restriction lists. At the same time, pre-open tables
839  * before going to jail.
840  */
841  client_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
843  helo_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
845  mail_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
847  relay_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
850  fake_relay_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
852  rcpt_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
854  etrn_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
856  data_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
858  eod_restrictions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
860 
861  /*
862  * Parse the pre-defined restriction classes.
863  */
864  smtpd_rest_classes = htable_create(1);
865  if (*var_rest_classes) {
866  cp = saved_classes = mystrdup(var_rest_classes);
867  while ((name = mystrtok(&cp, CHARS_COMMA_SP)) != 0) {
868  if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
869  msg_fatal("restriction class `%s' needs a definition", name);
870  /* XXX This store operation should not be case-sensitive. */
871  htable_enter(smtpd_rest_classes, name,
872  (void *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
873  value));
874  }
875  myfree(saved_classes);
876  }
877 
878  /*
879  * This is the place to specify definitions for complex restrictions such
880  * as check_relay_domains in terms of more elementary restrictions.
881  */
882 #if 0
883  htable_enter(smtpd_rest_classes, "check_relay_domains",
884  smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
885  "permit_mydomain reject_unauth_destination"));
886 #endif
887  htable_enter(smtpd_rest_classes, REJECT_SENDER_LOGIN_MISMATCH,
888  (void *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
891 
892  /*
893  * People screw up the relay restrictions too often. Require that they
894  * list at least one restriction that rejects mail by default. We allow
895  * relay restrictions to be empty for sites that require backwards
896  * compatibility.
897  */
898 #ifndef TEST
899  if (!has_required(rcpt_restrctions, rcpt_required)
900  && !has_required(relay_restrctions, rcpt_required))
901  fail_required(VAR_RELAY_CHECKS " or " VAR_RCPT_CHECKS, rcpt_required);
902 #endif
903 
904  /*
905  * Local rewrite policy.
906  */
907  local_rewrite_clients = smtpd_check_parse(SMTPD_CHECK_PARSE_MAPS,
909 
910  /*
911  * Tempfail_actions.
912  *
913  * XXX This name-to-number mapping should be encapsulated in a separate
914  * mail_conf_name_code.c module.
915  */
916  if ((unk_name_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE,
917  var_unk_name_tf_act)) < 0)
918  msg_fatal("bad configuration: %s = %s",
920  if ((unk_addr_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE,
921  var_unk_addr_tf_act)) < 0)
922  msg_fatal("bad configuration: %s = %s",
924  if ((unv_rcpt_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE,
925  var_unv_rcpt_tf_act)) < 0)
926  msg_fatal("bad configuration: %s = %s",
928  if ((unv_from_tf_act = name_code(tempfail_actions, NAME_CODE_FLAG_NONE,
929  var_unv_from_tf_act)) < 0)
930  msg_fatal("bad configuration: %s = %s",
932  if (msg_verbose) {
933  msg_info("%s = %s", VAR_UNK_NAME_TF_ACT, tempfail_actions[unk_name_tf_act].name);
934  msg_info("%s = %s", VAR_UNK_ADDR_TF_ACT, tempfail_actions[unk_addr_tf_act].name);
935  msg_info("%s = %s", VAR_UNV_RCPT_TF_ACT, tempfail_actions[unv_rcpt_tf_act].name);
936  msg_info("%s = %s", VAR_UNV_FROM_TF_ACT, tempfail_actions[unv_from_tf_act].name);
937  }
938 
939  /*
940  * Optional permit logging.
941  */
942  smtpd_acl_perm_log = string_list_init(VAR_SMTPD_ACL_PERM_LOG,
945 }
946 
947 /* log_whatsup - log as much context as we have */
948 
949 static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
950  const char *text)
951 {
952  VSTRING *buf = vstring_alloc(100);
953 
954  vstring_sprintf(buf, "%s: %s: %s from %s: %s;",
955  state->queue_id ? state->queue_id : "NOQUEUE",
956  whatsup, state->where, state->namaddr, text);
957  if (state->sender)
958  vstring_sprintf_append(buf, " from=<%s>", state->sender);
959  if (state->recipient)
960  vstring_sprintf_append(buf, " to=<%s>", state->recipient);
961  if (state->protocol)
962  vstring_sprintf_append(buf, " proto=%s", state->protocol);
963  if (state->helo_name)
964  vstring_sprintf_append(buf, " helo=<%s>", state->helo_name);
965  msg_info("%s", STR(buf));
966  vstring_free(buf);
967 }
968 
969 /* smtpd_acl_permit - permit request with optional logging */
970 
971 static int PRINTFLIKE(5, 6) smtpd_acl_permit(SMTPD_STATE *state,
972  const char *action,
973  const char *reply_class,
974  const char *reply_name,
975  const char *format,...)
976 {
977  const char myname[] = "smtpd_acl_permit";
978  va_list ap;
979  const char *whatsup;
980 
981 #ifdef notdef
982 #define NO_PRINT_ARGS ""
983 #else
984 #define NO_PRINT_ARGS "%s", ""
985 #endif
986 
987  /*
988  * First, find out if (and how) this permit action should be logged.
989  */
990  if (msg_verbose)
991  msg_info("%s: checking %s settings", myname, VAR_SMTPD_ACL_PERM_LOG);
992 
993  if (state->defer_if_permit.active) {
994  /* This action is overruled. Do not log. */
995  whatsup = 0;
996  } else if (string_list_match(smtpd_acl_perm_log, action) != 0) {
997  /* This is not a test. Logging is enabled. */
998  whatsup = "permit";
999  } else {
1000  /* This is not a test. Logging is disabled. */
1001  whatsup = 0;
1002  }
1003  if (whatsup != 0) {
1004  vstring_sprintf(error_text, "action=%s for %s=%s",
1005  action, reply_class, reply_name);
1006  if (format && *format) {
1007  vstring_strcat(error_text, " ");
1008  va_start(ap, format);
1009  vstring_vsprintf_append(error_text, format, ap);
1010  va_end(ap);
1011  }
1012  log_whatsup(state, whatsup, STR(error_text));
1013  } else {
1014  if (msg_verbose)
1015  msg_info("%s: %s: no match", myname, VAR_SMTPD_ACL_PERM_LOG);
1016  }
1017  return (SMTPD_CHECK_OK);
1018 }
1019 
1020 /* smtpd_check_reject - do the boring things that must be done */
1021 
1022 static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
1023  int code, const char *dsn,
1024  const char *format,...)
1025 {
1026  va_list ap;
1027  int warn_if_reject;
1028  const char *whatsup;
1029 
1030  /*
1031  * Do not reject mail if we were asked to warn only. However,
1032  * configuration/software/data errors cannot be converted into warnings.
1033  */
1034  if (state->warn_if_reject && error_class != MAIL_ERROR_SOFTWARE
1035  && error_class != MAIL_ERROR_RESOURCE
1036  && error_class != MAIL_ERROR_DATA) {
1037  warn_if_reject = 1;
1038  whatsup = "reject_warning";
1039  } else {
1040  warn_if_reject = 0;
1041  whatsup = "reject";
1042  }
1043 
1044  /*
1045  * Update the error class mask, and format the response. XXX What about
1046  * multi-line responses? For now we cheat and send whitespace.
1047  *
1048  * Format the response before complaining about configuration errors, so
1049  * that we can show the error in context.
1050  */
1051  state->error_mask |= error_class;
1052  vstring_sprintf(error_text, "%d %s ", code, dsn);
1053  va_start(ap, format);
1054  vstring_vsprintf_append(error_text, format, ap);
1055  va_end(ap);
1056 
1057  /*
1058  * Validate the response, that is, the response must begin with a
1059  * three-digit status code, and the first digit must be 4 or 5. If the
1060  * response is bad, log a warning and send a generic response instead.
1061  */
1062  if (code < 400 || code > 599) {
1063  msg_warn("SMTP reply code configuration error: %s", STR(error_text));
1064  vstring_strcpy(error_text, "450 4.7.1 Service unavailable");
1065  }
1066  if (!dsn_valid(STR(error_text) + 4)) {
1067  msg_warn("DSN detail code configuration error: %s", STR(error_text));
1068  vstring_strcpy(error_text, "450 4.7.1 Service unavailable");
1069  }
1070 
1071  /*
1072  * Ensure RFC compliance. We could do this inside smtpd_chat_reply() and
1073  * switch to multi-line for long replies.
1074  */
1075  vstring_truncate(error_text, 510);
1076  printable(STR(error_text), ' ');
1077 
1078  /*
1079  * Force this rejection into deferral because of some earlier temporary
1080  * error that may have prevented us from accepting mail, and report the
1081  * earlier problem instead.
1082  */
1083  if (!warn_if_reject && state->defer_if_reject.active && STR(error_text)[0] == '5') {
1084  state->warn_if_reject = state->defer_if_reject.active = 0;
1085  return (smtpd_check_reject(state, state->defer_if_reject.class,
1086  state->defer_if_reject.code,
1087  STR(state->defer_if_reject.dsn),
1088  "%s", STR(state->defer_if_reject.reason)));
1089  }
1090 
1091  /*
1092  * Soft bounce safety net.
1093  *
1094  * XXX The code below also appears in the Postfix SMTP server reply output
1095  * routine. It is duplicated here in order to avoid discrepancies between
1096  * the reply codes that are shown in "reject" logging and the reply codes
1097  * that are actually sent to the SMTP client.
1098  *
1099  * Implementing the soft_bounce safety net in the SMTP server reply output
1100  * routine has the advantage that it covers all 5xx replies, including
1101  * SMTP protocol or syntax errors, which makes soft_bounce great for
1102  * non-destructive tests (especially by people who are paranoid about
1103  * losing mail).
1104  *
1105  * We could eliminate the code duplication and implement the soft_bounce
1106  * safety net only in the code below. But then the safety net would cover
1107  * the UCE restrictions only. This would be at odds with documentation
1108  * which says soft_bounce changes all 5xx replies into 4xx ones.
1109  */
1110  if (var_soft_bounce && STR(error_text)[0] == '5')
1111  STR(error_text)[0] = '4';
1112 
1113  /*
1114  * In any case, enforce consistency between the SMTP code and DSN code.
1115  * SMTP has the higher precedence since it came here first.
1116  */
1117  STR(error_text)[4] = STR(error_text)[0];
1118 
1119  /*
1120  * Log what is happening. When the sysadmin discards policy violation
1121  * postmaster notices, this may be the only trace left that service was
1122  * rejected. Print the request, client name/address, and response.
1123  */
1124  log_whatsup(state, whatsup, STR(error_text));
1125 
1126  return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT);
1127 }
1128 
1129 /* defer_if - prepare to change our mind */
1130 
1131 static int defer_if(SMTPD_DEFER *defer, int error_class,
1132  int code, const char *dsn,
1133  const char *fmt,...)
1134 {
1135  va_list ap;
1136 
1137  /*
1138  * Keep the first reason for this type of deferral, to minimize
1139  * confusion.
1140  */
1141  if (defer->active == 0) {
1142  defer->active = 1;
1143  defer->class = error_class;
1144  defer->code = code;
1145  if (defer->dsn == 0)
1146  defer->dsn = vstring_alloc(10);
1147  vstring_strcpy(defer->dsn, dsn);
1148  if (defer->reason == 0)
1149  defer->reason = vstring_alloc(10);
1150  va_start(ap, fmt);
1151  vstring_vsprintf(defer->reason, fmt, ap);
1152  va_end(ap);
1153  }
1154  return (SMTPD_CHECK_DUNNO);
1155 }
1156 
1157 /* reject_dict_retry - reject with temporary failure if dict lookup fails */
1158 
1159 static NORETURN reject_dict_retry(SMTPD_STATE *state, const char *reply_name)
1160 {
1161  longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_DATA,
1162  451, "4.3.0",
1163  "<%s>: Temporary lookup failure",
1164  reply_name));
1165 }
1166 
1167 /* reject_server_error - reject with temporary failure after non-dict error */
1168 
1169 static NORETURN reject_server_error(SMTPD_STATE *state)
1170 {
1171  longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE,
1172  451, "4.3.5",
1173  "Server configuration error"));
1174 }
1175 
1176 /* check_mail_addr_find - reject with temporary failure if dict lookup fails */
1177 
1178 static const char *check_mail_addr_find(SMTPD_STATE *state,
1179  const char *reply_name,
1180  MAPS *maps, const char *key,
1181  char **ext)
1182 {
1183  const char *result;
1184 
1185  if ((result = mail_addr_find(maps, key, ext)) != 0 || maps->error == 0)
1186  return (result);
1187  if (maps->error == DICT_ERR_RETRY)
1188  /* Warning is already logged. */
1189  reject_dict_retry(state, reply_name);
1190  else
1191  reject_server_error(state);
1192 }
1193 
1194 /* reject_unknown_reverse_name - fail if reverse client hostname is unknown */
1195 
1196 static int reject_unknown_reverse_name(SMTPD_STATE *state)
1197 {
1198  const char *myname = "reject_unknown_reverse_name";
1199 
1200  if (msg_verbose)
1201  msg_info("%s: %s", myname, state->reverse_name);
1202 
1204  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1206  var_unk_client_code : 450, "4.7.1",
1207  "Client host rejected: cannot find your reverse hostname, [%s]",
1208  state->addr));
1209  return (SMTPD_CHECK_DUNNO);
1210 }
1211 
1212 /* reject_unknown_client - fail if client hostname is unknown */
1213 
1214 static int reject_unknown_client(SMTPD_STATE *state)
1215 {
1216  const char *myname = "reject_unknown_client";
1217 
1218  if (msg_verbose)
1219  msg_info("%s: %s %s", myname, state->name, state->addr);
1220 
1221  /* RFC 7372: Email Authentication Status Codes. */
1222  if (state->name_status != SMTPD_PEER_CODE_OK)
1223  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1224  state->name_status >= SMTPD_PEER_CODE_PERM ?
1225  var_unk_client_code : 450, "4.7.25",
1226  "Client host rejected: cannot find your hostname, [%s]",
1227  state->addr));
1228  return (SMTPD_CHECK_DUNNO);
1229 }
1230 
1231 /* reject_plaintext_session - fail if session is not encrypted */
1232 
1233 static int reject_plaintext_session(SMTPD_STATE *state)
1234 {
1235  const char *myname = "reject_plaintext_session";
1236 
1237  if (msg_verbose)
1238  msg_info("%s: %s %s", myname, state->name, state->addr);
1239 
1240 #ifdef USE_TLS
1241  if (state->tls_context == 0)
1242 #endif
1243  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1244  var_plaintext_code, "4.7.1",
1245  "Session encryption is required"));
1246  return (SMTPD_CHECK_DUNNO);
1247 }
1248 
1249 /* permit_inet_interfaces - succeed if client my own address */
1250 
1251 static int permit_inet_interfaces(SMTPD_STATE *state)
1252 {
1253  const char *myname = "permit_inet_interfaces";
1254 
1255  if (msg_verbose)
1256  msg_info("%s: %s %s", myname, state->name, state->addr);
1257 
1258  if (own_inet_addr((struct sockaddr *) &(state->sockaddr)))
1259  /* Permit logging in generic_checks() only. */
1260  return (SMTPD_CHECK_OK);
1261  return (SMTPD_CHECK_DUNNO);
1262 }
1263 
1264 /* permit_mynetworks - succeed if client is in a trusted network */
1265 
1266 static int permit_mynetworks(SMTPD_STATE *state)
1267 {
1268  const char *myname = "permit_mynetworks";
1269 
1270  if (msg_verbose)
1271  msg_info("%s: %s %s", myname, state->name, state->addr);
1272 
1273  if (namadr_list_match(mynetworks_curr, state->name, state->addr)) {
1275  && !namadr_list_match(mynetworks_new, state->name, state->addr))
1276  msg_info("using backwards-compatible default setting "
1277  VAR_MYNETWORKS_STYLE "=%s to permit request from "
1278  "client \"%s\"", var_mynetworks_style, state->namaddr);
1279  /* Permit logging in generic_checks() only. */
1280  return (SMTPD_CHECK_OK);
1281  } else if (mynetworks_curr->error == 0)
1282  return (SMTPD_CHECK_DUNNO);
1283  else
1284  return (mynetworks_curr->error);
1285 }
1286 
1287 /* dup_if_truncate - save hostname and truncate if it ends in dot */
1288 
1289 static char *dup_if_truncate(char *name)
1290 {
1291  ssize_t len;
1292  char *result;
1293 
1294  /*
1295  * Truncate hostnames ending in dot but not dot-dot.
1296  *
1297  * XXX This should not be distributed all over the code. Problem is,
1298  * addresses can enter the system via multiple paths: networks, local
1299  * forward/alias/include files, even as the result of address rewriting.
1300  */
1301  if ((len = strlen(name)) > 1
1302  && name[len - 1] == '.'
1303  && name[len - 2] != '.') {
1304  result = mystrndup(name, len - 1);
1305  } else
1306  result = name;
1307  return (result);
1308 }
1309 
1310 /* reject_invalid_hostaddr - fail if host address is incorrect */
1311 
1312 static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr,
1313  char *reply_name, char *reply_class)
1314 {
1315  const char *myname = "reject_invalid_hostaddr";
1316  ssize_t len;
1317  char *test_addr;
1318  int stat;
1319 
1320  if (msg_verbose)
1321  msg_info("%s: %s", myname, addr);
1322 
1323  if (addr[0] == '[' && (len = strlen(addr)) > 2 && addr[len - 1] == ']') {
1324  test_addr = mystrndup(addr + 1, len - 2);
1325  } else
1326  test_addr = addr;
1327 
1328  /*
1329  * Validate the address.
1330  */
1331  if (!valid_mailhost_addr(test_addr, DONT_GRIPE))
1332  stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
1333  var_bad_name_code, "5.5.2",
1334  "<%s>: %s rejected: invalid ip address",
1335  reply_name, reply_class);
1336  else
1337  stat = SMTPD_CHECK_DUNNO;
1338 
1339  /*
1340  * Cleanup.
1341  */
1342  if (test_addr != addr)
1343  myfree(test_addr);
1344 
1345  return (stat);
1346 }
1347 
1348 /* reject_invalid_hostname - fail if host/domain syntax is incorrect */
1349 
1350 static int reject_invalid_hostname(SMTPD_STATE *state, char *name,
1351  char *reply_name, char *reply_class)
1352 {
1353  const char *myname = "reject_invalid_hostname";
1354  char *test_name;
1355  int stat;
1356 
1357  if (msg_verbose)
1358  msg_info("%s: %s", myname, name);
1359 
1360  /*
1361  * Truncate hostnames ending in dot but not dot-dot.
1362  */
1363  test_name = dup_if_truncate(name);
1364 
1365  /*
1366  * Validate the HELO/EHLO hostname. Fix 20140706: EAI not allowed here.
1367  */
1368  if (!valid_hostname(test_name, DONT_GRIPE)
1369  && !valid_hostaddr(test_name, DONT_GRIPE)) /* XXX back compat */
1370  stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
1371  var_bad_name_code, "5.5.2",
1372  "<%s>: %s rejected: Invalid name",
1373  reply_name, reply_class);
1374  else
1375  stat = SMTPD_CHECK_DUNNO;
1376 
1377  /*
1378  * Cleanup.
1379  */
1380  if (test_name != name)
1381  myfree(test_name);
1382 
1383  return (stat);
1384 }
1385 
1386 /* reject_non_fqdn_hostname - fail if host name is not in fqdn form */
1387 
1388 static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name,
1389  char *reply_name, char *reply_class)
1390 {
1391  const char *myname = "reject_non_fqdn_hostname";
1392  char *test_name;
1393  int stat;
1394 
1395  if (msg_verbose)
1396  msg_info("%s: %s", myname, name);
1397 
1398  /*
1399  * Truncate hostnames ending in dot but not dot-dot.
1400  */
1401  test_name = dup_if_truncate(name);
1402 
1403  /*
1404  * Validate the hostname. For backwards compatibility, permit non-ASCII
1405  * names only when the client requested SMTPUTF8 support.
1406  */
1408  test_name, DONT_GRIPE) == 0 || strchr(test_name, '.') == 0)
1409  stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
1410  var_non_fqdn_code, "5.5.2",
1411  "<%s>: %s rejected: need fully-qualified hostname",
1412  reply_name, reply_class);
1413  else
1414  stat = SMTPD_CHECK_DUNNO;
1415 
1416  /*
1417  * Cleanup.
1418  */
1419  if (test_name != name)
1420  myfree(test_name);
1421 
1422  return (stat);
1423 }
1424 
1425 /* reject_unknown_hostname - fail if name has no A, AAAA or MX record */
1426 
1427 static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
1428  char *reply_name, char *reply_class)
1429 {
1430  const char *myname = "reject_unknown_hostname";
1431  int dns_status;
1432  DNS_RR *dummy;
1433 
1434  if (msg_verbose)
1435  msg_info("%s: %s", myname, name);
1436 
1437 #ifdef T_AAAA
1438 #define RR_ADDR_TYPES T_A, T_AAAA
1439 #else
1440 #define RR_ADDR_TYPES T_A
1441 #endif
1442 
1443  dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0,
1445  RR_ADDR_TYPES, T_MX, 0);
1446  if (dummy)
1447  dns_rr_free(dummy);
1448  /* Allow MTA names to have nullMX records. */
1449  if (dns_status != DNS_OK && dns_status != DNS_NULLMX) {
1450  if (dns_status == DNS_POLICY) {
1451  msg_warn("%s: address or MX lookup error: %s",
1452  name, "DNS reply filter drops all results");
1453  return (SMTPD_CHECK_DUNNO);
1454  }
1455  if (dns_status != DNS_RETRY)
1456  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1457  var_unk_name_code, "4.7.1",
1458  "<%s>: %s rejected: %s",
1459  reply_name, reply_class,
1460  dns_status == DNS_INVAL ?
1461  "Malformed DNS server reply" :
1462  "Host not found"));
1463  else
1464  return (DEFER_IF_PERMIT2(unk_name_tf_act, state, MAIL_ERROR_POLICY,
1465  450, "4.7.1",
1466  "<%s>: %s rejected: Host not found",
1467  reply_name, reply_class));
1468  }
1469  return (SMTPD_CHECK_DUNNO);
1470 }
1471 
1472 /* reject_unknown_mailhost - fail if name has no A, AAAA or MX record */
1473 
1474 static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
1475  const char *reply_name, const char *reply_class)
1476 {
1477  const char *myname = "reject_unknown_mailhost";
1478  int dns_status;
1479  DNS_RR *dummy;
1480  const char *aname;
1481 
1482  if (msg_verbose)
1483  msg_info("%s: %s", myname, name);
1484 
1485  /*
1486  * Fix 20140924: convert domain to ASCII.
1487  */
1488 #ifndef NO_EAI
1489  if (!allascii(name) && (aname = midna_domain_to_ascii(name)) != 0) {
1490  if (msg_verbose)
1491  msg_info("%s asciified to %s", name, aname);
1492  name = aname;
1493  }
1494 #endif
1495 
1496 #define MAILHOST_LOOKUP_FLAGS \
1497  (DNS_REQ_FLAG_STOP_OK | DNS_REQ_FLAG_STOP_INVAL | \
1498  DNS_REQ_FLAG_STOP_NULLMX | DNS_REQ_FLAG_STOP_MX_POLICY)
1499 
1500  dns_status = dns_lookup_l(name, 0, &dummy, (VSTRING *) 0,
1502  T_MX, RR_ADDR_TYPES, 0);
1503  if (dummy)
1504  dns_rr_free(dummy);
1505  if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
1506  if (dns_status == DNS_POLICY) {
1507  msg_warn("%s: MX or address lookup error: %s",
1508  name, "DNS reply filter drops all results");
1509  return (SMTPD_CHECK_DUNNO);
1510  }
1511  if (dns_status == DNS_NULLMX)
1512  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1513  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
1514  550 : 556,
1515  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
1516  "4.7.27" : "4.1.10",
1517  "<%s>: %s rejected: Domain %s "
1518  "does not accept mail (nullMX)",
1519  reply_name, reply_class, name));
1520  if (dns_status != DNS_RETRY)
1521  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1523  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
1524  "4.1.8" : "4.1.2",
1525  "<%s>: %s rejected: %s",
1526  reply_name, reply_class,
1527  dns_status == DNS_INVAL ?
1528  "Malformed DNS server reply" :
1529  "Domain not found"));
1530  else
1531  return (DEFER_IF_PERMIT2(unk_addr_tf_act, state, MAIL_ERROR_POLICY,
1532  450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
1533  "4.1.8" : "4.1.2",
1534  "<%s>: %s rejected: Domain not found",
1535  reply_name, reply_class));
1536  }
1537  return (SMTPD_CHECK_DUNNO);
1538 }
1539 
1540 static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
1541 
1542 /* permit_tls_clientcerts - OK/DUNNO for message relaying, or set dict_errno */
1543 
1544 static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
1545 {
1546 #ifdef USE_TLS
1547  const char *found = 0;
1548 
1549  if (!state->tls_context)
1550  return SMTPD_CHECK_DUNNO;
1551 
1552  if (TLS_CERT_IS_TRUSTED(state->tls_context) && permit_all_certs) {
1553  if (msg_verbose)
1554  msg_info("Relaying allowed for all verified client certificates");
1555  /* Permit logging in generic_checks() only. */
1556  return (SMTPD_CHECK_OK);
1557  }
1558 
1559  /*
1560  * When directly checking the fingerprint, it is OK if the issuing CA is
1561  * not trusted.
1562  */
1563  if (TLS_CERT_IS_PRESENT(state->tls_context)) {
1564  int i;
1565  char *prints[2];
1566 
1567  prints[0] = state->tls_context->peer_cert_fprint;
1568  prints[1] = state->tls_context->peer_pkey_fprint;
1569 
1570  /* After lookup error, leave relay_ccerts->error at non-zero value. */
1571  for (i = 0; i < 2; ++i) {
1572  found = maps_find(relay_ccerts, prints[i], DICT_FLAG_NONE);
1573  if (found != 0) {
1574  if (msg_verbose)
1575  msg_info("Relaying allowed for certified client: %s", found);
1576  /* Permit logging in generic_checks() only. */
1577  return (SMTPD_CHECK_OK);
1578  } else if (relay_ccerts->error != 0) {
1579  msg_warn("relay_clientcerts: lookup error for fingerprint '%s', "
1580  "pkey fingerprint %s", prints[0], prints[1]);
1581  return (relay_ccerts->error);
1582  }
1583  }
1584  if (msg_verbose)
1585  msg_info("relay_clientcerts: No match for fingerprint '%s', "
1586  "pkey fingerprint %s", prints[0], prints[1]);
1587  }
1588 #endif
1589  return (SMTPD_CHECK_DUNNO);
1590 }
1591 
1592 /* check_relay_domains - OK/FAIL for message relaying */
1593 
1594 static int check_relay_domains(SMTPD_STATE *state, char *recipient,
1595  char *reply_name, char *reply_class)
1596 {
1597  const char *myname = "check_relay_domains";
1598 
1599 #if 1
1600  static int once;
1601 
1602  if (once == 0) {
1603  once = 1;
1604  msg_warn("support for restriction \"%s\" will be removed from %s; "
1605  "use \"%s\" instead",
1607  }
1608 #endif
1609 
1610  if (msg_verbose)
1611  msg_info("%s: %s", myname, recipient);
1612 
1613  /*
1614  * Permit if the client matches the relay_domains list.
1615  */
1616  if (domain_list_match(relay_domains, state->name)) {
1618  msg_info("using backwards-compatible default setting "
1619  VAR_RELAY_DOMAINS "=$mydestination to permit "
1620  "request from client \"%s\"", state->name);
1621  return (SMTPD_CHECK_OK);
1622  }
1623 
1624  /*
1625  * Permit authorized destinations.
1626  */
1627  if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK)
1628  return (SMTPD_CHECK_OK);
1629 
1630  /*
1631  * Deny relaying between sites that both are not in relay_domains.
1632  */
1633  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1634  var_relay_code, "5.7.1",
1635  "<%s>: %s rejected: Relay access denied",
1636  reply_name, reply_class));
1637 }
1638 
1639 /* permit_auth_destination - OK for message relaying */
1640 
1641 static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
1642 {
1643  const char *myname = "permit_auth_destination";
1644  const RESOLVE_REPLY *reply;
1645  const char *domain;
1646 
1647  if (msg_verbose)
1648  msg_info("%s: %s", myname, recipient);
1649 
1650  /*
1651  * Resolve the address.
1652  */
1653  reply = smtpd_resolve_addr(state->sender, recipient);
1654  if (reply->flags & RESOLVE_FLAG_FAIL)
1655  reject_dict_retry(state, recipient);
1656 
1657  /*
1658  * Handle special case that is not supposed to happen.
1659  */
1660  if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
1661  return (SMTPD_CHECK_OK);
1662  domain += 1;
1663 
1664  /*
1665  * Skip source-routed non-local or virtual mail (uncertain destination).
1666  */
1667  if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
1668  return (SMTPD_CHECK_DUNNO);
1669 
1670  /*
1671  * Permit final delivery: the destination matches mydestination,
1672  * virtual_alias_domains, or virtual_mailbox_domains.
1673  */
1674  if (reply->flags & RESOLVE_CLASS_FINAL)
1675  return (SMTPD_CHECK_OK);
1676 
1677  /*
1678  * Permit if the destination matches the relay_domains list.
1679  */
1680  if (reply->flags & RESOLVE_CLASS_RELAY) {
1682  msg_info("using backwards-compatible default setting "
1683  VAR_RELAY_DOMAINS "=$mydestination to accept mail "
1684  "for domain \"%s\"", domain);
1685  return (SMTPD_CHECK_OK);
1686  }
1687 
1688  /*
1689  * Skip when not matched
1690  */
1691  return (SMTPD_CHECK_DUNNO);
1692 }
1693 
1694 /* reject_unauth_destination - FAIL for message relaying */
1695 
1696 static int reject_unauth_destination(SMTPD_STATE *state, char *recipient,
1697  int reply_code, const char *reply_dsn)
1698 {
1699  const char *myname = "reject_unauth_destination";
1700 
1701  if (msg_verbose)
1702  msg_info("%s: %s", myname, recipient);
1703 
1704  /*
1705  * Skip authorized destination.
1706  */
1707  if (permit_auth_destination(state, recipient) == SMTPD_CHECK_OK)
1708  return (SMTPD_CHECK_DUNNO);
1709 
1710  /*
1711  * Reject relaying to sites that are not listed in relay_domains.
1712  */
1713  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1714  reply_code, reply_dsn,
1715  "<%s>: Relay access denied",
1716  recipient));
1717 }
1718 
1719 /* reject_unauth_pipelining - reject improper use of SMTP command pipelining */
1720 
1721 static int reject_unauth_pipelining(SMTPD_STATE *state,
1722  const char *reply_name, const char *reply_class)
1723 {
1724  const char *myname = "reject_unauth_pipelining";
1725 
1726  if (msg_verbose)
1727  msg_info("%s: %s", myname, state->where);
1728 
1729  if (state->flags & SMTPD_FLAG_ILL_PIPELINING)
1730  return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
1731  503, "5.5.0",
1732  "<%s>: %s rejected: Improper use of SMTP command pipelining",
1733  reply_name, reply_class));
1734 
1735  return (SMTPD_CHECK_DUNNO);
1736 }
1737 
1738 /* all_auth_mx_addr - match host addresses against permit_mx_backup_networks */
1739 
1740 static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
1741  const char *reply_name, const char *reply_class)
1742 {
1743  const char *myname = "all_auth_mx_addr";
1744  MAI_HOSTADDR_STR hostaddr;
1745  DNS_RR *rr;
1746  DNS_RR *addr_list;
1747  int dns_status;
1748 
1749  if (msg_verbose)
1750  msg_info("%s: host %s", myname, host);
1751 
1752  /*
1753  * If we can't lookup the host, defer.
1754  */
1755 #define NOPE 0
1756 #define YUP 1
1757 
1758  /*
1759  * Verify that all host addresses are within permit_mx_backup_networks.
1760  */
1761  dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
1762  DNS_REQ_FLAG_NONE, inet_proto_info()->dns_atype_list);
1763  /* DNS_NULLMX is not applicable here. */
1764  if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
1766  450, "4.4.4",
1767  "<%s>: %s rejected: Unable to look up host "
1768  "%s as mail exchanger: %s",
1769  reply_name, reply_class, host,
1770  dns_status == DNS_POLICY ?
1771  "DNS reply filter policy" : dns_strerror(h_errno));
1772  return (NOPE);
1773  }
1774  for (rr = addr_list; rr != 0; rr = rr->next) {
1775  if (dns_rr_to_pa(rr, &hostaddr) == 0) {
1776  msg_warn("%s: skipping record type %s for host %s: %m",
1777  myname, dns_strtype(rr->type), host);
1778  continue;
1779  }
1780  if (msg_verbose)
1781  msg_info("%s: checking: %s", myname, hostaddr.buf);
1782 
1783  if (!namadr_list_match(perm_mx_networks, host, hostaddr.buf)) {
1784  if (perm_mx_networks->error == 0) {
1785 
1786  /*
1787  * Reject: at least one IP address is not listed in
1788  * permit_mx_backup_networks.
1789  */
1790  if (msg_verbose)
1791  msg_info("%s: address %s for %s does not match %s",
1792  myname, hostaddr.buf, host, VAR_PERM_MX_NETWORKS);
1793  } else {
1794  msg_warn("%s: %s lookup error for address %s for %s",
1795  myname, VAR_PERM_MX_NETWORKS, hostaddr.buf, host);
1797  450, "4.4.4",
1798  "<%s>: %s rejected: Unable to verify host %s as mail exchanger",
1799  reply_name, reply_class, host);
1800  }
1801  dns_rr_free(addr_list);
1802  return (NOPE);
1803  }
1804  }
1805  dns_rr_free(addr_list);
1806  return (YUP);
1807 }
1808 
1809 /* has_my_addr - see if this host name lists one of my network addresses */
1810 
1811 static int has_my_addr(SMTPD_STATE *state, const char *host,
1812  const char *reply_name, const char *reply_class)
1813 {
1814  const char *myname = "has_my_addr";
1815  struct addrinfo *res;
1816  struct addrinfo *res0;
1817  int aierr;
1818  MAI_HOSTADDR_STR hostaddr;
1819  INET_PROTO_INFO *proto_info = inet_proto_info();
1820 
1821  if (msg_verbose)
1822  msg_info("%s: host %s", myname, host);
1823 
1824  /*
1825  * If we can't lookup the host, defer rather than reject.
1826  */
1827 #define YUP 1
1828 #define NOPE 0
1829 
1830  aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0);
1831  if (aierr) {
1833  450, "4.4.4",
1834  "<%s>: %s rejected: Unable to look up mail exchanger host %s: %s",
1835  reply_name, reply_class, host, MAI_STRERROR(aierr));
1836  return (NOPE);
1837  }
1838 #define HAS_MY_ADDR_RETURN(x) { freeaddrinfo(res0); return (x); }
1839 
1840  for (res = res0; res != 0; res = res->ai_next) {
1841  if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
1842  if (msg_verbose)
1843  msg_info("skipping address family %d for host %s",
1844  res->ai_family, host);
1845  continue;
1846  }
1847  if (msg_verbose) {
1848  SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
1849  &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
1850  msg_info("%s: addr %s", myname, hostaddr.buf);
1851  }
1852  if (own_inet_addr(res->ai_addr))
1854  if (proxy_inet_addr(res->ai_addr))
1856  }
1857  if (msg_verbose)
1858  msg_info("%s: host %s: no match", myname, host);
1859 
1861 }
1862 
1863 /* i_am_mx - is this machine listed as MX relay */
1864 
1865 static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list,
1866  const char *reply_name, const char *reply_class)
1867 {
1868  const char *myname = "i_am_mx";
1869  DNS_RR *mx;
1870 
1871  /*
1872  * Compare hostnames first. Only if no name match is found, go through
1873  * the trouble of host address lookups.
1874  */
1875  for (mx = mx_list; mx != 0; mx = mx->next) {
1876  if (msg_verbose)
1877  msg_info("%s: resolve hostname: %s", myname, (char *) mx->data);
1878  if (resolve_local((char *) mx->data) > 0)
1879  return (YUP);
1880  /* if no match or error, match interface addresses instead. */
1881  }
1882 
1883  /*
1884  * Argh. Do further DNS lookups and match interface addresses.
1885  */
1886  for (mx = mx_list; mx != 0; mx = mx->next) {
1887  if (msg_verbose)
1888  msg_info("%s: address lookup: %s", myname, (char *) mx->data);
1889  if (has_my_addr(state, (char *) mx->data, reply_name, reply_class))
1890  return (YUP);
1891  }
1892 
1893  /*
1894  * This machine is not listed as MX relay.
1895  */
1896  if (msg_verbose)
1897  msg_info("%s: I am not listed as MX relay", myname);
1898  return (NOPE);
1899 }
1900 
1901 /* permit_mx_primary - authorize primary MX relays */
1902 
1903 static int permit_mx_primary(SMTPD_STATE *state, DNS_RR *mx_list,
1904  const char *reply_name, const char *reply_class)
1905 {
1906  const char *myname = "permit_mx_primary";
1907  DNS_RR *mx;
1908 
1909  if (msg_verbose)
1910  msg_info("%s", myname);
1911 
1912  /*
1913  * See if each best MX host has all IP addresses in
1914  * permit_mx_backup_networks.
1915  */
1916  for (mx = mx_list; mx != 0; mx = mx->next) {
1917  if (!all_auth_mx_addr(state, (char *) mx->data, reply_name, reply_class))
1918  return (NOPE);
1919  }
1920 
1921  /*
1922  * All IP addresses of the best MX hosts are within
1923  * permit_mx_backup_networks.
1924  */
1925  return (YUP);
1926 }
1927 
1928 /* permit_mx_backup - permit use of me as MX backup for recipient domain */
1929 
1930 static int permit_mx_backup(SMTPD_STATE *state, const char *recipient,
1931  const char *reply_name, const char *reply_class)
1932 {
1933  const char *myname = "permit_mx_backup";
1934  const RESOLVE_REPLY *reply;
1935  const char *domain;
1936  const char *adomain;
1937  DNS_RR *mx_list;
1938  DNS_RR *middle;
1939  DNS_RR *rest;
1940  int dns_status;
1941 
1942  if (msg_verbose)
1943  msg_info("%s: %s", myname, recipient);
1944 
1945  /*
1946  * Resolve the address.
1947  */
1948  reply = smtpd_resolve_addr(state->sender, recipient);
1949  if (reply->flags & RESOLVE_FLAG_FAIL)
1950  reject_dict_retry(state, recipient);
1951 
1952  /*
1953  * For backwards compatibility, emulate permit_auth_destination. However,
1954  * old permit_mx_backup implementations allow source routing with local
1955  * address class.
1956  */
1957  if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
1958  return (SMTPD_CHECK_OK);
1959  domain += 1;
1960 #if 0
1961  if (reply->flags & RESOLVE_CLASS_LOCAL)
1962  return (SMTPD_CHECK_OK);
1963 #endif
1964  if (var_allow_untrust_route == 0 && (reply->flags & RESOLVE_FLAG_ROUTED))
1965  return (SMTPD_CHECK_DUNNO);
1966  if (reply->flags & RESOLVE_CLASS_FINAL)
1967  return (SMTPD_CHECK_OK);
1968  if (reply->flags & RESOLVE_CLASS_RELAY) {
1970  msg_info("using backwards-compatible default setting "
1971  VAR_RELAY_DOMAINS "=$mydestination to accept mail "
1972  "for domain \"%s\"", domain);
1973  return (SMTPD_CHECK_OK);
1974  }
1975  if (msg_verbose)
1976  msg_info("%s: not local: %s", myname, recipient);
1977 
1978  /*
1979  * Skip numerical forms that didn't match the local system.
1980  */
1981  if (domain[0] == '[' && domain[strlen(domain) - 1] == ']')
1982  return (SMTPD_CHECK_DUNNO);
1983 
1984  /*
1985  * Fix 20140924: convert domain to ASCII.
1986  */
1987 #ifndef NO_EAI
1988  if (!allascii(domain) && (adomain = midna_domain_to_ascii(domain)) != 0) {
1989  if (msg_verbose)
1990  msg_info("%s asciified to %s", domain, adomain);
1991  domain = adomain;
1992  }
1993 #endif
1994 
1995  /*
1996  * Look up the list of MX host names for this domain. If no MX host is
1997  * found, perhaps it is a CNAME for the local machine. Clients aren't
1998  * supposed to send CNAMEs in SMTP commands, but it happens anyway. If we
1999  * can't look up the destination, play safe and turn reject into defer.
2000  */
2001  dns_status = dns_lookup(domain, T_MX, 0, &mx_list,
2002  (VSTRING *) 0, (VSTRING *) 0);
2003 #if 0
2004  if (dns_status == DNS_NOTFOUND)
2005  return (has_my_addr(state, domain, reply_name, reply_class) ?
2007 #endif
2008  if (dns_status != DNS_OK) { /* incl. DNS_INVAL */
2009  /* We don't special-case DNS_NULLMX. */
2010  if (dns_status == DNS_RETRY || dns_status == DNS_POLICY)
2012  450, "4.4.4",
2013  "<%s>: %s rejected: Unable to look up mail "
2014  "exchanger information: %s",
2015  reply_name, reply_class, dns_status == DNS_POLICY ?
2016  "DNS reply filter policy" : dns_strerror(h_errno));
2017  return (SMTPD_CHECK_DUNNO);
2018  }
2019 
2020  /*
2021  * Separate MX list into primaries and backups.
2022  */
2023  mx_list = dns_rr_sort(mx_list, dns_rr_compare_pref_any);
2024  for (middle = mx_list; /* see below */ ; middle = rest) {
2025  rest = middle->next;
2026  if (rest == 0)
2027  break;
2028  if (rest->pref != mx_list->pref) {
2029  middle->next = 0;
2030  break;
2031  }
2032  }
2033  /* postcondition: middle->next = 0, rest may be 0. */
2034 
2035 #define PERMIT_MX_BACKUP_RETURN(x) do { \
2036  middle->next = rest; \
2037  dns_rr_free(mx_list); \
2038  return (x); \
2039  } while (0)
2040 
2041  /*
2042  * First, see if we match any of the primary MX servers.
2043  */
2044  if (i_am_mx(state, mx_list, reply_name, reply_class))
2045  PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO);
2046 
2047  /*
2048  * Then, see if we match any of the backup MX servers.
2049  */
2050  if (rest == 0 || !i_am_mx(state, rest, reply_name, reply_class))
2051  PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO);
2052 
2053  /*
2054  * Optionally, see if the primary MX hosts are in a restricted list of
2055  * networks.
2056  */
2058  && !permit_mx_primary(state, mx_list, reply_name, reply_class))
2059  PERMIT_MX_BACKUP_RETURN(SMTPD_CHECK_DUNNO);
2060 
2061  /*
2062  * The destination passed all requirements.
2063  */
2065 }
2066 
2067 /* reject_non_fqdn_address - fail if address is not in fqdn form */
2068 
2069 static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr,
2070  char *reply_name, char *reply_class)
2071 {
2072  const char *myname = "reject_non_fqdn_address";
2073  char *domain;
2074  char *test_dom;
2075  int stat;
2076 
2077  if (msg_verbose)
2078  msg_info("%s: %s", myname, addr);
2079 
2080  /*
2081  * Locate the domain information.
2082  */
2083  if ((domain = strrchr(addr, '@')) != 0)
2084  domain++;
2085  else
2086  domain = "";
2087 
2088  /*
2089  * Skip forms that we can't handle yet.
2090  */
2091  if (domain[0] == '[' && domain[strlen(domain) - 1] == ']')
2092  return (SMTPD_CHECK_DUNNO);
2093 
2094  /*
2095  * Truncate names ending in dot but not dot-dot.
2096  */
2097  test_dom = dup_if_truncate(domain);
2098 
2099  /*
2100  * Validate the domain. For backwards compatibility, permit non-ASCII
2101  * names only when the client requested SMTPUTF8 support.
2102  */
2103  if (!*test_dom || !valid_utf8_hostname(state->flags & SMTPD_FLAG_SMTPUTF8,
2104  test_dom, DONT_GRIPE) || !strchr(test_dom, '.'))
2105  stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
2106  var_non_fqdn_code, "4.5.2",
2107  "<%s>: %s rejected: need fully-qualified address",
2108  reply_name, reply_class);
2109  else
2110  stat = SMTPD_CHECK_DUNNO;
2111 
2112  /*
2113  * Cleanup.
2114  */
2115  if (test_dom != domain)
2116  myfree(test_dom);
2117 
2118  return (stat);
2119 }
2120 
2121 /* reject_unknown_address - fail if address does not resolve */
2122 
2123 static int reject_unknown_address(SMTPD_STATE *state, const char *addr,
2124  const char *reply_name, const char *reply_class)
2125 {
2126  const char *myname = "reject_unknown_address";
2127  const RESOLVE_REPLY *reply;
2128  const char *domain;
2129 
2130  if (msg_verbose)
2131  msg_info("%s: %s", myname, addr);
2132 
2133  /*
2134  * Resolve the address.
2135  */
2136  reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
2137  state->recipient : state->sender, addr);
2138  if (reply->flags & RESOLVE_FLAG_FAIL)
2139  reject_dict_retry(state, addr);
2140 
2141  /*
2142  * Skip local destinations and non-DNS forms.
2143  */
2144  if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0)
2145  return (SMTPD_CHECK_DUNNO);
2146  domain += 1;
2147  if (reply->flags & RESOLVE_CLASS_FINAL)
2148  return (SMTPD_CHECK_DUNNO);
2149  if (domain[0] == '[' && domain[strlen(domain) - 1] == ']')
2150  return (SMTPD_CHECK_DUNNO);
2151 
2152  /*
2153  * Look up the name in the DNS.
2154  */
2155  return (reject_unknown_mailhost(state, domain, reply_name, reply_class));
2156 }
2157 
2158 /* reject_unverified_address - fail if address bounces */
2159 
2160 static int reject_unverified_address(SMTPD_STATE *state, const char *addr,
2161  const char *reply_name, const char *reply_class,
2162  int unv_addr_dcode, int unv_addr_rcode,
2163  int unv_addr_tf_act,
2164  const char *alt_reply)
2165 {
2166  const char *myname = "reject_unverified_address";
2167  VSTRING *why = vstring_alloc(10);
2168  int rqst_status = SMTPD_CHECK_DUNNO;
2169  int rcpt_status;
2170  int verify_status;
2171  int count;
2172  int reject_code = 0;
2173 
2174  if (msg_verbose)
2175  msg_info("%s: %s", myname, addr);
2176 
2177  /*
2178  * Verify the address. Don't waste too much of their or our time.
2179  */
2180  for (count = 0; /* see below */ ; /* see below */ ) {
2181  verify_status = verify_clnt_query(addr, &rcpt_status, why);
2182  if (verify_status != VRFY_STAT_OK || rcpt_status != DEL_RCPT_STAT_TODO)
2183  break;
2184  if (++count >= var_verify_poll_count)
2185  break;
2186  sleep(var_verify_poll_delay);
2187  }
2188  if (verify_status != VRFY_STAT_OK) {
2189  msg_warn("%s service failure", var_verify_service);
2190  rqst_status =
2191  DEFER_IF_PERMIT2(unv_addr_tf_act, state, MAIL_ERROR_POLICY,
2192  450, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
2193  SND_DSN : "4.1.1",
2194  "<%s>: %s rejected: address verification problem",
2195  reply_name, reply_class);
2196  } else {
2197  switch (rcpt_status) {
2198  default:
2199  msg_warn("unknown address verification status %d", rcpt_status);
2200  break;
2201  case DEL_RCPT_STAT_TODO:
2202  case DEL_RCPT_STAT_DEFER:
2203  reject_code = unv_addr_dcode;
2204  break;
2205  case DEL_RCPT_STAT_OK:
2206  break;
2207  case DEL_RCPT_STAT_BOUNCE:
2208  reject_code = unv_addr_rcode;
2209  break;
2210  }
2211  if (reject_code >= 400 && *alt_reply)
2212  vstring_strcpy(why, alt_reply);
2213  switch (reject_code / 100) {
2214  case 2:
2215  break;
2216  case 4:
2217  rqst_status =
2218  DEFER_IF_PERMIT3(unv_addr_tf_act, state, MAIL_ERROR_POLICY,
2219  reject_code,
2220  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
2221  SND_DSN : "4.1.1",
2222  "<%s>: %s rejected: unverified address: %.250s",
2223  reply_name, reply_class, STR(why));
2224  break;
2225  default:
2226  if (reject_code != 0)
2227  rqst_status =
2228  smtpd_check_reject(state, MAIL_ERROR_POLICY,
2229  reject_code,
2230  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
2231  SND_DSN : "4.1.1",
2232  "<%s>: %s rejected: undeliverable address: %s",
2233  reply_name, reply_class, STR(why));
2234  break;
2235  }
2236  }
2237  vstring_free(why);
2238  return (rqst_status);
2239 }
2240 
2241 /* can_delegate_action - can we delegate this to the cleanup server */
2242 
2243 #ifndef TEST
2244 
2245 static int not_in_client_helo(SMTPD_STATE *, const char *, const char *, const char *);
2246 
2247 static int can_delegate_action(SMTPD_STATE *state, const char *table,
2248  const char *action, const char *reply_class)
2249 {
2250 
2251  /*
2252  * If we're not using the cleanup server, then there is no way that we
2253  * can support actions such as FILTER or HOLD that are delegated to the
2254  * cleanup server.
2255  */
2256  if (USE_SMTPD_PROXY(state)) {
2257  msg_warn("access table %s: with %s specified, action %s is unavailable",
2258  table, VAR_SMTPD_PROXY_FILT, action);
2259  return (0);
2260  }
2261 
2262  /*
2263  * ETRN does not receive mail so we can't store queue file records.
2264  */
2265  if (strcmp(state->where, SMTPD_CMD_ETRN) == 0) {
2266  msg_warn("access table %s: action %s is unavailable in %s",
2267  table, action, VAR_ETRN_CHECKS);
2268  return (0);
2269  }
2270  return (not_in_client_helo(state, table, action, reply_class));
2271 }
2272 
2273 /* not_in_client_helo - not in client or helo restriction context */
2274 
2275 static int not_in_client_helo(SMTPD_STATE *state, const char *table,
2276  const char *action,
2277  const char *unused_reply_class)
2278 {
2279 
2280  /*
2281  * If delay_reject=no, then client and helo restrictions take effect
2282  * immediately, outside any particular mail transaction context. For
2283  * example, rejecting HELO does not affect subsequent mail deliveries.
2284  * Thus, if delay_reject=no, client and helo actions such as FILTER or
2285  * HOLD also should not affect subsequent mail deliveries. Hmm...
2286  *
2287  * XXX If the MAIL FROM command is rejected then we have to reset access map
2288  * side effects such as FILTER.
2289  */
2290  if (state->sender == 0) {
2291  msg_warn("access table %s: with %s=%s, "
2292  "action %s is always skipped in %s or %s restrictions",
2295  /* XXX What about ETRN? */
2296  return (0);
2297  }
2298  return (1);
2299 }
2300 
2301 #endif
2302 
2303 /* check_table_result - translate table lookup result into pass/reject */
2304 
2305 static int check_table_result(SMTPD_STATE *state, const char *table,
2306  const char *value, const char *datum,
2307  const char *reply_name,
2308  const char *reply_class,
2309  const char *def_acl)
2310 {
2311  const char *myname = "check_table_result";
2312  int code;
2313  ARGV *restrictions;
2314  jmp_buf savebuf;
2315  int status;
2316  const char *cmd_text;
2317  int cmd_len;
2318  static char def_dsn[] = "5.7.1";
2319  DSN_SPLIT dp;
2320  static VSTRING *buf;
2321 
2322 #ifdef DELAY_ACTION
2323  int defer_delay;
2324 
2325 #endif
2326 
2327  if (buf == 0)
2328  buf = vstring_alloc(10);
2329 
2330  /*
2331  * Parse into command and text. Do not change the input.
2332  */
2333  cmd_text = value + strcspn(value, " \t");
2334  cmd_len = cmd_text - value;
2335  vstring_strncpy(buf, value, cmd_len);
2336  while (*cmd_text && ISSPACE(*cmd_text))
2337  cmd_text++;
2338 
2339  if (msg_verbose)
2340  msg_info("%s: %s %s %s", myname, table, value, datum);
2341 
2342 #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
2343 
2344  /*
2345  * DUNNO means skip this table. Silently ignore optional text.
2346  */
2347  if (STREQUAL(value, "DUNNO", cmd_len))
2348  return (SMTPD_CHECK_DUNNO);
2349 
2350  /*
2351  * REJECT means NO. Use optional text or generate a generic error
2352  * response.
2353  */
2354  if (STREQUAL(value, "REJECT", cmd_len)) {
2355  dsn_split(&dp, "5.7.1", cmd_text);
2356  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
2359  reply_class),
2360  "<%s>: %s rejected: %s",
2361  reply_name, reply_class,
2362  *dp.text ? dp.text : "Access denied"));
2363  }
2364 
2365  /*
2366  * DEFER means "try again". Use optional text or generate a generic error
2367  * response.
2368  */
2369  if (STREQUAL(value, "DEFER", cmd_len)) {
2370  dsn_split(&dp, "4.7.1", cmd_text);
2371  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
2374  reply_class),
2375  "<%s>: %s rejected: %s",
2376  reply_name, reply_class,
2377  *dp.text ? dp.text : "Access denied"));
2378  }
2379 #ifndef SHUT_RDWR
2380 #define SHUT_RDWR 2
2381 #endif
2382 
2383  /*
2384  * HANGUP. Text is optional. Drop the connection without sending any
2385  * reply.
2386  *
2387  * Note: this is an unsupported test feature. No attempt is made to maintain
2388  * compatibility between successive versions.
2389  */
2390  if (STREQUAL(value, "HANGUP", cmd_len)) {
2391  shutdown(vstream_fileno(state->client), SHUT_RDWR);
2392  log_whatsup(state, "hangup", cmd_text);
2394  }
2395 
2396  /*
2397  * INFO. Text is optional.
2398  */
2399  if (STREQUAL(value, "INFO", cmd_len)) {
2400  log_whatsup(state, "info", cmd_text);
2401  return (SMTPD_CHECK_DUNNO);
2402  }
2403 
2404  /*
2405  * WARN. Text is optional.
2406  */
2407  if (STREQUAL(value, "WARN", cmd_len)) {
2408  log_whatsup(state, "warn", cmd_text);
2409  return (SMTPD_CHECK_DUNNO);
2410  }
2411 
2412  /*
2413  * FILTER means deliver to content filter. But we may still change our
2414  * mind, and reject/discard the message for other reasons.
2415  */
2416  if (STREQUAL(value, "FILTER", cmd_len)) {
2417 #ifndef TEST
2418  if (can_delegate_action(state, table, "FILTER", reply_class) == 0)
2419  return (SMTPD_CHECK_DUNNO);
2420 #endif
2421  if (*cmd_text == 0) {
2422  msg_warn("access table %s entry \"%s\" has FILTER entry without value",
2423  table, datum);
2424  return (SMTPD_CHECK_DUNNO);
2425  } else if (strchr(cmd_text, ':') == 0) {
2426  msg_warn("access table %s entry \"%s\" requires transport:destination",
2427  table, datum);
2428  return (SMTPD_CHECK_DUNNO);
2429  } else {
2430  vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s",
2431  reply_name, reply_class, cmd_text);
2432  log_whatsup(state, "filter", STR(error_text));
2433 #ifndef TEST
2434  UPDATE_STRING(state->saved_filter, cmd_text);
2435 #endif
2436  return (SMTPD_CHECK_DUNNO);
2437  }
2438  }
2439 
2440  /*
2441  * HOLD means deliver later. But we may still change our mind, and
2442  * reject/discard the message for other reasons.
2443  */
2444  if (STREQUAL(value, "HOLD", cmd_len)) {
2445 #ifndef TEST
2446  if (can_delegate_action(state, table, "HOLD", reply_class) == 0
2447  || (state->saved_flags & CLEANUP_FLAG_HOLD))
2448  return (SMTPD_CHECK_DUNNO);
2449 #endif
2450  vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
2451  *cmd_text ? cmd_text : "triggers HOLD action");
2452  log_whatsup(state, "hold", STR(error_text));
2453 #ifndef TEST
2454  state->saved_flags |= CLEANUP_FLAG_HOLD;
2455 #endif
2456  return (SMTPD_CHECK_DUNNO);
2457  }
2458 
2459  /*
2460  * DELAY means deliver later. But we may still change our mind, and
2461  * reject/discard the message for other reasons.
2462  *
2463  * This feature is deleted because it has too many problems. 1) It does not
2464  * work on some remote file systems; 2) mail will be delivered anyway
2465  * with "sendmail -q" etc.; 3) while the mail is queued it bogs down the
2466  * deferred queue scan with huge amounts of useless disk I/O operations.
2467  */
2468 #ifdef DELAY_ACTION
2469  if (STREQUAL(value, "DELAY", cmd_len)) {
2470 #ifndef TEST
2471  if (can_delegate_action(state, table, "DELAY", reply_class) == 0)
2472  return (SMTPD_CHECK_DUNNO);
2473 #endif
2474  if (*cmd_text == 0) {
2475  msg_warn("access table %s entry \"%s\" has DELAY entry without value",
2476  table, datum);
2477  return (SMTPD_CHECK_DUNNO);
2478  }
2479  if (conv_time(cmd_text, &defer_delay, 's') == 0) {
2480  msg_warn("access table %s entry \"%s\" has invalid DELAY argument \"%s\"",
2481  table, datum, cmd_text);
2482  return (SMTPD_CHECK_DUNNO);
2483  }
2484  vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
2485  *cmd_text ? cmd_text : "triggers DELAY action");
2486  log_whatsup(state, "delay", STR(error_text));
2487 #ifndef TEST
2488  state->saved_delay = defer_delay;
2489 #endif
2490  return (SMTPD_CHECK_DUNNO);
2491  }
2492 #endif
2493 
2494  /*
2495  * DISCARD means silently discard and claim successful delivery.
2496  */
2497  if (STREQUAL(value, "DISCARD", cmd_len)) {
2498 #ifndef TEST
2499  if (can_delegate_action(state, table, "DISCARD", reply_class) == 0)
2500  return (SMTPD_CHECK_DUNNO);
2501 #endif
2502  vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
2503  *cmd_text ? cmd_text : "triggers DISCARD action");
2504  log_whatsup(state, "discard", STR(error_text));
2505 #ifndef TEST
2507  state->discard = 1;
2508 #endif
2509  return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name,
2510  "from %s", table));
2511  }
2512 
2513  /*
2514  * REDIRECT means deliver to designated recipient. But we may still
2515  * change our mind, and reject/discard the message for other reasons.
2516  */
2517  if (STREQUAL(value, "REDIRECT", cmd_len)) {
2518 #ifndef TEST
2519  if (can_delegate_action(state, table, "REDIRECT", reply_class) == 0)
2520  return (SMTPD_CHECK_DUNNO);
2521 #endif
2522  if (strchr(cmd_text, '@') == 0) {
2523  msg_warn("access table %s entry \"%s\" requires user@domain target",
2524  table, datum);
2525  return (SMTPD_CHECK_DUNNO);
2526  } else {
2527  vstring_sprintf(error_text, "<%s>: %s triggers REDIRECT %s",
2528  reply_name, reply_class, cmd_text);
2529  log_whatsup(state, "redirect", STR(error_text));
2530 #ifndef TEST
2531  UPDATE_STRING(state->saved_redirect, cmd_text);
2532 #endif
2533  return (SMTPD_CHECK_DUNNO);
2534  }
2535  }
2536 
2537  /*
2538  * BCC means deliver to designated recipient. But we may still change our
2539  * mind, and reject/discard the message for other reasons.
2540  */
2541  if (STREQUAL(value, "BCC", cmd_len)) {
2542 #ifndef TEST
2543  if (can_delegate_action(state, table, "BCC", reply_class) == 0)
2544  return (SMTPD_CHECK_DUNNO);
2545 #endif
2546  if (strchr(cmd_text, '@') == 0) {
2547  msg_warn("access table %s entry \"%s\" requires user@domain target",
2548  table, datum);
2549  return (SMTPD_CHECK_DUNNO);
2550  } else {
2551  vstring_sprintf(error_text, "<%s>: %s triggers BCC %s",
2552  reply_name, reply_class, cmd_text);
2553  log_whatsup(state, "bcc", STR(error_text));
2554 #ifndef TEST
2555  if (state->saved_bcc == 0)
2556  state->saved_bcc = argv_alloc(1);
2557  argv_add(state->saved_bcc, cmd_text, (char *) 0);
2558 #endif
2559  return (SMTPD_CHECK_DUNNO);
2560  }
2561  }
2562 
2563  /*
2564  * DEFER_IF_PERMIT changes "permit" into "maybe". Use optional text or
2565  * generate a generic error response.
2566  */
2567  if (STREQUAL(value, DEFER_IF_PERMIT, cmd_len)) {
2568  dsn_split(&dp, "4.7.1", cmd_text);
2571  smtpd_dsn_fix(DSN_STATUS(dp.dsn), reply_class),
2572  "<%s>: %s rejected: %s",
2573  reply_name, reply_class,
2574  *dp.text ? dp.text : "Service unavailable"));
2575  }
2576 
2577  /*
2578  * DEFER_IF_REJECT changes "reject" into "maybe". Use optional text or
2579  * generate a generic error response.
2580  */
2581  if (STREQUAL(value, DEFER_IF_REJECT, cmd_len)) {
2582  dsn_split(&dp, "4.7.1", cmd_text);
2585  smtpd_dsn_fix(DSN_STATUS(dp.dsn), reply_class),
2586  "<%s>: %s rejected: %s",
2587  reply_name, reply_class,
2588  *dp.text ? dp.text : "Service unavailable");
2589  return (SMTPD_CHECK_DUNNO);
2590  }
2591 
2592  /*
2593  * PREPEND prepends the specified message header text.
2594  */
2595  if (STREQUAL(value, "PREPEND", cmd_len)) {
2596 #ifndef TEST
2597  /* XXX what about ETRN. */
2598  if (not_in_client_helo(state, table, "PREPEND", reply_class) == 0)
2599  return (SMTPD_CHECK_DUNNO);
2600 #endif
2601  if (strcmp(state->where, SMTPD_AFTER_DOT) == 0) {
2602  msg_warn("access table %s: action PREPEND must be used before %s",
2603  table, VAR_EOD_CHECKS);
2604  return (SMTPD_CHECK_DUNNO);
2605  }
2606  if (*cmd_text == 0 || is_header(cmd_text) == 0) {
2607  msg_warn("access table %s entry \"%s\" requires header: text",
2608  table, datum);
2609  return (SMTPD_CHECK_DUNNO);
2610  } else {
2611  if (state->prepend == 0)
2612  state->prepend = argv_alloc(1);
2613  argv_add(state->prepend, cmd_text, (char *) 0);
2614  return (SMTPD_CHECK_DUNNO);
2615  }
2616  }
2617 
2618  /*
2619  * All-numeric result probably means OK - some out-of-band authentication
2620  * mechanism uses this as time stamp.
2621  */
2622  if (alldig(value))
2623  return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name,
2624  "from %s", table));
2625 
2626  /*
2627  * 4xx or 5xx means NO as well. smtpd_check_reject() will validate the
2628  * response status code.
2629  *
2630  * If the caller specifies an RFC 3463 enhanced status code, put it
2631  * immediately after the SMTP status code as described in RFC 2034.
2632  */
2633  if (cmd_len == 3 && *cmd_text
2634  && (value[0] == '4' || value[0] == '5')
2635  && ISDIGIT(value[1]) && ISDIGIT(value[2])) {
2636  code = atoi(value);
2637  def_dsn[0] = value[0];
2638  dsn_split(&dp, def_dsn, cmd_text);
2639  return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
2640  code,
2642  reply_class),
2643  "<%s>: %s rejected: %s",
2644  reply_name, reply_class,
2645  *dp.text ? dp.text : "Access denied"));
2646  }
2647 
2648  /*
2649  * OK or RELAY means YES. Ignore trailing text.
2650  */
2651  if (STREQUAL(value, "OK", cmd_len) || STREQUAL(value, "RELAY", cmd_len))
2652  return (smtpd_acl_permit(state, STR(buf), reply_class, reply_name,
2653  "from %s", table));
2654 
2655  /*
2656  * Unfortunately, maps must be declared ahead of time so they can be
2657  * opened before we go to jail. We could insist that the RHS can only
2658  * contain a pre-defined restriction class name, but that would be too
2659  * restrictive. Instead we warn if an access table references any map.
2660  *
2661  * XXX Don't use passwd files or address rewriting maps as access tables.
2662  */
2663  if (strchr(value, ':') != 0) {
2664  msg_warn("access table %s has entry with lookup table: %s",
2665  table, value);
2666  msg_warn("do not specify lookup tables inside SMTPD access maps");
2667  msg_warn("define a restriction class and specify its name instead.");
2668  reject_server_error(state);
2669  }
2670 
2671  /*
2672  * Don't get carried away with recursion.
2673  */
2674  if (state->recursion > 100) {
2675  msg_warn("access table %s entry %s causes unreasonable recursion",
2676  table, value);
2677  reject_server_error(state);
2678  }
2679 
2680  /*
2681  * Recursively evaluate the restrictions given in the right-hand side. In
2682  * the dark ages, an empty right-hand side meant OK. Make some
2683  * discouraging comments.
2684  *
2685  * XXX Jump some hoops to avoid a minute memory leak in case of a file
2686  * configuration error.
2687  */
2688 #define ADDROF(x) ((char *) &(x))
2689 
2690  restrictions = argv_splitq(value, CHARS_COMMA_SP, CHARS_BRACE);
2691  memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf));
2692  status = setjmp(smtpd_check_buf);
2693  if (status != 0) {
2694  argv_free(restrictions);
2695  memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf),
2696  sizeof(smtpd_check_buf));
2697  longjmp(smtpd_check_buf, status);
2698  }
2699  if (restrictions->argc == 0) {
2700  msg_warn("access table %s entry %s has empty value",
2701  table, value);
2702  status = SMTPD_CHECK_OK;
2703  } else {
2704  status = generic_checks(state, restrictions, reply_name,
2705  reply_class, def_acl);
2706  }
2707  argv_free(restrictions);
2708  memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf), sizeof(smtpd_check_buf));
2709  return (status);
2710 }
2711 
2712 /* check_access - table lookup without substring magic */
2713 
2714 static int check_access(SMTPD_STATE *state, const char *table, const char *name,
2715  int flags, int *found, const char *reply_name,
2716  const char *reply_class, const char *def_acl)
2717 {
2718  const char *myname = "check_access";
2719  const char *value;
2720  MAPS *maps;
2721 
2722 #define CHK_ACCESS_RETURN(x,y) \
2723  { *found = y; return(x); }
2724 #define FULL 0
2725 #define PARTIAL DICT_FLAG_FIXED
2726 #define FOUND 1
2727 #define MISSED 0
2728 
2729  if (msg_verbose)
2730  msg_info("%s: %s", myname, name);
2731 
2732  if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
2733  msg_warn("%s: unexpected dictionary: %s", myname, table);
2734  value = "451 4.3.5 Server configuration error";
2735  CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
2736  reply_name, reply_class,
2737  def_acl), FOUND);
2738  }
2739  if ((value = maps_find(maps, name, flags)) != 0)
2740  CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
2741  reply_name, reply_class,
2742  def_acl), FOUND);
2743  if (maps->error != 0) {
2744  /* Warning is already logged. */
2745  value = "451 4.3.5 Server configuration error";
2746  CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
2747  reply_name, reply_class,
2748  def_acl), FOUND);
2749  }
2750  CHK_ACCESS_RETURN(SMTPD_CHECK_DUNNO, MISSED);
2751 }
2752 
2753 /* check_domain_access - domainname-based table lookup */
2754 
2755 static int check_domain_access(SMTPD_STATE *state, const char *table,
2756  const char *domain, int flags,
2757  int *found, const char *reply_name,
2758  const char *reply_class,
2759  const char *def_acl)
2760 {
2761  const char *myname = "check_domain_access";
2762  const char *name;
2763  const char *next;
2764  const char *value;
2765  MAPS *maps;
2766  int maybe_numerical = 1;
2767 
2768  if (msg_verbose)
2769  msg_info("%s: %s", myname, domain);
2770 
2771  /*
2772  * Try the name and its parent domains. Including top-level domains.
2773  *
2774  * Helo names can end in ".". The test below avoids lookups of the empty
2775  * key, because Berkeley DB cannot deal with it. [Victor Duchovni, Morgan
2776  * Stanley].
2777  *
2778  * TODO(wietse) move to mail_domain_find library module.
2779  */
2780 #define CHK_DOMAIN_RETURN(x,y) { *found = y; return(x); }
2781 
2782  if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
2783  msg_warn("%s: unexpected dictionary: %s", myname, table);
2784  value = "451 4.3.5 Server configuration error";
2785  CHK_DOMAIN_RETURN(check_table_result(state, table, value,
2786  domain, reply_name, reply_class,
2787  def_acl), FOUND);
2788  }
2789  for (name = domain; *name != 0; name = next) {
2790  if ((value = maps_find(maps, name, flags)) != 0)
2791  CHK_DOMAIN_RETURN(check_table_result(state, table, value,
2792  domain, reply_name, reply_class,
2793  def_acl), FOUND);
2794  if (maps->error != 0) {
2795  /* Warning is already logged. */
2796  value = "451 4.3.5 Server configuration error";
2797  CHK_DOMAIN_RETURN(check_table_result(state, table, value,
2798  domain, reply_name, reply_class,
2799  def_acl), FOUND);
2800  }
2801  /* Don't apply subdomain magic to numerical hostnames. */
2802  if (maybe_numerical
2803  && (maybe_numerical = valid_hostaddr(domain, DONT_GRIPE)) != 0)
2804  break;
2805  if ((next = strchr(name + 1, '.')) == 0)
2806  break;
2807  if (access_parent_style == MATCH_FLAG_PARENT)
2808  next += 1;
2809  flags = PARTIAL;
2810  }
2811  CHK_DOMAIN_RETURN(SMTPD_CHECK_DUNNO, MISSED);
2812 }
2813 
2814 /* check_addr_access - address-based table lookup */
2815 
2816 static int check_addr_access(SMTPD_STATE *state, const char *table,
2817  const char *address, int flags,
2818  int *found, const char *reply_name,
2819  const char *reply_class,
2820  const char *def_acl)
2821 {
2822  const char *myname = "check_addr_access";
2823  char *addr;
2824  const char *value;
2825  MAPS *maps;
2826  int delim;
2827 
2828  if (msg_verbose)
2829  msg_info("%s: %s", myname, address);
2830 
2831  /*
2832  * Try the address and its parent networks.
2833  *
2834  * TODO(wietse) move to mail_ipaddr_find library module.
2835  */
2836 #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
2837 
2838  addr = STR(vstring_strcpy(error_text, address));
2839 #ifdef HAS_IPV6
2840  if (strchr(addr, ':') != 0)
2841  delim = ':';
2842  else
2843 #endif
2844  delim = '.';
2845 
2846  if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
2847  msg_warn("%s: unexpected dictionary: %s", myname, table);
2848  value = "451 4.3.5 Server configuration error";
2849  CHK_ADDR_RETURN(check_table_result(state, table, value, address,
2850  reply_name, reply_class,
2851  def_acl), FOUND);
2852  }
2853  do {
2854  if ((value = maps_find(maps, addr, flags)) != 0)
2855  CHK_ADDR_RETURN(check_table_result(state, table, value, address,
2856  reply_name, reply_class,
2857  def_acl), FOUND);
2858  if (maps->error != 0) {
2859  /* Warning is already logged. */
2860  value = "451 4.3.5 Server configuration error";
2861  CHK_ADDR_RETURN(check_table_result(state, table, value, address,
2862  reply_name, reply_class,
2863  def_acl), FOUND);
2864  }
2865  flags = PARTIAL;
2866  } while (split_at_right(addr, delim));
2867 
2868  CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
2869 }
2870 
2871 /* check_namadr_access - OK/FAIL based on host name/address lookup */
2872 
2873 static int check_namadr_access(SMTPD_STATE *state, const char *table,
2874  const char *name, const char *addr,
2875  int flags, int *found,
2876  const char *reply_name,
2877  const char *reply_class,
2878  const char *def_acl)
2879 {
2880  const char *myname = "check_namadr_access";
2881  int status;
2882 
2883  if (msg_verbose)
2884  msg_info("%s: name %s addr %s", myname, name, addr);
2885 
2886  /*
2887  * Look up the host name, or parent domains thereof. XXX A domain
2888  * wildcard may pre-empt a more specific address table entry.
2889  */
2890  if ((status = check_domain_access(state, table, name, flags,
2891  found, reply_name, reply_class,
2892  def_acl)) != 0 || *found)
2893  return (status);
2894 
2895  /*
2896  * Look up the network address, or parent networks thereof.
2897  */
2898  if ((status = check_addr_access(state, table, addr, flags,
2899  found, reply_name, reply_class,
2900  def_acl)) != 0 || *found)
2901  return (status);
2902 
2903  /*
2904  * Undecided when the host was not found.
2905  */
2906  return (SMTPD_CHECK_DUNNO);
2907 }
2908 
2909 /* check_server_access - access control by server host name or address */
2910 
2911 static int check_server_access(SMTPD_STATE *state, const char *table,
2912  const char *name,
2913  int type,
2914  const char *reply_name,
2915  const char *reply_class,
2916  const char *def_acl)
2917 {
2918  const char *myname = "check_server_access";
2919  const char *domain;
2920  const char *adomain;
2921  int dns_status;
2922  DNS_RR *server_list;
2923  DNS_RR *server;
2924  int found = 0;
2925  MAI_HOSTADDR_STR addr_string;
2926  int aierr;
2927  struct addrinfo *res0;
2928  struct addrinfo *res;
2929  int status;
2930  INET_PROTO_INFO *proto_info;
2931 
2932  /*
2933  * Sanity check.
2934  */
2935  if (type != T_MX && type != T_NS && type != T_A
2936 #ifdef HAS_IPV6
2937  && type != T_AAAA
2938 #endif
2939  )
2940  msg_panic("%s: unexpected resource type \"%s\" in request",
2941  myname, dns_strtype(type));
2942 
2943  if (msg_verbose)
2944  msg_info("%s: %s %s", myname, dns_strtype(type), name);
2945 
2946  /*
2947  * Skip over local-part.
2948  */
2949  if ((domain = strrchr(name, '@')) != 0)
2950  domain += 1;
2951  else
2952  domain = name;
2953 
2954  /*
2955  * Treat an address literal as its own MX server, just like we treat a
2956  * name without MX record as its own MX server. There is, however, no
2957  * applicable NS server equivalent.
2958  */
2959  if (*domain == '[') {
2960  char *saved_addr;
2961  const char *bare_addr;
2962  ssize_t len;
2963 
2964  if (type != T_A && type != T_MX)
2965  return (SMTPD_CHECK_DUNNO);
2966  len = strlen(domain);
2967  if (domain[len - 1] != ']')
2968  return (SMTPD_CHECK_DUNNO);
2969  /* Memory leak alert: no early returns after this point. */
2970  saved_addr = mystrndup(domain + 1, len - 2);
2971  if ((bare_addr = valid_mailhost_addr(saved_addr, DONT_GRIPE)) == 0)
2972  status = SMTPD_CHECK_DUNNO;
2973  else
2974  status = check_addr_access(state, table, bare_addr, FULL,
2975  &found, reply_name, reply_class,
2976  def_acl);
2977  myfree(saved_addr);
2978  return (status);
2979  }
2980 
2981  /*
2982  * Fix 20140924: convert domain to ASCII.
2983  */
2984 #ifndef NO_EAI
2985  if (!allascii(domain) && (adomain = midna_domain_to_ascii(domain)) != 0) {
2986  if (msg_verbose)
2987  msg_info("%s asciified to %s", domain, adomain);
2988  domain = adomain;
2989  }
2990 #endif
2991 
2992  /*
2993  * If the request is type A or AAAA, fabricate an MX record that points
2994  * to the domain name itself, and skip name-based access control.
2995  *
2996  * If the domain name does not exist then we apply no restriction.
2997  *
2998  * If the domain name exists but no MX record exists, fabricate an MX record
2999  * that points to the domain name itself.
3000  *
3001  * If the domain name exists but no NS record exists, look up parent domain
3002  * NS records.
3003  *
3004  * XXX 20150707 Work around broken DNS servers that reply with NXDOMAIN
3005  * instead of "no data".
3006  */
3007  if (type == T_A
3008 #ifdef HAS_IPV6
3009  || type == T_AAAA
3010 #endif
3011  ) {
3012  server_list = dns_rr_create(domain, domain, T_MX, C_IN, 0, 0,
3013  domain, strlen(domain) + 1);
3014  } else {
3015  dns_status = dns_lookup(domain, type, 0, &server_list,
3016  (VSTRING *) 0, (VSTRING *) 0);
3017  if (dns_status == DNS_NULLMX)
3018  return (SMTPD_CHECK_DUNNO);
3019  if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) {
3020  if (type == T_MX) {
3021  server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
3022  domain, strlen(domain) + 1);
3023  dns_status = DNS_OK;
3024  } else if (type == T_NS /* && h_errno == NO_DATA */ ) {
3025  while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
3026  domain += 1;
3027  dns_status = dns_lookup(domain, type, 0, &server_list,
3028  (VSTRING *) 0, (VSTRING *) 0);
3029  if (dns_status != DNS_NOTFOUND /* || h_errno != NO_DATA */ )
3030  break;
3031  }
3032  }
3033  }
3034  if (dns_status != DNS_OK) {
3035  msg_warn("Unable to look up %s host for %s: %s", dns_strtype(type),
3036  domain && domain[1] ? domain : name, dns_status == DNS_POLICY ?
3037  "DNS reply filter policy" : dns_strerror(h_errno));
3038  return (SMTPD_CHECK_DUNNO);
3039  }
3040  }
3041 
3042  /*
3043  * No bare returns after this point or we have a memory leak.
3044  */
3045 #define CHECK_SERVER_RETURN(x) { dns_rr_free(server_list); return(x); }
3046 
3047  /*
3048  * Check the hostnames first, then the addresses.
3049  */
3050  proto_info = inet_proto_info();
3051  for (server = server_list; server != 0; server = server->next) {
3052  if (msg_verbose)
3053  msg_info("%s: %s hostname check: %s",
3054  myname, dns_strtype(type), (char *) server->data);
3055  if (valid_hostaddr((char *) server->data, DONT_GRIPE)) {
3056  if ((status = check_addr_access(state, table, (char *) server->data,
3057  FULL, &found, reply_name, reply_class,
3058  def_acl)) != 0 || found)
3059  CHECK_SERVER_RETURN(status);
3060  continue;
3061  }
3062  if (type != T_A && type != T_AAAA
3063  && ((status = check_domain_access(state, table, (char *) server->data,
3064  FULL, &found, reply_name, reply_class,
3065  def_acl)) != 0 || found))
3066  CHECK_SERVER_RETURN(status);
3067  if ((aierr = hostname_to_sockaddr((char *) server->data,
3068  (char *) 0, 0, &res0)) != 0) {
3069  if (type != T_A && type != T_AAAA)
3070  msg_warn("Unable to look up %s host %s for %s %s: %s",
3071  dns_strtype(type), (char *) server->data,
3072  reply_class, reply_name, MAI_STRERROR(aierr));
3073  continue;
3074  }
3075  /* Now we must also free the addrinfo result. */
3076  if (msg_verbose)
3077  msg_info("%s: %s host address check: %s",
3078  myname, dns_strtype(type), (char *) server->data);
3079  for (res = res0; res != 0; res = res->ai_next) {
3080  if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
3081  if (msg_verbose)
3082  msg_info("skipping address family %d for host %s",
3083  res->ai_family, server->data);
3084  continue;
3085  }
3086  SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
3087  &addr_string, (MAI_SERVPORT_STR *) 0, 0);
3088  status = check_addr_access(state, table, addr_string.buf, FULL,
3089  &found, reply_name, reply_class,
3090  def_acl);
3091  if (status != 0 || found) {
3092  freeaddrinfo(res0); /* 200412 */
3093  CHECK_SERVER_RETURN(status);
3094  }
3095  }
3096  freeaddrinfo(res0); /* 200412 */
3097  }
3098  CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
3099 }
3100 
3101 /* check_ccert_access - access for TLS clients by certificate fingerprint */
3102 
3103 
3104 static int check_ccert_access(SMTPD_STATE *state, const char *table,
3105  const char *def_acl)
3106 {
3107  int result = SMTPD_CHECK_DUNNO;
3108 
3109 #ifdef USE_TLS
3110  const char *myname = "check_ccert_access";
3111  int found;
3112 
3113  /*
3114  * When directly checking the fingerprint, it is OK if the issuing CA is
3115  * not trusted.
3116  */
3117  if (TLS_CERT_IS_PRESENT(state->tls_context)) {
3118  int i;
3119  char *prints[2];
3120 
3121  prints[0] = state->tls_context->peer_cert_fprint;
3122  prints[1] = state->tls_context->peer_pkey_fprint;
3123 
3124  for (i = 0; i < 2; ++i) {
3125  if (msg_verbose)
3126  msg_info("%s: %s", myname, prints[i]);
3127 
3128  /*
3129  * Regexp tables don't make sense for certificate fingerprints.
3130  * That may be so, but we can't ignore the entire
3131  * check_ccert_access request without logging a warning.
3132  *
3133  * Log the peer CommonName when access is denied. Non-printable
3134  * characters will be neutered by smtpd_check_reject(). The SMTP
3135  * client name and address are always syslogged as part of a
3136  * "reject" event.
3137  */
3138  result = check_access(state, table, prints[i],
3139  DICT_FLAG_NONE, &found,
3140  state->tls_context->peer_CN,
3141  SMTPD_NAME_CCERT, def_acl);
3142  if (result != SMTPD_CHECK_DUNNO)
3143  break;
3144  }
3145  }
3146 #endif
3147  return (result);
3148 }
3149 
3150 /* check_sasl_access - access by SASL user name */
3151 
3152 #ifdef USE_SASL_AUTH
3153 
3154 static int check_sasl_access(SMTPD_STATE *state, const char *table,
3155  const char *def_acl)
3156 {
3157  int result;
3158  int unused_found;
3159  char *sane_username = printable(mystrdup(state->sasl_username), '_');
3160 
3161  result = check_access(state, table, state->sasl_username,
3162  DICT_FLAG_NONE, &unused_found, sane_username,
3163  SMTPD_NAME_SASL_USER, def_acl);
3164  myfree(sane_username);
3165  return (result);
3166 }
3167 
3168 #endif
3169 
3170 /* check_mail_access - OK/FAIL based on mail address lookup */
3171 
3172 static int check_mail_access(SMTPD_STATE *state, const char *table,
3173  const char *addr, int *found,
3174  const char *reply_name,
3175  const char *reply_class,
3176  const char *def_acl)
3177 {
3178  const char *myname = "check_mail_access";
3179  const RESOLVE_REPLY *reply;
3180  const char *value;
3181  int lookup_strategy;
3182  int status;
3183  MAPS *maps;
3184 
3185  if (msg_verbose)
3186  msg_info("%s: %s", myname, addr);
3187 
3188  /*
3189  * Resolve the address.
3190  */
3191  reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
3192  state->recipient : state->sender, addr);
3193  if (reply->flags & RESOLVE_FLAG_FAIL)
3194  reject_dict_retry(state, addr);
3195 
3196  /*
3197  * Garbage in, garbage out. Every address from rewrite_clnt_internal()
3198  * and from resolve_clnt_query() must be fully qualified.
3199  */
3200  if (strrchr(CONST_STR(reply->recipient), '@') == 0) {
3201  msg_warn("%s: no @domain in address: %s", myname,
3202  CONST_STR(reply->recipient));
3203  return (0);
3204  }
3205 
3206  /*
3207  * Source-routed (non-local or virtual) recipient addresses are too
3208  * suspicious for returning an "OK" result. The complicated expression
3209  * below was brought to you by the keyboard of Victor Duchovni, Morgan
3210  * Stanley and hacked up a bit by Wietse.
3211  */
3212 #define SUSPICIOUS(reply, reply_class) \
3213  (var_allow_untrust_route == 0 \
3214  && (reply->flags & RESOLVE_FLAG_ROUTED) \
3215  && strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0)
3216 
3217  /*
3218  * Look up user+foo@domain if the address has an extension, user@domain
3219  * otherwise.
3220  */
3221  lookup_strategy = MA_FIND_FULL | MA_FIND_NOEXT | MA_FIND_DOMAIN
3223  | (access_parent_style == MATCH_FLAG_PARENT ?
3225 
3226  if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
3227  msg_warn("%s: unexpected dictionary: %s", myname, table);
3228  value = "451 4.3.5 Server configuration error";
3229  return (check_table_result(state, table, value,
3230  CONST_STR(reply->recipient),
3231  reply_name, reply_class,
3232  def_acl));
3233  }
3234  if ((value = mail_addr_find_strategy(maps, CONST_STR(reply->recipient),
3235  (char **) 0, lookup_strategy)) != 0) {
3236  *found = 1;
3237  status = check_table_result(state, table, value,
3238  CONST_STR(reply->recipient),
3239  reply_name, reply_class, def_acl);
3240  return (status == SMTPD_CHECK_OK && SUSPICIOUS(reply, reply_class) ?
3241  SMTPD_CHECK_DUNNO : status);
3242  } else if (maps->error != 0) {
3243  /* Warning is already logged. */
3244  value = "451 4.3.5 Server configuration error";
3245  return (check_table_result(state, table, value,
3246  CONST_STR(reply->recipient),
3247  reply_name, reply_class,
3248  def_acl));
3249  }
3250 
3251  /*
3252  * Undecided when no match found.
3253  */
3254  return (SMTPD_CHECK_DUNNO);
3255 }
3256 
3257 /* Support for different DNSXL lookup results. */
3258 
3259 static SMTPD_RBL_STATE dnsxl_stat_soft[1];
3260 
3261 #define SMTPD_DNSXL_STAT_SOFT(dnsxl_res) ((dnsxl_res) == dnsxl_stat_soft)
3262 #define SMTPD_DNXSL_STAT_HARD(dnsxl_res) ((dnsxl_res) == 0)
3263 #define SMTPD_DNSXL_STAT_OK(dnsxl_res) \
3264  !(SMTPD_DNXSL_STAT_HARD(dnsxl_res) || SMTPD_DNSXL_STAT_SOFT(dnsxl_res))
3265 
3266 /* rbl_pagein - look up an RBL lookup result */
3267 
3268 static void *rbl_pagein(const char *query, void *unused_context)
3269 {
3270  DNS_RR *txt_list;
3271  VSTRING *why;
3272  int dns_status;
3273  SMTPD_RBL_STATE *rbl = 0;
3274  DNS_RR *addr_list;
3275  DNS_RR *rr;
3276  DNS_RR *next;
3277  VSTRING *buf;
3278  int space_left;
3279 
3280  /*
3281  * Do the query. If the DNS lookup produces no definitive reply, give the
3282  * requestor the benefit of the doubt. We can't block all email simply
3283  * because an RBL server is unavailable.
3284  *
3285  * Don't do this for AAAA records. Yet.
3286  */
3287  why = vstring_alloc(10);
3288  dns_status = dns_lookup(query, T_A, 0, &addr_list, (VSTRING *) 0, why);
3289  if (dns_status != DNS_OK && dns_status != DNS_NOTFOUND) {
3290  msg_warn("%s: RBL lookup error: %s", query, STR(why));
3291  rbl = dnsxl_stat_soft;
3292  }
3293  vstring_free(why);
3294  if (dns_status != DNS_OK)
3295  return ((void *) rbl);
3296 
3297  /*
3298  * Save the result. Yes, we cache negative results as well as positive
3299  * results. Concatenate multiple TXT records, up to some limit.
3300  */
3301 #define RBL_TXT_LIMIT 500
3302 
3303  rbl = (SMTPD_RBL_STATE *) mymalloc(sizeof(*rbl));
3304  dns_status = dns_lookup(query, T_TXT, 0, &txt_list,
3305  (VSTRING *) 0, (VSTRING *) 0);
3306  if (dns_status == DNS_OK) {
3307  buf = vstring_alloc(1);
3308  space_left = RBL_TXT_LIMIT;
3309  for (rr = txt_list; rr != 0 && space_left > 0; rr = next) {
3310  vstring_strncat(buf, rr->data, (int) rr->data_len > space_left ?
3311  space_left : rr->data_len);
3312  space_left = RBL_TXT_LIMIT - VSTRING_LEN(buf);
3313  next = rr->next;
3314  if (next && space_left > 3) {
3315  vstring_strcat(buf, " / ");
3316  space_left -= 3;
3317  }
3318  }
3319  rbl->txt = vstring_export(buf);
3320  dns_rr_free(txt_list);
3321  } else {
3322  if (dns_status == DNS_POLICY)
3323  msg_warn("%s: TXT lookup error: %s",
3324  query, "DNS reply filter drops all results");
3325  rbl->txt = 0;
3326  }
3327  rbl->a = addr_list;
3328  return ((void *) rbl);
3329 }
3330 
3331 /* rbl_pageout - discard an RBL lookup result */
3332 
3333 static void rbl_pageout(void *data, void *unused_context)
3334 {
3335  SMTPD_RBL_STATE *rbl = (SMTPD_RBL_STATE *) data;
3336 
3337  if (SMTPD_DNSXL_STAT_OK(rbl)) {
3338  if (rbl->txt)
3339  myfree(rbl->txt);
3340  if (rbl->a)
3341  dns_rr_free(rbl->a);
3342  myfree((void *) rbl);
3343  }
3344 }
3345 
3346 /* rbl_byte_pagein - parse RBL reply pattern, save byte codes */
3347 
3348 static void *rbl_byte_pagein(const char *query, void *unused_context)
3349 {
3350  VSTRING *byte_codes = vstring_alloc(100);
3351  char *saved_query = mystrdup(query);
3352  char *saved_byte_codes;
3353  char *err;
3354 
3355  if ((err = ip_match_parse(byte_codes, saved_query)) != 0)
3356  msg_fatal("RBL reply error: %s", err);
3357  saved_byte_codes = ip_match_save(byte_codes);
3358  myfree(saved_query);
3359  vstring_free(byte_codes);
3360  return (saved_byte_codes);
3361 }
3362 
3363 /* rbl_byte_pageout - discard parsed RBL reply byte codes */
3364 
3365 static void rbl_byte_pageout(void *data, void *unused_context)
3366 {
3367  myfree(data);
3368 }
3369 
3370 /* rbl_expand_lookup - RBL specific $name expansion */
3371 
3372 static const char *rbl_expand_lookup(const char *name, int mode,
3373  void *context)
3374 {
3375  SMTPD_RBL_EXPAND_CONTEXT *rbl_exp = (SMTPD_RBL_EXPAND_CONTEXT *) context;
3376  SMTPD_STATE *state = rbl_exp->state;
3377 
3378 #define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
3379 
3380  if (state->expand_buf == 0)
3381  state->expand_buf = vstring_alloc(10);
3382 
3383  if (msg_verbose > 1)
3384  msg_info("rbl_expand_lookup: ${%s}", name);
3385 
3386  /*
3387  * Be sure to return NULL only for non-existent names.
3388  */
3389  if (STREQ(name, MAIL_ATTR_RBL_CODE)) {
3391  return (STR(state->expand_buf));
3392  } else if (STREQ(name, MAIL_ATTR_RBL_DOMAIN)) {
3393  return (rbl_exp->domain);
3394  } else if (STREQ(name, MAIL_ATTR_RBL_REASON)) {
3395  return (rbl_exp->txt);
3396  } else if (STREQ(name, MAIL_ATTR_RBL_TXT)) {/* LaMont compat */
3397  return (rbl_exp->txt);
3398  } else if (STREQ(name, MAIL_ATTR_RBL_WHAT)) {
3399  return (rbl_exp->what);
3400  } else if (STREQ(name, MAIL_ATTR_RBL_CLASS)) {
3401  return (rbl_exp->class);
3402  } else {
3403  return (smtpd_expand_lookup(name, mode, (void *) state));
3404  }
3405 }
3406 
3407 /* rbl_reject_reply - format reply after RBL reject */
3408 
3409 static int rbl_reject_reply(SMTPD_STATE *state, const SMTPD_RBL_STATE *rbl,
3410  const char *rbl_domain,
3411  const char *what,
3412  const char *reply_class)
3413 {
3414  const char *myname = "rbl_reject_reply";
3415  VSTRING *why = 0;
3416  const char *template = 0;
3417  SMTPD_RBL_EXPAND_CONTEXT rbl_exp;
3418  int result;
3419  DSN_SPLIT dp;
3420  int code;
3421 
3422  /*
3423  * Use the server-specific reply template or use the default one.
3424  */
3425  if (*var_rbl_reply_maps) {
3426  template = maps_find(rbl_reply_maps, rbl_domain, DICT_FLAG_NONE);
3427  if (rbl_reply_maps->error)
3428  reject_server_error(state);
3429  }
3430  why = vstring_alloc(100);
3431  rbl_exp.state = state;
3432  rbl_exp.domain = mystrdup(rbl_domain);
3433  (void) split_at(rbl_exp.domain, '=');
3434  rbl_exp.what = what;
3435  rbl_exp.class = reply_class;
3436  rbl_exp.txt = (rbl->txt == 0 ? "" : rbl->txt);
3437 
3438  for (;;) {
3439  if (template == 0)
3440  template = var_def_rbl_reply;
3441  if (mac_expand(why, template, MAC_EXP_FLAG_NONE,
3442  STR(smtpd_expand_filter), rbl_expand_lookup,
3443  (void *) &rbl_exp) == 0)
3444  break;
3445  if (template == var_def_rbl_reply)
3446  msg_fatal("%s: bad default rbl reply template: %s",
3447  myname, var_def_rbl_reply);
3448  msg_warn("%s: bad rbl reply template for domain %s: %s",
3449  myname, rbl_domain, template);
3450  template = 0; /* pretend not found */
3451  }
3452 
3453  /*
3454  * XXX Impedance mis-match.
3455  *
3456  * Validate the response, that is, the response must begin with a
3457  * three-digit status code, and the first digit must be 4 or 5. If the
3458  * response is bad, log a warning and send a generic response instead.
3459  */
3460  if ((STR(why)[0] != '4' && STR(why)[0] != '5')
3461  || !ISDIGIT(STR(why)[1]) || !ISDIGIT(STR(why)[2])
3462  || STR(why)[3] != ' ') {
3463  msg_warn("rbl response code configuration error: %s", STR(why));
3464  result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
3465  450, "4.7.1", "Service unavailable");
3466  } else {
3467  code = atoi(STR(why));
3468  dsn_split(&dp, "4.7.1", STR(why) + 4);
3469  result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
3470  code,
3472  reply_class),
3473  "%s", *dp.text ?
3474  dp.text : "Service unavailable");
3475  }
3476 
3477  /*
3478  * Clean up.
3479  */
3480  myfree(rbl_exp.domain);
3481  vstring_free(why);
3482 
3483  return (result);
3484 }
3485 
3486 /* rbl_match_addr - match address list */
3487 
3488 static int rbl_match_addr(SMTPD_RBL_STATE *rbl, const char *byte_codes)
3489 {
3490  const char *myname = "rbl_match_addr";
3491  DNS_RR *rr;
3492 
3493  for (rr = rbl->a; rr != 0; rr = rr->next) {
3494  if (rr->type == T_A) {
3495  if (ip_match_execute(byte_codes, rr->data))
3496  return (1);
3497  } else {
3498  msg_warn("%s: skipping record type %s for query %s",
3499  myname, dns_strtype(rr->type), rr->qname);
3500  }
3501  }
3502  return (0);
3503 }
3504 
3505 /* find_dnsxl_addr - look up address in DNSXL */
3506 
3507 static const SMTPD_RBL_STATE *find_dnsxl_addr(SMTPD_STATE *state,
3508  const char *rbl_domain,
3509  const char *addr)
3510 {
3511  const char *myname = "find_dnsxl_addr";
3512  ARGV *octets;
3513  VSTRING *query;
3514  int i;
3515  SMTPD_RBL_STATE *rbl;
3516  const char *reply_addr;
3517  const char *byte_codes;
3518  struct addrinfo *res;
3519  unsigned char *ipv6_addr;
3520 
3521  query = vstring_alloc(100);
3522 
3523  /*
3524  * Reverse the client IPV6 address, represented as 32 hexadecimal
3525  * nibbles. We use the binary address to avoid tricky code. Asking for an
3526  * AAAA record makes no sense here. Just like with IPv4 we use the lookup
3527  * result as a bit mask, not as an IP address.
3528  */
3529 #ifdef HAS_IPV6
3530  if (valid_ipv6_hostaddr(addr, DONT_GRIPE)) {
3531  if (hostaddr_to_sockaddr(addr, (char *) 0, 0, &res) != 0
3532  || res->ai_family != PF_INET6)
3533  msg_fatal("%s: unable to convert address %s", myname, addr);
3534  ipv6_addr = (unsigned char *) &SOCK_ADDR_IN6_ADDR(res->ai_addr);
3535  for (i = sizeof(SOCK_ADDR_IN6_ADDR(res->ai_addr)) - 1; i >= 0; i--)
3536  vstring_sprintf_append(query, "%x.%x.",
3537  ipv6_addr[i] & 0xf, ipv6_addr[i] >> 4);
3538  freeaddrinfo(res);
3539  } else
3540 #endif
3541 
3542  /*
3543  * Reverse the client IPV4 address, represented as four decimal octet
3544  * values. We use the textual address for convenience.
3545  */
3546  {
3547  octets = argv_split(addr, ".");
3548  for (i = octets->argc - 1; i >= 0; i--) {
3549  vstring_strcat(query, octets->argv[i]);
3550  vstring_strcat(query, ".");
3551  }
3552  argv_free(octets);
3553  }
3554 
3555  /*
3556  * Tack on the RBL domain name and query the DNS for an A record.
3557  */
3558  vstring_strcat(query, rbl_domain);
3559  reply_addr = split_at(STR(query), '=');
3560  rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query));
3561  if (reply_addr != 0)
3562  byte_codes = ctable_locate(smtpd_rbl_byte_cache, reply_addr);
3563 
3564  /*
3565  * If the record exists, match the result address.
3566  */
3567  if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0
3568  && !rbl_match_addr(rbl, byte_codes))
3569  rbl = 0;
3570  vstring_free(query);
3571  return (rbl);
3572 }
3573 
3574 /* reject_rbl_addr - reject address in real-time blackhole list */
3575 
3576 static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain,
3577  const char *addr, const char *reply_class)
3578 {
3579  const char *myname = "reject_rbl_addr";
3580  const SMTPD_RBL_STATE *rbl;
3581 
3582  if (msg_verbose)
3583  msg_info("%s: %s %s", myname, reply_class, addr);
3584 
3585  rbl = find_dnsxl_addr(state, rbl_domain, addr);
3586  if (!SMTPD_DNSXL_STAT_OK(rbl)) {
3587  return (SMTPD_CHECK_DUNNO);
3588  } else {
3589  return (rbl_reject_reply(state, rbl, rbl_domain, addr, reply_class));
3590  }
3591 }
3592 
3593 /* permit_dnswl_addr - permit address in DNSWL */
3594 
3595 static int permit_dnswl_addr(SMTPD_STATE *state, const char *dnswl_domain,
3596  const char *addr, const char *reply_class)
3597 {
3598  const char *myname = "permit_dnswl_addr";
3599  const SMTPD_RBL_STATE *dnswl_result;
3600 
3601  if (msg_verbose)
3602  msg_info("%s: %s", myname, addr);
3603 
3604  /* Safety: don't whitelist unauthorized recipients. */
3605  if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0
3606  && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK)
3607  return (SMTPD_CHECK_DUNNO);
3608 
3609  dnswl_result = find_dnsxl_addr(state, dnswl_domain, addr);
3610  if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) {
3611  return (SMTPD_CHECK_DUNNO);
3612  } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) {
3613  /* XXX: Make configurable as dnswl_tempfail_action. */
3615  450, "4.7.1",
3616  "<%s>: %s rejected: %s",
3617  addr, reply_class,
3618  "Service unavailable");
3619  return (SMTPD_CHECK_DUNNO);
3620  } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) {
3621  return (SMTPD_CHECK_OK);
3622  } else {
3623  /* Future proofing, in case find_dnsxl_addr() result is changed. */
3624  msg_panic("%s: find_dnsxl_addr API failure", myname);
3625  }
3626 }
3627 
3628 /* find_dnsxl_domain - reject if domain in real-time blackhole list */
3629 
3630 static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state,
3631  const char *rbl_domain, const char *what)
3632 {
3633  VSTRING *query;
3634  SMTPD_RBL_STATE *rbl;
3635  const char *domain;
3636  const char *reply_addr;
3637  const char *byte_codes;
3638  const char *suffix;
3639  const char *adomain;
3640 
3641  /*
3642  * Extract the domain, tack on the RBL domain name and query the DNS for
3643  * an A record.
3644  */
3645  if ((domain = strrchr(what, '@')) != 0) {
3646  domain += 1;
3647  if (domain[0] == '[')
3648  return (SMTPD_CHECK_DUNNO);
3649  } else
3650  domain = what;
3651 
3652  /*
3653  * XXX Some Spamhaus RHSBL rejects lookups with "No IP queries" even if
3654  * the name has an alphanumerical prefix. We play safe, and skip both
3655  * RHSBL and RHSWL queries for names ending in a numerical suffix.
3656  */
3657  if (domain[0] == 0)
3658  return (SMTPD_CHECK_DUNNO);
3659  suffix = strrchr(domain, '.');
3660  if (alldig(suffix == 0 ? domain : suffix + 1))
3661  return (SMTPD_CHECK_DUNNO);
3662 
3663  /*
3664  * Fix 20140706: convert domain to ASCII.
3665  */
3666 #ifndef NO_EAI
3667  if (!allascii(domain) && (adomain = midna_domain_to_ascii(domain)) != 0) {
3668  if (msg_verbose)
3669  msg_info("%s asciified to %s", domain, adomain);
3670  domain = adomain;
3671  }
3672 #endif
3673  if (domain[0] == 0 || valid_hostname(domain, DONT_GRIPE) == 0)
3674  return (SMTPD_CHECK_DUNNO);
3675 
3676  query = vstring_alloc(100);
3677  vstring_sprintf(query, "%s.%s", domain, rbl_domain);
3678  reply_addr = split_at(STR(query), '=');
3679  rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query));
3680  if (reply_addr != 0)
3681  byte_codes = ctable_locate(smtpd_rbl_byte_cache, reply_addr);
3682 
3683  /*
3684  * If the record exists, match the result address.
3685  */
3686  if (SMTPD_DNSXL_STAT_OK(rbl) && reply_addr != 0
3687  && !rbl_match_addr(rbl, byte_codes))
3688  rbl = 0;
3689  vstring_free(query);
3690  return (rbl);
3691 }
3692 
3693 /* reject_rbl_domain - reject if domain in real-time blackhole list */
3694 
3695 static int reject_rbl_domain(SMTPD_STATE *state, const char *rbl_domain,
3696  const char *what, const char *reply_class)
3697 {
3698  const char *myname = "reject_rbl_domain";
3699  const SMTPD_RBL_STATE *rbl;
3700 
3701  if (msg_verbose)
3702  msg_info("%s: %s %s", myname, rbl_domain, what);
3703 
3704  rbl = find_dnsxl_domain(state, rbl_domain, what);
3705  if (!SMTPD_DNSXL_STAT_OK(rbl)) {
3706  return (SMTPD_CHECK_DUNNO);
3707  } else {
3708  return (rbl_reject_reply(state, rbl, rbl_domain, what, reply_class));
3709  }
3710 }
3711 
3712 /* permit_dnswl_domain - permit domain in DNSWL */
3713 
3714 static int permit_dnswl_domain(SMTPD_STATE *state, const char *dnswl_domain,
3715  const char *what, const char *reply_class)
3716 {
3717  const char *myname = "permit_dnswl_domain";
3718  const SMTPD_RBL_STATE *dnswl_result;
3719 
3720  if (msg_verbose)
3721  msg_info("%s: %s", myname, what);
3722 
3723  /* Safety: don't whitelist unauthorized recipients. */
3724  if (strcmp(state->where, SMTPD_CMD_RCPT) == 0 && state->recipient != 0
3725  && permit_auth_destination(state, state->recipient) != SMTPD_CHECK_OK)
3726  return (SMTPD_CHECK_DUNNO);
3727 
3728  dnswl_result = find_dnsxl_domain(state, dnswl_domain, what);
3729  if (SMTPD_DNXSL_STAT_HARD(dnswl_result)) {
3730  return (SMTPD_CHECK_DUNNO);
3731  } else if (SMTPD_DNSXL_STAT_SOFT(dnswl_result)) {
3732  /* XXX: Make configurable as rhswl_tempfail_action. */
3734  450, "4.7.1",
3735  "<%s>: %s rejected: %s",
3736  what, reply_class,
3737  "Service unavailable");
3738  return (SMTPD_CHECK_DUNNO);
3739  } else if (SMTPD_DNSXL_STAT_OK(dnswl_result)) {
3740  return (SMTPD_CHECK_OK);
3741  } else {
3742  /* Future proofing, in case find_dnsxl_addr() result is changed. */
3743  msg_panic("%s: find_dnsxl_addr API failure", myname);
3744  }
3745 }
3746 
3747 /* reject_maps_rbl - reject if client address in real-time blackhole list */
3748 
3749 static int reject_maps_rbl(SMTPD_STATE *state)
3750 {
3751  const char *myname = "reject_maps_rbl";
3752  char *saved_domains = mystrdup(var_maps_rbl_domains);
3753  char *bp = saved_domains;
3754  char *rbl_domain;
3755  int result = SMTPD_CHECK_DUNNO;
3756  static int warned;
3757 
3758  if (msg_verbose)
3759  msg_info("%s: %s", myname, state->addr);
3760 
3761  if (warned == 0) {
3762  warned++;
3763  msg_warn("support for restriction \"%s\" will be removed from %s; "
3764  "use \"%s domain-name\" instead",
3766  }
3767  while ((rbl_domain = mystrtok(&bp, CHARS_COMMA_SP)) != 0) {
3768  result = reject_rbl_addr(state, rbl_domain, state->addr,
3770  if (result != SMTPD_CHECK_DUNNO)
3771  break;
3772  }
3773 
3774  /*
3775  * Clean up.
3776  */
3777  myfree(saved_domains);
3778 
3779  return (result);
3780 }
3781 
3782 #ifdef USE_SASL_AUTH
3783 
3784 /* reject_auth_sender_login_mismatch - logged in client must own sender address */
3785 
3786 static int reject_auth_sender_login_mismatch(SMTPD_STATE *state, const char *sender, int allow_unknown_sender)
3787 {
3788  const RESOLVE_REPLY *reply;
3789  const char *owners;
3790  char *saved_owners;
3791  char *cp;
3792  char *name;
3793  int found = 0;
3794 
3795 #define ALLOW_UNKNOWN_SENDER 1
3796 #define FORBID_UNKNOWN_SENDER 0
3797 
3798  /*
3799  * Reject if the client is logged in and does not own the sender address.
3800  */
3801  if (smtpd_sender_login_maps && state->sasl_username) {
3802  reply = smtpd_resolve_addr(state->recipient, sender);
3803  if (reply->flags & RESOLVE_FLAG_FAIL)
3804  reject_dict_retry(state, sender);
3805  if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps,
3806  STR(reply->recipient), (char **) 0)) != 0) {
3807  cp = saved_owners = mystrdup(owners);
3808  while ((name = mystrtok(&cp, CHARS_COMMA_SP)) != 0) {
3809  if (strcasecmp_utf8(state->sasl_username, name) == 0) {
3810  found = 1;
3811  break;
3812  }
3813  }
3814  myfree(saved_owners);
3815  } else if (allow_unknown_sender)
3816  return (SMTPD_CHECK_DUNNO);
3817  if (!found)
3818  return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 553, "5.7.1",
3819  "<%s>: Sender address rejected: not owned by user %s",
3820  sender, state->sasl_username));
3821  }
3822  return (SMTPD_CHECK_DUNNO);
3823 }
3824 
3825 /* reject_unauth_sender_login_mismatch - sender requires client is logged in */
3826 
3827 static int reject_unauth_sender_login_mismatch(SMTPD_STATE *state, const char *sender)
3828 {
3829  const RESOLVE_REPLY *reply;
3830 
3831  /*
3832  * Reject if the client is not logged in and the sender address has an
3833  * owner.
3834  */
3835  if (smtpd_sender_login_maps && !state->sasl_username) {
3836  reply = smtpd_resolve_addr(state->recipient, sender);
3837  if (reply->flags & RESOLVE_FLAG_FAIL)
3838  reject_dict_retry(state, sender);
3839  if (check_mail_addr_find(state, sender, smtpd_sender_login_maps,
3840  STR(reply->recipient), (char **) 0) != 0)
3841  return (smtpd_check_reject(state, MAIL_ERROR_POLICY, 553, "5.7.1",
3842  "<%s>: Sender address rejected: not logged in", sender));
3843  }
3844  return (SMTPD_CHECK_DUNNO);
3845 }
3846 
3847 #endif
3848 
3849 /* valid_utf8_action - validate UTF-8 policy server response */
3850 
3851 static int valid_utf8_action(const char *server, const char *action)
3852 {
3853  int retval;
3854 
3855  if ((retval = valid_utf8_string(action, strlen(action))) == 0)
3856  msg_warn("malformed UTF-8 in policy server %s response: \"%s\"",
3857  server, action);
3858  return (retval);
3859 }
3860 
3861 /* check_policy_service - check delegated policy service */
3862 
3863 static int check_policy_service(SMTPD_STATE *state, const char *server,
3864  const char *reply_name, const char *reply_class,
3865  const char *def_acl)
3866 {
3867  static VSTRING *action = 0;
3868  SMTPD_POLICY_CLNT *policy_clnt;
3869 
3870 #ifdef USE_TLS
3871  VSTRING *subject_buf;
3872  VSTRING *issuer_buf;
3873  const char *subject;
3874  const char *issuer;
3875 
3876 #endif
3877  int ret;
3878 
3879  /*
3880  * Sanity check.
3881  */
3882  if (!policy_clnt_table
3883  || (policy_clnt = (SMTPD_POLICY_CLNT *)
3884  htable_find(policy_clnt_table, server)) == 0)
3885  msg_panic("check_policy_service: no client endpoint for server %s",
3886  server);
3887 
3888  /*
3889  * Initialize.
3890  */
3891  if (action == 0)
3892  action = vstring_alloc(10);
3893 
3894 #ifdef USE_TLS
3895 #define ENCODE_CN(coded_CN, coded_CN_buf, CN) do { \
3896  if (!TLS_CERT_IS_TRUSTED(state->tls_context) || *(CN) == 0) { \
3897  coded_CN_buf = 0; \
3898  coded_CN = ""; \
3899  } else { \
3900  coded_CN_buf = vstring_alloc(strlen(CN) + 1); \
3901  xtext_quote(coded_CN_buf, CN, ""); \
3902  coded_CN = STR(coded_CN_buf); \
3903  } \
3904  } while (0);
3905 
3906  ENCODE_CN(subject, subject_buf, state->tls_context->peer_CN);
3907  ENCODE_CN(issuer, issuer_buf, state->tls_context->issuer_CN);
3908 #endif
3909 
3910  if (attr_clnt_request(policy_clnt->client,
3911  ATTR_FLAG_NONE, /* Query attributes. */
3912  SEND_ATTR_STR(MAIL_ATTR_REQ, "smtpd_access_policy"),
3919  state->reverse_name),
3921  state->dest_addr),
3923  state->dest_port),
3925  state->helo_name ? state->helo_name : ""),
3927  state->sender ? state->sender : ""),
3929  state->recipient ? state->recipient : ""),
3931  ((strcasecmp(state->where, SMTPD_CMD_DATA) == 0) ||
3932  (strcasecmp(state->where, SMTPD_AFTER_DOT) == 0)) ?
3933  state->rcpt_count : 0),
3935  state->queue_id ? state->queue_id : ""),
3937  STR(state->instance)),
3939  (unsigned long) (state->act_size > 0 ?
3940  state->act_size : state->msg_size)),
3942  state->etrn_name ? state->etrn_name : ""),
3944 #ifdef USE_SASL_AUTH
3946  state->sasl_method ? state->sasl_method : ""),
3948  state->sasl_username ? state->sasl_username : ""),
3950  state->sasl_sender ? state->sasl_sender : ""),
3951 #endif
3952 #ifdef USE_TLS
3953 #define IF_ENCRYPTED(x, y) ((state->tls_context && ((x) != 0)) ? (x) : (y))
3956 
3957  /*
3958  * When directly checking the fingerprint, it is OK if the issuing CA is
3959  * not trusted.
3960  */
3962  IF_ENCRYPTED(state->tls_context->peer_cert_fprint, "")),
3964  IF_ENCRYPTED(state->tls_context->peer_pkey_fprint, "")),
3966  IF_ENCRYPTED(state->tls_context->protocol, "")),
3968  IF_ENCRYPTED(state->tls_context->cipher_name, "")),
3970  IF_ENCRYPTED(state->tls_context->cipher_usebits, 0)),
3971 #endif
3973  policy_clnt->policy_context),
3974  ATTR_TYPE_END,
3975  ATTR_FLAG_MISSING, /* Reply attributes. */
3977  ATTR_TYPE_END) != 1
3978  || (var_smtputf8_enable && valid_utf8_action(server, STR(action)) == 0)) {
3979  NOCLOBBER static int nesting_level = 0;
3980  jmp_buf savebuf;
3981  int status;
3982 
3983  /*
3984  * Safety to prevent recursive execution of the default action.
3985  */
3986  nesting_level += 1;
3987  memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf));
3988  status = setjmp(smtpd_check_buf);
3989  if (status != 0) {
3990  nesting_level -= 1;
3991  memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf),
3992  sizeof(smtpd_check_buf));
3993  longjmp(smtpd_check_buf, status);
3994  }
3995  ret = check_table_result(state, server, nesting_level == 1 ?
3996  policy_clnt->def_action :
3998  "policy query", reply_name,
3999  reply_class, def_acl);
4000  nesting_level -= 1;
4001  memcpy(ADDROF(smtpd_check_buf), ADDROF(savebuf),
4002  sizeof(smtpd_check_buf));
4003  } else {
4004 
4005  /*
4006  * XXX This produces bogus error messages when the reply is
4007  * malformed.
4008  */
4009  ret = check_table_result(state, server, STR(action),
4010  "policy query", reply_name,
4011  reply_class, def_acl);
4012  }
4013 #ifdef USE_TLS
4014  if (subject_buf)
4015  vstring_free(subject_buf);
4016  if (issuer_buf)
4017  vstring_free(issuer_buf);
4018 #endif
4019  return (ret);
4020 }
4021 
4022 /* is_map_command - restriction has form: check_xxx_access type:name */
4023 
4024 static int is_map_command(SMTPD_STATE *state, const char *name,
4025  const char *command, char ***argp)
4026 {
4027 
4028  /*
4029  * This is a three-valued function: (a) this is not a check_xxx_access
4030  * command, (b) this is a malformed check_xxx_access command, (c) this is
4031  * a well-formed check_xxx_access command. That's too clumsy for function
4032  * result values, so we use regular returns for (a) and (c), and use long
4033  * jumps for the error case (b).
4034  */
4035  if (strcasecmp(name, command) != 0) {
4036  return (0);
4037  } else if (*(*argp + 1) == 0 || strchr(*(*argp += 1), ':') == 0) {
4038  msg_warn("restriction %s: bad argument \"%s\": need maptype:mapname",
4039  command, **argp);
4040  reject_server_error(state);
4041  } else {
4042  return (1);
4043  }
4044 }
4045 
4046 /* forbid_whitelist - disallow whitelisting */
4047 
4048 static void forbid_whitelist(SMTPD_STATE *state, const char *name,
4049  int status, const char *target)
4050 {
4051  if (state->discard == 0 && status == SMTPD_CHECK_OK) {
4052  msg_warn("restriction %s returns OK for %s", name, target);
4053  msg_warn("this is not allowed for security reasons");
4054  msg_warn("use DUNNO instead of OK if you want to make an exception");
4055  reject_server_error(state);
4056  }
4057 }
4058 
4059 /* generic_checks - generic restrictions */
4060 
4061 static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
4062  const char *reply_name,
4063  const char *reply_class,
4064  const char *def_acl)
4065 {
4066  const char *myname = "generic_checks";
4067  char **cpp;
4068  const char *name;
4069  int status = 0;
4070  ARGV *list;
4071  int found;
4072  int saved_recursion = state->recursion++;
4073 
4074  if (msg_verbose)
4075  msg_info(">>> START %s RESTRICTIONS <<<", reply_class);
4076 
4077  for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) {
4078 
4079  if (state->discard != 0)
4080  break;
4081 
4082  if (msg_verbose)
4083  msg_info("%s: name=%s", myname, name);
4084 
4085  /*
4086  * Pseudo restrictions.
4087  */
4088  if (strcasecmp(name, WARN_IF_REJECT) == 0) {
4089  if (state->warn_if_reject == 0)
4090  state->warn_if_reject = state->recursion;
4091  continue;
4092  }
4093 
4094  /*
4095  * Spoof the is_map_command() routine, so that we do not have to make
4096  * special cases for the implicit short-hand access map notation.
4097  */
4098 #define NO_DEF_ACL 0
4099 
4100  if (strchr(name, ':') != 0) {
4101  if (def_acl == NO_DEF_ACL) {
4102  msg_warn("specify one of (%s, %s, %s, %s, %s, %s) before %s restriction \"%s\"",
4104  CHECK_RECIP_ACL, CHECK_ETRN_ACL, reply_class, name);
4105  reject_server_error(state);
4106  }
4107  name = def_acl;
4108  cpp -= 1;
4109  }
4110 
4111  /*
4112  * Generic restrictions.
4113  */
4114  if (strcasecmp(name, PERMIT_ALL) == 0) {
4115  status = smtpd_acl_permit(state, name, reply_class,
4116  reply_name, NO_PRINT_ARGS);
4117  if (status == SMTPD_CHECK_OK && cpp[1] != 0)
4118  msg_warn("restriction `%s' after `%s' is ignored",
4119  cpp[1], PERMIT_ALL);
4120  } else if (strcasecmp(name, DEFER_ALL) == 0) {
4121  status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
4122  var_defer_code, "4.3.2",
4123  "<%s>: %s rejected: Try again later",
4124  reply_name, reply_class);
4125  if (cpp[1] != 0 && state->warn_if_reject == 0)
4126  msg_warn("restriction `%s' after `%s' is ignored",
4127  cpp[1], DEFER_ALL);
4128  } else if (strcasecmp(name, REJECT_ALL) == 0) {
4129  status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
4130  var_reject_code, "5.7.1",
4131  "<%s>: %s rejected: Access denied",
4132  reply_name, reply_class);
4133  if (cpp[1] != 0 && state->warn_if_reject == 0)
4134  msg_warn("restriction `%s' after `%s' is ignored",
4135  cpp[1], REJECT_ALL);
4136  } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) {
4137  status = reject_unauth_pipelining(state, reply_name, reply_class);
4138  } else if (strcasecmp(name, CHECK_POLICY_SERVICE) == 0) {
4139  if (cpp[1] == 0 || strchr(cpp[1], ':') == 0) {
4140  msg_warn("restriction %s must be followed by transport:server",
4142  reject_server_error(state);
4143  } else
4144  status = check_policy_service(state, *++cpp, reply_name,
4145  reply_class, def_acl);
4146  } else if (strcasecmp(name, DEFER_IF_PERMIT) == 0) {
4148  state, MAIL_ERROR_POLICY,
4149  450, "4.7.0",
4150  "<%s>: %s rejected: defer_if_permit requested",
4151  reply_name, reply_class);
4152  } else if (strcasecmp(name, DEFER_IF_REJECT) == 0) {
4154  450, "4.7.0",
4155  "<%s>: %s rejected: defer_if_reject requested",
4156  reply_name, reply_class);
4157  } else if (strcasecmp(name, SLEEP) == 0) {
4158  if (cpp[1] == 0 || alldig(cpp[1]) == 0) {
4159  msg_warn("restriction %s must be followed by number", SLEEP);
4160  reject_server_error(state);
4161  } else
4162  sleep(atoi(*++cpp));
4163  } else if (strcasecmp(name, REJECT_PLAINTEXT_SESSION) == 0) {
4164  status = reject_plaintext_session(state);
4165  }
4166 
4167  /*
4168  * Client name/address restrictions.
4169  */
4170  else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT_HOSTNAME) == 0
4171  || strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
4172  status = reject_unknown_client(state);
4173  } else if (strcasecmp(name, REJECT_UNKNOWN_REVERSE_HOSTNAME) == 0) {
4174  status = reject_unknown_reverse_name(state);
4175  } else if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) {
4176  status = permit_inet_interfaces(state);
4177  if (status == SMTPD_CHECK_OK)
4178  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4179  state->namaddr, NO_PRINT_ARGS);
4180  } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
4181  status = permit_mynetworks(state);
4182  if (status == SMTPD_CHECK_OK)
4183  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4184  state->namaddr, NO_PRINT_ARGS);
4185  } else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) {
4186  status = check_namadr_access(state, *cpp, state->name, state->addr,
4187  FULL, &found, state->namaddr,
4188  SMTPD_NAME_CLIENT, def_acl);
4189  } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_ACL, &cpp)) {
4190  status = check_namadr_access(state, *cpp, state->reverse_name, state->addr,
4191  FULL, &found, state->reverse_name,
4192  SMTPD_NAME_REV_CLIENT, def_acl);
4193  forbid_whitelist(state, name, status, state->reverse_name);
4194  } else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
4195  status = reject_maps_rbl(state);
4196  } else if (strcasecmp(name, REJECT_RBL_CLIENT) == 0
4197  || strcasecmp(name, REJECT_RBL) == 0) {
4198  if (cpp[1] == 0)
4199  msg_warn("restriction %s requires domain name argument", name);
4200  else
4201  status = reject_rbl_addr(state, *(cpp += 1), state->addr,
4203  } else if (strcasecmp(name, PERMIT_DNSWL_CLIENT) == 0) {
4204  if (cpp[1] == 0)
4205  msg_warn("restriction %s requires domain name argument", name);
4206  else {
4207  status = permit_dnswl_addr(state, *(cpp += 1), state->addr,
4209  if (status == SMTPD_CHECK_OK)
4210  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4211  state->namaddr, NO_PRINT_ARGS);
4212  }
4213  } else if (strcasecmp(name, REJECT_RHSBL_CLIENT) == 0) {
4214  if (cpp[1] == 0)
4215  msg_warn("restriction %s requires domain name argument",
4216  name);
4217  else {
4218  cpp += 1;
4219  if (strcasecmp(state->name, "unknown") != 0)
4220  status = reject_rbl_domain(state, *cpp, state->name,
4222  }
4223  } else if (strcasecmp(name, PERMIT_RHSWL_CLIENT) == 0) {
4224  if (cpp[1] == 0)
4225  msg_warn("restriction %s requires domain name argument",
4226  name);
4227  else {
4228  cpp += 1;
4229  if (strcasecmp(state->name, "unknown") != 0) {
4230  status = permit_dnswl_domain(state, *cpp, state->name,
4232  if (status == SMTPD_CHECK_OK)
4233  status = smtpd_acl_permit(state, name,
4235  }
4236  }
4237  } else if (strcasecmp(name, REJECT_RHSBL_REVERSE_CLIENT) == 0) {
4238  if (cpp[1] == 0)
4239  msg_warn("restriction %s requires domain name argument",
4240  name);
4241  else {
4242  cpp += 1;
4243  if (strcasecmp(state->reverse_name, "unknown") != 0)
4244  status = reject_rbl_domain(state, *cpp, state->reverse_name,
4246  }
4247  } else if (is_map_command(state, name, CHECK_CCERT_ACL, &cpp)) {
4248  status = check_ccert_access(state, *cpp, def_acl);
4249 #ifdef USE_SASL_AUTH
4250  } else if (is_map_command(state, name, CHECK_SASL_ACL, &cpp)) {
4251  if (var_smtpd_sasl_enable) {
4252  if (state->sasl_username && state->sasl_username[0])
4253  status = check_sasl_access(state, *cpp, def_acl);
4254  } else
4255 #endif
4256  msg_warn("restriction `%s' ignored: no SASL support", name);
4257  } else if (is_map_command(state, name, CHECK_CLIENT_NS_ACL, &cpp)) {
4258  if (strcasecmp(state->name, "unknown") != 0) {
4259  status = check_server_access(state, *cpp, state->name,
4260  T_NS, state->namaddr,
4261  SMTPD_NAME_CLIENT, def_acl);
4262  forbid_whitelist(state, name, status, state->name);
4263  }
4264  } else if (is_map_command(state, name, CHECK_CLIENT_MX_ACL, &cpp)) {
4265  if (strcasecmp(state->name, "unknown") != 0) {
4266  status = check_server_access(state, *cpp, state->name,
4267  T_MX, state->namaddr,
4268  SMTPD_NAME_CLIENT, def_acl);
4269  forbid_whitelist(state, name, status, state->name);
4270  }
4271  } else if (is_map_command(state, name, CHECK_CLIENT_A_ACL, &cpp)) {
4272  if (strcasecmp(state->name, "unknown") != 0) {
4273  status = check_server_access(state, *cpp, state->name,
4274  T_A, state->namaddr,
4275  SMTPD_NAME_CLIENT, def_acl);
4276  forbid_whitelist(state, name, status, state->name);
4277  }
4278  } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_NS_ACL, &cpp)) {
4279  if (strcasecmp(state->reverse_name, "unknown") != 0) {
4280  status = check_server_access(state, *cpp, state->reverse_name,
4281  T_NS, state->reverse_name,
4282  SMTPD_NAME_REV_CLIENT, def_acl);
4283  forbid_whitelist(state, name, status, state->reverse_name);
4284  }
4285  } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_MX_ACL, &cpp)) {
4286  if (strcasecmp(state->reverse_name, "unknown") != 0) {
4287  status = check_server_access(state, *cpp, state->reverse_name,
4288  T_MX, state->reverse_name,
4289  SMTPD_NAME_REV_CLIENT, def_acl);
4290  forbid_whitelist(state, name, status, state->reverse_name);
4291  }
4292  } else if (is_map_command(state, name, CHECK_REVERSE_CLIENT_A_ACL, &cpp)) {
4293  if (strcasecmp(state->reverse_name, "unknown") != 0) {
4294  status = check_server_access(state, *cpp, state->reverse_name,
4295  T_A, state->reverse_name,
4296  SMTPD_NAME_REV_CLIENT, def_acl);
4297  forbid_whitelist(state, name, status, state->reverse_name);
4298  }
4299  }
4300 
4301  /*
4302  * HELO/EHLO parameter restrictions.
4303  */
4304  else if (is_map_command(state, name, CHECK_HELO_ACL, &cpp)) {
4305  if (state->helo_name)
4306  status = check_domain_access(state, *cpp, state->helo_name,
4307  FULL, &found, state->helo_name,
4308  SMTPD_NAME_HELO, def_acl);
4309  } else if (strcasecmp(name, REJECT_INVALID_HELO_HOSTNAME) == 0
4310  || strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
4311  if (state->helo_name) {
4312  if (*state->helo_name != '[')
4313  status = reject_invalid_hostname(state, state->helo_name,
4314  state->helo_name, SMTPD_NAME_HELO);
4315  else
4316  status = reject_invalid_hostaddr(state, state->helo_name,
4317  state->helo_name, SMTPD_NAME_HELO);
4318  }
4319  } else if (strcasecmp(name, REJECT_UNKNOWN_HELO_HOSTNAME) == 0
4320  || strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
4321  if (state->helo_name) {
4322  if (*state->helo_name != '[')
4323  status = reject_unknown_hostname(state, state->helo_name,
4324  state->helo_name, SMTPD_NAME_HELO);
4325  else
4326  status = reject_invalid_hostaddr(state, state->helo_name,
4327  state->helo_name, SMTPD_NAME_HELO);
4328  }
4329  } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
4330  msg_warn("restriction %s is deprecated. Use %s or %s instead",
4332  if (state->helo_name) {
4333  if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0
4334  && (status = reject_invalid_hostaddr(state, state->helo_name,
4335  state->helo_name, SMTPD_NAME_HELO)) == 0)
4336  status = smtpd_acl_permit(state, name, SMTPD_NAME_HELO,
4337  state->helo_name, NO_PRINT_ARGS);
4338  }
4339  } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) {
4340  if (state->helo_name) {
4341  status = check_server_access(state, *cpp, state->helo_name,
4342  T_NS, state->helo_name,
4343  SMTPD_NAME_HELO, def_acl);
4344  forbid_whitelist(state, name, status, state->helo_name);
4345  }
4346  } else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) {
4347  if (state->helo_name) {
4348  status = check_server_access(state, *cpp, state->helo_name,
4349  T_MX, state->helo_name,
4350  SMTPD_NAME_HELO, def_acl);
4351  forbid_whitelist(state, name, status, state->helo_name);
4352  }
4353  } else if (is_map_command(state, name, CHECK_HELO_A_ACL, &cpp)) {
4354  if (state->helo_name) {
4355  status = check_server_access(state, *cpp, state->helo_name,
4356  T_A, state->helo_name,
4357  SMTPD_NAME_HELO, def_acl);
4358  forbid_whitelist(state, name, status, state->helo_name);
4359  }
4360  } else if (strcasecmp(name, REJECT_NON_FQDN_HELO_HOSTNAME) == 0
4361  || strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
4362  if (state->helo_name) {
4363  if (*state->helo_name != '[')
4364  status = reject_non_fqdn_hostname(state, state->helo_name,
4365  state->helo_name, SMTPD_NAME_HELO);
4366  else
4367  status = reject_invalid_hostaddr(state, state->helo_name,
4368  state->helo_name, SMTPD_NAME_HELO);
4369  }
4370  } else if (strcasecmp(name, REJECT_RHSBL_HELO) == 0) {
4371  if (cpp[1] == 0)
4372  msg_warn("restriction %s requires domain name argument",
4373  name);
4374  else {
4375  cpp += 1;
4376  if (state->helo_name)
4377  status = reject_rbl_domain(state, *cpp, state->helo_name,
4378  SMTPD_NAME_HELO);
4379  }
4380  }
4381 
4382  /*
4383  * Sender mail address restrictions.
4384  */
4385  else if (is_map_command(state, name, CHECK_SENDER_ACL, &cpp)) {
4386  if (state->sender && *state->sender)
4387  status = check_mail_access(state, *cpp, state->sender,
4388  &found, state->sender,
4389  SMTPD_NAME_SENDER, def_acl);
4390  if (state->sender && !*state->sender)
4391  status = check_access(state, *cpp, var_smtpd_null_key, FULL,
4392  &found, state->sender,
4393  SMTPD_NAME_SENDER, def_acl);
4394  } else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
4395  if (state->sender && *state->sender)
4396  status = reject_unknown_address(state, state->sender,
4397  state->sender, SMTPD_NAME_SENDER);
4398  } else if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) {
4399  if (state->sender && *state->sender)
4400  status = reject_unknown_address(state, state->sender,
4401  state->sender, SMTPD_NAME_SENDER);
4402  } else if (strcasecmp(name, REJECT_UNVERIFIED_SENDER) == 0) {
4403  if (state->sender && *state->sender)
4404  status = reject_unverified_address(state, state->sender,
4405  state->sender, SMTPD_NAME_SENDER,
4407  unv_from_tf_act,
4409  } else if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
4410  if (state->sender && *state->sender)
4411  status = reject_non_fqdn_address(state, state->sender,
4412  state->sender, SMTPD_NAME_SENDER);
4413  } else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) {
4414 #ifdef USE_SASL_AUTH
4415  if (var_smtpd_sasl_enable) {
4416  if (state->sender && *state->sender)
4417  status = reject_auth_sender_login_mismatch(state,
4418  state->sender, FORBID_UNKNOWN_SENDER);
4419  } else
4420 #endif
4421  msg_warn("restriction `%s' ignored: no SASL support", name);
4422  } else if (strcasecmp(name, REJECT_KNOWN_SENDER_LOGIN_MISMATCH) == 0) {
4423 #ifdef USE_SASL_AUTH
4424  if (var_smtpd_sasl_enable) {
4425  if (state->sender && *state->sender) {
4426  if (state->sasl_username)
4427  status = reject_auth_sender_login_mismatch(state,
4428  state->sender, ALLOW_UNKNOWN_SENDER);
4429  else
4430  status = reject_unauth_sender_login_mismatch(state, state->sender);
4431  }
4432  } else
4433 #endif
4434  msg_warn("restriction `%s' ignored: no SASL support", name);
4435  } else if (strcasecmp(name, REJECT_UNAUTH_SENDER_LOGIN_MISMATCH) == 0) {
4436 #ifdef USE_SASL_AUTH
4437  if (var_smtpd_sasl_enable) {
4438  if (state->sender && *state->sender)
4439  status = reject_unauth_sender_login_mismatch(state, state->sender);
4440  } else
4441 #endif
4442  msg_warn("restriction `%s' ignored: no SASL support", name);
4443  } else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) {
4444  if (state->sender && *state->sender) {
4445  status = check_server_access(state, *cpp, state->sender,
4446  T_NS, state->sender,
4447  SMTPD_NAME_SENDER, def_acl);
4448  forbid_whitelist(state, name, status, state->sender);
4449  }
4450  } else if (is_map_command(state, name, CHECK_SENDER_MX_ACL, &cpp)) {
4451  if (state->sender && *state->sender) {
4452  status = check_server_access(state, *cpp, state->sender,
4453  T_MX, state->sender,
4454  SMTPD_NAME_SENDER, def_acl);
4455  forbid_whitelist(state, name, status, state->sender);
4456  }
4457  } else if (is_map_command(state, name, CHECK_SENDER_A_ACL, &cpp)) {
4458  if (state->sender && *state->sender) {
4459  status = check_server_access(state, *cpp, state->sender,
4460  T_A, state->sender,
4461  SMTPD_NAME_SENDER, def_acl);
4462  forbid_whitelist(state, name, status, state->sender);
4463  }
4464  } else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) {
4465  if (cpp[1] == 0)
4466  msg_warn("restriction %s requires domain name argument", name);
4467  else {
4468  cpp += 1;
4469  if (state->sender && *state->sender)
4470  status = reject_rbl_domain(state, *cpp, state->sender,
4472  }
4473  } else if (strcasecmp(name, REJECT_UNLISTED_SENDER) == 0) {
4474  if (state->sender && *state->sender)
4475  status = check_sender_rcpt_maps(state, state->sender);
4476  }
4477 
4478  /*
4479  * Recipient mail address restrictions.
4480  */
4481  else if (is_map_command(state, name, CHECK_RECIP_ACL, &cpp)) {
4482  if (state->recipient)
4483  status = check_mail_access(state, *cpp, state->recipient,
4484  &found, state->recipient,
4485  SMTPD_NAME_RECIPIENT, def_acl);
4486  } else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
4487  if (state->recipient) {
4488  status = permit_mx_backup(state, state->recipient,
4490  if (status == SMTPD_CHECK_OK)
4491  status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT,
4492  state->recipient, NO_PRINT_ARGS);
4493  }
4494  } else if (strcasecmp(name, PERMIT_AUTH_DEST) == 0) {
4495  if (state->recipient) {
4496  status = permit_auth_destination(state, state->recipient);
4497  if (status == SMTPD_CHECK_OK)
4498  status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT,
4499  state->recipient, NO_PRINT_ARGS);
4500  }
4501  } else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) {
4502  if (state->recipient)
4503  status = reject_unauth_destination(state, state->recipient,
4504  var_relay_code, "5.7.1");
4505  } else if (strcasecmp(name, DEFER_UNAUTH_DEST) == 0) {
4506  if (state->recipient)
4507  status = reject_unauth_destination(state, state->recipient,
4508  var_relay_code - 100, "4.7.1");
4509  } else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
4510  if (state->recipient)
4511  status = check_relay_domains(state, state->recipient,
4513  if (status == SMTPD_CHECK_OK)
4514  status = smtpd_acl_permit(state, name, SMTPD_NAME_RECIPIENT,
4515  state->recipient, NO_PRINT_ARGS);
4516  if (cpp[1] != 0 && state->warn_if_reject == 0)
4517  msg_warn("restriction `%s' after `%s' is ignored",
4518  cpp[1], CHECK_RELAY_DOMAINS);
4519  } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
4520 #ifdef USE_SASL_AUTH
4521  if (smtpd_sasl_is_active(state)) {
4522  status = permit_sasl_auth(state,
4523  SMTPD_CHECK_OK, SMTPD_CHECK_DUNNO);
4524  if (status == SMTPD_CHECK_OK)
4525  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4526  state->namaddr, NO_PRINT_ARGS);
4527  }
4528 #endif
4529  } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
4530  status = permit_tls_clientcerts(state, 1);
4531  if (status == SMTPD_CHECK_OK)
4532  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4533  state->namaddr, NO_PRINT_ARGS);
4534  } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
4535  status = permit_tls_clientcerts(state, 0);
4536  if (status == SMTPD_CHECK_OK)
4537  status = smtpd_acl_permit(state, name, SMTPD_NAME_CLIENT,
4538  state->namaddr, NO_PRINT_ARGS);
4539  } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
4540  if (state->recipient)
4541  status = reject_unknown_address(state, state->recipient,
4543  } else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
4544  if (state->recipient)
4545  status = reject_non_fqdn_address(state, state->recipient,
4547  } else if (is_map_command(state, name, CHECK_RECIP_NS_ACL, &cpp)) {
4548  if (state->recipient && *state->recipient) {
4549  status = check_server_access(state, *cpp, state->recipient,
4550  T_NS, state->recipient,
4551  SMTPD_NAME_RECIPIENT, def_acl);
4552  forbid_whitelist(state, name, status, state->recipient);
4553  }
4554  } else if (is_map_command(state, name, CHECK_RECIP_MX_ACL, &cpp)) {
4555  if (state->recipient && *state->recipient) {
4556  status = check_server_access(state, *cpp, state->recipient,
4557  T_MX, state->recipient,
4558  SMTPD_NAME_RECIPIENT, def_acl);
4559  forbid_whitelist(state, name, status, state->recipient);
4560  }
4561  } else if (is_map_command(state, name, CHECK_RECIP_A_ACL, &cpp)) {
4562  if (state->recipient && *state->recipient) {
4563  status = check_server_access(state, *cpp, state->recipient,
4564  T_A, state->recipient,
4565  SMTPD_NAME_RECIPIENT, def_acl);
4566  forbid_whitelist(state, name, status, state->recipient);
4567  }
4568  } else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) {
4569  if (cpp[1] == 0)
4570  msg_warn("restriction %s requires domain name argument", name);
4571  else {
4572  cpp += 1;
4573  if (state->recipient)
4574  status = reject_rbl_domain(state, *cpp, state->recipient,
4576  }
4577  } else if (strcasecmp(name, CHECK_RCPT_MAPS) == 0
4578  || strcasecmp(name, REJECT_UNLISTED_RCPT) == 0) {
4579  if (state->recipient && *state->recipient)
4580  status = check_recipient_rcpt_maps(state, state->recipient);
4581  } else if (strcasecmp(name, REJECT_MUL_RCPT_BOUNCE) == 0) {
4582  if (state->sender && *state->sender == 0 && state->rcpt_count
4583  > (strcmp(state->where, SMTPD_CMD_DATA) ? 0 : 1))
4584  status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
4585  var_mul_rcpt_code, "5.5.3",
4586  "<%s>: %s rejected: Multi-recipient bounce",
4587  reply_name, reply_class);
4588  } else if (strcasecmp(name, REJECT_UNVERIFIED_RECIP) == 0) {
4589  if (state->recipient && *state->recipient)
4590  status = reject_unverified_address(state, state->recipient,
4593  unv_rcpt_tf_act,
4595  }
4596 
4597  /*
4598  * ETRN domain name restrictions.
4599  */
4600  else if (is_map_command(state, name, CHECK_ETRN_ACL, &cpp)) {
4601  if (state->etrn_name)
4602  status = check_domain_access(state, *cpp, state->etrn_name,
4603  FULL, &found, state->etrn_name,
4604  SMTPD_NAME_ETRN, def_acl);
4605  }
4606 
4607  /*
4608  * User-defined restriction class.
4609  */
4610  else if ((list = (ARGV *) htable_find(smtpd_rest_classes, name)) != 0) {
4611  status = generic_checks(state, list, reply_name,
4612  reply_class, def_acl);
4613  }
4614 
4615  /*
4616  * Error: undefined restriction name.
4617  */
4618  else {
4619  msg_warn("unknown smtpd restriction: \"%s\"", name);
4620  reject_server_error(state);
4621  }
4622  if (msg_verbose)
4623  msg_info("%s: name=%s status=%d", myname, name, status);
4624 
4625  if (status < 0) {
4626  if (status == DICT_ERR_RETRY)
4627  reject_dict_retry(state, reply_name);
4628  else
4629  reject_server_error(state);
4630  }
4631  if (state->warn_if_reject >= state->recursion)
4632  state->warn_if_reject = 0;
4633 
4634  if (status != 0)
4635  break;
4636 
4637  if (state->defer_if_permit.active && state->defer_if_reject.active)
4638  break;
4639  }
4640  if (msg_verbose)
4641  msg_info(">>> END %s RESTRICTIONS <<<", reply_class);
4642 
4643  state->recursion = saved_recursion;
4644 
4645  /* In case the list terminated with one or more warn_if_mumble. */
4646  if (state->warn_if_reject >= state->recursion)
4647  state->warn_if_reject = 0;
4648 
4649  return (status);
4650 }
4651 
4652 /* smtpd_check_addr - address sanity check */
4653 
4654 int smtpd_check_addr(const char *sender, const char *addr, int smtputf8)
4655 {
4656  const RESOLVE_REPLY *resolve_reply;
4657  const char *myname = "smtpd_check_addr";
4658  const char *domain;
4659 
4660  if (msg_verbose)
4661  msg_info("%s: addr=%s", myname, addr);
4662 
4663  /*
4664  * Catch syntax errors early on if we can, but be prepared to re-compute
4665  * the result later when the cache fills up with lots of recipients, at
4666  * which time errors can still happen.
4667  */
4668  if (addr == 0 || *addr == 0)
4669  return (0);
4670  resolve_reply = smtpd_resolve_addr(sender, addr);
4671  if (resolve_reply->flags & RESOLVE_FLAG_ERROR)
4672  return (-1);
4673 
4674  /*
4675  * Backwards compatibility: if the client does not request SMTPUTF8
4676  * support, then behave like Postfix < 3.0 trivial-rewrite, and don't
4677  * allow non-ASCII email domains. Historically, Postfix does not reject
4678  * UTF8 etc. in the address localpart.
4679  */
4680  if (smtputf8 == 0
4681  && (domain = strrchr(STR(resolve_reply->recipient), '@')) != 0
4682  && *(domain += 1) != 0 && !allascii(domain))
4683  return (-1);
4684 
4685  return (0);
4686 }
4687 
4688 /* smtpd_check_rewrite - choose address qualification context */
4689 
4690 char *smtpd_check_rewrite(SMTPD_STATE *state)
4691 {
4692  const char *myname = "smtpd_check_rewrite";
4693  int status;
4694  char **cpp;
4695  MAPS *maps;
4696  char *name;
4697 
4698  /*
4699  * We don't use generic_checks() because it produces results that aren't
4700  * applicable such as DEFER or REJECT.
4701  */
4702  for (cpp = local_rewrite_clients->argv; *cpp != 0; cpp++) {
4703  if (msg_verbose)
4704  msg_info("%s: trying: %s", myname, *cpp);
4705  status = SMTPD_CHECK_DUNNO;
4706  if (strchr(name = *cpp, ':') != 0) {
4707  name = CHECK_ADDR_MAP;
4708  cpp -= 1;
4709  }
4710  if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) {
4711  status = permit_inet_interfaces(state);
4712  } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
4713  status = permit_mynetworks(state);
4714  } else if (is_map_command(state, name, CHECK_ADDR_MAP, &cpp)) {
4715  if ((maps = (MAPS *) htable_find(map_command_table, *cpp)) == 0)
4716  msg_panic("%s: dictionary not found: %s", myname, *cpp);
4717  if (maps_find(maps, state->addr, 0) != 0)
4718  status = SMTPD_CHECK_OK;
4719  else if (maps->error != 0) {
4720  /* Warning is already logged. */
4721  status = maps->error;
4722  }
4723  } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
4724 #ifdef USE_SASL_AUTH
4725  if (smtpd_sasl_is_active(state))
4726  status = permit_sasl_auth(state, SMTPD_CHECK_OK,
4727  SMTPD_CHECK_DUNNO);
4728 #endif
4729  } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
4730  status = permit_tls_clientcerts(state, 1);
4731  } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
4732  status = permit_tls_clientcerts(state, 0);
4733  } else {
4734  msg_warn("parameter %s: invalid request: %s",
4735  VAR_LOC_RWR_CLIENTS, name);
4736  continue;
4737  }
4738  if (status < 0) {
4739  if (status == DICT_ERR_RETRY) {
4740  state->error_mask |= MAIL_ERROR_RESOURCE;
4741  log_whatsup(state, "reject",
4742  "451 4.3.0 Temporary lookup error");
4743  return ("451 4.3.0 Temporary lookup error");
4744  } else {
4745  state->error_mask |= MAIL_ERROR_SOFTWARE;
4746  log_whatsup(state, "reject",
4747  "451 4.3.5 Server configuration error");
4748  return ("451 4.3.5 Server configuration error");
4749  }
4750  }
4751  if (status == SMTPD_CHECK_OK) {
4753  return (0);
4754  }
4755  }
4757  return (0);
4758 }
4759 
4760 /* smtpd_check_client - validate client name or address */
4761 
4762 char *smtpd_check_client(SMTPD_STATE *state)
4763 {
4764  int status;
4765 
4766  /*
4767  * Initialize.
4768  */
4769  if (state->name == 0 || state->addr == 0)
4770  return (0);
4771 
4772 #define SMTPD_CHECK_RESET() { \
4773  state->recursion = 0; \
4774  state->warn_if_reject = 0; \
4775  state->defer_if_reject.active = 0; \
4776  }
4777 
4778  /*
4779  * Reset the defer_if_permit flag.
4780  */
4781  state->defer_if_permit.active = 0;
4782 
4783  /*
4784  * Apply restrictions in the order as specified.
4785  */
4787  status = setjmp(smtpd_check_buf);
4788  if (status == 0 && client_restrctions->argc)
4789  status = generic_checks(state, client_restrctions, state->namaddr,
4792 
4793  return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
4794 }
4795 
4796 /* smtpd_check_helo - validate HELO hostname */
4797 
4798 char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
4799 {
4800  int status;
4801  char *saved_helo;
4802 
4803  /*
4804  * Initialize.
4805  */
4806  if (helohost == 0)
4807  return (0);
4808 
4809  /*
4810  * Minor kluge so that we can delegate work to the generic routine and so
4811  * that we can syslog the recipient with the reject messages.
4812  */
4813 #define SMTPD_CHECK_PUSH(backup, current, new) { \
4814  backup = current; \
4815  current = (new ? mystrdup(new) : 0); \
4816  }
4817 
4818 #define SMTPD_CHECK_POP(current, backup) { \
4819  if (current) myfree(current); \
4820  current = backup; \
4821  }
4822 
4823  SMTPD_CHECK_PUSH(saved_helo, state->helo_name, helohost);
4824 
4825 #define SMTPD_CHECK_HELO_RETURN(x) { \
4826  SMTPD_CHECK_POP(state->helo_name, saved_helo); \
4827  return (x); \
4828  }
4829 
4830  /*
4831  * Restore the defer_if_permit flag to its value before HELO/EHLO, and do
4832  * not set the flag when it was already raised by a previous protocol
4833  * stage.
4834  */
4836 
4837  /*
4838  * Apply restrictions in the order as specified.
4839  */
4841  status = setjmp(smtpd_check_buf);
4842  if (status == 0 && helo_restrctions->argc)
4843  status = generic_checks(state, helo_restrctions, state->helo_name,
4846 
4847  SMTPD_CHECK_HELO_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
4848 }
4849 
4850 /* smtpd_check_mail - validate sender address, driver */
4851 
4852 char *smtpd_check_mail(SMTPD_STATE *state, char *sender)
4853 {
4854  int status;
4855  char *saved_sender;
4856 
4857  /*
4858  * Initialize.
4859  */
4860  if (sender == 0)
4861  return (0);
4862 
4863  /*
4864  * Minor kluge so that we can delegate work to the generic routine and so
4865  * that we can syslog the recipient with the reject messages.
4866  */
4867  SMTPD_CHECK_PUSH(saved_sender, state->sender, sender);
4868 
4869 #define SMTPD_CHECK_MAIL_RETURN(x) { \
4870  SMTPD_CHECK_POP(state->sender, saved_sender); \
4871  return (x); \
4872  }
4873 
4874  /*
4875  * Restore the defer_if_permit flag to its value before MAIL FROM, and do
4876  * not set the flag when it was already raised by a previous protocol
4877  * stage. The client may skip the helo/ehlo.
4878  */
4880  | state->defer_if_permit_helo;
4881  state->sender_rcptmap_checked = 0;
4882 
4883  /*
4884  * Apply restrictions in the order as specified.
4885  */
4887  status = setjmp(smtpd_check_buf);
4888  if (status == 0 && mail_restrctions->argc)
4889  status = generic_checks(state, mail_restrctions, sender,
4892 
4893  /*
4894  * If the "reject_unlisted_sender" restriction still needs to be applied,
4895  * validate the sender here.
4896  */
4898  && status != SMTPD_CHECK_REJECT && state->sender_rcptmap_checked == 0
4899  && state->discard == 0 && *sender)
4900  status = check_sender_rcpt_maps(state, sender);
4901 
4902  SMTPD_CHECK_MAIL_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
4903 }
4904 
4905 /* smtpd_check_rcpt - validate recipient address, driver */
4906 
4907 char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
4908 {
4909  int status;
4910  char *saved_recipient;
4911  char *err;
4912  ARGV *restrctions[2];
4913  int n;
4914 
4915  /*
4916  * Initialize.
4917  */
4918  if (recipient == 0)
4919  return (0);
4920 
4921  /*
4922  * XXX 2821: Section 3.6 requires that "postmaster" be accepted even when
4923  * specified without a fully qualified domain name.
4924  */
4925  if (strcasecmp(recipient, "postmaster") == 0)
4926  return (0);
4927 
4928  /*
4929  * Minor kluge so that we can delegate work to the generic routine and so
4930  * that we can syslog the recipient with the reject messages.
4931  */
4932  SMTPD_CHECK_PUSH(saved_recipient, state->recipient, recipient);
4933 
4934 #define SMTPD_CHECK_RCPT_RETURN(x) { \
4935  SMTPD_CHECK_POP(state->recipient, saved_recipient); \
4936  return (x); \
4937  }
4938 
4939  /*
4940  * The "check_recipient_maps" restriction is relevant only when
4941  * responding to RCPT TO or VRFY.
4942  */
4943  state->recipient_rcptmap_checked = 0;
4944 
4945  /*
4946  * Apply delayed restrictions.
4947  */
4949  if ((err = smtpd_check_client(state)) != 0
4950  || (err = smtpd_check_helo(state, state->helo_name)) != 0
4951  || (err = smtpd_check_mail(state, state->sender)) != 0)
4953 
4954  /*
4955  * Restore the defer_if_permit flag to its value before RCPT TO, and do
4956  * not set the flag when it was already raised by a previous protocol
4957  * stage.
4958  */
4960 
4961  /*
4962  * Apply restrictions in the order as specified. We allow relay
4963  * restrictions to be empty, for sites that require backwards
4964  * compatibility.
4965  *
4966  * If compatibility_level < 1 and smtpd_relay_restrictions is left at its
4967  * default value, find out if the new smtpd_relay_restrictions default
4968  * value would block the request, without logging REJECT messages.
4969  * Approach: evaluate fake relay restrictions (permit_mynetworks,
4970  * permit_sasl_authenticated, permit_auth_destination) and log a warning
4971  * if the result is DUNNO instead of OK, i.e. a reject_unauth_destinatin
4972  * at the end would have blocked the request.
4973  */
4975  restrctions[0] = rcpt_restrctions;
4976  restrctions[1] = warn_compat_break_relay_restrictions ?
4977  fake_relay_restrctions : relay_restrctions;
4978  for (n = 0; n < 2; n++) {
4979  status = setjmp(smtpd_check_buf);
4980  if (status == 0 && restrctions[n]->argc)
4981  status = generic_checks(state, restrctions[n],
4984  && status == SMTPD_CHECK_DUNNO) {
4985  msg_info("using backwards-compatible default setting \""
4986  VAR_RELAY_CHECKS " = (empty)\" to avoid \"Relay "
4987  "access denied\" error for recipient \"%s\" from "
4988  "client \"%s\"", state->recipient, state->namaddr);
4989  }
4990  if (status == SMTPD_CHECK_REJECT)
4991  break;
4992  }
4993 
4994  /*
4995  * Force permission into deferral when some earlier temporary error may
4996  * have prevented us from rejecting mail, and report the earlier problem.
4997  */
4998  if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active)
4999  status = smtpd_check_reject(state, state->defer_if_permit.class,
5000  state->defer_if_permit.code,
5001  STR(state->defer_if_permit.dsn),
5002  "%s", STR(state->defer_if_permit.reason));
5003 
5004  /*
5005  * If the "reject_unlisted_recipient" restriction still needs to be
5006  * applied, validate the recipient here.
5007  */
5009  && status != SMTPD_CHECK_REJECT
5010  && state->recipient_rcptmap_checked == 0
5011  && state->discard == 0)
5012  status = check_recipient_rcpt_maps(state, recipient);
5013 
5014  SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5015 }
5016 
5017 /* smtpd_check_etrn - validate ETRN request */
5018 
5019 char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
5020 {
5021  int status;
5022  char *saved_etrn_name;
5023  char *err;
5024 
5025  /*
5026  * Initialize.
5027  */
5028  if (domain == 0)
5029  return (0);
5030 
5031  /*
5032  * Minor kluge so that we can delegate work to the generic routine and so
5033  * that we can syslog the recipient with the reject messages.
5034  */
5035  SMTPD_CHECK_PUSH(saved_etrn_name, state->etrn_name, domain);
5036 
5037 #define SMTPD_CHECK_ETRN_RETURN(x) { \
5038  SMTPD_CHECK_POP(state->etrn_name, saved_etrn_name); \
5039  return (x); \
5040  }
5041 
5042  /*
5043  * Apply delayed restrictions.
5044  */
5046  if ((err = smtpd_check_client(state)) != 0
5047  || (err = smtpd_check_helo(state, state->helo_name)) != 0)
5049 
5050  /*
5051  * Restore the defer_if_permit flag to its value before ETRN, and do not
5052  * set the flag when it was already raised by a previous protocol stage.
5053  * The client may skip the helo/ehlo.
5054  */
5056  | state->defer_if_permit_helo;
5057 
5058  /*
5059  * Apply restrictions in the order as specified.
5060  */
5062  status = setjmp(smtpd_check_buf);
5063  if (status == 0 && etrn_restrctions->argc)
5064  status = generic_checks(state, etrn_restrctions, domain,
5066 
5067  /*
5068  * Force permission into deferral when some earlier temporary error may
5069  * have prevented us from rejecting mail, and report the earlier problem.
5070  */
5071  if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active)
5072  status = smtpd_check_reject(state, state->defer_if_permit.class,
5073  state->defer_if_permit.code,
5074  STR(state->defer_if_permit.dsn),
5075  "%s", STR(state->defer_if_permit.reason));
5076 
5077  SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5078 }
5079 
5080 /* check_recipient_rcpt_maps - generic_checks() recipient table check */
5081 
5082 static int check_recipient_rcpt_maps(SMTPD_STATE *state, const char *recipient)
5083 {
5084 
5085  /*
5086  * Duplicate suppression. There's an implicit check_recipient_maps
5087  * restriction at the end of all recipient restrictions.
5088  */
5090  return (0);
5091  if (state->recipient_rcptmap_checked == 1)
5092  return (0);
5093  if (state->warn_if_reject == 0)
5094  /* We really validate the recipient address. */
5095  state->recipient_rcptmap_checked = 1;
5096  return (check_rcpt_maps(state, state->sender, recipient,
5098 }
5099 
5100 /* check_sender_rcpt_maps - generic_checks() sender table check */
5101 
5102 static int check_sender_rcpt_maps(SMTPD_STATE *state, const char *sender)
5103 {
5104 
5105  /*
5106  * Duplicate suppression. There's an implicit check_sender_maps
5107  * restriction at the end of all sender restrictions.
5108  */
5109  if (smtpd_input_transp_mask & INPUT_TRANSP_UNKNOWN_RCPT)
5110  return (0);
5111  if (state->sender_rcptmap_checked == 1)
5112  return (0);
5113  if (state->warn_if_reject == 0)
5114  /* We really validate the sender address. */
5115  state->sender_rcptmap_checked = 1;
5116  return (check_rcpt_maps(state, state->recipient, sender,
5118 }
5119 
5120 /* check_rcpt_maps - generic_checks() interface for recipient table check */
5121 
5122 static int check_rcpt_maps(SMTPD_STATE *state, const char *sender,
5123  const char *recipient,
5124  const char *reply_class)
5125 {
5126  const RESOLVE_REPLY *reply;
5127  DSN_SPLIT dp;
5128 
5129  if (msg_verbose)
5130  msg_info(">>> CHECKING %s VALIDATION MAPS <<<", reply_class);
5131 
5132  /*
5133  * Resolve the address.
5134  */
5135  reply = smtpd_resolve_addr(sender, recipient);
5136  if (reply->flags & RESOLVE_FLAG_FAIL)
5137  reject_dict_retry(state, recipient);
5138 
5139  /*
5140  * Make complex expressions more readable?
5141  */
5142 #define MATCH(map, rcpt) \
5143  check_mail_addr_find(state, recipient, map, rcpt, (char **) 0)
5144 
5145 #define NOMATCH(map, rcpt) (MATCH(map, rcpt) == 0)
5146 
5147  /*
5148  * XXX We assume the recipient address is OK if it matches a canonical
5149  * map or virtual alias map. Eventually, the address resolver should give
5150  * us the final resolved recipient address, and the SMTP server should
5151  * write the final resolved recipient address to the output record
5152  * stream. See also the next comment block on recipients in virtual alias
5153  * domains.
5154  */
5155  if (MATCH(rcpt_canon_maps, CONST_STR(reply->recipient))
5156  || (strcmp(reply_class, SMTPD_NAME_SENDER) == 0
5157  && MATCH(send_canon_maps, CONST_STR(reply->recipient)))
5158  || MATCH(canonical_maps, CONST_STR(reply->recipient))
5159  || MATCH(virt_alias_maps, CONST_STR(reply->recipient)))
5160  return (0);
5161 
5162  /*
5163  * At this point, anything that resolves to the error mailer is known to
5164  * be undeliverable.
5165  *
5166  * XXX Until the address resolver does final address resolution, known and
5167  * unknown recipients in virtual alias domains will both resolve to
5168  * "error:user unknown".
5169  */
5170  if (strcmp(STR(reply->transport), MAIL_SERVICE_ERROR) == 0) {
5171  dsn_split(&dp, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
5172  "5.1.0" : "5.1.1", STR(reply->nexthop));
5173  return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
5174  (reply->flags & RESOLVE_CLASS_ALIAS) ?
5175  var_virt_alias_code : 550,
5177  reply_class),
5178  "<%s>: %s rejected: %s",
5179  recipient, reply_class,
5180  dp.text));
5181  }
5182  if (strcmp(STR(reply->transport), MAIL_SERVICE_RETRY) == 0) {
5183  dsn_split(&dp, strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
5184  "4.1.0" : "4.1.1", STR(reply->nexthop));
5185  return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, 450,
5187  reply_class),
5188  "<%s>: %s rejected: %s",
5189  recipient, reply_class,
5190  dp.text));
5191  }
5192 
5193  /*
5194  * Search the recipient lookup tables of the respective address class.
5195  *
5196  * XXX Use the less expensive maps_find() (built-in case folding) instead of
5197  * the baroque mail_addr_find(). But then we have to strip the domain and
5198  * deal with address extensions ourselves.
5199  *
5200  * XXX But that would break sites that use the virtual delivery agent for
5201  * local delivery, because the virtual delivery agent requires
5202  * user@domain style addresses in its user database.
5203  */
5204 #define MATCH_LEFT(l, r, n) \
5205  (strncasecmp_utf8((l), (r), (n)) == 0 && (r)[n] == '@')
5206 
5207  switch (reply->flags & RESOLVE_CLASS_MASK) {
5208 
5209  /*
5210  * Reject mail to unknown addresses in local domains (domains that
5211  * match $mydestination or ${proxy,inet}_interfaces).
5212  */
5213  case RESOLVE_CLASS_LOCAL:
5214  if (*var_local_rcpt_maps
5215  /* Generated by bounce, absorbed by qmgr. */
5217  strlen(var_double_bounce_sender))
5218  /* Absorbed by qmgr. */
5220  strlen(MAIL_ADDR_POSTMASTER))
5221  /* Generated by bounce. */
5223  strlen(MAIL_ADDR_MAIL_DAEMON))
5224  && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient)))
5225  return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
5227  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
5228  "5.1.0" : "5.1.1",
5229  "<%s>: %s rejected: User unknown%s",
5230  recipient, reply_class,
5232  " in local recipient table" : ""));
5233  break;
5234 
5235  /*
5236  * Reject mail to unknown addresses in virtual mailbox domains.
5237  */
5238  case RESOLVE_CLASS_VIRTUAL:
5240  && NOMATCH(virt_mailbox_maps, CONST_STR(reply->recipient)))
5241  return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
5243  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
5244  "5.1.0" : "5.1.1",
5245  "<%s>: %s rejected: User unknown%s",
5246  recipient, reply_class,
5248  " in virtual mailbox table" : ""));
5249  break;
5250 
5251  /*
5252  * Reject mail to unknown addresses in relay domains.
5253  */
5254  case RESOLVE_CLASS_RELAY:
5255  if (*var_relay_rcpt_maps
5256  && NOMATCH(relay_rcpt_maps, CONST_STR(reply->recipient)))
5257  return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
5259  strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ?
5260  "5.1.0" : "5.1.1",
5261  "<%s>: %s rejected: User unknown%s",
5262  recipient, reply_class,
5264  " in relay recipient table" : ""));
5266  msg_info("using backwards-compatible default setting "
5267  VAR_RELAY_DOMAINS "=$mydestination to accept mail "
5268  "for address \"%s\"", recipient);
5269  break;
5270  }
5271 
5272  /*
5273  * Accept all other addresses - including addresses that passed the above
5274  * tests because of some table lookup problem.
5275  */
5276  return (0);
5277 }
5278 
5279 /* smtpd_check_size - check optional SIZE parameter value */
5280 
5281 char *smtpd_check_size(SMTPD_STATE *state, off_t size)
5282 {
5283  int status;
5284 
5285  /*
5286  * Return here in case of serious trouble.
5287  */
5289  if ((status = setjmp(smtpd_check_buf)) != 0)
5290  return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5291 
5292  /*
5293  * Check against file size limit.
5294  */
5295  if (var_message_limit > 0 && size > var_message_limit) {
5296  (void) smtpd_check_reject(state, MAIL_ERROR_POLICY,
5297  552, "5.3.4",
5298  "Message size exceeds fixed limit");
5299  return (STR(error_text));
5300  }
5301  return (0);
5302 }
5303 
5304 /* smtpd_check_queue - check queue space */
5305 
5306 char *smtpd_check_queue(SMTPD_STATE *state)
5307 {
5308  const char *myname = "smtpd_check_queue";
5309  struct fsspace fsbuf;
5310  int status;
5311 
5312  /*
5313  * Return here in case of serious trouble.
5314  */
5316  if ((status = setjmp(smtpd_check_buf)) != 0)
5317  return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5318 
5319  /*
5320  * Avoid overflow/underflow when comparing message size against available
5321  * space.
5322  */
5323 #define BLOCKS(x) ((x) / fsbuf.block_size)
5324 
5325  fsspace(".", &fsbuf);
5326  if (msg_verbose)
5327  msg_info("%s: blocks %lu avail %lu min_free %lu msg_size_limit %lu",
5328  myname,
5329  (unsigned long) fsbuf.block_size,
5330  (unsigned long) fsbuf.block_free,
5331  (unsigned long) var_queue_minfree,
5332  (unsigned long) var_message_limit);
5333  if (BLOCKS(var_queue_minfree) >= fsbuf.block_free
5334  || BLOCKS(var_message_limit) >= fsbuf.block_free / smtpd_space_multf) {
5335  (void) smtpd_check_reject(state, MAIL_ERROR_RESOURCE,
5336  452, "4.3.1",
5337  "Insufficient system storage");
5338  msg_warn("not enough free space in mail queue: %lu bytes < "
5339  "%g*message size limit",
5340  (unsigned long) fsbuf.block_free * fsbuf.block_size,
5341  smtpd_space_multf);
5342  return (STR(error_text));
5343  }
5344  return (0);
5345 }
5346 
5347 /* smtpd_check_data - check DATA command */
5348 
5349 char *smtpd_check_data(SMTPD_STATE *state)
5350 {
5351  int status;
5352  char *NOCLOBBER saved_recipient;
5353 
5354  /*
5355  * Minor kluge so that we can delegate work to the generic routine. We
5356  * provide no recipient information in the case of multiple recipients,
5357  * This restriction applies to all recipients alike, and logging only one
5358  * of them would be misleading.
5359  */
5360  if (state->rcpt_count > 1) {
5361  saved_recipient = state->recipient;
5362  state->recipient = 0;
5363  }
5364 
5365  /*
5366  * Reset the defer_if_permit flag. This is necessary when some recipients
5367  * were accepted but the last one was rejected.
5368  */
5369  state->defer_if_permit.active = 0;
5370 
5371  /*
5372  * Apply restrictions in the order as specified.
5373  *
5374  * XXX We cannot specify a default target for a bare access map.
5375  */
5377  status = setjmp(smtpd_check_buf);
5378  if (status == 0 && data_restrctions->argc)
5379  status = generic_checks(state, data_restrctions,
5381 
5382  /*
5383  * Force permission into deferral when some earlier temporary error may
5384  * have prevented us from rejecting mail, and report the earlier problem.
5385  */
5386  if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active)
5387  status = smtpd_check_reject(state, state->defer_if_permit.class,
5388  state->defer_if_permit.code,
5389  STR(state->defer_if_permit.dsn),
5390  "%s", STR(state->defer_if_permit.reason));
5391 
5392  if (state->rcpt_count > 1)
5393  state->recipient = saved_recipient;
5394 
5395  return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5396 }
5397 
5398 /* smtpd_check_eod - check end-of-data command */
5399 
5400 char *smtpd_check_eod(SMTPD_STATE *state)
5401 {
5402  int status;
5403  char *NOCLOBBER saved_recipient;
5404 
5405  /*
5406  * Minor kluge so that we can delegate work to the generic routine. We
5407  * provide no recipient information in the case of multiple recipients,
5408  * This restriction applies to all recipients alike, and logging only one
5409  * of them would be misleading.
5410  */
5411  if (state->rcpt_count > 1) {
5412  saved_recipient = state->recipient;
5413  state->recipient = 0;
5414  }
5415 
5416  /*
5417  * Reset the defer_if_permit flag. This is necessary when some recipients
5418  * were accepted but the last one was rejected.
5419  */
5420  state->defer_if_permit.active = 0;
5421 
5422  /*
5423  * Apply restrictions in the order as specified.
5424  *
5425  * XXX We cannot specify a default target for a bare access map.
5426  */
5428  status = setjmp(smtpd_check_buf);
5429  if (status == 0 && eod_restrictions->argc)
5430  status = generic_checks(state, eod_restrictions,
5432 
5433  /*
5434  * Force permission into deferral when some earlier temporary error may
5435  * have prevented us from rejecting mail, and report the earlier problem.
5436  */
5437  if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active)
5438  status = smtpd_check_reject(state, state->defer_if_permit.class,
5439  state->defer_if_permit.code,
5440  STR(state->defer_if_permit.dsn),
5441  "%s", STR(state->defer_if_permit.reason));
5442 
5443  if (state->rcpt_count > 1)
5444  state->recipient = saved_recipient;
5445 
5446  return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
5447 }
5448 
5449 #ifdef TEST
5450 
5451  /*
5452  * Test program to try out all these restrictions without having to go live.
5453  * This is not entirely stand-alone, as it requires access to the Postfix
5454  * rewrite/resolve service. This is just for testing code, not for debugging
5455  * configuration files.
5456  */
5457 #include <stdlib.h>
5458 
5459 #include <msg_vstream.h>
5460 #include <vstring_vstream.h>
5461 
5462 #include <mail_conf.h>
5463 #include <rewrite_clnt.h>
5464 #include <dns.h>
5465 
5466 #include <smtpd_chat.h>
5467 
5469 
5470  /*
5471  * Dummies. These are never set.
5472  */
5473 char *var_client_checks = "";
5474 char *var_helo_checks = "";
5475 char *var_mail_checks = "";
5476 char *var_relay_checks = "";
5477 char *var_rcpt_checks = "";
5478 char *var_etrn_checks = "";
5479 char *var_data_checks = "";
5480 char *var_eod_checks = "";
5481 char *var_relay_domains = "";
5482 char *var_smtpd_uproxy_proto = "";
5483 int var_smtpd_uproxy_tmout = 0;
5484 
5485 #ifdef USE_TLS
5486 char *var_relay_ccerts = "";
5487 
5488 #endif
5489 char *var_mynetworks = "";
5490 char *var_notify_classes = "";
5491 char *var_smtpd_policy_def_action = "";
5492 char *var_smtpd_policy_context = "";
5493 
5494  /*
5495  * String-valued configuration parameters.
5496  */
5497 char *var_maps_rbl_domains;
5498 char *var_myorigin;
5499 char *var_mydest;
5500 char *var_inet_interfaces;
5501 char *var_proxy_interfaces;
5502 char *var_rcpt_delim;
5503 char *var_rest_classes;
5504 char *var_alias_maps;
5505 char *var_send_canon_maps;
5506 char *var_rcpt_canon_maps;
5507 char *var_canonical_maps;
5508 char *var_virt_alias_maps;
5509 char *var_virt_alias_doms;
5510 char *var_virt_mailbox_maps;
5511 char *var_virt_mailbox_doms;
5512 char *var_local_rcpt_maps;
5513 char *var_perm_mx_networks;
5514 char *var_par_dom_match;
5515 char *var_smtpd_null_key;
5518 char *var_rbl_reply_maps;
5519 char *var_smtpd_exp_filter;
5520 char *var_def_rbl_reply;
5521 char *var_relay_rcpt_maps;
5522 char *var_verify_sender;
5523 char *var_smtpd_sasl_opts;
5524 char *var_local_rwr_clients;
5526 char *var_unv_from_why;
5527 char *var_unv_rcpt_why;
5528 char *var_stress;
5529 char *var_unk_name_tf_act;
5530 char *var_unk_addr_tf_act;
5531 char *var_unv_rcpt_tf_act;
5532 char *var_unv_from_tf_act;
5534 
5535 typedef struct {
5536  char *name;
5537  char *defval;
5538  char **target;
5539 } STRING_TABLE;
5540 
5541 #undef DEF_VIRT_ALIAS_MAPS
5542 #define DEF_VIRT_ALIAS_MAPS ""
5543 
5544 #undef DEF_LOCAL_RCPT_MAPS
5545 #define DEF_LOCAL_RCPT_MAPS ""
5546 
5547 static const STRING_TABLE string_table[] = {
5581  /* XXX Can't use ``$name'' type default values below. */
5586  /* XXX Can't use ``$name'' type default values above. */
5589  0,
5590 };
5591 
5592 /* string_init - initialize string parameters */
5593 
5594 static void string_init(void)
5595 {
5596  const STRING_TABLE *sp;
5597 
5598  for (sp = string_table; sp->name; sp++)
5599  sp->target[0] = mystrdup(sp->defval);
5600 }
5601 
5602 /* string_update - update string parameter */
5603 
5604 static int string_update(char **argv)
5605 {
5606  const STRING_TABLE *sp;
5607 
5608  for (sp = string_table; sp->name; sp++) {
5609  if (strcasecmp(argv[0], sp->name) == 0) {
5610  myfree(sp->target[0]);
5611  sp->target[0] = mystrdup(argv[1]);
5612  return (1);
5613  }
5614  }
5615  return (0);
5616 }
5617 
5618  /*
5619  * Integer parameters.
5620  */
5621 int var_queue_minfree; /* XXX use off_t */
5622 typedef struct {
5623  char *name;
5624  int defval;
5625  int *target;
5626 } INT_TABLE;
5627 
5629 int var_bad_name_code;
5630 int var_unk_name_code;
5631 int var_unk_addr_code;
5632 int var_relay_code;
5633 int var_maps_rbl_code;
5635 int var_map_defer_code;
5636 int var_reject_code;
5637 int var_defer_code;
5638 int var_non_fqdn_code;
5641 int var_mul_rcpt_code;
5642 int var_unv_from_rcode;
5643 int var_unv_from_dcode;
5644 int var_unv_rcpt_rcode;
5645 int var_unv_rcpt_dcode;
5661 int var_plaintext_code;
5665 
5666 #define int_table test_int_table
5667 
5668 static const INT_TABLE int_table[] = {
5669  "msg_verbose", 0, &msg_verbose,
5699  0,
5700 };
5701 
5702 /* int_init - initialize int parameters */
5703 
5704 static void int_init(void)
5705 {
5706  const INT_TABLE *sp;
5707 
5708  for (sp = int_table; sp->name; sp++)
5709  sp->target[0] = sp->defval;
5710 }
5711 
5712 /* int_update - update int parameter */
5713 
5714 static int int_update(char **argv)
5715 {
5716  const INT_TABLE *ip;
5717 
5718  for (ip = int_table; ip->name; ip++) {
5719  if (strcasecmp(argv[0], ip->name) == 0) {
5720  if (!ISDIGIT(*argv[1]))
5721  msg_fatal("bad number: %s %s", ip->name, argv[1]);
5722  ip->target[0] = atoi(argv[1]);
5723  return (1);
5724  }
5725  }
5726  return (0);
5727 }
5728 
5729  /*
5730  * Restrictions.
5731  */
5732 typedef struct {
5733  char *name;
5734  ARGV **target;
5735 } REST_TABLE;
5736 
5737 static const REST_TABLE rest_table[] = {
5738  "client_restrictions", &client_restrctions,
5739  "helo_restrictions", &helo_restrctions,
5740  "sender_restrictions", &mail_restrctions,
5741  "relay_restrictions", &relay_restrctions,
5742  "recipient_restrictions", &rcpt_restrctions,
5743  "etrn_restrictions", &etrn_restrctions,
5744  0,
5745 };
5746 
5747 /* rest_update - update restriction */
5748 
5749 static int rest_update(char **argv)
5750 {
5751  const REST_TABLE *rp;
5752 
5753  for (rp = rest_table; rp->name; rp++) {
5754  if (strcasecmp(rp->name, argv[0]) == 0) {
5755  argv_free(rp->target[0]);
5756  rp->target[0] = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, argv[1]);
5757  return (1);
5758  }
5759  }
5760  return (0);
5761 }
5762 
5763 /* rest_class - (re)define a restriction class */
5764 
5765 static void rest_class(char *class)
5766 {
5767  char *cp = class;
5768  char *name;
5769  HTABLE_INFO *entry;
5770 
5771  if (smtpd_rest_classes == 0)
5772  smtpd_rest_classes = htable_create(1);
5773 
5774  if ((name = mystrtok(&cp, CHARS_COMMA_SP)) == 0)
5775  msg_panic("rest_class: null class name");
5776  if ((entry = htable_locate(smtpd_rest_classes, name)) != 0)
5777  argv_free((ARGV *) entry->value);
5778  else
5779  entry = htable_enter(smtpd_rest_classes, name, (void *) 0);
5780  entry->value = (void *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, cp);
5781 }
5782 
5783 /* resolve_clnt_init - initialize reply */
5784 
5785 void resolve_clnt_init(RESOLVE_REPLY *reply)
5786 {
5787  reply->flags = 0;
5788  reply->transport = vstring_alloc(100);
5789  reply->nexthop = vstring_alloc(100);
5790  reply->recipient = vstring_alloc(100);
5791 }
5792 
5793 void resolve_clnt_free(RESOLVE_REPLY *reply)
5794 {
5795  vstring_free(reply->transport);
5796  vstring_free(reply->nexthop);
5797  vstring_free(reply->recipient);
5798 }
5799 
5800 bool var_smtpd_sasl_enable = 0;
5801 
5802 #ifdef USE_SASL_AUTH
5803 
5804 /* smtpd_sasl_activate - stub */
5805 
5806 void smtpd_sasl_activate(SMTPD_STATE *state, const char *opts_name,
5807  const char *opts_var)
5808 {
5809  msg_panic("smtpd_sasl_activate was called");
5810 }
5811 
5812 /* smtpd_sasl_deactivate - stub */
5813 
5814 void smtpd_sasl_deactivate(SMTPD_STATE *state)
5815 {
5816  msg_panic("smtpd_sasl_deactivate was called");
5817 }
5818 
5819 /* permit_sasl_auth - stub */
5820 
5821 int permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
5822 {
5823  return (ifnot);
5824 }
5825 
5826 /* smtpd_sasl_state_init - the real deal */
5827 
5828 void smtpd_sasl_state_init(SMTPD_STATE *state)
5829 {
5830  state->sasl_username = 0;
5831  state->sasl_method = 0;
5832  state->sasl_sender = 0;
5833 }
5834 
5835 #endif
5836 
5837 /* verify_clnt_query - stub */
5838 
5839 int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
5840 {
5841  *addr_status = DEL_RCPT_STAT_OK;
5842  return (VRFY_STAT_OK);
5843 }
5844 
5845 /* rewrite_clnt_internal - stub */
5846 
5847 VSTRING *rewrite_clnt_internal(const char *context, const char *addr,
5848  VSTRING *result)
5849 {
5850  if (addr == STR(result))
5851  msg_panic("rewrite_clnt_internal: result clobbers input");
5852  if (*addr && strchr(addr, '@') == 0)
5853  msg_fatal("%s: address rewriting is disabled", addr);
5854  vstring_strcpy(result, addr);
5855  return (result);
5856 }
5857 
5858 /* resolve_clnt_query - stub */
5859 
5860 void resolve_clnt(const char *class, const char *unused_sender, const char *addr,
5861  RESOLVE_REPLY *reply)
5862 {
5863  const char *domain;
5864  int rc;
5865 
5866  if (addr == CONST_STR(reply->recipient))
5867  msg_panic("resolve_clnt_query: result clobbers input");
5868  if (strchr(addr, '%'))
5869  msg_fatal("%s: address rewriting is disabled", addr);
5870  if ((domain = strrchr(addr, '@')) == 0)
5871  msg_fatal("%s: unqualified address", addr);
5872  domain += 1;
5873  if ((rc = resolve_local(domain)) > 0) {
5874  reply->flags = RESOLVE_CLASS_LOCAL;
5876  vstring_strcpy(reply->nexthop, domain);
5877  } else if (rc < 0) {
5878  reply->flags = RESOLVE_FLAG_FAIL;
5879  } else if (string_list_match(virt_alias_doms, domain)) {
5880  reply->flags = RESOLVE_CLASS_ALIAS;
5882  vstring_strcpy(reply->nexthop, "user unknown");
5883  } else if (virt_alias_doms->error) {
5884  reply->flags = RESOLVE_FLAG_FAIL;
5885  } else if (string_list_match(virt_mailbox_doms, domain)) {
5886  reply->flags = RESOLVE_CLASS_VIRTUAL;
5888  vstring_strcpy(reply->nexthop, domain);
5889  } else if (virt_mailbox_doms->error) {
5890  reply->flags = RESOLVE_FLAG_FAIL;
5891  } else if (domain_list_match(relay_domains, domain)) {
5892  reply->flags = RESOLVE_CLASS_RELAY;
5894  vstring_strcpy(reply->nexthop, domain);
5895  } else if (relay_domains->error) {
5896  reply->flags = RESOLVE_FLAG_FAIL;
5897  } else {
5898  reply->flags = RESOLVE_CLASS_DEFAULT;
5900  vstring_strcpy(reply->nexthop, domain);
5901  }
5902  vstring_strcpy(reply->recipient, addr);
5903 }
5904 
5905 /* smtpd_chat_reset - stub */
5906 
5907 void smtpd_chat_reset(SMTPD_STATE *unused_state)
5908 {
5909 }
5910 
5911 /* usage - scream and terminate */
5912 
5913 static NORETURN usage(char *myname)
5914 {
5915  msg_fatal("usage: %s", myname);
5916 }
5917 
5918 int main(int argc, char **argv)
5919 {
5920  VSTRING *buf = vstring_alloc(100);
5921  SMTPD_STATE state;
5922  ARGV *args;
5923  char *bp;
5924  char *resp;
5925  char *addr;
5926 
5927  /*
5928  * Initialization. Use dummies for client information.
5929  */
5930  msg_vstream_init(argv[0], VSTREAM_ERR);
5931  if (argc != 1)
5932  usage(argv[0]);
5933  string_init();
5934  int_init();
5935  smtpd_check_init();
5937  (void) inet_proto_init(argv[0], INET_PROTO_NAME_IPV4);
5938  smtpd_state_init(&state, VSTREAM_IN, "smtpd");
5939  state.queue_id = "<queue id>";
5940 
5941  /*
5942  * Main loop: update config parameters or test the client, helo, sender
5943  * and recipient restrictions.
5944  */
5945  while (vstring_fgets_nonl(buf, VSTREAM_IN) != 0) {
5946 
5947  /*
5948  * Tokenize the command. Note, the comma is not a separator, so that
5949  * restriction lists can be entered as comma-separated lists.
5950  */
5951  bp = STR(buf);
5952  if (!isatty(0)) {
5953  vstream_printf(">>> %s\n", bp);
5955  }
5956  if (*bp == '#')
5957  continue;
5958 
5959  if (*bp == '!') {
5960  vstream_printf("exit %d\n", system(bp + 1));
5961  continue;
5962  }
5963  args = argv_splitq(bp, CHARS_SPACE, CHARS_BRACE);
5964 
5965  /*
5966  * Recognize the command.
5967  */
5968  resp = "bad command";
5969  switch (args->argc) {
5970 
5971  /*
5972  * Emtpy line.
5973  */
5974  case 0:
5975  argv_free(args);
5976  continue;
5977 
5978  /*
5979  * Special case: rewrite context.
5980  */
5981  case 1:
5982  if (strcasecmp(args->argv[0], "rewrite") == 0) {
5983  resp = smtpd_check_rewrite(&state);
5984  break;
5985  }
5986 
5987  /*
5988  * Other parameter-less commands.
5989  */
5990  if (strcasecmp(args->argv[0], "flush_dnsxl_cache") == 0) {
5991  if (smtpd_rbl_cache) {
5992  ctable_free(smtpd_rbl_cache);
5993  ctable_free(smtpd_rbl_byte_cache);
5994  }
5995  smtpd_rbl_cache = ctable_create(100, rbl_pagein,
5996  rbl_pageout, (void *) 0);
5997  smtpd_rbl_byte_cache = ctable_create(1000, rbl_byte_pagein,
5998  rbl_byte_pageout, (void *) 0);
5999  resp = 0;
6000  break;
6001  }
6002 
6003  /*
6004  * Special case: client identity.
6005  */
6006  case 4:
6007  case 3:
6008  if (strcasecmp(args->argv[0], "client") == 0) {
6009  state.where = SMTPD_AFTER_CONNECT;
6010  UPDATE_STRING(state.name, args->argv[1]);
6011  UPDATE_STRING(state.reverse_name, args->argv[1]);
6012  UPDATE_STRING(state.addr, args->argv[2]);
6013  if (args->argc == 4)
6014  state.name_status =
6015  state.reverse_name_status =
6016  atoi(args->argv[3]);
6017  else if (strcmp(state.name, "unknown") == 0)
6018  state.name_status =
6019  state.reverse_name_status =
6021  else
6022  state.name_status =
6023  state.reverse_name_status =
6025  if (state.namaddr)
6026  myfree(state.namaddr);
6027  state.namaddr = concatenate(state.name, "[", state.addr,
6028  "]", (char *) 0);
6029  resp = smtpd_check_client(&state);
6030  }
6031  break;
6032 
6033  /*
6034  * Try config settings.
6035  */
6036 #define UPDATE_MAPS(ptr, var, val, lock) \
6037  { if (ptr) maps_free(ptr); ptr = maps_create(var, val, lock); }
6038 
6039 #define UPDATE_LIST(ptr, var, val) \
6040  { if (ptr) string_list_free(ptr); \
6041  ptr = string_list_init(var, MATCH_FLAG_NONE, val); }
6042 
6043  case 2:
6044  if (strcasecmp(args->argv[0], VAR_MYDEST) == 0) {
6045  UPDATE_STRING(var_mydest, args->argv[1]);
6047  smtpd_resolve_init(100);
6048  resp = 0;
6049  break;
6050  }
6051  if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_MAPS) == 0) {
6052  UPDATE_STRING(var_virt_alias_maps, args->argv[1]);
6053  UPDATE_MAPS(virt_alias_maps, VAR_VIRT_ALIAS_MAPS,
6054  var_virt_alias_maps, DICT_FLAG_LOCK
6056  resp = 0;
6057  break;
6058  }
6059  if (strcasecmp(args->argv[0], VAR_VIRT_ALIAS_DOMS) == 0) {
6060  UPDATE_STRING(var_virt_alias_doms, args->argv[1]);
6061  UPDATE_LIST(virt_alias_doms, VAR_VIRT_ALIAS_DOMS,
6062  var_virt_alias_doms);
6063  smtpd_resolve_init(100);
6064  resp = 0;
6065  break;
6066  }
6067  if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_MAPS) == 0) {
6068  UPDATE_STRING(var_virt_mailbox_maps, args->argv[1]);
6069  UPDATE_MAPS(virt_mailbox_maps, VAR_VIRT_MAILBOX_MAPS,
6070  var_virt_mailbox_maps, DICT_FLAG_LOCK
6072  resp = 0;
6073  break;
6074  }
6075  if (strcasecmp(args->argv[0], VAR_VIRT_MAILBOX_DOMS) == 0) {
6076  UPDATE_STRING(var_virt_mailbox_doms, args->argv[1]);
6077  UPDATE_LIST(virt_mailbox_doms, VAR_VIRT_MAILBOX_DOMS,
6078  var_virt_mailbox_doms);
6079  smtpd_resolve_init(100);
6080  resp = 0;
6081  break;
6082  }
6083  if (strcasecmp(args->argv[0], VAR_LOCAL_RCPT_MAPS) == 0) {
6084  UPDATE_STRING(var_local_rcpt_maps, args->argv[1]);
6085  UPDATE_MAPS(local_rcpt_maps, VAR_LOCAL_RCPT_MAPS,
6086  var_local_rcpt_maps, DICT_FLAG_LOCK
6088  resp = 0;
6089  break;
6090  }
6091  if (strcasecmp(args->argv[0], VAR_RELAY_RCPT_MAPS) == 0) {
6092  UPDATE_STRING(var_relay_rcpt_maps, args->argv[1]);
6093  UPDATE_MAPS(relay_rcpt_maps, VAR_RELAY_RCPT_MAPS,
6094  var_relay_rcpt_maps, DICT_FLAG_LOCK
6096  resp = 0;
6097  break;
6098  }
6099  if (strcasecmp(args->argv[0], VAR_CANONICAL_MAPS) == 0) {
6100  UPDATE_STRING(var_canonical_maps, args->argv[1]);
6101  UPDATE_MAPS(canonical_maps, VAR_CANONICAL_MAPS,
6102  var_canonical_maps, DICT_FLAG_LOCK
6104  resp = 0;
6105  break;
6106  }
6107  if (strcasecmp(args->argv[0], VAR_SEND_CANON_MAPS) == 0) {
6108  UPDATE_STRING(var_send_canon_maps, args->argv[1]);
6109  UPDATE_MAPS(send_canon_maps, VAR_SEND_CANON_MAPS,
6110  var_send_canon_maps, DICT_FLAG_LOCK
6112  resp = 0;
6113  break;
6114  }
6115  if (strcasecmp(args->argv[0], VAR_RCPT_CANON_MAPS) == 0) {
6116  UPDATE_STRING(var_rcpt_canon_maps, args->argv[1]);
6117  UPDATE_MAPS(rcpt_canon_maps, VAR_RCPT_CANON_MAPS,
6118  var_rcpt_canon_maps, DICT_FLAG_LOCK
6120  resp = 0;
6121  break;
6122  }
6123  if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) {
6124  UPDATE_STRING(var_rbl_reply_maps, args->argv[1]);
6125  UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS,
6126  var_rbl_reply_maps, DICT_FLAG_LOCK
6128  resp = 0;
6129  break;
6130  }
6131  if (strcasecmp(args->argv[0], VAR_MYNETWORKS) == 0) {
6132  /* NOT: UPDATE_STRING */
6133  namadr_list_free(mynetworks_curr);
6134  mynetworks_curr =
6137  args->argv[1]);
6138  smtpd_resolve_init(100);
6139  resp = 0;
6140  break;
6141  }
6142  if (strcasecmp(args->argv[0], VAR_RELAY_DOMAINS) == 0) {
6143  /* NOT: UPDATE_STRING */
6144  domain_list_free(relay_domains);
6145  relay_domains =
6148  args->argv[1]);
6149  smtpd_resolve_init(100);
6150  resp = 0;
6151  break;
6152  }
6153  if (strcasecmp(args->argv[0], VAR_PERM_MX_NETWORKS) == 0) {
6154  UPDATE_STRING(var_perm_mx_networks, args->argv[1]);
6155  domain_list_free(perm_mx_networks);
6156  perm_mx_networks =
6159  args->argv[1]);
6160  resp = 0;
6161  break;
6162  }
6163  if (strcasecmp(args->argv[0], VAR_SMTPD_DNS_RE_FILTER) == 0) {
6164  /* NOT: UPDATE_STRING */
6166  resp = 0;
6167  break;
6168  }
6169 #ifdef USE_TLS
6170  if (strcasecmp(args->argv[0], VAR_RELAY_CCERTS) == 0) {
6171  UPDATE_STRING(var_smtpd_relay_ccerts, args->argv[1]);
6172  UPDATE_MAPS(relay_ccerts, VAR_RELAY_CCERTS,
6173  var_smtpd_relay_ccerts, DICT_FLAG_LOCK
6174  | DICT_FLAG_FOLD_FIX);
6175  resp = 0;
6176  }
6177 #endif
6178  if (strcasecmp(args->argv[0], "restriction_class") == 0) {
6179  rest_class(args->argv[1]);
6180  resp = 0;
6181  break;
6182  }
6183  if (strcasecmp(args->argv[0], VAR_LOC_RWR_CLIENTS) == 0) {
6184  UPDATE_STRING(var_local_rwr_clients, args->argv[1]);
6185  argv_free(local_rewrite_clients);
6186  local_rewrite_clients = smtpd_check_parse(SMTPD_CHECK_PARSE_MAPS,
6187  var_local_rwr_clients);
6188  }
6189  if (int_update(args->argv)
6190  || string_update(args->argv)
6191  || rest_update(args->argv)) {
6192  resp = 0;
6193  break;
6194  }
6195 
6196  /*
6197  * Try restrictions.
6198  */
6199 #define TRIM_ADDR(src, res) { \
6200  if (*(res = src) == '<') { \
6201  res += strlen(res) - 1; \
6202  if (*res == '>') \
6203  *res = 0; \
6204  res = src + 1; \
6205  } \
6206  }
6207 
6208  if (strcasecmp(args->argv[0], "helo") == 0) {
6209  state.where = "HELO";
6210  resp = smtpd_check_helo(&state, args->argv[1]);
6211  UPDATE_STRING(state.helo_name, args->argv[1]);
6212  } else if (strcasecmp(args->argv[0], "mail") == 0) {
6213  state.where = "MAIL";
6214  TRIM_ADDR(args->argv[1], addr);
6215  UPDATE_STRING(state.sender, addr);
6216  resp = smtpd_check_mail(&state, addr);
6217  } else if (strcasecmp(args->argv[0], "rcpt") == 0) {
6218  state.where = "RCPT";
6219  TRIM_ADDR(args->argv[1], addr);
6220  resp = smtpd_check_rcpt(&state, addr);
6221 #ifdef USE_TLS
6222  } else if (strcasecmp(args->argv[0], "fingerprint") == 0) {
6223  if (state.tls_context == 0) {
6224  state.tls_context =
6225  (TLS_SESS_STATE *) mymalloc(sizeof(*state.tls_context));
6226  memset((void *) state.tls_context, 0,
6227  sizeof(*state.tls_context));
6228  state.tls_context->peer_cert_fprint =
6229  state.tls_context->peer_pkey_fprint = 0;
6230  }
6231  state.tls_context->peer_status |= TLS_CERT_FLAG_PRESENT;
6232  UPDATE_STRING(state.tls_context->peer_cert_fprint,
6233  args->argv[1]);
6234  state.tls_context->peer_pkey_fprint =
6235  state.tls_context->peer_cert_fprint;
6236  resp = "OK";
6237  break;
6238 #endif
6239  }
6240  break;
6241 
6242  /*
6243  * Show commands.
6244  */
6245  default:
6246  if (strcasecmp(args->argv[0], "check_rewrite") == 0) {
6247  smtpd_check_rewrite(&state);
6248  resp = state.rewrite_context;
6249  break;
6250  }
6251  resp = "Commands...\n\
6252  client <name> <address> [<code>]\n\
6253  helo <hostname>\n\
6254  sender <address>\n\
6255  recipient <address>\n\
6256  check_rewrite\n\
6257  msg_verbose <level>\n\
6258  client_restrictions <restrictions>\n\
6259  helo_restrictions <restrictions>\n\
6260  sender_restrictions <restrictions>\n\
6261  recipient_restrictions <restrictions>\n\
6262  restriction_class name,<restrictions>\n\
6263  flush_dnsxl_cache\n\
6264  \n\
6265  Note: no address rewriting \n";
6266  break;
6267  }
6268  vstream_printf("%s\n", resp ? resp : "OK");
6270  argv_free(args);
6271  }
6272  vstring_free(buf);
6273  smtpd_state_reset(&state);
6274 #define FREE_STRING(s) { if (s) myfree(s); }
6275  FREE_STRING(state.helo_name);
6276  FREE_STRING(state.sender);
6277 #ifdef USE_TLS
6278  if (state.tls_context) {
6279  FREE_STRING(state.tls_context->peer_cert_fprint);
6280  myfree((void *) state.tls_context);
6281  }
6282 #endif
6283  exit(0);
6284 }
6285 
6286 #endif
#define CHECK_SENDER_NS_ACL
Definition: mail_params.h:2295
int msg_verbose
Definition: msg.c:177
#define DEF_UNK_ADDR_CODE
Definition: mail_params.h:2200
int valid_hostaddr(const char *addr, int gripe)
#define ATTR_CLNT_CTL_TRY_LIMIT
Definition: attr_clnt.h:39
#define CHECK_HELO_NS_ACL
Definition: mail_params.h:2294
unsigned short pref
Definition: dns.h:146
char * var_mail_name
Definition: mail_params.c:230
void * value
Definition: htable.h:18
const char * dns_strtype(unsigned)
Definition: dns_strtype.c:187
#define vstring_fgets_nonl(s, p)
#define MAIL_ATTR_ACT_HELO_NAME
Definition: mail_proto.h:219
int valid_ipv6_hostaddr(const char *addr, int gripe)
#define RESOLVE_FLAG_FAIL
Definition: resolve_clnt.h:28
char * var_verify_sender
#define MAIL_ATTR_PROTO_STATE
Definition: mail_proto.h:227
char * var_relay_checks
Definition: smtpd.c:1239
char * var_unv_from_tf_act
Definition: smtpd.c:1406
#define ATTR_FLAG_NONE
Definition: attr.h:98
const char * valid_mailhost_addr(const char *addr, int gripe)
#define DEFER_IF_REJECT
Definition: mail_params.h:2141
#define CONFIG_BOOL_NO
Definition: mail_conf.h:31
int warn_compat_break_relay_domains
Definition: mail_params.c:356
#define VAR_RELAY_RCPT_CODE
Definition: mail_params.h:2061
void myfree(void *ptr)
Definition: mymalloc.c:207
int defer_if_permit_sender
Definition: smtpd.h:139
#define DEF_RBL_REPLY_MAPS
Definition: mail_params.h:2317
#define MATCH_FLAG_RETURN
Definition: match_list.h:40
#define CTABLE
Definition: ctable.h:19
#define SMTPD_NAME_REV_CLIENT
Definition: smtpd_dsn_fix.h:16
#define STREQUAL(x, y, l)
#define VAR_SMTPD_POLICY_TRY_LIMIT
Definition: mail_params.h:3036
#define MAIL_ERROR_RESOURCE
Definition: mail_error.h:26
#define DEF_UNV_FROM_RCODE
Definition: mail_params.h:2222
HTABLE_INFO * htable_locate(HTABLE *table, const char *key)
Definition: htable.c:242
#define VAR_UNK_ADDR_TF_ACT
Definition: mail_params.h:2203
#define CA_ATTR_OVER_END
Definition: attr_override.h:50
#define VAR_REJECT_CODE
Definition: mail_params.h:2131
void freeaddrinfo(struct addrinfo *ai)
Definition: myaddrinfo.c:742
bool var_smtpd_rej_unl_from
Definition: smtpd.c:1323
int match_parent_style(const char *name)
#define VAR_SMTPD_CLIENT_PORT_LOG
Definition: mail_params.h:3447
int var_unv_rcpt_dcode
Definition: smtpd.c:1295
#define DEF_MAP_DEFER_CODE
Definition: mail_params.h:2275
#define MAIL_ATTR_RBL_WHAT
Definition: mail_proto.h:190
#define SMTPD_PEER_CODE_PERM
Definition: smtpd.h:333
#define MAIL_ATTR_RBL_REASON
Definition: mail_proto.h:192
#define MAIL_ERROR_DATA
Definition: mail_error.h:29
#define VAR_DEF_RBL_REPLY
Definition: mail_params.h:2320
#define CA_ATTR_OVER_INT_TABLE(v)
Definition: attr_override.h:53
#define CHARS_BRACE
Definition: sys_defs.h:1763
#define MAIL_ATTR_CCERT_CERT_FPRINT
Definition: mail_proto.h:175
DSN_SPLIT * dsn_split(DSN_SPLIT *dp, const char *def_dsn, const char *text)
Definition: dsn_util.c:138
#define NOCLOBBER
Definition: sys_defs.h:1670
size_t dsn_valid(const char *text)
Definition: dsn_util.c:112
#define DEF_UNV_FROM_WHY
Definition: mail_params.h:2246
#define MAIL_ADDR_POSTMASTER
Definition: mail_addr.h:17
#define SMTPD_DNSXL_STAT_SOFT(dnsxl_res)
Definition: smtpd_check.c:3261
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define VAR_UNV_FROM_DCODE
Definition: mail_params.h:2229
int var_plaintext_code
Definition: smtpd.c:1379
#define MA_FIND_NOEXT
#define RBL_TXT_LIMIT
int mac_expand(VSTRING *result, const char *pattern, int flags, const char *filter, MAC_EXP_LOOKUP_FN lookup, void *context)
Definition: mac_expand.c:593
#define VAR_PROXY_INTERFACES
Definition: mail_params.h:182
char * extpar(char **bp, const char *parens, int flags)
Definition: extpar.c:77
char * smtpd_check_mail(SMTPD_STATE *state, char *sender)
Definition: smtpd_check.c:4852
#define CHECK_POLICY_SERVICE
Definition: mail_params.h:3052
#define PERMIT_MX_BACKUP
Definition: mail_params.h:2264
#define CHECK_CLIENT_A_ACL
Definition: mail_params.h:2297
char * dest_port
Definition: smtpd.h:83
char * qname
Definition: dns.h:140
char * var_smtpd_snd_auth_maps
Definition: proxymap.c:268
bool var_smtpd_sasl_enable
Definition: smtpd.c:1274
char * smtpd_check_eod(SMTPD_STATE *state)
Definition: smtpd_check.c:5400
#define SMTPD_AFTER_DOT
Definition: smtpd.h:226
#define MAIL_SERVICE_ERROR
Definition: mail_proto.h:52
#define STREQ(x, y)
char * var_perm_mx_networks
Definition: smtpd.c:1285
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
#define USE_SMTPD_PROXY(state)
Definition: smtpd.h:316
unsigned long block_free
Definition: fsspace.h:17
char * smtpd_check_etrn(SMTPD_STATE *state, char *domain)
Definition: smtpd_check.c:5019
char * var_local_rwr_clients
Definition: smtpd.c:1333
#define NORETURN
Definition: sys_defs.h:1583
Definition: argv.h:17
int var_soft_bounce
Definition: mail_params.c:281
#define MATCH_LEFT(l, r, n)
#define DEF_SHOW_UNK_RCPT_TABLE
Definition: mail_params.h:42
char * saved_redirect
Definition: smtpd.h:142
int var_virt_alias_code
Definition: smtpd.c:1301
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define MAIL_ATTR_CRYPTO_CIPHER
Definition: mail_proto.h:178
void smtpd_expand_init(void)
Definition: smtpd_expand.c:89
const char * smtpd_expand_lookup(const char *name, int unused_mode, void *context)
Definition: smtpd_expand.c:174
#define VAR_RELAY_DOMAINS
Definition: mail_params.h:2048
off_t act_size
Definition: smtpd.h:112
int var_map_defer_code
Definition: smtpd.c:1251
#define DEF_MAPS_RBL_CODE
Definition: mail_params.h:2326
#define MAIL_ATTR_RBL_CLASS
Definition: mail_proto.h:194
#define DEF_VIRT_ALIAS_DOMS
Definition: mail_params.h:435
#define VSTREAM_OUT
Definition: vstream.h:67
#define EXTPAR_FLAG_NONE
Definition: stringops.h:56
#define DEL_RCPT_STAT_TODO
#define MAIL_SERVICE_VIRTUAL
Definition: mail_proto.h:48
#define PERMIT_NAKED_IP_ADDR
Definition: mail_params.h:2166
#define ATTR_FLAG_MISSING
Definition: attr.h:99
#define ATTR_CLNT_CTL_END
Definition: attr_clnt.h:36
#define stat(p, s)
Definition: warn_stat.h:18
int var_verify_poll_count
Definition: smtpd.c:1306
#define SMTPD_CHECK_PUSH(backup, current, new)
#define inet_proto_info()
Definition: inet_proto.h:29
#define VAR_RCPT_DELIM
Definition: mail_params.h:644
#define STRING_LIST
Definition: string_list.h:22
#define DEF_SMTPD_DNS_RE_FILTER
Definition: mail_params.h:4008
#define DNS_RETRY
Definition: dns.h:282
char * var_smtpd_dns_re_filter
Definition: smtpd.c:1345
#define MAIL_ATTR_REQ
Definition: mail_proto.h:124
#define domain_list_match
Definition: domain_list.h:26
int var_unv_rcpt_rcode
Definition: smtpd.c:1293
#define DEF_LOCAL_RCPT_MAPS
Definition: mail_params.h:2357
int main(int argc, char **argv)
Definition: anvil.c:1010
#define REJECT_UNAUTH_DEST
Definition: mail_params.h:2255
#define REJECT_NON_FQDN_HELO_HOSTNAME
Definition: mail_params.h:2184
int valid_utf8_string(const char *, ssize_t)
#define DICT_ERR_RETRY
Definition: dict.h:178
#define DNS_NOTFOUND
Definition: dns.h:278
char * queue_id
Definition: smtpd.h:96
#define MAIL_ATTR_SIZE
Definition: mail_proto.h:139
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
Definition: inet_proto.c:180
#define VAR_STRESS
Definition: mail_params.h:3532
VSTRING * rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *result)
Definition: rewrite_clnt.c:175
#define DEF_NON_FQDN_CODE
Definition: mail_params.h:2189
char * name
Definition: smtpd.h:75
VSTRING * vstring_strncat(VSTRING *vp, const char *src, ssize_t len)
Definition: vstring.c:471
void attr_override(char *cp, const char *sep, const char *parens,...)
Definition: attr_override.c:91
int var_relay_code
Definition: smtpd.c:1248
#define VAR_MAPS_RBL_DOMAINS
Definition: mail_params.h:2329
#define SMTPD_CMD_ETRN
Definition: smtpd.h:243
int var_defer_code
Definition: smtpd.c:1256
bool var_smtpd_peername_lookup
Definition: smtpd.c:1378
int conv_time(const char *strval, int *timval, int def_unit)
Definition: conv_time.c:67
#define hostname_to_sockaddr(host, serv, sock, res)
Definition: myaddrinfo.h:171
char * saved_filter
Definition: smtpd.h:141
#define MISSED
#define VAR_UNV_RCPT_TF_ACT
Definition: mail_params.h:2233
#define CHECK_ETRN_ACL
Definition: mail_params.h:2285
const void * ctable_locate(CTABLE *cache, const char *key)
Definition: ctable.c:140
#define vstream_longjmp(stream, val)
Definition: vstream.h:249
#define PERMIT_TLS_ALL_CLIENTCERTS
Definition: mail_params.h:2259
#define MAIL_ERROR_BOUNCE
Definition: mail_error.h:24
#define REJECT_SENDER_LOGIN_MISMATCH
Definition: mail_params.h:1659
#define DEF_BAD_NAME_CODE
Definition: mail_params.h:2171
char data[1]
Definition: dns.h:149
#define VAR_SMTPD_NULL_KEY
Definition: mail_params.h:2339
Definition: maps.h:22
char * var_relay_domains
Definition: mail_params.c:286
char ** argv
Definition: argv.h:20
#define MAIL_SERVICE_SMTP
Definition: mail_proto.h:49
#define PERMIT_RHSWL_CLIENT
Definition: mail_params.h:2314
char * var_rest_classes
Definition: smtpd.c:1261
#define DEF_VERIFY_SENDER
Definition: mail_params.h:2823
#define CHECK_SENDER_ACL
Definition: mail_params.h:2283
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
int resolve_local(const char *addr)
Definition: resolve_local.c:78
#define MAIL_ATTR_RBL_TXT
Definition: mail_proto.h:193
#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock)
Definition: myaddrinfo.h:197
#define ATTR_TYPE_END
Definition: attr.h:39
#define dns_lookup_l(name, rflags, list, fqdn, why, lflags,...)
Definition: dns.h:235
#define DEF_SMTPD_NULL_KEY
Definition: mail_params.h:2340
void resolve_clnt_free(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:287
int var_smtpd_delay_reject
Definition: smtpd.c:1260
#define CLEANUP_FLAG_DISCARD
Definition: cleanup_user.h:21
#define MAIL_ATTR_RWR_LOCAL
Definition: mail_proto.h:166
#define MAIL_ATTR_ACT_CLIENT_ADDR
Definition: mail_proto.h:216
#define SMTP_ERR_QUIET
Definition: smtp_stream.h:32
void argv_add(ARGV *argvp,...)
Definition: argv.c:197
#define SMTPD_CHECK_HELO_RETURN(x)
#define DEF_PROXY_INTERFACES
Definition: mail_params.h:183
#define SMTPD_CMD_DATA
Definition: smtpd.h:238
int var_reject_code
Definition: smtpd.c:1255
int var_smtpd_policy_ttl
Definition: smtpd.c:1320
#define MAIL_ATTR_ACT_SERVER_ADDR
Definition: mail_proto.h:224
VSTRING * reason
Definition: smtpd.h:48
char * smtpd_check_helo(SMTPD_STATE *state, char *helohost)
Definition: smtpd_check.c:4798
#define DEF_INET_INTERFACES
Definition: mail_params.h:179
char * mystrtokq(char **src, const char *sep, const char *parens)
Definition: mystrtok.c:80
#define DSN_STATUS(dsn_buf)
Definition: dsn_util.h:46
double smtpd_space_multf
Definition: smtpd_check.c:469
#define VAR_INET_INTERFACES
Definition: mail_params.h:176
#define DICT_FLAG_UTF8_REQUEST
Definition: dict.h:130
int ip_match_execute(const char *byte_codes, const char *addr_bytes)
Definition: ip_match.c:272
#define VAR_SMTPD_REJ_UNL_FROM
Definition: mail_params.h:2207
int var_smtputf8_enable
Definition: mail_params.c:343
#define MAIL_ATTR_SASL_METHOD
Definition: mail_proto.h:156
int own_inet_addr(struct sockaddr *addr)
char * var_virt_alias_doms
Definition: proxymap.c:257
int var_smtpd_policy_idle
Definition: smtpd.c:1319
#define VSTREAM_IN
Definition: vstream.h:66
#define MAIL_ATTR_RWR_REMOTE
Definition: mail_proto.h:167
#define DEL_RCPT_STAT_BOUNCE
#define SMTPD_AFTER_CONNECT
Definition: smtpd.h:224
char * var_verify_service
Definition: mail_params.c:310
VSTRING * dsn
Definition: smtpd.h:49
#define strcasecmp_utf8(s1, s2)
Definition: stringops.h:75
void smtpd_chat_reset(SMTPD_STATE *state)
Definition: smtpd_chat.c:99
int alldig(const char *string)
Definition: alldig.c:38
#define CHECK_RECIP_ACL
Definition: mail_params.h:2284
char * var_myorigin
Definition: mail_params.c:225
char * var_smtpd_sasl_opts
Definition: smtpd.c:1276
#define DEF_SMTPD_REJ_UNL_FROM
Definition: mail_params.h:2208
#define T_TXT
Definition: dns.h:115
int var_smtpd_policy_try_delay
Definition: smtpd.c:1316
#define MAIL_ERROR_POLICY
Definition: mail_error.h:22
#define CHECK_SERVER_RETURN(x)
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
ARGV * argv_alloc(ssize_t len)
Definition: argv.c:149
#define smtpd_sasl_is_active(s)
#define VAR_SEND_CANON_MAPS
Definition: mail_params.h:446
#define VSTRING_LEN(vp)
Definition: vstring.h:72
Definition: htable.h:25
#define SHUT_RDWR
#define DOMAIN_LIST
Definition: domain_list.h:22
#define RESOLVE_CLASS_FINAL
Definition: resolve_clnt.h:36
char * var_def_rbl_reply
Definition: smtpd.c:1291
#define VAR_RELAY_CHECKS
Definition: mail_params.h:2085
#define VAR_SMTPD_POLICY_DEF_ACTION
Definition: mail_params.h:3044
#define CA_ATTR_OVER_TIME_TABLE(v)
Definition: attr_override.h:52
#define VAR_UNV_RCPT_DCODE
Definition: mail_params.h:2225
char * rewrite_context
Definition: smtpd.h:115
#define DEF_SMTPD_POLICY_TRY_DELAY
Definition: mail_params.h:3041
#define CLEANUP_FLAG_HOLD
Definition: cleanup_user.h:20
#define DICT_FLAG_FOLD_FIX
Definition: dict.h:124
char * smtpd_check_data(SMTPD_STATE *state)
Definition: smtpd_check.c:5349
#define VAR_SMTPD_PEERNAME_LOOKUP
Definition: mail_params.h:2349
#define RESOLVE_FLAG_ROUTED
Definition: resolve_clnt.h:26
#define CHECK_CLIENT_ACL
Definition: mail_params.h:2278
#define CHK_DOMAIN_RETURN(x, y)
#define RESOLVE_CLASS_VIRTUAL
Definition: resolve_clnt.h:32
#define DEF_MAPS_RBL_DOMAINS
Definition: mail_params.h:2330
#define PERMIT_DNSWL_CLIENT
Definition: mail_params.h:2313
#define DEF_RELAY_CODE
Definition: mail_params.h:2261
#define VAR_MAP_REJECT_CODE
Definition: mail_params.h:2270
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
Definition: myaddrinfo.c:464
VSTRING * expand_buf
Definition: smtpd.h:148
#define REJECT_UNKNOWN_REVERSE_HOSTNAME
Definition: mail_params.h:2156
char * var_send_canon_maps
Definition: cleanup_init.c:124
#define DEF_SMTPD_POLICY_TMOUT
Definition: mail_params.h:3021
#define VAR_VIRT_ALIAS_MAPS
Definition: mail_params.h:430
ATTR_CLNT * attr_clnt_create(const char *service, int timeout, int max_idle, int max_ttl)
Definition: attr_clnt.c:130
bool var_allow_untrust_route
Definition: smtpd.c:1271
#define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype)
Definition: dns.h:238
#define VAR_VIRT_MAILBOX_DOMS
Definition: mail_params.h:2525
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
const char * dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *)
Definition: dns_rr_to_pa.c:53
#define VAR_VIRT_ALIAS_DOMS
Definition: mail_params.h:434
#define VAR_UNK_ADDR_CODE
Definition: mail_params.h:2199
char * var_eod_checks
Definition: smtpd.c:1243
char * helo_name
Definition: smtpd.h:95
#define DEF_REST_CLASSES
Definition: mail_params.h:2117
#define VAR_UNK_NAME_CODE
Definition: mail_params.h:2176
int warn_if_reject
Definition: smtpd.h:134
#define VAR_UNV_FROM_TF_ACT
Definition: mail_params.h:2237
#define string_list_init(o, f, p)
Definition: string_list.h:24
#define DEF_SMTPD_ACL_PERM_LOG
Definition: mail_params.h:3941
int const char * fmt
long var_message_limit
Definition: mail_params.c:265
char * var_rcpt_delim
Definition: mail_params.c:274
char * var_relay_rcpt_maps
Definition: proxymap.c:260
#define DEF_SMTPD_POLICY_DEF_ACTION
Definition: mail_params.h:3045
#define DEF_UNV_RCPT_WHY
Definition: mail_params.h:2242
HTABLE * htable_create(ssize_t size)
Definition: htable.c:179
#define VAR_VIRT_MAILBOX_MAPS
Definition: mail_params.h:2521
DNS_RR * dns_rr_create(const char *, const char *, ushort, ushort, unsigned, unsigned, const char *, size_t)
const char * smtpd_dsn_fix(const char *status, const char *reply_class)
Definition: smtpd_dsn_fix.c:94
#define RESOLVE_CLASS_LOCAL
Definition: resolve_clnt.h:30
int permit_sasl_auth(SMTPD_STATE *, int, int)
int valid_hostname(const char *name, int gripe)
const char * mynetworks_host(void)
Definition: mynetworks.c:306
char * ip_match_save(const VSTRING *byte_codes)
Definition: ip_match.c:142
int code
Definition: smtpd.h:50
#define SLEEP
Definition: mail_params.h:2147
#define string_list_match
Definition: string_list.h:26
#define is_header(str)
Definition: is_header.h:17
VSTREAM * client
Definition: smtpd.h:70
#define REJECT_UNAUTH_SENDER_LOGIN_MISMATCH
Definition: mail_params.h:1664
char * var_smtpd_policy_context
Definition: smtpd.c:1318
#define DNS_NULLMX
Definition: dns.h:279
#define VAR_ALLOW_UNTRUST_ROUTE
Definition: mail_params.h:2120
char * var_rcpt_checks
Definition: smtpd.c:1240
const char * dns_strerror(unsigned)
Definition: dns_strerror.c:57
int var_unk_name_code
Definition: smtpd.c:1246
int warn_compat_break_mynetworks_style
Definition: mail_params.c:358
int sender_rcptmap_checked
Definition: smtpd.h:132
#define VAR_CANONICAL_MAPS
Definition: mail_params.h:442
#define VAR_LOCAL_RCPT_MAPS
Definition: mail_params.h:2356
#define VAR_ETRN_CHECKS
Definition: mail_params.h:2104
#define DEFER_IF_PERMIT_ACT
#define DEFER_UNAUTH_DEST
Definition: mail_params.h:2256
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
#define NO_DEF_ACL
int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
Definition: verify_clnt.c:95
#define MAIL_ATTR_STRESS
Definition: mail_proto.h:161
#define UPDATE_STRING(ptr, val)
Definition: smtpd_check.c:381
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
#define DEF_SMTPD_POLICY_IDLE
Definition: mail_params.h:3029
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
Definition: vstring.c:614
#define SMTPD_CHECK_ETRN_RETURN(x)
char * var_unv_rcpt_tf_act
Definition: smtpd.c:1405
#define SUSPICIOUS(reply, reply_class)
#define SMTPD_CHECK_PARSE_MAPS
#define MAIL_ATTR_ACT_CLIENT_PORT
Definition: mail_proto.h:217
#define DEF_RELAY_RCPT_CODE
Definition: mail_params.h:2062
#define VAR_UNV_RCPT_RCODE
Definition: mail_params.h:2216
#define CHECK_REVERSE_CLIENT_ACL
Definition: mail_params.h:2279
#define MAC_EXP_FLAG_NONE
Definition: mac_expand.h:23
#define DEF_CANONICAL_MAPS
Definition: mail_params.h:443
#define MA_FIND_FULL
#define MAIL_ATTR_CRYPTO_KEYSIZE
Definition: mail_proto.h:179
#define SMTPD_NAME_ETRN
Definition: smtpd_dsn_fix.h:22
#define VAR_MYNETWORKS
Definition: mail_params.h:2035
#define SMTPD_CHECK_PARSE_POLICY
#define PERMIT_ALL
Definition: mail_params.h:2129
#define RESOLVE_FLAG_ERROR
Definition: resolve_clnt.h:27
#define REJECT_INVALID_HOSTNAME
Definition: mail_params.h:2169
#define domain_list_free
Definition: domain_list.h:27
ARGV * argv_splitq(const char *, const char *, const char *)
Definition: argv_splitq.c:67
#define SMTPD_CHECK_RESET()
int valid_utf8_hostname(int enable_utf8, const char *name, int gripe)
#define ISDIGIT(c)
Definition: sys_defs.h:1748
void attr_clnt_control(ATTR_CLNT *client, int name,...)
Definition: attr_clnt.c:246
const char * text
Definition: dsn_util.h:55
SMTPD_DEFER defer_if_permit
Definition: smtpd.h:136
#define MATCH_FLAG_PARENT
Definition: match_list.h:39
char * var_notify_classes
Definition: bounce.c:193
#define SMTPD_NAME_HELO
Definition: smtpd_dsn_fix.h:19
#define DNS_REQ_FLAG_STOP_OK
Definition: dns.h:245
#define CHECK_CCERT_ACL
Definition: mail_params.h:2280
#define DEF_ALIAS_MAPS
Definition: mail_params.h:527
#define ATTR_CLNT_CTL_TRY_DELAY
Definition: attr_clnt.h:40
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
Definition: maps.c:112
void resolve_clnt_init(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:147
#define SMTPD_CMD_EOD
Definition: smtpd.h:239
unsigned long block_size
Definition: fsspace.h:16
#define VAR_DOUBLE_BOUNCE
Definition: mail_params.h:1965
#define CHECK_REVERSE_CLIENT_A_ACL
Definition: mail_params.h:2298
void smtpd_sasl_deactivate(SMTPD_STATE *)
#define VAR_EOD_CHECKS
Definition: mail_params.h:2112
char * var_double_bounce_sender
Definition: mail_params.c:262
bool var_show_unk_rcpt_table
Definition: smtpd.c:1305
#define PERMIT_AUTH_DEST
Definition: mail_params.h:2254
void smtpd_sasl_state_init(SMTPD_STATE *)
char * var_unv_from_why
Definition: smtpd.c:1296
#define mail_addr_find(maps, address, extension)
#define ATTR_CLNT_CTL_REQ_LIMIT
Definition: attr_clnt.h:38
#define DEF_DEFER_CODE
Definition: mail_params.h:2137
#define DEF_VIRT_ALIAS_MAPS
Definition: mail_params.h:431
#define REJECT_RHSBL_REVERSE_CLIENT
Definition: mail_params.h:2308
#define DEFER_IF_PERMIT3(type, state, class, code, dsn, fmt, a1, a2, a3)
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
char * port
Definition: smtpd.h:78
#define REJECT_RHSBL_HELO
Definition: mail_params.h:2309
#define DEF_RELAY_CCERTS
Definition: mail_params.h:2066
int smtpd_check_addr(const char *sender, const char *addr, int smtputf8)
Definition: smtpd_check.c:4654
#define MAIL_ATTR_SASL_SENDER
Definition: mail_proto.h:158
#define VAR_SHOW_UNK_RCPT_TABLE
Definition: mail_params.h:41
#define STR
Definition: smtpd_check.c:379
#define CHECK_HELO_MX_ACL
Definition: mail_params.h:2289
#define DEF_SMTPD_SND_AUTH_MAPS
Definition: mail_params.h:1656
char * var_rcpt_canon_maps
Definition: cleanup_init.c:125
#define DEF_PAR_DOM_MATCH
Definition: mail_params.h:2639
#define DNS_OK
Definition: dns.h:284
#define CA_ATTR_OVER_STR_TABLE(v)
Definition: attr_override.h:51
#define VAR_PERM_MX_NETWORKS
Definition: mail_params.h:2266
#define DICT_FLAG_LOCK
Definition: dict.h:116
ARGV * saved_bcc
Definition: smtpd.h:143
#define namadr_list_free
Definition: namadr_list.h:27
char * var_unk_name_tf_act
Definition: smtpd.c:1403
bool var_smtpd_rej_unl_rcpt
Definition: smtpd.c:1324
#define MAIL_ADDR_MAIL_DAEMON
Definition: mail_addr.h:18
char * var_smtpd_exp_filter
Definition: postscreen.c:517
char * var_stress
Definition: smtpd.c:1400
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define DEF_SMTPD_PEERNAME_LOOKUP
Definition: mail_params.h:2350
#define DEF_UNK_CLIENT_CODE
Definition: mail_params.h:2159
#define MAIL_ATTR_ACT_CLIENT_NAME
Definition: mail_proto.h:215
char * var_maps_rbl_domains
Definition: smtpd.c:1252
#define DEF_LOC_RWR_CLIENTS
Definition: mail_params.h:3115
#define CHECK_REVERSE_CLIENT_MX_ACL
Definition: mail_params.h:2288
CTABLE * ctable_create(ssize_t limit, CTABLE_CREATE_FN create, CTABLE_DELETE_FN delete, void *context)
Definition: ctable.c:119
#define DEF_SMTPD_SASL_OPTS
Definition: mail_params.h:1620
#define REJECT_UNKNOWN_ADDRESS
Definition: mail_params.h:2194
#define MAIL_ERROR_SOFTWARE
Definition: mail_error.h:25
off_t msg_size
Definition: smtpd.h:111
void resolve_local_init(void)
Definition: resolve_local.c:67
#define REJECT_NON_FQDN_RCPT
Definition: mail_params.h:2187
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define CHECK_RECIP_MX_ACL
Definition: mail_params.h:2291
int var_map_reject_code
Definition: smtpd.c:1250
#define DNS_INVAL
Definition: dns.h:281
#define VAR_RBL_REPLY_MAPS
Definition: mail_params.h:2316
#define VAR_MYORIGIN
Definition: mail_params.h:125
#define NOPE
#define CHARS_SPACE
Definition: sys_defs.h:1762
#define SMTPD_FLAG_SMTPUTF8
Definition: smtpd.h:197
#define REJECT_MUL_RCPT_BOUNCE
Definition: mail_params.h:2249
#define NAME_CODE_FLAG_NONE
Definition: name_code.h:22
#define CONST_STR(x)
Definition: smtpd_check.c:380
void smtpd_resolve_init(int cache_size)
#define REJECT_NON_FQDN_SENDER
Definition: mail_params.h:2186
char * sender
Definition: smtpd.h:103
char * var_mynetworks
Definition: mail_params.c:261
const RESOLVE_REPLY * smtpd_resolve_addr(const char *sender, const char *addr)
#define VAR_RELAY_CCERTS
Definition: mail_params.h:2065
#define DEF_SMTPD_REJ_UNL_RCPT
Definition: mail_params.h:2212
unsigned char * sa_family_list
Definition: inet_proto.h:21
#define DEF_RCPT_CANON_MAPS
Definition: mail_params.h:451
#define MAIL_ATTR_ACT_REVERSE_CLIENT_NAME
Definition: mail_proto.h:221
int warn_compat_break_relay_restrictions
Definition: mail_params.c:366
#define SMTPD_NAME_SENDER
Definition: smtpd_dsn_fix.h:20
size_t data_len
Definition: dns.h:148
#define VAR_MAP_DEFER_CODE
Definition: mail_params.h:2274
#define PERMIT_SASL_AUTH
Definition: mail_params.h:1798
#define CHECK_CLIENT_MX_ACL
Definition: mail_params.h:2287
#define DEF_MAIL_NAME
Definition: mail_params.h:28
DSN_STAT dsn
Definition: dsn_util.h:54
void * htable_find(HTABLE *table, const char *key)
Definition: htable.c:227
#define DEF_DOUBLE_BOUNCE
Definition: mail_params.h:1966
#define VAR_MAPS_RBL_CODE
Definition: mail_params.h:2325
#define MAIL_ATTR_CCERT_PKEY_FPRINT
Definition: mail_proto.h:176
#define DEF_SMTPD_CLIENT_PORT_LOG
Definition: mail_params.h:3448
#define CHECK_RELAY_DOMAINS
Definition: mail_params.h:2257
struct DNS_RR * next
Definition: dns.h:147
#define VAR_NON_FQDN_CODE
Definition: mail_params.h:2188
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
#define VAR_UNV_FROM_RCODE
Definition: mail_params.h:2221
#define DEF_UNV_RCPT_RCODE
Definition: mail_params.h:2217
int class
Definition: smtpd.h:51
char * var_canonical_maps
Definition: cleanup_init.c:123
#define SMTPD_CHECK_PARSE_ALL
#define SMTPD_CHECK_DUNNO
Definition: smtpd_check.c:271
#define DEF_ALLOW_UNTRUST_ROUTE
Definition: mail_params.h:2121
#define DEF_VIRT_MAILBOX_DOMS
Definition: mail_params.h:2526
#define REJECT_RBL
Definition: mail_params.h:2305
int var_smtpd_policy_try_limit
Definition: smtpd.c:1315
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
#define VAR_ALIAS_MAPS
Definition: mail_params.h:523
#define VAR_SMTPD_DELAY_REJECT
Definition: mail_params.h:2333
char * smtpd_check_size(SMTPD_STATE *state, off_t size)
Definition: smtpd_check.c:5281
#define allascii(s)
Definition: stringops.h:66
#define MAIL_ATTR_ACT_SERVER_PORT
Definition: mail_proto.h:225
int name_code(const NAME_CODE *table, int flags, const char *name)
Definition: name_code.c:65
#define VAR_UNK_NAME_TF_ACT
Definition: mail_params.h:2180
#define VAR_RCPT_CANON_MAPS
Definition: mail_params.h:450
#define SMTPD_ACCESS_MAPS
Definition: mail_params.h:2648
#define SEND_ATTR_LONG(name, val)
Definition: attr.h:67
#define MATCH(map, rcpt)
int proxy_inet_addr(struct sockaddr *addr)
#define SMTPD_NAME_DATA
Definition: smtpd_dsn_fix.h:23
#define CHECK_SENDER_MX_ACL
Definition: mail_params.h:2290
#define DEF_REJECT_CODE
Definition: mail_params.h:2132
#define VAR_UNV_FROM_WHY
Definition: mail_params.h:2245
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define VAR_SMTPD_DNS_RE_FILTER
Definition: mail_params.h:4007
SMTPD_RBL_STATE
Definition: smtpd_check.c:447
char * var_smtpd_acl_perm_log
Definition: smtpd.c:1344
#define VAR_PAR_DOM_MATCH
Definition: mail_params.h:2638
const char * mail_conf_lookup_eval(const char *name)
Definition: mail_conf.c:262
#define VAR_SMTPD_PROXY_FILT
Definition: mail_params.h:2992
#define REJECT_INVALID_HELO_HOSTNAME
Definition: mail_params.h:2168
char * etrn_name
Definition: smtpd.h:107
char * var_client_checks
Definition: smtpd.c:1236
#define SMTPD_DNXSL_STAT_HARD(dnsxl_res)
Definition: smtpd_check.c:3262
SMTPD_DEFER defer_if_reject
Definition: smtpd.h:135
#define INPUT_TRANSP_UNKNOWN_RCPT
Definition: input_transp.h:17
#define DEF_LOCAL_RCPT_CODE
Definition: mail_params.h:2361
#define VAR_LOCAL_RCPT_CODE
Definition: mail_params.h:2360
char * var_smtpd_relay_ccerts
ARGV * prepend
Definition: smtpd.h:149
int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *)
Definition: dns_rr.c:214
#define DEF_PLAINTEXT_CODE
Definition: mail_params.h:2151
char * smtpd_check_client(SMTPD_STATE *state)
Definition: smtpd_check.c:4762
VSTRING * recipient
Definition: resolve_clnt.h:46
#define VAR_VERIFY_POLL_COUNT
Definition: mail_params.h:2830
#define CHARS_COMMA_SP
Definition: sys_defs.h:1761
#define domain_list_init(o, f, p)
Definition: domain_list.h:24
#define RESOLVE_CLASS_MASK
Definition: resolve_clnt.h:39
char * where
Definition: smtpd.h:109
#define VAR_SMTPD_REJ_UNL_RCPT
Definition: mail_params.h:2211
int var_relay_rcpt_code
Definition: smtpd.c:1303
#define VAR_SMTPD_POLICY_TTL
Definition: mail_params.h:3032
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define namadr_list_match
Definition: namadr_list.h:26
char * var_virt_mailbox_doms
Definition: proxymap.c:259
int error_mask
Definition: smtpd.h:93
char * var_virt_alias_maps
Definition: cleanup_init.c:129
#define YUP
#define MA_FIND_PDDMDS
#define MAIL_SERVICE_RETRY
Definition: mail_proto.h:53
int defer_if_permit_client
Definition: smtpd.h:137
#define VAR_SMTPD_ACL_PERM_LOG
Definition: mail_params.h:3940
char * concatenate(const char *arg0,...)
Definition: concatenate.c:42
#define DEF_UNK_NAME_CODE
Definition: mail_params.h:2177
int error
Definition: maps.h:25
#define RR_ADDR_TYPES
char * mystrndup(const char *str, ssize_t len)
Definition: mymalloc.c:242
#define SMTPD_FLAG_ILL_PIPELINING
Definition: smtpd.h:195
#define REJECT_UNKNOWN_CLIENT
Definition: mail_params.h:2154
#define VAR_RELAY_CODE
Definition: mail_params.h:2260
char * reverse_name
Definition: smtpd.h:76
#define REJECT_UNKNOWN_HELO_HOSTNAME
Definition: mail_params.h:2174
#define MAIL_ATTR_RBL_CODE
Definition: mail_proto.h:195
char * var_data_checks
Definition: smtpd.c:1242
#define ADDROF(x)
int defer_if_permit_helo
Definition: smtpd.h:138
#define DEFER_IF_PERMIT2(type, state, class, code, dsn, fmt, a1, a2)
ARGV * argv_split(const char *, const char *)
Definition: argv_split.c:63
#define MAIL_ATTR_CRYPTO_PROTOCOL
Definition: mail_proto.h:177
int name_status
Definition: smtpd.h:88
char * var_virt_mailbox_maps
Definition: proxymap.c:258
#define REJECT_UNKNOWN_HOSTNAME
Definition: mail_params.h:2175
#define HAS_MY_ADDR_RETURN(x)
int reverse_name_status
Definition: smtpd.h:89
char * var_helo_checks
Definition: smtpd.c:1237
#define DEF_MUL_RCPT_CODE
Definition: mail_params.h:2251
char * smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
Definition: smtpd_check.c:4907
int var_unk_addr_code
Definition: smtpd.c:1247
#define MAIL_ATTR_SASL_USERNAME
Definition: mail_proto.h:157
#define MAIL_ATTR_RCPT_COUNT
Definition: mail_proto.h:132
VSTRING * smtpd_expand_filter
Definition: smtpd_expand.c:80
int active
Definition: smtpd.h:47
#define FULL
#define VAR_SMTPD_EXP_FILTER
Definition: mail_params.h:2343
#define MA_FIND_LOCALPART_AT
#define MAIL_ATTR_CCERT_ISSUER
Definition: mail_proto.h:174
#define VAR_SMTPD_POLICY_CONTEXT
Definition: mail_params.h:3048
#define link_override_table_to_variable(table, var)
Definition: smtpd_check.c:503
char * smtpd_check_queue(SMTPD_STATE *state)
Definition: smtpd_check.c:5306
#define REJECT_MAPS_RBL
Definition: mail_params.h:2324
#define MAIL_ATTR_INSTANCE
Definition: mail_proto.h:155
void smtpd_state_init(SMTPD_STATE *, VSTREAM *, const char *)
Definition: smtpd_state.c:78
#define DEF_RCPT_DELIM
Definition: mail_params.h:645
#define DEF_SMTPD_DELAY_REJECT
Definition: mail_params.h:2334
char * ip_match_parse(VSTRING *byte_codes, char *pattern)
Definition: ip_match.c:434
char * dest_addr
Definition: smtpd.h:82
int var_smtpd_policy_req_limit
Definition: smtpd.c:1314
#define SMTPD_NAME_SASL_USER
Definition: smtpd_dsn_fix.h:18
int var_mul_rcpt_code
Definition: smtpd.c:1298
#define CHECK_REVERSE_CLIENT_NS_ACL
Definition: mail_params.h:2293
#define CHECK_HELO_A_ACL
Definition: mail_params.h:2299
#define RESOLVE_CLASS_RELAY
Definition: resolve_clnt.h:33
int var_virt_mailbox_code
Definition: smtpd.c:1302
#define VAR_SMTPD_POLICY_REQ_LIMIT
Definition: mail_params.h:3024
#define REJECT_UNVERIFIED_SENDER
Definition: mail_params.h:2220
#define DEF_STRESS
Definition: mail_params.h:3533
#define REJECT_UNKNOWN_RCPTDOM
Definition: mail_params.h:2193
int var_unk_client_code
Definition: smtpd.c:1244
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:41
int attr_clnt_request(ATTR_CLNT *client, int send_flags,...)
Definition: attr_clnt.c:148
#define REJECT_RHSBL_SENDER
Definition: mail_params.h:2310
#define MA_FIND_PDMS
#define RESOLVE_CLASS_ALIAS
Definition: resolve_clnt.h:31
#define MAIL_ATTR_RECIP
Definition: mail_proto.h:134
char * addr
Definition: smtpd.h:77
void resolve_clnt(const char *class, const char *sender, const char *addr, RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:157
#define NO_PRINT_ARGS
#define DEF_PERM_MX_NETWORKS
Definition: mail_params.h:2267
#define DEFER_IF_REJECT3(state, class, code, dsn, fmt, a1, a2, a3)
VSTRING * vstring_vsprintf_append(VSTRING *vp, const char *format, va_list ap)
Definition: vstring.c:636
#define SMTPD_CHECK_REJECT
Definition: smtpd_check.c:273
#define MAIL_ATTR_RBL_DOMAIN
Definition: mail_proto.h:191
#define DEF_UNV_FROM_DCODE
Definition: mail_params.h:2230
const char * midna_domain_to_ascii(const char *name)
Definition: midna_domain.c:261
#define DEF_MYORIGIN
Definition: mail_params.h:126
#define DEF_VIRT_MAILBOX_CODE
Definition: mail_params.h:2530
#define REJECT_AUTH_SENDER_LOGIN_MISMATCH
Definition: mail_params.h:1660
#define VAR_VERIFY_SENDER
Definition: mail_params.h:2822
#define VAR_MYNETWORKS_STYLE
Definition: mail_params.h:2038
#define MAIL_ERROR_PROTOCOL
Definition: mail_error.h:23
#define VAR_SMTPD_POLICY_TMOUT
Definition: mail_params.h:3020
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
int rcpt_count
Definition: smtpd.h:99
char * var_rbl_reply_maps
Definition: smtpd.c:1253
#define VAR_UNV_RCPT_WHY
Definition: mail_params.h:2241
#define FAKE_RELAY_CHECKS
Definition: mail_params.h:2096
int var_bad_name_code
Definition: smtpd.c:1245
#define MAIL_ATTR_ETRN_DOMAIN
Definition: mail_proto.h:159
#define MAIL_ATTR_CCERT_SUBJECT
Definition: mail_proto.h:173
VSTRING * nexthop
Definition: resolve_clnt.h:45
int var_smtpd_policy_tmout
Definition: smtpd.c:1313
#define REJECT_UNLISTED_RCPT
Definition: mail_params.h:2196
#define DEF_MYDEST
Definition: mail_params.h:134
int var_maps_rbl_code
Definition: smtpd.c:1249
#define MAIL_ATTR_SENDER
Definition: mail_proto.h:131
#define NOMATCH(map, rcpt)
#define PARTIAL
VSTRING * transport
Definition: resolve_clnt.h:44
#define SND_DSN
Definition: smtpd_dsn_fix.h:31
char * var_smtpd_null_key
Definition: smtpd.c:1288
#define BLOCKS(x)
char * split_at(char *string, int delimiter)
Definition: split_at.c:53
#define vstream_fileno(vp)
Definition: vstream.h:115
#define MAI_STRERROR(e)
Definition: myaddrinfo.h:169
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
DNS_RR * dns_rr_sort(DNS_RR *, int(*)(DNS_RR *, DNS_RR *))
Definition: dns_rr.c:242
int var_smtpd_uproxy_tmout
Definition: smtpd.c:1417
#define CHK_ADDR_RETURN(x, y)
int discard
Definition: smtpd.h:140
int var_local_rcpt_code
Definition: smtpd.c:1300
char * recipient
Definition: smtpd.h:106
#define SMTPD_DNSXL_STAT_OK(dnsxl_res)
Definition: smtpd_check.c:3263
#define REJECT_UNVERIFIED_RECIP
Definition: mail_params.h:2215
int flags
Definition: smtpd.h:68
#define NAMADR_LIST
Definition: namadr_list.h:22
#define VAR_PLAINTEXT_CODE
Definition: mail_params.h:2150
#define PERMIT_MX_BACKUP_RETURN(x)
int var_queue_minfree
Definition: smtpd.c:1233
char * var_proxy_interfaces
Definition: mail_params.c:259
#define MAILHOST_LOOKUP_FLAGS
#define DEF_VIRT_ALIAS_CODE
Definition: mail_params.h:439
#define PRINTFLIKE(x, y)
Definition: sys_defs.h:1600
#define REJECT_RHSBL_RECIPIENT
Definition: mail_params.h:2311
#define MAIL_SERVICE_RELAY
Definition: mail_proto.h:57
#define WARN_IF_REJECT
Definition: mail_params.h:2303
#define CHECK_SASL_ACL
Definition: mail_params.h:2281
#define VAR_SMTPD_POLICY_IDLE
Definition: mail_params.h:3028
char * var_unk_addr_tf_act
Definition: smtpd.c:1404
#define VAR_BAD_NAME_CODE
Definition: mail_params.h:2170
#define ISSPACE(c)
Definition: sys_defs.h:1753
#define mail_addr_find_strategy(maps, address, extension, strategy)
ssize_t argc
Definition: argv.h:19
#define DNS_REQ_FLAG_NONE
Definition: dns.h:250
#define PERMIT_TLS_CLIENTCERTS
Definition: mail_params.h:2258
#define DEF_VIRT_MAILBOX_MAPS
Definition: mail_params.h:2522
#define CHK_ACCESS_RETURN(x, y)
#define CHECK_ADDR_MAP
Definition: mail_params.h:3112
#define MAIL_ATTR_ACT_PROTO_NAME
Definition: mail_proto.h:220
#define SMTPD_NAME_RECIPIENT
Definition: smtpd_dsn_fix.h:21
#define DEFER_IF_REJECT4(state, class, code, dsn, fmt, a1, a2, a3, a4)
#define MAIL_ATTR_QUEUEID
Definition: mail_proto.h:130
#define RESOLVE_CLASS_DEFAULT
Definition: resolve_clnt.h:34
#define MAIL_SERVICE_LOCAL
Definition: mail_proto.h:42
ATTR_CLNT * client
Definition: smtpd_check.c:475
#define REJECT_ALL
Definition: mail_params.h:2130
#define CHECK_RECIP_NS_ACL
Definition: mail_params.h:2296
#define CHECK_RECIP_A_ACL
Definition: mail_params.h:2301
#define SMTPD_CMD_RCPT
Definition: smtpd.h:237
#define VAR_RCPT_CHECKS
Definition: mail_params.h:2100
#define VAR_MYDEST
Definition: mail_params.h:133
char * smtpd_check_rewrite(SMTPD_STATE *state)
Definition: smtpd_check.c:4690
char * printable(char *string, int replacement)
Definition: printable.c:49
#define SMTPD_CHECK_MAIL_RETURN(x)
void smtpd_sasl_activate(SMTPD_STATE *, const char *, const char *)
#define DEFER_IF_REJECT2(state, class, code, dsn, fmt, a1, a2)
bool var_smtpd_client_port_log
Definition: smtpd.c:1399
#define REJECT_NON_FQDN_HOSTNAME
Definition: mail_params.h:2185
#define DEL_RCPT_STAT_OK
#define DEF_SMTPD_EXP_FILTER
Definition: mail_params.h:2344
#define PERMIT_INET_INTERFACES
Definition: mail_params.h:2162
#define SMTPD_PEER_CODE_TEMP
Definition: smtpd.h:332
#define VAR_SMTPD_SASL_OPTS
Definition: mail_params.h:1619
#define REJECT_UNLISTED_SENDER
Definition: mail_params.h:2195
#define CHECK_RCPT_MAPS
Definition: mail_params.h:2197
#define VAR_UNK_CLIENT_CODE
Definition: mail_params.h:2158
#define DEF_MAP_REJECT_CODE
Definition: mail_params.h:2271
#define DICT_FLAG_NONE
Definition: dict.h:109
void smtpd_check_init(void)
Definition: smtpd_check.c:721
int var_unv_from_rcode
Definition: smtpd.c:1292
int recipient_rcptmap_checked
Definition: smtpd.h:133
#define MA_FIND_DOMAIN
#define REJECT_UNKNOWN_CLIENT_HOSTNAME
Definition: mail_params.h:2155
#define SMTPD_NAME_CLIENT
Definition: smtpd_dsn_fix.h:15
unsigned short type
Definition: dns.h:142
void ctable_free(CTABLE *cache)
Definition: ctable.c:226
#define VAR_MAIL_NAME
Definition: mail_params.h:27
#define VAR_SMTPD_SND_AUTH_MAPS
Definition: mail_params.h:1655
char * protocol
Definition: smtpd.h:108
const char * maps_find(MAPS *maps, const char *name, int flags)
Definition: maps.c:162
void dns_rr_free(DNS_RR *)
Definition: dns_rr.c:137
int recursion
Definition: smtpd.h:110
#define INET_PROTO_NAME_IPV4
Definition: mail_params.h:990
#define DEFER_ALL
Definition: mail_params.h:2135
int var_verify_poll_delay
Definition: smtpd.c:1307
#define DEFER_IF_PERMIT
Definition: mail_params.h:2140
#define VAR_MUL_RCPT_CODE
Definition: mail_params.h:2250
#define CHECK_SENDER_A_ACL
Definition: mail_params.h:2300
#define DEL_RCPT_STAT_DEFER
Definition: dns.h:139
char * var_inet_interfaces
Definition: mail_params.c:258
#define VRFY_STAT_OK
Definition: verify_clnt.h:33
char * var_etrn_checks
Definition: smtpd.c:1241
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
Definition: vstring.c:445
void fsspace(const char *path, struct fsspace *sp)
Definition: fsspace.c:68
char * var_local_rcpt_maps
Definition: proxymap.c:255
int saved_flags
Definition: smtpd.h:144
int smtpd_input_transp_mask
Definition: smtpd.c:1467
char * var_alias_maps
Definition: local.c:651
char * var_unv_rcpt_why
Definition: smtpd.c:1297
#define VAR_SMTPD_POLICY_TRY_DELAY
Definition: mail_params.h:3040
#define SEND_ATTR_STR(name, val)
Definition: attr.h:64
char * var_par_dom_match
Definition: mail_params.c:292
char * split_at_right(char *string, int delimiter)
Definition: split_at.c:64
char * var_mail_checks
Definition: smtpd.c:1238
#define REJECT_UNKNOWN_SENDDOM
Definition: mail_params.h:2192
#define dns_lookup(name, type, rflags, list, fqdn, why)
Definition: dns.h:229
#define SMTPD_NAME_EOD
Definition: smtpd_dsn_fix.h:24
#define MAIL_ATTR_ACTION
Definition: mail_proto.h:151
int var_unv_from_dcode
Definition: smtpd.c:1294
#define MAIL_ATTR_POL_CONTEXT
Definition: mail_proto.h:164
#define DEF_UNV_RCPT_DCODE
Definition: mail_params.h:2226
#define DEF_REJECT_TMPF_ACT
Definition: mail_params.h:2144
#define REJECT_RBL_CLIENT
Definition: mail_params.h:2306
#define MATCH_FLAG_NONE
Definition: match_list.h:38
char * var_smtpd_policy_def_action
Definition: smtpd.c:1317
#define DEF_RELAY_RCPT_MAPS
Definition: mail_params.h:2058
char * var_smtpd_uproxy_proto
Definition: smtpd.c:1416
#define CHECK_HELO_ACL
Definition: mail_params.h:2282
#define REJECT_PLAINTEXT_SESSION
Definition: mail_params.h:2149
#define VAR_LOC_RWR_CLIENTS
Definition: mail_params.h:3114
#define DNS_POLICY
Definition: dns.h:283
char * var_mynetworks_style
Definition: mail_params.c:288
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
Definition: vstring.c:459
#define CHECK_CLIENT_NS_ACL
Definition: mail_params.h:2292
char * vstring_export(VSTRING *vp)
Definition: vstring.c:569
#define REJECT_KNOWN_SENDER_LOGIN_MISMATCH
Definition: mail_params.h:1662
int var_non_fqdn_code
Definition: smtpd.c:1258
#define VSTREAM_ERR
Definition: vstream.h:68
#define REJECT_RHSBL_CLIENT
Definition: mail_params.h:2307
struct sockaddr_storage sockaddr
Definition: smtpd.h:84
#define DEF_DEF_RBL_REPLY
Definition: mail_params.h:2321
#define DEFER_ALL_ACT
char * namaddr
Definition: smtpd.h:79
#define VAR_RELAY_RCPT_MAPS
Definition: mail_params.h:2057
void dns_rr_filter_compile(const char *, const char *)
Definition: dns_rr_filter.c:85
#define DEF_SEND_CANON_MAPS
Definition: mail_params.h:447
#define SMTPD_PEER_CODE_OK
Definition: smtpd.h:331
#define VAR_REST_CLASSES
Definition: mail_params.h:2116
#define PERMIT_MYNETWORKS
Definition: mail_params.h:2164
#define SMTPD_CHECK_OK
Definition: smtpd_check.c:272
#define VAR_DEFER_CODE
Definition: mail_params.h:2136
#define RECV_ATTR_STR(name, val)
Definition: attr.h:72
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
#define DONT_GRIPE
Definition: haproxy_srvr.h:31
#define REJECT_UNAUTH_PIPE
Definition: mail_params.h:2337
#define SMTPD_NAME_CCERT
Definition: smtpd_dsn_fix.h:17
void argv_terminate(ARGV *argvp)
Definition: argv.c:242
#define DEF_SMTPD_POLICY_TTL
Definition: mail_params.h:3033
#define SMTPD_CHECK_RCPT_RETURN(x)
#define FOUND
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
Definition: htable.c:212
void msg_info(const char *fmt,...)
Definition: msg.c:199
VSTRING * instance
Definition: smtpd.h:150
void smtpd_state_reset(SMTPD_STATE *)
Definition: smtpd_state.c:190
#define VAR_VIRT_MAILBOX_CODE
Definition: mail_params.h:2529
#define namadr_list_init(o, f, p)
Definition: namadr_list.h:24
#define VAR_VIRT_ALIAS_CODE
Definition: mail_params.h:438
char * var_mydest
Definition: mail_params.c:226