1 /* 2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * Functions for returning the canonical host name of the remote site. 6 * 7 * As far as I am concerned, the code I have written for this software 8 * can be used freely for any purpose. Any derived versions of this 9 * software must be clearly marked as such, and if the derived work is 10 * incompatible with the protocol description in the RFC file, it must be 11 * called by a name other than "ssh" or "Secure Shell". 12 */ 13 /* 14 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 15 * Use is subject to license terms. 16 * 17 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 18 */ 19 20 #include "includes.h" 21 RCSID("$OpenBSD: canohost.c,v 1.34 2002/09/23 20:46:27 stevesk Exp $"); 22 23 #include "packet.h" 24 #include "xmalloc.h" 25 #include "log.h" 26 #include "canohost.h" 27 28 static const char *inet_ntop_native(int af, const void *src, 29 char *dst, size_t size); 30 31 32 /* 33 * Return the canonical name of the host at the other end of the socket. The 34 * caller should free the returned string with xfree. 35 */ 36 37 static char * 38 get_remote_hostname(int socket, int verify_reverse_mapping) 39 { 40 struct sockaddr_storage from; 41 int i, res; 42 socklen_t fromlen; 43 struct addrinfo hints, *ai, *aitop; 44 char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; 45 46 /* Get IP address of client. */ 47 fromlen = sizeof(from); 48 memset(&from, 0, sizeof(from)); 49 if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) { 50 debug("getpeername failed: %.100s", strerror(errno)); 51 fatal_cleanup(); 52 } 53 54 if ((res = getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), 55 NULL, 0, NI_NUMERICHOST)) != 0) 56 fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed: %d", res); 57 58 #ifdef IPV4_IN_IPV6 59 if (from.ss_family == AF_INET6) { 60 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; 61 62 (void) inet_ntop_native(from.ss_family, 63 from6->sin6_addr.s6_addr, 64 ntop, sizeof(ntop)); 65 } 66 #endif /* IPV4_IN_IPV6 */ 67 68 if (!verify_reverse_mapping) 69 return xstrdup(ntop); 70 71 debug3("Trying to reverse map address %.100s.", ntop); 72 /* Map the IP address to a host name. */ 73 if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), 74 NULL, 0, NI_NAMEREQD) != 0) { 75 /* Host name not found. Use ip address. */ 76 #if 0 77 log("Could not reverse map address %.100s.", ntop); 78 #endif 79 return xstrdup(ntop); 80 } 81 82 /* Got host name. */ 83 name[sizeof(name) - 1] = '\0'; 84 /* 85 * Convert it to all lowercase (which is expected by the rest 86 * of this software). 87 */ 88 for (i = 0; name[i]; i++) 89 if (isupper(name[i])) 90 name[i] = tolower(name[i]); 91 92 /* 93 * Map it back to an IP address and check that the given 94 * address actually is an address of this host. This is 95 * necessary because anyone with access to a name server can 96 * define arbitrary names for an IP address. Mapping from 97 * name to IP address can be trusted better (but can still be 98 * fooled if the intruder has access to the name server of 99 * the domain). 100 */ 101 memset(&hints, 0, sizeof(hints)); 102 hints.ai_family = from.ss_family; 103 hints.ai_socktype = SOCK_STREAM; 104 if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { 105 log("reverse mapping checking getaddrinfo for %.700s " 106 "failed - POSSIBLE BREAKIN ATTEMPT!", name); 107 return xstrdup(ntop); 108 } 109 /* Look for the address from the list of addresses. */ 110 for (ai = aitop; ai; ai = ai->ai_next) { 111 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, 112 sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && 113 (strcmp(ntop, ntop2) == 0)) 114 break; 115 } 116 freeaddrinfo(aitop); 117 /* If we reached the end of the list, the address was not there. */ 118 if (!ai) { 119 /* Address not found for the host name. */ 120 log("Address %.100s maps to %.600s, but this does not " 121 "map back to the address - POSSIBLE BREAKIN ATTEMPT!", 122 ntop, name); 123 return xstrdup(ntop); 124 } 125 return xstrdup(name); 126 } 127 128 /* 129 * Return the canonical name of the host in the other side of the current 130 * connection. The host name is cached, so it is efficient to call this 131 * several times. 132 */ 133 134 const char * 135 get_canonical_hostname(int verify_reverse_mapping) 136 { 137 static char *canonical_host_name = NULL; 138 static int verify_reverse_mapping_done = 0; 139 140 /* Check if we have previously retrieved name with same option. */ 141 if (canonical_host_name != NULL) { 142 if (verify_reverse_mapping_done != verify_reverse_mapping) 143 xfree(canonical_host_name); 144 else 145 return canonical_host_name; 146 } 147 148 /* Get the real hostname if socket; otherwise return UNKNOWN. */ 149 if (packet_connection_is_on_socket()) 150 canonical_host_name = get_remote_hostname( 151 packet_get_connection_in(), verify_reverse_mapping); 152 else 153 canonical_host_name = xstrdup("UNKNOWN"); 154 155 verify_reverse_mapping_done = verify_reverse_mapping; 156 return canonical_host_name; 157 } 158 159 /* 160 * Returns the remote IP-address of socket as a string. The returned 161 * string must be freed. 162 */ 163 char * 164 get_socket_address(int socket, int remote, int flags) 165 { 166 struct sockaddr_storage addr; 167 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; 168 socklen_t addrlen; 169 char ntop[NI_MAXHOST]; 170 const char *result; 171 char abuf[INET6_ADDRSTRLEN]; 172 173 /* Get IP address of client. */ 174 addrlen = sizeof (addr); 175 memset(&addr, 0, sizeof (addr)); 176 177 if (remote) { 178 if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) 179 < 0) { 180 debug("get_socket_ipaddr: getpeername failed: %.100s", 181 strerror(errno)); 182 return (NULL); 183 } 184 } else { 185 if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) 186 < 0) { 187 debug("get_socket_ipaddr: getsockname failed: %.100s", 188 strerror(errno)); 189 return (NULL); 190 } 191 } 192 193 /* Get the address in ascii. */ 194 if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof (ntop), 195 NULL, 0, flags) != 0) { 196 error("get_socket_ipaddr: getnameinfo %d failed", flags); 197 return (NULL); 198 } 199 200 if (addr.ss_family == AF_INET) { 201 return (xstrdup(ntop)); 202 } 203 204 result = inet_ntop_native(addr.ss_family, 205 addr6->sin6_addr.s6_addr, abuf, sizeof (abuf)); 206 207 return (xstrdup(result)); 208 } 209 #if 0 210 static char * 211 get_socket_address(int socket, int remote, int flags) 212 { 213 struct sockaddr_storage addr; 214 socklen_t addrlen; 215 char ntop[NI_MAXHOST]; 216 217 /* Get IP address of client. */ 218 addrlen = sizeof(addr); 219 memset(&addr, 0, sizeof(addr)); 220 221 if (remote) { 222 if (getpeername(socket, (struct sockaddr *)&addr, &addrlen) 223 < 0) 224 return NULL; 225 } else { 226 if (getsockname(socket, (struct sockaddr *)&addr, &addrlen) 227 < 0) 228 return NULL; 229 } 230 /* Get the address in ascii. */ 231 if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), 232 NULL, 0, flags) != 0) { 233 error("get_socket_ipaddr: getnameinfo %d failed", flags); 234 return NULL; 235 } 236 return xstrdup(ntop); 237 } 238 #endif 239 240 char * 241 get_peer_ipaddr(int socket) 242 { 243 char *p; 244 245 if ((p = get_socket_address(socket, 1, NI_NUMERICHOST)) != NULL) 246 return p; 247 return xstrdup("UNKNOWN"); 248 } 249 250 char * 251 get_local_ipaddr(int socket) 252 { 253 char *p; 254 255 if ((p = get_socket_address(socket, 0, NI_NUMERICHOST)) != NULL) 256 return p; 257 return xstrdup("UNKNOWN"); 258 } 259 260 char * 261 get_local_name(int socket) 262 { 263 return get_socket_address(socket, 0, NI_NAMEREQD); 264 } 265 266 /* 267 * Returns the IP-address of the remote host as a string. The returned 268 * string must not be freed. 269 */ 270 271 const char * 272 get_remote_ipaddr(void) 273 { 274 static char *canonical_host_ip = NULL; 275 276 /* Check whether we have cached the ipaddr. */ 277 if (canonical_host_ip == NULL) { 278 if (packet_connection_is_on_socket()) { 279 canonical_host_ip = 280 get_peer_ipaddr(packet_get_connection_in()); 281 if (canonical_host_ip == NULL) 282 fatal_cleanup(); 283 } else { 284 /* If not on socket, return UNKNOWN. */ 285 canonical_host_ip = xstrdup("UNKNOWN"); 286 } 287 } 288 return canonical_host_ip; 289 } 290 291 const char * 292 get_remote_name_or_ip(u_int utmp_len, int verify_reverse_mapping) 293 { 294 static const char *remote = ""; 295 if (utmp_len > 0) 296 remote = get_canonical_hostname(verify_reverse_mapping); 297 if (utmp_len == 0 || strlen(remote) > utmp_len) 298 remote = get_remote_ipaddr(); 299 return remote; 300 } 301 302 /* Returns the local/remote port for the socket. */ 303 304 static int 305 get_sock_port(int sock, int local) 306 { 307 struct sockaddr_storage from; 308 socklen_t fromlen; 309 char strport[NI_MAXSERV]; 310 311 /* Get IP address of client. */ 312 fromlen = sizeof(from); 313 memset(&from, 0, sizeof(from)); 314 if (local) { 315 if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) { 316 error("getsockname failed: %.100s", strerror(errno)); 317 return 0; 318 } 319 } else { 320 if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) { 321 debug("getpeername failed: %.100s", strerror(errno)); 322 fatal_cleanup(); 323 } 324 } 325 /* Return port number. */ 326 if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, 327 strport, sizeof(strport), NI_NUMERICSERV) != 0) 328 fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed"); 329 return atoi(strport); 330 } 331 332 /* Returns remote/local port number for the current connection. */ 333 334 static int 335 get_port(int local) 336 { 337 /* 338 * If the connection is not a socket, return 65535. This is 339 * intentionally chosen to be an unprivileged port number. 340 */ 341 if (!packet_connection_is_on_socket()) 342 return 65535; 343 344 /* Get socket and return the port number. */ 345 return get_sock_port(packet_get_connection_in(), local); 346 } 347 348 int 349 get_peer_port(int sock) 350 { 351 return get_sock_port(sock, 0); 352 } 353 354 int 355 get_remote_port(void) 356 { 357 return get_port(0); 358 } 359 360 int 361 get_local_port(void) 362 { 363 return get_port(1); 364 } 365 366 /* 367 * Taken from inetd.c 368 * This is a wrapper function for inet_ntop(). In case the af is AF_INET6 369 * and the address pointed by src is a IPv4-mapped IPv6 address, it 370 * returns printable IPv4 address, not IPv4-mapped IPv6 address. In other cases 371 * it behaves just like inet_ntop(). 372 */ 373 static const char * 374 inet_ntop_native(int af, const void *src, char *dst, size_t size) 375 { 376 struct in_addr src4; 377 const char *result; 378 379 if (af == AF_INET6) { 380 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) { 381 IN6_V4MAPPED_TO_INADDR((struct in6_addr *)src, &src4); 382 result = inet_ntop(AF_INET, &src4, dst, size); 383 } else { 384 result = inet_ntop(AF_INET6, src, dst, size); 385 } 386 } else { 387 result = inet_ntop(af, src, dst, size); 388 } 389 390 return (result); 391 } 392