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