7 /* determine if domain resolves to local mail system
9 /* #include <resolve_local.h>
11 /* void resolve_local_init()
13 /* int resolve_local(domain)
14 /* const char *domain;
16 /* resolve_local() determines if the named domain resolves to the
17 /* local mail system, either by case-insensitive exact match
18 /* against the domains, files or tables listed in $mydestination,
19 /* or by a match of an [address-literal] against of the network
20 /* addresses listed in $inet_interfaces or in $proxy_interfaces.
22 /* resolve_local_init() performs initialization. If this routine is
23 /* not called explicitly ahead of time, it will be called on the fly.
25 /* Calling resolve_local_init() on the fly is an incomplete solution.
26 /* It is bound to fail with applications that enter a chroot jail.
28 /* own_inet_addr(3), find out my own network interfaces
29 /* match_list(3), generic pattern matching engine
30 /* match_ops(3), generic pattern matching operators
34 /* The Secure Mailer license must be distributed with this software.
37 /* IBM T.J. Watson Research
39 /* Yorktown Heights, NY 10598, USA
46 /* Utility library. */
50 #include <string_list.h>
51 #include <myaddrinfo.h>
52 #include <valid_mailhost_addr.h>
56 #include <mail_params.h>
57 #include <own_inet_addr.h>
58 #include <resolve_local.h>
60 /* Application-specific */
62 static STRING_LIST
*resolve_local_list
;
64 /* resolve_local_init - initialize lookup table */
66 void resolve_local_init(void)
68 if (resolve_local_list
)
69 msg_panic("resolve_local_init: duplicate initialization");
70 resolve_local_list
= string_list_init(MATCH_FLAG_NONE
, var_mydest
);
73 /* resolve_local - match domain against list of local destinations */
75 int resolve_local(const char *addr
)
77 char *saved_addr
= mystrdup(addr
);
79 const char *bare_dest
;
80 struct addrinfo
*res0
= 0;
84 * The optimizer will eliminate tests that always fail.
94 if (resolve_local_list
== 0)
98 * Strip one trailing dot but not dot-dot.
100 * XXX This should not be distributed all over the code. Problem is,
101 * addresses can enter the system via multiple paths: networks, local
102 * forward/alias/include files, even as the result of address rewriting.
104 len
= strlen(saved_addr
);
107 if (saved_addr
[len
- 1] == '.')
108 saved_addr
[--len
] = 0;
109 if (len
== 0 || saved_addr
[len
- 1] == '.')
113 * Compare the destination against the list of destinations that we
116 if (string_list_match(resolve_local_list
, saved_addr
))
120 * Compare the destination against the list of interface addresses that
121 * we are supposed to listen on.
123 * The destination may be an IPv6 address literal that was buried somewhere
124 * inside a deeply recursively nested address. This information comes
125 * from an untrusted source, and Wietse is not confident that everyone's
126 * getaddrinfo() etc. implementation is sufficiently robust. The syntax
127 * is complex enough with null field compression and with IPv4-in-IPv6
128 * addresses that errors are likely.
130 * The solution below is ad-hoc. We neutralize the string as soon as we
131 * realize that its contents could be harmful. We neutralize the string
132 * here, instead of neutralizing it in every resolve_local() caller.
133 * That's because resolve_local knows how the address is going to be
134 * parsed and converted into binary form.
136 * There are several more structural solutions to this.
138 * - One solution is to disallow address literals. This is not as bad as it
139 * seems: I have never seen actual legitimate use of address literals.
141 * - Another solution is to label each string with a trustworthiness label
142 * and to expect that all Postfix infrastructure will exercise additional
143 * caution when given a string with untrusted content. This is not likely
146 * FIX 200501 IPv6 patch did not require "IPv6:" prefix in numerical
150 if (*dest
== '[' && dest
[len
- 1] == ']') {
153 if ((bare_dest
= valid_mailhost_addr(dest
, DO_GRIPE
)) != 0
154 && hostaddr_to_sockaddr(bare_dest
, (char *) 0, 0, &res0
) == 0) {
155 if (own_inet_addr(res0
->ai_addr
) || proxy_inet_addr(res0
->ai_addr
))
161 * Must be remote, or a syntax error.
169 #include <mail_conf.h>
171 int main(int argc
, char **argv
)
174 msg_fatal("usage: %s domain", argv
[0]);
176 vstream_printf("%s\n", resolve_local(argv
[1]) ? "yes" : "no");
177 vstream_fflush(VSTREAM_OUT
);