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 }