Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / resolve_local.c
bloba20fcda7d5b8ec3cadae550efbaa56033ae18511
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* resolve_local 3
6 /* SUMMARY
7 /* determine if domain resolves to local mail system
8 /* SYNOPSIS
9 /* #include <resolve_local.h>
11 /* void resolve_local_init()
13 /* int resolve_local(domain)
14 /* const char *domain;
15 /* DESCRIPTION
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.
24 /* BUGS
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.
27 /* SEE ALSO
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
31 /* LICENSE
32 /* .ad
33 /* .fi
34 /* The Secure Mailer license must be distributed with this software.
35 /* AUTHOR(S)
36 /* Wietse Venema
37 /* IBM T.J. Watson Research
38 /* P.O. Box 704
39 /* Yorktown Heights, NY 10598, USA
40 /*--*/
42 /* System library. */
44 #include <sys_defs.h>
46 /* Utility library. */
48 #include <msg.h>
49 #include <mymalloc.h>
50 #include <string_list.h>
51 #include <myaddrinfo.h>
52 #include <valid_mailhost_addr.h>
54 /* Global library. */
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);
78 char *dest;
79 const char *bare_dest;
80 struct addrinfo *res0 = 0;
81 ssize_t len;
84 * The optimizer will eliminate tests that always fail.
86 #define RETURN(x) \
87 do { \
88 myfree(saved_addr); \
89 if (res0) \
90 freeaddrinfo(res0); \
91 return(x); \
92 } while (0)
94 if (resolve_local_list == 0)
95 resolve_local_init();
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);
105 if (len == 0)
106 RETURN(0);
107 if (saved_addr[len - 1] == '.')
108 saved_addr[--len] = 0;
109 if (len == 0 || saved_addr[len - 1] == '.')
110 RETURN(0);
113 * Compare the destination against the list of destinations that we
114 * consider local.
116 if (string_list_match(resolve_local_list, saved_addr))
117 RETURN(1);
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
144 * to happen.
146 * FIX 200501 IPv6 patch did not require "IPv6:" prefix in numerical
147 * addresses.
149 dest = saved_addr;
150 if (*dest == '[' && dest[len - 1] == ']') {
151 dest++;
152 dest[len -= 2] = 0;
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))
156 RETURN(1);
161 * Must be remote, or a syntax error.
163 RETURN(0);
166 #ifdef TEST
168 #include <vstream.h>
169 #include <mail_conf.h>
171 int main(int argc, char **argv)
173 if (argc != 2)
174 msg_fatal("usage: %s domain", argv[0]);
175 mail_conf_read();
176 vstream_printf("%s\n", resolve_local(argv[1]) ? "yes" : "no");
177 vstream_fflush(VSTREAM_OUT);
178 return (0);
181 #endif