No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / smtpd / smtpd_peer.c
blobce1ba772cd9a7ec1a27b875dc16e629750739bb5
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* smtpd_peer 3
6 /* SUMMARY
7 /* look up peer name/address information
8 /* SYNOPSIS
9 /* #include "smtpd.h"
11 /* void smtpd_peer_init(state)
12 /* SMTPD_STATE *state;
14 /* void smtpd_peer_reset(state)
15 /* SMTPD_STATE *state;
16 /* DESCRIPTION
17 /* The smtpd_peer_init() routine attempts to produce a printable
18 /* version of the peer name and address of the specified socket.
19 /* Where information is unavailable, the name and/or address
20 /* are set to "unknown".
22 /* This module uses the local name service via getaddrinfo()
23 /* and getnameinfo(). It does not query the DNS directly.
25 /* smtpd_peer_init() updates the following fields:
26 /* .IP name
27 /* The verified client hostname. This name is represented by
28 /* the string "unknown" when 1) the address->name lookup failed,
29 /* 2) the name->address mapping fails, or 3) the name->address
30 /* mapping does not produce the client IP address.
31 /* .IP reverse_name
32 /* The unverified client hostname as found with address->name
33 /* lookup; it is not verified for consistency with the client
34 /* IP address result from name->address lookup.
35 /* .IP forward_name
36 /* The unverified client hostname as found with address->name
37 /* lookup followed by name->address lookup; it is not verified
38 /* for consistency with the result from address->name lookup.
39 /* For example, when the address->name lookup produces as
40 /* hostname an alias, the name->address lookup will produce
41 /* as hostname the expansion of that alias, so that the two
42 /* lookups produce different names.
43 /* .IP addr
44 /* Printable representation of the client address.
45 /* .IP namaddr
46 /* String of the form: "name[addr]:port".
47 /* .IP rfc_addr
48 /* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
49 /* in Received: message headers.
50 /* .IP name_status
51 /* The name_status result field specifies how the name
52 /* information should be interpreted:
53 /* .RS
54 /* .IP 2
55 /* The address->name lookup and name->address lookup produced
56 /* the client IP address.
57 /* .IP 4
58 /* The address->name lookup or name->address lookup failed
59 /* with a recoverable error.
60 /* .IP 5
61 /* The address->name lookup or name->address lookup failed
62 /* with an unrecoverable error, or the result did not match
63 /* the client IP address.
64 /* .RE
65 /* .IP reverse_name_status
66 /* The reverse_name_status result field specifies how the
67 /* reverse_name information should be interpreted:
68 /* .RS .IP 2
69 /* The address->name lookup succeeded.
70 /* .IP 4
71 /* The address->name lookup failed with a recoverable error.
72 /* .IP 5
73 /* The address->name lookup failed with an unrecoverable error.
74 /* .RE .IP forward_name_status
75 /* The forward_name_status result field specifies how the
76 /* forward_name information should be interpreted:
77 /* .RS .IP 2
78 /* The address->name and name->address lookup succeeded.
79 /* .IP 4
80 /* The address->name lookup or name->address failed with a
81 /* recoverable error.
82 /* .IP 5
83 /* The address->name lookup or name->address failed with an
84 /* unrecoverable error.
85 /* .RE
86 /* .PP
87 /* smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
88 /* LICENSE
89 /* .ad
90 /* .fi
91 /* The Secure Mailer license must be distributed with this software.
92 /* AUTHOR(S)
93 /* Wietse Venema
94 /* IBM T.J. Watson Research
95 /* P.O. Box 704
96 /* Yorktown Heights, NY 10598, USA
97 /*--*/
99 /* System library. */
101 #include <sys_defs.h>
102 #include <sys/socket.h>
103 #include <netinet/in.h>
104 #include <arpa/inet.h>
105 #include <stdio.h> /* strerror() */
106 #include <errno.h>
107 #include <netdb.h>
108 #include <string.h>
110 /* Utility library. */
112 #include <msg.h>
113 #include <mymalloc.h>
114 #include <stringops.h>
115 #include <myaddrinfo.h>
116 #include <sock_addr.h>
117 #include <inet_proto.h>
119 /* Global library. */
121 #include <mail_proto.h>
122 #include <valid_mailhost_addr.h>
123 #include <mail_params.h>
125 /* Application-specific. */
127 #include "smtpd.h"
129 /* smtpd_peer_init - initialize peer information */
131 void smtpd_peer_init(SMTPD_STATE *state)
133 const char *myname = "smtpd_peer_init";
134 SOCKADDR_SIZE sa_length;
135 struct sockaddr *sa;
136 INET_PROTO_INFO *proto_info = inet_proto_info();
138 sa = (struct sockaddr *) & (state->sockaddr);
139 sa_length = sizeof(state->sockaddr);
142 * Look up the peer address information.
144 * XXX If we make local endpoint (getsockname) information available to
145 * Milter applications as {if_name} and {if_addr}, then we also must be
146 * able to provide this via the XCLIENT command for Milter testing.
148 * XXX If we make local or remote port information available to policy
149 * servers or Milter applications, then we must also make this testable
150 * with the XCLIENT command, otherwise there will be confusion.
152 * XXX If we make local or remote port information available via logging,
153 * then we must also support these attributes with the XFORWARD command.
155 * XXX If support were to be added for Milter applications in down-stream
156 * MTAs, then consistency demands that we propagate a lot of Sendmail
157 * macro information via the XFORWARD command. Otherwise we could end up
158 * with a very confusing situation.
160 if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) {
161 errno = 0;
165 * If peer went away, give up.
167 if (errno != 0 && errno != ENOTSOCK) {
168 state->name = mystrdup(CLIENT_NAME_UNKNOWN);
169 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
170 state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
171 state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
172 state->addr_family = AF_UNSPEC;
173 state->name_status = SMTPD_PEER_CODE_PERM;
174 state->reverse_name_status = SMTPD_PEER_CODE_PERM;
175 state->port = mystrdup(CLIENT_PORT_UNKNOWN);
179 * Convert the client address to printable address and hostname.
181 * XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd, while
182 * Postfix IPv6 (or IPv4) support is turned off, don't (skip to the final
183 * else clause, pretend the origin is localhost[127.0.0.1], and become an
184 * open relay).
186 else if (errno == 0
187 && (sa->sa_family == AF_INET
188 #ifdef AF_INET6
189 || sa->sa_family == AF_INET6
190 #endif
191 )) {
192 MAI_HOSTNAME_STR client_name;
193 MAI_HOSTADDR_STR client_addr;
194 MAI_SERVPORT_STR client_port;
195 int aierr;
196 char *colonp;
199 * Sanity check: we can't use sockets that we're not configured for.
201 if (strchr((char *) proto_info->sa_family_list, sa->sa_family) == 0)
202 msg_fatal("cannot handle socket type %s with \"%s = %s\"",
203 #ifdef AF_INET6
204 sa->sa_family == AF_INET6 ? "AF_INET6" :
205 #endif
206 sa->sa_family == AF_INET ? "AF_INET" :
207 "other", VAR_INET_PROTOCOLS, var_inet_protocols);
210 * Sorry, but there are some things that we just cannot do while
211 * connected to the network.
213 if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
214 msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
215 (unsigned long) getuid(), (unsigned long) geteuid());
216 msg_fatal("the Postfix SMTP server must run with $%s privileges",
217 VAR_MAIL_OWNER);
221 * Convert the client address to printable form.
223 if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
224 &client_port, 0)) != 0)
225 msg_fatal("%s: cannot convert client address/port to string: %s",
226 myname, MAI_STRERROR(aierr));
227 state->port = mystrdup(client_port.buf);
230 * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
231 * but only if IPv4 support is enabled (why would anyone want to turn
232 * it off)? With IPv4 support enabled we have no need for the IPv6
233 * form in logging, hostname verification and access checks.
235 #ifdef HAS_IPV6
236 if (sa->sa_family == AF_INET6) {
237 if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
238 && IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
239 && (colonp = strrchr(client_addr.buf, ':')) != 0) {
240 struct addrinfo *res0;
242 if (msg_verbose > 1)
243 msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
244 myname, client_addr.buf, colonp + 1);
246 state->addr = mystrdup(colonp + 1);
247 state->rfc_addr = mystrdup(colonp + 1);
248 state->addr_family = AF_INET;
249 aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
250 if (aierr)
251 msg_fatal("%s: cannot convert %s from string to binary: %s",
252 myname, state->addr, MAI_STRERROR(aierr));
253 sa_length = res0->ai_addrlen;
254 if (sa_length > sizeof(state->sockaddr))
255 sa_length = sizeof(state->sockaddr);
256 memcpy((char *) sa, res0->ai_addr, sa_length);
257 freeaddrinfo(res0); /* 200412 */
261 * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
262 * a prefix of 'IPv6:'. We do this consistently for all IPv6
263 * addresses that that appear in headers or envelopes. The fact
264 * that valid_mailhost_addr() enforces the form helps of course.
265 * We use the form without IPV6: prefix when doing access
266 * control, or when accessing the connection cache.
268 else {
269 state->addr = mystrdup(client_addr.buf);
270 state->rfc_addr =
271 concatenate(IPV6_COL, client_addr.buf, (char *) 0);
272 state->addr_family = sa->sa_family;
277 * An IPv4 address is in dotted quad decimal form.
279 else
280 #endif
282 state->addr = mystrdup(client_addr.buf);
283 state->rfc_addr = mystrdup(client_addr.buf);
284 state->addr_family = sa->sa_family;
288 * Look up and sanity check the client hostname.
290 * It is unsafe to allow numeric hostnames, especially because there
291 * exists pressure to turn off the name->addr double check. In that
292 * case an attacker could trivally bypass access restrictions.
294 * sockaddr_to_hostname() already rejects malformed or numeric names.
296 #define TEMP_AI_ERROR(e) \
297 ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
299 #define REJECT_PEER_NAME(state, code) { \
300 myfree(state->name); \
301 state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
302 state->name_status = code; \
305 if (var_smtpd_peername_lookup == 0) {
306 state->name = mystrdup(CLIENT_NAME_UNKNOWN);
307 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
308 state->name_status = SMTPD_PEER_CODE_PERM;
309 state->reverse_name_status = SMTPD_PEER_CODE_PERM;
310 } else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name,
311 (MAI_SERVNAME_STR *) 0, 0)) != 0) {
312 state->name = mystrdup(CLIENT_NAME_UNKNOWN);
313 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
314 state->name_status = (TEMP_AI_ERROR(aierr) ?
315 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
316 state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
317 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
318 } else {
319 struct addrinfo *res0;
320 struct addrinfo *res;
322 state->name = mystrdup(client_name.buf);
323 state->reverse_name = mystrdup(client_name.buf);
324 state->name_status = SMTPD_PEER_CODE_OK;
325 state->reverse_name_status = SMTPD_PEER_CODE_OK;
328 * Reject the hostname if it does not list the peer address.
329 * Without further validation or qualification, such information
330 * must not be allowed to enter the audit trail, as people would
331 * draw false conclusions.
333 aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
334 if (aierr) {
335 msg_warn("%s: hostname %s verification failed: %s",
336 state->addr, state->name, MAI_STRERROR(aierr));
337 REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
338 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED));
339 } else {
340 for (res = res0; /* void */ ; res = res->ai_next) {
341 if (res == 0) {
342 msg_warn("%s: address not listed for hostname %s",
343 state->addr, state->name);
344 REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED);
345 break;
347 if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
348 msg_info("skipping address family %d for host %s",
349 res->ai_family, state->name);
350 continue;
352 if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
353 break; /* keep peer name */
355 freeaddrinfo(res0);
361 * If it's not Internet, assume the client is local, and avoid using the
362 * naming service because that can hang when the machine is disconnected.
364 else {
365 state->name = mystrdup("localhost");
366 state->reverse_name = mystrdup("localhost");
367 state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */
368 state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
369 state->addr_family = AF_UNSPEC;
370 state->name_status = SMTPD_PEER_CODE_OK;
371 state->reverse_name_status = SMTPD_PEER_CODE_OK;
372 state->port = mystrdup("0"); /* XXX bogus. */
376 * Do the name[addr]:port formatting for pretty reports.
378 state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr,
379 state->port);
382 /* smtpd_peer_reset - destroy peer information */
384 void smtpd_peer_reset(SMTPD_STATE *state)
386 myfree(state->name);
387 myfree(state->reverse_name);
388 myfree(state->addr);
389 myfree(state->namaddr);
390 myfree(state->rfc_addr);
391 myfree(state->port);