canohost.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* $OpenBSD: canohost.c,v 1.74 2019/06/28 13:35:04 deraadt 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. #include "includes.h"
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <sys/un.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <errno.h>
  21. #include <netdb.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include <unistd.h>
  27. #include "xmalloc.h"
  28. #include "packet.h"
  29. #include "log.h"
  30. #include "canohost.h"
  31. #include "misc.h"
  32. void
  33. ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
  34. {
  35. struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;
  36. struct sockaddr_in *a4 = (struct sockaddr_in *)addr;
  37. struct in_addr inaddr;
  38. u_int16_t port;
  39. if (addr->ss_family != AF_INET6 ||
  40. !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr))
  41. return;
  42. debug3("Normalising mapped IPv4 in IPv6 address");
  43. memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
  44. port = a6->sin6_port;
  45. memset(a4, 0, sizeof(*a4));
  46. a4->sin_family = AF_INET;
  47. *len = sizeof(*a4);
  48. memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr));
  49. a4->sin_port = port;
  50. }
  51. /*
  52. * Returns the local/remote IP-address/hostname of socket as a string.
  53. * The returned string must be freed.
  54. */
  55. static char *
  56. get_socket_address(int sock, int remote, int flags)
  57. {
  58. struct sockaddr_storage addr;
  59. socklen_t addrlen;
  60. char ntop[NI_MAXHOST];
  61. int r;
  62. /* Get IP address of client. */
  63. addrlen = sizeof(addr);
  64. memset(&addr, 0, sizeof(addr));
  65. if (remote) {
  66. if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0)
  67. return NULL;
  68. } else {
  69. if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0)
  70. return NULL;
  71. }
  72. /* Work around Linux IPv6 weirdness */
  73. if (addr.ss_family == AF_INET6) {
  74. addrlen = sizeof(struct sockaddr_in6);
  75. ipv64_normalise_mapped(&addr, &addrlen);
  76. }
  77. switch (addr.ss_family) {
  78. case AF_INET:
  79. case AF_INET6:
  80. /* Get the address in ascii. */
  81. if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
  82. sizeof(ntop), NULL, 0, flags)) != 0) {
  83. error("%s: getnameinfo %d failed: %s", __func__,
  84. flags, ssh_gai_strerror(r));
  85. return NULL;
  86. }
  87. return xstrdup(ntop);
  88. case AF_UNIX:
  89. /* Get the Unix domain socket path. */
  90. return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
  91. default:
  92. /* We can't look up remote Unix domain sockets. */
  93. return NULL;
  94. }
  95. }
  96. char *
  97. get_peer_ipaddr(int sock)
  98. {
  99. char *p;
  100. if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL)
  101. return p;
  102. return xstrdup("UNKNOWN");
  103. }
  104. char *
  105. get_local_ipaddr(int sock)
  106. {
  107. char *p;
  108. if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL)
  109. return p;
  110. return xstrdup("UNKNOWN");
  111. }
  112. char *
  113. get_local_name(int fd)
  114. {
  115. char *host, myname[NI_MAXHOST];
  116. /* Assume we were passed a socket */
  117. if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL)
  118. return host;
  119. /* Handle the case where we were passed a pipe */
  120. if (gethostname(myname, sizeof(myname)) == -1) {
  121. verbose("%s: gethostname: %s", __func__, strerror(errno));
  122. host = xstrdup("UNKNOWN");
  123. } else {
  124. host = xstrdup(myname);
  125. }
  126. return host;
  127. }
  128. /* Returns the local/remote port for the socket. */
  129. static int
  130. get_sock_port(int sock, int local)
  131. {
  132. struct sockaddr_storage from;
  133. socklen_t fromlen;
  134. char strport[NI_MAXSERV];
  135. int r;
  136. /* Get IP address of client. */
  137. fromlen = sizeof(from);
  138. memset(&from, 0, sizeof(from));
  139. if (local) {
  140. if (getsockname(sock, (struct sockaddr *)&from, &fromlen) == -1) {
  141. error("getsockname failed: %.100s", strerror(errno));
  142. return 0;
  143. }
  144. } else {
  145. if (getpeername(sock, (struct sockaddr *)&from, &fromlen) == -1) {
  146. debug("getpeername failed: %.100s", strerror(errno));
  147. return -1;
  148. }
  149. }
  150. /* Work around Linux IPv6 weirdness */
  151. if (from.ss_family == AF_INET6)
  152. fromlen = sizeof(struct sockaddr_in6);
  153. /* Non-inet sockets don't have a port number. */
  154. if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
  155. return 0;
  156. /* Return port number. */
  157. if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
  158. strport, sizeof(strport), NI_NUMERICSERV)) != 0)
  159. fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__,
  160. ssh_gai_strerror(r));
  161. return atoi(strport);
  162. }
  163. int
  164. get_peer_port(int sock)
  165. {
  166. return get_sock_port(sock, 0);
  167. }
  168. int
  169. get_local_port(int sock)
  170. {
  171. return get_sock_port(sock, 1);
  172. }