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