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/* This module uses the local name service via getaddrinfo() 21/* and getnameinfo(). It does not query the DNS directly. 22/* 23/* smtpd_peer_init() updates the following fields: 24/* .IP name 25/* The verified client hostname. This name is represented by 26/* the string "unknown" when 1) the address->name lookup failed, 27/* 2) the name->address mapping fails, or 3) the name->address 28/* mapping does not produce the client IP address. 29/* .IP reverse_name 30/* The unverified client hostname as found with address->name 31/* lookup; it is not verified for consistency with the client 32/* IP address result from name->address lookup. 33/* .IP forward_name 34/* The unverified client hostname as found with address->name 35/* lookup followed by name->address lookup; it is not verified 36/* for consistency with the result from address->name lookup. 37/* For example, when the address->name lookup produces as 38/* hostname an alias, the name->address lookup will produce 39/* as hostname the expansion of that alias, so that the two 40/* lookups produce different names. 41/* .IP addr 42/* Printable representation of the client address. 43/* .IP namaddr 44/* String of the form: "name[addr]:port". 45/* .IP rfc_addr 46/* String of the form "ipv4addr" or "ipv6:ipv6addr" for use 47/* in Received: message headers. 48/* .IP name_status 49/* The name_status result field specifies how the name 50/* information should be interpreted: 51/* .RS 52/* .IP 2 53/* The address->name lookup and name->address lookup produced 54/* the client IP address. 55/* .IP 4 56/* The address->name lookup or name->address lookup failed 57/* with a recoverable error. 58/* .IP 5 59/* The address->name lookup or name->address lookup failed 60/* with an unrecoverable error, or the result did not match 61/* the client IP address. 62/* .RE 63/* .IP reverse_name_status 64/* The reverse_name_status result field specifies how the 65/* reverse_name information should be interpreted: 66/* .RS .IP 2 67/* The address->name lookup succeeded. 68/* .IP 4 69/* The address->name lookup failed with a recoverable error. 70/* .IP 5 71/* The address->name lookup failed with an unrecoverable error. 72/* .RE .IP forward_name_status 73/* The forward_name_status result field specifies how the 74/* forward_name information should be interpreted: 75/* .RS .IP 2 76/* The address->name and name->address lookup succeeded. 77/* .IP 4 78/* The address->name lookup or name->address failed with a 79/* recoverable error. 80/* .IP 5 81/* The address->name lookup or name->address failed with an 82/* unrecoverable error. 83/* .RE 84/* .PP 85/* smtpd_peer_reset() releases memory allocated by smtpd_peer_init(). 86/* LICENSE 87/* .ad 88/* .fi 89/* The Secure Mailer license must be distributed with this software. 90/* AUTHOR(S) 91/* Wietse Venema 92/* IBM T.J. Watson Research 93/* P.O. Box 704 94/* Yorktown Heights, NY 10598, USA 95/*--*/ 96 97/* System library. */ 98 99#include <sys_defs.h> 100#include <sys/socket.h> 101#include <netinet/in.h> 102#include <arpa/inet.h> 103#include <stdio.h> /* strerror() */ 104#include <errno.h> 105#include <netdb.h> 106#include <string.h> 107 108/* Utility library. */ 109 110#include <msg.h> 111#include <mymalloc.h> 112#include <stringops.h> 113#include <myaddrinfo.h> 114#include <sock_addr.h> 115#include <inet_proto.h> 116#include <split_at.h> 117 118/* Global library. */ 119 120#include <mail_proto.h> 121#include <valid_mailhost_addr.h> 122#include <mail_params.h> 123 124/* Application-specific. */ 125 126#include "smtpd.h" 127 128/* smtpd_peer_init - initialize peer information */ 129 130void smtpd_peer_init(SMTPD_STATE *state) 131{ 132 const char *myname = "smtpd_peer_init"; 133 SOCKADDR_SIZE sa_length; 134 struct sockaddr *sa; 135 INET_PROTO_INFO *proto_info = inet_proto_info(); 136 137 sa = (struct sockaddr *) & (state->sockaddr); 138 sa_length = sizeof(state->sockaddr); 139 140 /* 141 * Look up the peer address information. 142 * 143 * XXX If we make local endpoint (getsockname) information available to 144 * Milter applications as {if_name} and {if_addr}, then we also must be 145 * able to provide this via the XCLIENT command for Milter testing. 146 * 147 * XXX If we make local or remote port information available to policy 148 * servers or Milter applications, then we must also make this testable 149 * with the XCLIENT command, otherwise there will be confusion. 150 * 151 * XXX If we make local or remote port information available via logging, 152 * then we must also support these attributes with the XFORWARD command. 153 * 154 * XXX If support were to be added for Milter applications in down-stream 155 * MTAs, then consistency demands that we propagate a lot of Sendmail 156 * macro information via the XFORWARD command. Otherwise we could end up 157 * with a very confusing situation. 158 */ 159 if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) { 160 errno = 0; 161 } 162 163 /* 164 * If peer went away, give up. 165 */ 166 if (errno != 0 && errno != ENOTSOCK) { 167 state->name = mystrdup(CLIENT_NAME_UNKNOWN); 168 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN); 169 state->addr = mystrdup(CLIENT_ADDR_UNKNOWN); 170 state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN); 171 state->addr_family = AF_UNSPEC; 172 state->name_status = SMTPD_PEER_CODE_PERM; 173 state->reverse_name_status = SMTPD_PEER_CODE_PERM; 174 state->port = mystrdup(CLIENT_PORT_UNKNOWN); 175 } 176 177 /* 178 * Convert the client address to printable address and hostname. 179 * 180 * XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd, while 181 * Postfix IPv6 (or IPv4) support is turned off, don't (skip to the final 182 * else clause, pretend the origin is localhost[127.0.0.1], and become an 183 * open relay). 184 */ 185 else if (errno == 0 186 && (sa->sa_family == AF_INET 187#ifdef AF_INET6 188 || sa->sa_family == AF_INET6 189#endif 190 )) { 191 MAI_HOSTNAME_STR client_name; 192 MAI_HOSTADDR_STR client_addr; 193 MAI_SERVPORT_STR client_port; 194 int aierr; 195 char *colonp; 196 197 /* 198 * Sanity check: we can't use sockets that we're not configured for. 199 */ 200 if (strchr((char *) proto_info->sa_family_list, sa->sa_family) == 0) 201 msg_fatal("cannot handle socket type %s with \"%s = %s\"", 202#ifdef AF_INET6 203 sa->sa_family == AF_INET6 ? "AF_INET6" : 204#endif 205 sa->sa_family == AF_INET ? "AF_INET" : 206 "other", VAR_INET_PROTOCOLS, var_inet_protocols); 207 208 /* 209 * Sorry, but there are some things that we just cannot do while 210 * connected to the network. 211 */ 212 if (geteuid() != var_owner_uid || getuid() != var_owner_uid) { 213 msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu", 214 (unsigned long) getuid(), (unsigned long) geteuid()); 215 msg_fatal("the Postfix SMTP server must run with $%s privileges", 216 VAR_MAIL_OWNER); 217 } 218 219 /* 220 * Convert the client address to printable form. 221 */ 222 if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr, 223 &client_port, 0)) != 0) 224 msg_fatal("%s: cannot convert client address/port to string: %s", 225 myname, MAI_STRERROR(aierr)); 226 state->port = mystrdup(client_port.buf); 227 228 /* 229 * XXX Strip off the IPv6 datalink suffix to avoid false alarms with 230 * strict address syntax checks. 231 */ 232#ifdef HAS_IPV6 233 (void) split_at(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 = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0); 257 if (aierr) 258 msg_fatal("%s: cannot convert %s from string to binary: %s", 259 myname, state->addr, MAI_STRERROR(aierr)); 260 sa_length = res0->ai_addrlen; 261 if (sa_length > sizeof(state->sockaddr)) 262 sa_length = sizeof(state->sockaddr); 263 memcpy((char *) sa, res0->ai_addr, sa_length); 264 freeaddrinfo(res0); /* 200412 */ 265 } 266 267 /* 268 * Following RFC 2821 section 4.1.3, an IPv6 address literal gets 269 * a prefix of 'IPv6:'. We do this consistently for all IPv6 270 * addresses that that appear in headers or envelopes. The fact 271 * that valid_mailhost_addr() enforces the form helps of course. 272 * We use the form without IPV6: prefix when doing access 273 * control, or when accessing the connection cache. 274 */ 275 else { 276 state->addr = mystrdup(client_addr.buf); 277 state->rfc_addr = 278 concatenate(IPV6_COL, client_addr.buf, (char *) 0); 279 state->addr_family = sa->sa_family; 280 } 281 } 282 283 /* 284 * An IPv4 address is in dotted quad decimal form. 285 */ 286 else 287#endif 288 { 289 state->addr = mystrdup(client_addr.buf); 290 state->rfc_addr = mystrdup(client_addr.buf); 291 state->addr_family = sa->sa_family; 292 } 293 294 /* 295 * Look up and sanity check the client hostname. 296 * 297 * It is unsafe to allow numeric hostnames, especially because there 298 * exists pressure to turn off the name->addr double check. In that 299 * case an attacker could trivally bypass access restrictions. 300 * 301 * sockaddr_to_hostname() already rejects malformed or numeric names. 302 */ 303#define TEMP_AI_ERROR(e) \ 304 ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM) 305 306#define REJECT_PEER_NAME(state, code) { \ 307 myfree(state->name); \ 308 state->name = mystrdup(CLIENT_NAME_UNKNOWN); \ 309 state->name_status = code; \ 310 } 311 312 if (var_smtpd_peername_lookup == 0) { 313 state->name = mystrdup(CLIENT_NAME_UNKNOWN); 314 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN); 315 state->name_status = SMTPD_PEER_CODE_PERM; 316 state->reverse_name_status = SMTPD_PEER_CODE_PERM; 317 } else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name, 318 (MAI_SERVNAME_STR *) 0, 0)) != 0) { 319 state->name = mystrdup(CLIENT_NAME_UNKNOWN); 320 state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN); 321 state->name_status = (TEMP_AI_ERROR(aierr) ? 322 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM); 323 state->reverse_name_status = (TEMP_AI_ERROR(aierr) ? 324 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM); 325 } else { 326 struct addrinfo *res0; 327 struct addrinfo *res; 328 329 state->name = mystrdup(client_name.buf); 330 state->reverse_name = mystrdup(client_name.buf); 331 state->name_status = SMTPD_PEER_CODE_OK; 332 state->reverse_name_status = SMTPD_PEER_CODE_OK; 333 334 /* 335 * Reject the hostname if it does not list the peer address. 336 * Without further validation or qualification, such information 337 * must not be allowed to enter the audit trail, as people would 338 * draw false conclusions. 339 */ 340 aierr = hostname_to_sockaddr_pf(state->name, state->addr_family, 341 (char *) 0, 0, &res0); 342 if (aierr) { 343 msg_warn("hostname %s does not resolve to address %s: %s", 344 state->name, state->addr, MAI_STRERROR(aierr)); 345 REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ? 346 SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED)); 347 } else { 348 for (res = res0; /* void */ ; res = res->ai_next) { 349 if (res == 0) { 350 msg_warn("hostname %s does not resolve to address %s", 351 state->name, state->addr); 352 REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED); 353 break; 354 } 355 if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) { 356 msg_info("skipping address family %d for host %s", 357 res->ai_family, state->name); 358 continue; 359 } 360 if (sock_addr_cmp_addr(res->ai_addr, sa) == 0) 361 break; /* keep peer name */ 362 } 363 freeaddrinfo(res0); 364 } 365 } 366 } 367 368 /* 369 * If it's not Internet, assume the client is local, and avoid using the 370 * naming service because that can hang when the machine is disconnected. 371 */ 372 else { 373 state->name = mystrdup("localhost"); 374 state->reverse_name = mystrdup("localhost"); 375 if (proto_info->sa_family_list[0] == PF_INET6) { 376 state->addr = mystrdup("::1"); /* XXX bogus. */ 377 state->rfc_addr = mystrdup(IPV6_COL "::1"); /* XXX bogus. */ 378 } else { 379 state->addr = mystrdup("127.0.0.1");/* XXX bogus. */ 380 state->rfc_addr = mystrdup("127.0.0.1"); /* XXX bogus. */ 381 } 382 state->addr_family = AF_UNSPEC; 383 state->name_status = SMTPD_PEER_CODE_OK; 384 state->reverse_name_status = SMTPD_PEER_CODE_OK; 385 state->port = mystrdup("0"); /* XXX bogus. */ 386 } 387 388 /* 389 * Do the name[addr]:port formatting for pretty reports. 390 */ 391 state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr, 392 state->port); 393} 394 395/* smtpd_peer_reset - destroy peer information */ 396 397void smtpd_peer_reset(SMTPD_STATE *state) 398{ 399 myfree(state->name); 400 myfree(state->reverse_name); 401 myfree(state->addr); 402 myfree(state->namaddr); 403 myfree(state->rfc_addr); 404 myfree(state->port); 405} 406