1 /* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */ 2 /* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@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