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