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