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