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/*	Alternatively, the peer address and port may be obtained
21/*	from a proxy server.
22/*
23/*	This module uses the local name service via getaddrinfo()
24/*	and getnameinfo(). It does not query the DNS directly.
25/*
26/*	smtpd_peer_init() updates the following fields:
27/* .IP name
28/*	The verified client hostname. This name is represented by
29/*	the string "unknown" when 1) the address->name lookup failed,
30/*	2) the name->address mapping fails, or 3) the name->address
31/*	mapping does not produce the client IP address.
32/* .IP reverse_name
33/*	The unverified client hostname as found with address->name
34/*	lookup; it is not verified for consistency with the client
35/*	IP address result from name->address lookup.
36/* .IP forward_name
37/*	The unverified client hostname as found with address->name
38/*	lookup followed by name->address lookup; it is not verified
39/*	for consistency with the result from address->name lookup.
40/*	For example, when the address->name lookup produces as
41/*	hostname an alias, the name->address lookup will produce
42/*	as hostname the expansion of that alias, so that the two
43/*	lookups produce different names.
44/* .IP addr
45/*	Printable representation of the client address.
46/* .IP namaddr
47/*	String of the form: "name[addr]:port".
48/* .IP rfc_addr
49/*      String of the form "ipv4addr" or "ipv6:ipv6addr" for use
50/*	in Received: message headers.
51/* .IP dest_addr
52/*	Server address, used by the Dovecot authentication server.
53/* .IP name_status
54/*	The name_status result field specifies how the name
55/*	information should be interpreted:
56/* .RS
57/* .IP 2
58/*	The address->name lookup and name->address lookup produced
59/*	the client IP address.
60/* .IP 4
61/*	The address->name lookup or name->address lookup failed
62/*	with a recoverable error.
63/* .IP 5
64/*	The address->name lookup or name->address lookup failed
65/*	with an unrecoverable error, or the result did not match
66/*	the client IP address.
67/* .RE
68/* .IP reverse_name_status
69/*	The reverse_name_status result field specifies how the
70/*	reverse_name information should be interpreted:
71/* .RS .IP 2
72/*	The address->name lookup succeeded.
73/* .IP 4
74/*	The address->name lookup failed with a recoverable error.
75/* .IP 5
76/*	The address->name lookup failed with an unrecoverable error.
77/* .RE .IP forward_name_status
78/*	The forward_name_status result field specifies how the
79/*	forward_name information should be interpreted:
80/* .RS .IP 2
81/*	The address->name and name->address lookup succeeded.
82/* .IP 4
83/*	The address->name lookup or name->address failed with a
84/*	recoverable error.
85/* .IP 5
86/*	The address->name lookup or name->address failed with an
87/*	unrecoverable error.
88/* .RE
89/* .PP
90/*	smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
91/* LICENSE
92/* .ad
93/* .fi
94/*	The Secure Mailer license must be distributed with this software.
95/* AUTHOR(S)
96/*	Wietse Venema
97/*	IBM T.J. Watson Research
98/*	P.O. Box 704
99/*	Yorktown Heights, NY 10598, USA
100/*--*/
101
102/* System library. */
103
104#include <sys_defs.h>
105#include <sys/socket.h>
106#include <netinet/in.h>
107#include <arpa/inet.h>
108#include <stdio.h>			/* strerror() */
109#include <errno.h>
110#include <netdb.h>
111#include <string.h>
112#include <htable.h>
113
114/* Utility library. */
115
116#include <msg.h>
117#include <mymalloc.h>
118#include <stringops.h>
119#include <myaddrinfo.h>
120#include <sock_addr.h>
121#include <inet_proto.h>
122#include <split_at.h>
123
124/* Global library. */
125
126#include <mail_proto.h>
127#include <valid_mailhost_addr.h>
128#include <mail_params.h>
129#include <haproxy_srvr.h>
130
131/* Application-specific. */
132
133#include "smtpd.h"
134
135static INET_PROTO_INFO *proto_info;
136
137 /*
138  * XXX If we make local endpoint (getsockname) information available to
139  * Milter applications as {if_name} and {if_addr}, then we also must be able
140  * to provide this via the XCLIENT command for Milter testing.
141  *
142  * XXX If we make local port information available to policy servers or Milter
143  * applications, then we must also make this testable with the XCLIENT
144  * command, otherwise there will be confusion.
145  *
146  * XXX If we make local port information available via logging, then we must
147  * also support these attributes with the XFORWARD command.
148  *
149  * XXX If support were to be added for Milter applications in down-stream MTAs,
150  * then consistency demands that we propagate a lot of Sendmail macro
151  * information via the XFORWARD command. Otherwise we could end up with a
152  * very confusing situation.
153  */
154
155/* smtpd_peer_sockaddr_to_hostaddr - client address/port to printable form */
156
157static int smtpd_peer_sockaddr_to_hostaddr(SMTPD_STATE *state)
158{
159    const char *myname = "smtpd_peer_sockaddr_to_hostaddr";
160    struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
161    SOCKADDR_SIZE sa_length = state->sockaddr_len;
162
163    /*
164     * XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd,
165     * while Postfix IPv6 (or IPv4) support is turned off, don't (skip to the
166     * final else clause, pretend the origin is localhost[127.0.0.1], and
167     * become an open relay).
168     */
169    if (sa->sa_family == AF_INET
170#ifdef AF_INET6
171	|| sa->sa_family == AF_INET6
172#endif
173	) {
174	MAI_HOSTADDR_STR client_addr;
175	MAI_SERVPORT_STR client_port;
176	int     aierr;
177	char   *colonp;
178
179	/*
180	 * Sanity check: we can't use sockets that we're not configured for.
181	 */
182	if (strchr((char *) proto_info->sa_family_list, sa->sa_family) == 0)
183	    msg_fatal("cannot handle socket type %s with \"%s = %s\"",
184#ifdef AF_INET6
185		      sa->sa_family == AF_INET6 ? "AF_INET6" :
186#endif
187		      sa->sa_family == AF_INET ? "AF_INET" :
188		      "other", VAR_INET_PROTOCOLS, var_inet_protocols);
189
190	/*
191	 * Sorry, but there are some things that we just cannot do while
192	 * connected to the network.
193	 */
194	if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
195	    msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
196		      (unsigned long) getuid(), (unsigned long) geteuid());
197	    msg_fatal("the Postfix SMTP server must run with $%s privileges",
198		      VAR_MAIL_OWNER);
199	}
200
201	/*
202	 * Convert the client address to printable form.
203	 */
204	if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
205					  &client_port, 0)) != 0)
206	    msg_fatal("%s: cannot convert client address/port to string: %s",
207		      myname, MAI_STRERROR(aierr));
208	state->port = mystrdup(client_port.buf);
209
210	/*
211	 * XXX Require that the infrastructure strips off the IPv6 datalink
212	 * suffix to avoid false alarms with strict address syntax checks.
213	 */
214#ifdef HAS_IPV6
215	if (strchr(client_addr.buf, '%') != 0)
216	    msg_panic("%s: address %s has datalink suffix",
217		      myname, client_addr.buf);
218#endif
219
220	/*
221	 * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
222	 * but only if IPv4 support is enabled (why would anyone want to turn
223	 * it off)? With IPv4 support enabled we have no need for the IPv6
224	 * form in logging, hostname verification and access checks.
225	 */
226#ifdef HAS_IPV6
227	if (sa->sa_family == AF_INET6) {
228	    if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
229		&& IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
230		&& (colonp = strrchr(client_addr.buf, ':')) != 0) {
231		struct addrinfo *res0;
232
233		if (msg_verbose > 1)
234		    msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
235			     myname, client_addr.buf, colonp + 1);
236
237		state->addr = mystrdup(colonp + 1);
238		state->rfc_addr = mystrdup(colonp + 1);
239		state->addr_family = AF_INET;
240		aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
241		if (aierr)
242		    msg_fatal("%s: cannot convert %s from string to binary: %s",
243			      myname, state->addr, MAI_STRERROR(aierr));
244		sa_length = res0->ai_addrlen;
245		if (sa_length > sizeof(state->sockaddr))
246		    sa_length = sizeof(state->sockaddr);
247		memcpy((char *) sa, res0->ai_addr, sa_length);
248		freeaddrinfo(res0);		/* 200412 */
249	    }
250
251	    /*
252	     * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
253	     * a prefix of 'IPv6:'. We do this consistently for all IPv6
254	     * addresses that that appear in headers or envelopes. The fact
255	     * that valid_mailhost_addr() enforces the form helps of course.
256	     * We use the form without IPV6: prefix when doing access
257	     * control, or when accessing the connection cache.
258	     */
259	    else {
260		state->addr = mystrdup(client_addr.buf);
261		state->rfc_addr =
262		    concatenate(IPV6_COL, client_addr.buf, (char *) 0);
263		state->addr_family = sa->sa_family;
264	    }
265	}
266
267	/*
268	 * An IPv4 address is in dotted quad decimal form.
269	 */
270	else
271#endif
272	{
273	    state->addr = mystrdup(client_addr.buf);
274	    state->rfc_addr = mystrdup(client_addr.buf);
275	    state->addr_family = sa->sa_family;
276	}
277	return (0);
278    }
279
280    /*
281     * It's not Internet.
282     */
283    else {
284	return (-1);
285    }
286}
287
288/* smtpd_peer_sockaddr_to_hostname - client hostname lookup */
289
290static void smtpd_peer_sockaddr_to_hostname(SMTPD_STATE *state)
291{
292    struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
293    SOCKADDR_SIZE sa_length = state->sockaddr_len;
294    MAI_HOSTNAME_STR client_name;
295    int     aierr;
296
297    /*
298     * Look up and sanity check the client hostname.
299     *
300     * It is unsafe to allow numeric hostnames, especially because there exists
301     * pressure to turn off the name->addr double check. In that case an
302     * attacker could trivally bypass access restrictions.
303     *
304     * sockaddr_to_hostname() already rejects malformed or numeric names.
305     */
306#define TEMP_AI_ERROR(e) \
307	((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
308
309#define REJECT_PEER_NAME(state, code) { \
310	myfree(state->name); \
311	state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
312	state->name_status = code; \
313    }
314
315    if (var_smtpd_peername_lookup == 0) {
316	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
317	state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
318	state->name_status = SMTPD_PEER_CODE_PERM;
319	state->reverse_name_status = SMTPD_PEER_CODE_PERM;
320    } else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name,
321					 (MAI_SERVNAME_STR *) 0, 0)) != 0) {
322	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
323	state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
324	state->name_status = (TEMP_AI_ERROR(aierr) ?
325			      SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
326	state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
327			       SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
328    } else {
329	struct addrinfo *res0;
330	struct addrinfo *res;
331
332	state->name = mystrdup(client_name.buf);
333	state->reverse_name = mystrdup(client_name.buf);
334	state->name_status = SMTPD_PEER_CODE_OK;
335	state->reverse_name_status = SMTPD_PEER_CODE_OK;
336
337	/*
338	 * Reject the hostname if it does not list the peer address. Without
339	 * further validation or qualification, such information must not be
340	 * allowed to enter the audit trail, as people would draw false
341	 * conclusions.
342	 */
343	aierr = hostname_to_sockaddr_pf(state->name, state->addr_family,
344					(char *) 0, 0, &res0);
345	if (aierr) {
346	    msg_warn("hostname %s does not resolve to address %s: %s",
347		     state->name, state->addr, MAI_STRERROR(aierr));
348	    REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
349			    SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED));
350	} else {
351	    for (res = res0; /* void */ ; res = res->ai_next) {
352		if (res == 0) {
353		    msg_warn("hostname %s does not resolve to address %s",
354			     state->name, state->addr);
355		    REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED);
356		    break;
357		}
358		if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
359		    msg_info("skipping address family %d for host %s",
360			     res->ai_family, state->name);
361		    continue;
362		}
363		if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
364		    break;			/* keep peer name */
365	    }
366	    freeaddrinfo(res0);
367	}
368    }
369}
370
371/* smtpd_peer_hostaddr_to_sockaddr - convert numeric string to binary */
372
373static void smtpd_peer_hostaddr_to_sockaddr(SMTPD_STATE *state)
374{
375    const char *myname = "smtpd_peer_hostaddr_to_sockaddr";
376    struct addrinfo *res;
377    int     aierr;
378
379    if ((aierr = hostaddr_to_sockaddr(state->addr, state->port,
380				      SOCK_STREAM, &res)) != 0)
381	msg_fatal("%s: cannot convert client address/port to string: %s",
382		  myname, MAI_STRERROR(aierr));
383    if (res->ai_addrlen > sizeof(state->sockaddr))
384	msg_panic("%s: address length > struct sockaddr_storage", myname);
385    memcpy((char *) &(state->sockaddr), res->ai_addr, res->ai_addrlen);
386    state->sockaddr_len = res->ai_addrlen;
387    freeaddrinfo(res);
388}
389
390/* smtpd_peer_not_inet - non-socket or non-Internet endpoint */
391
392static void smtpd_peer_not_inet(SMTPD_STATE *state)
393{
394
395    /*
396     * If it's not Internet, assume the client is local, and avoid using the
397     * naming service because that can hang when the machine is disconnected.
398     */
399    state->name = mystrdup("localhost");
400    state->reverse_name = mystrdup("localhost");
401#ifdef AF_INET6
402    if (proto_info->sa_family_list[0] == PF_INET6) {
403	state->addr = mystrdup("::1");		/* XXX bogus. */
404	state->rfc_addr = mystrdup(IPV6_COL "::1");	/* XXX bogus. */
405    } else
406#endif
407    {
408	state->addr = mystrdup("127.0.0.1");	/* XXX bogus. */
409	state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
410    }
411    state->addr_family = AF_UNSPEC;
412    state->name_status = SMTPD_PEER_CODE_OK;
413    state->reverse_name_status = SMTPD_PEER_CODE_OK;
414    state->port = mystrdup("0");		/* XXX bogus. */
415}
416
417/* smtpd_peer_no_client - peer went away, or peer info unavailable */
418
419static void smtpd_peer_no_client(SMTPD_STATE *state)
420{
421    smtpd_peer_reset(state);
422    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
423    state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
424    state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
425    state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
426    state->addr_family = AF_UNSPEC;
427    state->name_status = SMTPD_PEER_CODE_PERM;
428    state->reverse_name_status = SMTPD_PEER_CODE_PERM;
429    state->port = mystrdup(CLIENT_PORT_UNKNOWN);
430}
431
432/* smtpd_peer_from_pass_attr - initialize from attribute hash */
433
434static void smtpd_peer_from_pass_attr(SMTPD_STATE *state)
435{
436    HTABLE *attr = (HTABLE *) vstream_context(state->client);
437    const char *cp;
438
439    /*
440     * Extract the client endpoint information from the attribute hash.
441     */
442    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0)
443	msg_fatal("missing client address from proxy");
444    if (strrchr(cp, ':') != 0) {
445	if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0)
446	    msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
447	state->addr = mystrdup(cp);
448	state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0);
449	state->addr_family = AF_INET6;
450    } else {
451	if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0)
452	    msg_fatal("bad IPv4 client address syntax from proxy: %s", cp);
453	state->addr = mystrdup(cp);
454	state->rfc_addr = mystrdup(cp);
455	state->addr_family = AF_INET;
456    }
457    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0)
458	msg_fatal("missing client port from proxy");
459    if (valid_hostport(cp, DO_GRIPE) == 0)
460	msg_fatal("bad TCP client port number syntax from proxy: %s", cp);
461    state->port = mystrdup(cp);
462
463    /*
464     * Avoid surprises in the Dovecot authentication server.
465     */
466    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0)
467	msg_fatal("missing server address from proxy");
468    if (valid_hostaddr(cp, DO_GRIPE) == 0)
469	msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
470    state->dest_addr = mystrdup(cp);
471
472    /*
473     * Convert the client address from string to binary form.
474     */
475    smtpd_peer_hostaddr_to_sockaddr(state);
476}
477
478/* smtpd_peer_from_default - try to initialize peer information from socket */
479
480static void smtpd_peer_from_default(SMTPD_STATE *state)
481{
482    SOCKADDR_SIZE sa_length = sizeof(state->sockaddr);
483    struct sockaddr *sa = (struct sockaddr *) & (state->sockaddr);
484
485    /*
486     * The "no client" routine provides surrogate information so that the
487     * application can produce sensible logging when a client disconnects
488     * before the server wakes up. The "not inet" routine provides surrogate
489     * state for (presumably) local IPC channels.
490     */
491    if (getpeername(vstream_fileno(state->client), sa, &sa_length) < 0) {
492	if (errno == ENOTSOCK)
493	    smtpd_peer_not_inet(state);
494	else
495	    smtpd_peer_no_client(state);
496    } else {
497	state->sockaddr_len = sa_length;
498	if (smtpd_peer_sockaddr_to_hostaddr(state) < 0)
499	    smtpd_peer_not_inet(state);
500    }
501}
502
503/* smtpd_peer_from_proxy - get endpoint info from proxy agent */
504
505static void smtpd_peer_from_proxy(SMTPD_STATE *state)
506{
507    typedef struct {
508	const char *name;
509	int     (*endpt_lookup) (SMTPD_STATE *);
510    } SMTPD_ENDPT_LOOKUP_INFO;
511    static const SMTPD_ENDPT_LOOKUP_INFO smtpd_endpt_lookup_info[] = {
512	HAPROXY_PROTO_NAME, smtpd_peer_from_haproxy,
513	0,
514    };
515    const SMTPD_ENDPT_LOOKUP_INFO *pp;
516
517    /*
518     * When the proxy information is unavailable, we can't maintain an audit
519     * trail or enforce access control, therefore we forcibly hang up.
520     */
521    for (pp = smtpd_endpt_lookup_info; /* see below */ ; pp++) {
522	if (pp->name == 0)
523	    msg_fatal("unsupported %s value: %s",
524		      VAR_SMTPD_UPROXY_PROTO, var_smtpd_uproxy_proto);
525	if (strcmp(var_smtpd_uproxy_proto, pp->name) == 0)
526	    break;
527    }
528    if (pp->endpt_lookup(state) < 0) {
529	smtpd_peer_no_client(state);
530	state->flags |= SMTPD_FLAG_HANGUP;
531    } else {
532	smtpd_peer_hostaddr_to_sockaddr(state);
533    }
534}
535
536/* smtpd_peer_init - initialize peer information */
537
538void    smtpd_peer_init(SMTPD_STATE *state)
539{
540
541    /*
542     * Initialize.
543     */
544    if (proto_info == 0)
545	proto_info = inet_proto_info();
546
547    /*
548     * Prepare for partial initialization after error.
549     */
550    memset((char *) &(state->sockaddr), 0, sizeof(state->sockaddr));
551    state->sockaddr_len = 0;
552    state->name = 0;
553    state->reverse_name = 0;
554    state->addr = 0;
555    state->namaddr = 0;
556    state->rfc_addr = 0;
557    state->port = 0;
558    state->dest_addr = 0;
559
560    /*
561     * Determine the remote SMTP client address and port.
562     *
563     * XXX In stand-alone mode, don't assume that the peer will be a local
564     * process. That could introduce a gaping hole when the SMTP daemon is
565     * hooked up to the network via inetd or some other super-server.
566     */
567    if (vstream_context(state->client) != 0) {
568	smtpd_peer_from_pass_attr(state);
569	if (*var_smtpd_uproxy_proto != 0)
570	    msg_warn("ignoring non-empty %s setting behind postscreen",
571		     VAR_SMTPD_UPROXY_PROTO);
572    } else if (SMTPD_STAND_ALONE(state) || *var_smtpd_uproxy_proto == 0) {
573	smtpd_peer_from_default(state);
574    } else {
575	smtpd_peer_from_proxy(state);
576    }
577
578    /*
579     * Determine the remote SMTP client hostname. Note: some of the handlers
580     * above provide surrogate endpoint information in case of error. In that
581     * case, leave the surrogate information alone.
582     */
583    if (state->name == 0)
584	smtpd_peer_sockaddr_to_hostname(state);
585
586    /*
587     * Do the name[addr]:port formatting for pretty reports.
588     */
589    state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr,
590					     state->port);
591}
592
593/* smtpd_peer_reset - destroy peer information */
594
595void    smtpd_peer_reset(SMTPD_STATE *state)
596{
597    if (state->name)
598	myfree(state->name);
599    if (state->reverse_name)
600	myfree(state->reverse_name);
601    if (state->addr)
602	myfree(state->addr);
603    if (state->namaddr)
604	myfree(state->namaddr);
605    if (state->rfc_addr)
606	myfree(state->rfc_addr);
607    if (state->port)
608	myfree(state->port);
609    if (state->dest_addr)
610	myfree(state->dest_addr);
611}
612