Home | History | Annotate | Download | only in openssh
      1 /* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */
      2 /*
      3  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      4  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      5  *                    All rights reserved
      6  * Functions for returning the canonical host name of the remote site.
      7  *
      8  * As far as I am concerned, the code I have written for this software
      9  * can be used freely for any purpose.  Any derived versions of this
     10  * software must be clearly marked as such, and if the derived work is
     11  * incompatible with the protocol description in the RFC file, it must be
     12  * called by a name other than "ssh" or "Secure Shell".
     13  */
     14 
     15 #include "includes.h"
     16 
     17 #include <sys/types.h>
     18 #include <sys/socket.h>
     19 #include <sys/un.h>
     20 
     21 #include <netinet/in.h>
     22 #include <arpa/inet.h>
     23 
     24 #include <errno.h>
     25 #include <netdb.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <stdarg.h>
     30 #include <unistd.h>
     31 
     32 #include "xmalloc.h"
     33 #include "packet.h"
     34 #include "log.h"
     35 #include "canohost.h"
     36 #include "misc.h"
     37 
     38 static void check_ip_options(int, char *);
     39 static char *canonical_host_ip = NULL;
     40 static int cached_port = -1;
     41 
     42 /*
     43  * Return the canonical name of the host at the other end of the socket. The
     44  * caller should free the returned string.
     45  */
     46 
     47 static char *
     48 get_remote_hostname(int sock, int use_dns)
     49 {
     50 	struct sockaddr_storage from;
     51 	socklen_t fromlen;
     52 	struct addrinfo hints, *ai, *aitop;
     53 	char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
     54 
     55 	/* Get IP address of client. */
     56 	fromlen = sizeof(from);
     57 	memset(&from, 0, sizeof(from));
     58 	if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
     59 		debug("getpeername failed: %.100s", strerror(errno));
     60 		cleanup_exit(255);
     61 	}
     62 
     63 	if (from.ss_family == AF_INET)
     64 		check_ip_options(sock, ntop);
     65 
     66 	ipv64_normalise_mapped(&from, &fromlen);
     67 
     68 	if (from.ss_family == AF_INET6)
     69 		fromlen = sizeof(struct sockaddr_in6);
     70 
     71 	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
     72 	    NULL, 0, NI_NUMERICHOST) != 0)
     73 		fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
     74 
     75 	if (!use_dns)
     76 		return xstrdup(ntop);
     77 
     78 	debug3("Trying to reverse map address %.100s.", ntop);
     79 	/* Map the IP address to a host name. */
     80 	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
     81 	    NULL, 0, NI_NAMEREQD) != 0) {
     82 		/* Host name not found.  Use ip address. */
     83 		return xstrdup(ntop);
     84 	}
     85 
     86 	/*
     87 	 * if reverse lookup result looks like a numeric hostname,
     88 	 * someone is trying to trick us by PTR record like following:
     89 	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5
     90 	 */
     91 	memset(&hints, 0, sizeof(hints));
     92 	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
     93 	hints.ai_flags = AI_NUMERICHOST;
     94 	if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
     95 		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
     96 		    name, ntop);
     97 		freeaddrinfo(ai);
     98 		return xstrdup(ntop);
     99 	}
    100 
    101 	/* Names are stores in lowercase. */
    102 	lowercase(name);
    103 
    104 	/*
    105 	 * Map it back to an IP address and check that the given
    106 	 * address actually is an address of this host.  This is
    107 	 * necessary because anyone with access to a name server can
    108 	 * define arbitrary names for an IP address. Mapping from
    109 	 * name to IP address can be trusted better (but can still be
    110 	 * fooled if the intruder has access to the name server of
    111 	 * the domain).
    112 	 */
    113 	memset(&hints, 0, sizeof(hints));
    114 	hints.ai_family = from.ss_family;
    115 	hints.ai_socktype = SOCK_STREAM;
    116 	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
    117 		logit("reverse mapping checking getaddrinfo for %.700s "
    118 		    "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
    119 		return xstrdup(ntop);
    120 	}
    121 	/* Look for the address from the list of addresses. */
    122 	for (ai = aitop; ai; ai = ai->ai_next) {
    123 		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
    124 		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
    125 		    (strcmp(ntop, ntop2) == 0))
    126 				break;
    127 	}
    128 	freeaddrinfo(aitop);
    129 	/* If we reached the end of the list, the address was not there. */
    130 	if (!ai) {
    131 		/* Address not found for the host name. */
    132 		logit("Address %.100s maps to %.600s, but this does not "
    133 		    "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
    134 		    ntop, name);
    135 		return xstrdup(ntop);
    136 	}
    137 	return xstrdup(name);
    138 }
    139 
    140 /*
    141  * If IP options are supported, make sure there are none (log and
    142  * disconnect them if any are found).  Basically we are worried about
    143  * source routing; it can be used to pretend you are somebody
    144  * (ip-address) you are not. That itself may be "almost acceptable"
    145  * under certain circumstances, but rhosts autentication is useless
    146  * if source routing is accepted. Notice also that if we just dropped
    147  * source routing here, the other side could use IP spoofing to do
    148  * rest of the interaction and could still bypass security.  So we
    149  * exit here if we detect any IP options.
    150  */
    151 /* IPv4 only */
    152 static void
    153 check_ip_options(int sock, char *ipaddr)
    154 {
    155 #ifdef IP_OPTIONS
    156 	u_char options[200];
    157 	char text[sizeof(options) * 3 + 1];
    158 	socklen_t option_size, i;
    159 	int ipproto;
    160 	struct protoent *ip;
    161 
    162 	if ((ip = getprotobyname("ip")) != NULL)
    163 		ipproto = ip->p_proto;
    164 	else
    165 		ipproto = IPPROTO_IP;
    166 	option_size = sizeof(options);
    167 	if (getsockopt(sock, ipproto, IP_OPTIONS, options,
    168 	    &option_size) >= 0 && option_size != 0) {
    169 		text[0] = '\0';
    170 		for (i = 0; i < option_size; i++)
    171 			snprintf(text + i*3, sizeof(text) - i*3,
    172 			    " %2.2x", options[i]);
    173 		fatal("Connection from %.100s with IP options:%.800s",
    174 		    ipaddr, text);
    175 	}
    176 #endif /* IP_OPTIONS */
    177 }
    178 
    179 void
    180 ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
    181 {
    182 	struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;
    183 	struct sockaddr_in *a4 = (struct sockaddr_in *)addr;
    184 	struct in_addr inaddr;
    185 	u_int16_t port;
    186 
    187 	if (addr->ss_family != AF_INET6 ||
    188 	    !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr))
    189 		return;
    190 
    191 	debug3("Normalising mapped IPv4 in IPv6 address");
    192 
    193 	memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
    194 	port = a6->sin6_port;
    195 
    196 	memset(a4, 0, sizeof(*a4));
    197 
    198 	a4->sin_family = AF_INET;
    199 	*len = sizeof(*a4);
    200 	memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr));
    201 	a4->sin_port = port;
    202 }
    203 
    204 /*
    205  * Return the canonical name of the host in the other side of the current
    206  * connection.  The host name is cached, so it is efficient to call this
    207  * several times.
    208  */
    209 
    210 const char *
    211 get_canonical_hostname(int use_dns)
    212 {
    213 	char *host;
    214 	static char *canonical_host_name = NULL;
    215 	static char *remote_ip = NULL;
    216 
    217 	/* Check if we have previously retrieved name with same option. */
    218 	if (use_dns && canonical_host_name != NULL)
    219 		return canonical_host_name;
    220 	if (!use_dns && remote_ip != NULL)
    221 		return remote_ip;
    222 
    223 	/* Get the real hostname if socket; otherwise return UNKNOWN. */
    224 	if (packet_connection_is_on_socket())
    225 		host = get_remote_hostname(packet_get_connection_in(), use_dns);
    226 	else
    227 		host = "UNKNOWN";
    228 
    229 	if (use_dns)
    230 		canonical_host_name = host;
    231 	else
    232 		remote_ip = host;
    233 	return host;
    234 }
    235 
    236 /*
    237  * Returns the local/remote IP-address/hostname of socket as a string.
    238  * The returned string must be freed.
    239  */
    240 static char *
    241 get_socket_address(int sock, int remote, int flags)
    242 {
    243 	struct sockaddr_storage addr;
    244 	socklen_t addrlen;
    245 	char ntop[NI_MAXHOST];
    246 	int r;
    247 
    248 	/* Get IP address of client. */
    249 	addrlen = sizeof(addr);
    250 	memset(&addr, 0, sizeof(addr));
    251 
    252 	if (remote) {
    253 		if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
    254 		    < 0)
    255 			return NULL;
    256 	} else {
    257 		if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
    258 		    < 0)
    259 			return NULL;
    260 	}
    261 
    262 	/* Work around Linux IPv6 weirdness */
    263 	if (addr.ss_family == AF_INET6) {
    264 		addrlen = sizeof(struct sockaddr_in6);
    265 		ipv64_normalise_mapped(&addr, &addrlen);
    266 	}
    267 
    268 	switch (addr.ss_family) {
    269 	case AF_INET:
    270 	case AF_INET6:
    271 		/* Get the address in ascii. */
    272 		if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
    273 		    sizeof(ntop), NULL, 0, flags)) != 0) {
    274 			error("get_socket_address: getnameinfo %d failed: %s",
    275 			    flags, ssh_gai_strerror(r));
    276 			return NULL;
    277 		}
    278 		return xstrdup(ntop);
    279 	case AF_UNIX:
    280 		/* Get the Unix domain socket path. */
    281 		return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
    282 	default:
    283 		/* We can't look up remote Unix domain sockets. */
    284 		return NULL;
    285 	}
    286 }
    287 
    288 char *
    289 get_peer_ipaddr(int sock)
    290 {
    291 	char *p;
    292 
    293 	if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL)
    294 		return p;
    295 	return xstrdup("UNKNOWN");
    296 }
    297 
    298 char *
    299 get_local_ipaddr(int sock)
    300 {
    301 	char *p;
    302 
    303 	if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL)
    304 		return p;
    305 	return xstrdup("UNKNOWN");
    306 }
    307 
    308 char *
    309 get_local_name(int fd)
    310 {
    311 	char *host, myname[NI_MAXHOST];
    312 
    313 	/* Assume we were passed a socket */
    314 	if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL)
    315 		return host;
    316 
    317 	/* Handle the case where we were passed a pipe */
    318 	if (gethostname(myname, sizeof(myname)) == -1) {
    319 		verbose("get_local_name: gethostname: %s", strerror(errno));
    320 	} else {
    321 		host = xstrdup(myname);
    322 	}
    323 
    324 	return host;
    325 }
    326 
    327 void
    328 clear_cached_addr(void)
    329 {
    330 	free(canonical_host_ip);
    331 	canonical_host_ip = NULL;
    332 	cached_port = -1;
    333 }
    334 
    335 /*
    336  * Returns the IP-address of the remote host as a string.  The returned
    337  * string must not be freed.
    338  */
    339 
    340 const char *
    341 get_remote_ipaddr(void)
    342 {
    343 	/* Check whether we have cached the ipaddr. */
    344 	if (canonical_host_ip == NULL) {
    345 		if (packet_connection_is_on_socket()) {
    346 			canonical_host_ip =
    347 			    get_peer_ipaddr(packet_get_connection_in());
    348 			if (canonical_host_ip == NULL)
    349 				cleanup_exit(255);
    350 		} else {
    351 			/* If not on socket, return UNKNOWN. */
    352 			canonical_host_ip = xstrdup("UNKNOWN");
    353 		}
    354 	}
    355 	return canonical_host_ip;
    356 }
    357 
    358 const char *
    359 get_remote_name_or_ip(u_int utmp_len, int use_dns)
    360 {
    361 	static const char *remote = "";
    362 	if (utmp_len > 0)
    363 		remote = get_canonical_hostname(use_dns);
    364 	if (utmp_len == 0 || strlen(remote) > utmp_len)
    365 		remote = get_remote_ipaddr();
    366 	return remote;
    367 }
    368 
    369 /* Returns the local/remote port for the socket. */
    370 
    371 int
    372 get_sock_port(int sock, int local)
    373 {
    374 	struct sockaddr_storage from;
    375 	socklen_t fromlen;
    376 	char strport[NI_MAXSERV];
    377 	int r;
    378 
    379 	/* Get IP address of client. */
    380 	fromlen = sizeof(from);
    381 	memset(&from, 0, sizeof(from));
    382 	if (local) {
    383 		if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
    384 			error("getsockname failed: %.100s", strerror(errno));
    385 			return 0;
    386 		}
    387 	} else {
    388 		if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
    389 			debug("getpeername failed: %.100s", strerror(errno));
    390 			return -1;
    391 		}
    392 	}
    393 
    394 	/* Work around Linux IPv6 weirdness */
    395 	if (from.ss_family == AF_INET6)
    396 		fromlen = sizeof(struct sockaddr_in6);
    397 
    398 	/* Non-inet sockets don't have a port number. */
    399 	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
    400 		return 0;
    401 
    402 	/* Return port number. */
    403 	if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
    404 	    strport, sizeof(strport), NI_NUMERICSERV)) != 0)
    405 		fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed: %s",
    406 		    ssh_gai_strerror(r));
    407 	return atoi(strport);
    408 }
    409 
    410 /* Returns remote/local port number for the current connection. */
    411 
    412 static int
    413 get_port(int local)
    414 {
    415 	/*
    416 	 * If the connection is not a socket, return 65535.  This is
    417 	 * intentionally chosen to be an unprivileged port number.
    418 	 */
    419 	if (!packet_connection_is_on_socket())
    420 		return 65535;
    421 
    422 	/* Get socket and return the port number. */
    423 	return get_sock_port(packet_get_connection_in(), local);
    424 }
    425 
    426 int
    427 get_peer_port(int sock)
    428 {
    429 	return get_sock_port(sock, 0);
    430 }
    431 
    432 int
    433 get_remote_port(void)
    434 {
    435 	/* Cache to avoid getpeername() on a dead connection */
    436 	if (cached_port == -1)
    437 		cached_port = get_port(0);
    438 
    439 	return cached_port;
    440 }
    441 
    442 int
    443 get_local_port(void)
    444 {
    445 	return get_port(1);
    446 }
    447