7 /* look up peer name/address information
11 /* void smtpd_peer_init(state)
12 /* SMTPD_STATE *state;
14 /* void smtpd_peer_reset(state)
15 /* SMTPD_STATE *state;
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:
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.
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.
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.
44 /* Printable representation of the client address.
46 /* String of the form: "name[addr]:port".
48 /* String of the form "ipv4addr" or "ipv6:ipv6addr" for use
49 /* in Received: message headers.
51 /* The name_status result field specifies how the name
52 /* information should be interpreted:
55 /* The address->name lookup and name->address lookup produced
56 /* the client IP address.
58 /* The address->name lookup or name->address lookup failed
59 /* with a recoverable error.
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.
65 /* .IP reverse_name_status
66 /* The reverse_name_status result field specifies how the
67 /* reverse_name information should be interpreted:
69 /* The address->name lookup succeeded.
71 /* The address->name lookup failed with a recoverable error.
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:
78 /* The address->name and name->address lookup succeeded.
80 /* The address->name lookup or name->address failed with a
83 /* The address->name lookup or name->address failed with an
84 /* unrecoverable error.
87 /* smtpd_peer_reset() releases memory allocated by smtpd_peer_init().
91 /* The Secure Mailer license must be distributed with this software.
94 /* IBM T.J. Watson Research
96 /* Yorktown Heights, NY 10598, USA
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() */
110 /* Utility library. */
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. */
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
;
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) {
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
187 && (sa
->sa_family
== AF_INET
189 || sa
->sa_family
== AF_INET6
192 MAI_HOSTNAME_STR client_name
;
193 MAI_HOSTADDR_STR client_addr
;
194 MAI_SERVPORT_STR client_port
;
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\"",
204 sa
->sa_family
== AF_INET6
? "AF_INET6" :
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",
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.
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
;
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
);
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.
269 state
->addr
= mystrdup(client_addr
.buf
);
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.
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
);
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
);
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
));
340 for (res
= res0
; /* void */ ; res
= res
->ai_next
) {
342 msg_warn("%s: address not listed for hostname %s",
343 state
->addr
, state
->name
);
344 REJECT_PEER_NAME(state
, SMTPD_PEER_CODE_FORGED
);
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
);
352 if (sock_addr_cmp_addr(res
->ai_addr
, sa
) == 0)
353 break; /* keep peer name */
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.
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
,
382 /* smtpd_peer_reset - destroy peer information */
384 void smtpd_peer_reset(SMTPD_STATE
*state
)
387 myfree(state
->reverse_name
);
389 myfree(state
->namaddr
);
390 myfree(state
->rfc_addr
);