clientname.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * Functions for looking up the remote name or addr of a socket.
  3. *
  4. * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
  5. * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
  6. * Copyright (C) 2002-2009 Wayne Davison
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, visit the http://fsf.org website.
  20. */
  21. /*
  22. * This file is now converted to use the new-style getaddrinfo()
  23. * interface, which supports IPv6 but is also supported on recent
  24. * IPv4-only machines. On systems that don't have that interface, we
  25. * emulate it using the KAME implementation.
  26. */
  27. #include "rsync.h"
  28. static const char default_name[] = "UNKNOWN";
  29. extern int am_server;
  30. /**
  31. * Return the IP addr of the client as a string
  32. **/
  33. char *client_addr(int fd)
  34. {
  35. static char addr_buf[100];
  36. static int initialised;
  37. struct sockaddr_storage ss;
  38. socklen_t length = sizeof ss;
  39. char *ssh_info, *p;
  40. if (initialised)
  41. return addr_buf;
  42. initialised = 1;
  43. if (am_server) { /* daemon over --rsh mode */
  44. strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
  45. if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
  46. || (ssh_info = getenv("SSH_CLIENT")) != NULL
  47. || (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
  48. strlcpy(addr_buf, ssh_info, sizeof addr_buf);
  49. /* Truncate the value to just the IP address. */
  50. if ((p = strchr(addr_buf, ' ')) != NULL)
  51. *p = '\0';
  52. }
  53. } else {
  54. client_sockaddr(fd, &ss, &length);
  55. getnameinfo((struct sockaddr *)&ss, length,
  56. addr_buf, sizeof addr_buf, NULL, 0, NI_NUMERICHOST);
  57. }
  58. return addr_buf;
  59. }
  60. static int get_sockaddr_family(const struct sockaddr_storage *ss)
  61. {
  62. return ((struct sockaddr *) ss)->sa_family;
  63. }
  64. /**
  65. * Return the DNS name of the client.
  66. *
  67. * The name is statically cached so that repeated lookups are quick,
  68. * so there is a limit of one lookup per customer.
  69. *
  70. * If anything goes wrong, including the name->addr->name check, then
  71. * we just use "UNKNOWN", so you can use that value in hosts allow
  72. * lines.
  73. *
  74. * After translation from sockaddr to name we do a forward lookup to
  75. * make sure nobody is spoofing PTR records.
  76. **/
  77. char *client_name(int fd)
  78. {
  79. static char name_buf[100];
  80. static char port_buf[100];
  81. static int initialised;
  82. struct sockaddr_storage ss;
  83. socklen_t ss_len;
  84. if (initialised)
  85. return name_buf;
  86. strlcpy(name_buf, default_name, sizeof name_buf);
  87. initialised = 1;
  88. memset(&ss, 0, sizeof ss);
  89. if (am_server) { /* daemon over --rsh mode */
  90. char *addr = client_addr(fd);
  91. struct addrinfo hint, *answer;
  92. int err;
  93. if (strcmp(addr, "0.0.0.0") == 0)
  94. return name_buf;
  95. memset(&hint, 0, sizeof hint);
  96. #ifdef AI_NUMERICHOST
  97. hint.ai_flags = AI_NUMERICHOST;
  98. #endif
  99. hint.ai_socktype = SOCK_STREAM;
  100. if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
  101. rprintf(FLOG, "malformed address %s: %s\n",
  102. addr, gai_strerror(err));
  103. return name_buf;
  104. }
  105. switch (answer->ai_family) {
  106. case AF_INET:
  107. ss_len = sizeof (struct sockaddr_in);
  108. memcpy(&ss, answer->ai_addr, ss_len);
  109. break;
  110. #ifdef INET6
  111. case AF_INET6:
  112. ss_len = sizeof (struct sockaddr_in6);
  113. memcpy(&ss, answer->ai_addr, ss_len);
  114. break;
  115. #endif
  116. default:
  117. exit_cleanup(RERR_SOCKETIO);
  118. }
  119. freeaddrinfo(answer);
  120. } else {
  121. ss_len = sizeof ss;
  122. client_sockaddr(fd, &ss, &ss_len);
  123. }
  124. if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
  125. port_buf, sizeof port_buf) == 0)
  126. check_name(fd, &ss, name_buf, sizeof name_buf);
  127. return name_buf;
  128. }
  129. /**
  130. * Get the sockaddr for the client.
  131. *
  132. * If it comes in as an ipv4 address mapped into IPv6 format then we
  133. * convert it back to a regular IPv4.
  134. **/
  135. void client_sockaddr(int fd,
  136. struct sockaddr_storage *ss,
  137. socklen_t *ss_len)
  138. {
  139. memset(ss, 0, sizeof *ss);
  140. if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
  141. /* FIXME: Can we really not continue? */
  142. rsyserr(FLOG, errno, "getpeername on fd%d failed", fd);
  143. exit_cleanup(RERR_SOCKETIO);
  144. }
  145. #ifdef INET6
  146. if (get_sockaddr_family(ss) == AF_INET6 &&
  147. IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
  148. /* OK, so ss is in the IPv6 family, but it is really
  149. * an IPv4 address: something like
  150. * "::ffff:10.130.1.2". If we use it as-is, then the
  151. * reverse lookup might fail or perhaps something else
  152. * bad might happen. So instead we convert it to an
  153. * equivalent address in the IPv4 address family. */
  154. struct sockaddr_in6 sin6;
  155. struct sockaddr_in *sin;
  156. memcpy(&sin6, ss, sizeof sin6);
  157. sin = (struct sockaddr_in *)ss;
  158. memset(sin, 0, sizeof *sin);
  159. sin->sin_family = AF_INET;
  160. *ss_len = sizeof (struct sockaddr_in);
  161. #ifdef HAVE_SOCKADDR_IN_LEN
  162. sin->sin_len = *ss_len;
  163. #endif
  164. sin->sin_port = sin6.sin6_port;
  165. /* There is a macro to extract the mapped part
  166. * (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
  167. * to be present in the Linux headers. */
  168. memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
  169. sizeof sin->sin_addr);
  170. }
  171. #endif
  172. }
  173. /**
  174. * Look up a name from @p ss into @p name_buf.
  175. *
  176. * @param fd file descriptor for client socket.
  177. **/
  178. int lookup_name(int fd, const struct sockaddr_storage *ss,
  179. socklen_t ss_len,
  180. char *name_buf, size_t name_buf_size,
  181. char *port_buf, size_t port_buf_size)
  182. {
  183. int name_err;
  184. /* reverse lookup */
  185. name_err = getnameinfo((struct sockaddr *) ss, ss_len,
  186. name_buf, name_buf_size,
  187. port_buf, port_buf_size,
  188. NI_NAMEREQD | NI_NUMERICSERV);
  189. if (name_err != 0) {
  190. strlcpy(name_buf, default_name, name_buf_size);
  191. rprintf(FLOG, "name lookup failed for %s: %s\n",
  192. client_addr(fd), gai_strerror(name_err));
  193. return name_err;
  194. }
  195. return 0;
  196. }
  197. /**
  198. * Compare an addrinfo from the resolver to a sockinfo.
  199. *
  200. * Like strcmp, returns 0 for identical.
  201. **/
  202. int compare_addrinfo_sockaddr(const struct addrinfo *ai,
  203. const struct sockaddr_storage *ss)
  204. {
  205. int ss_family = get_sockaddr_family(ss);
  206. const char fn[] = "compare_addrinfo_sockaddr";
  207. if (ai->ai_family != ss_family) {
  208. rprintf(FLOG, "%s: response family %d != %d\n",
  209. fn, ai->ai_family, ss_family);
  210. return 1;
  211. }
  212. /* The comparison method depends on the particular AF. */
  213. if (ss_family == AF_INET) {
  214. const struct sockaddr_in *sin1, *sin2;
  215. sin1 = (const struct sockaddr_in *) ss;
  216. sin2 = (const struct sockaddr_in *) ai->ai_addr;
  217. return memcmp(&sin1->sin_addr, &sin2->sin_addr,
  218. sizeof sin1->sin_addr);
  219. }
  220. #ifdef INET6
  221. if (ss_family == AF_INET6) {
  222. const struct sockaddr_in6 *sin1, *sin2;
  223. sin1 = (const struct sockaddr_in6 *) ss;
  224. sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
  225. if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
  226. rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
  227. fn, (int)ai->ai_addrlen);
  228. return 1;
  229. }
  230. if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
  231. sizeof sin1->sin6_addr))
  232. return 1;
  233. #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
  234. if (sin1->sin6_scope_id != sin2->sin6_scope_id)
  235. return 1;
  236. #endif
  237. return 0;
  238. }
  239. #endif /* INET6 */
  240. /* don't know */
  241. return 1;
  242. }
  243. /**
  244. * Do a forward lookup on @p name_buf and make sure it corresponds to
  245. * @p ss -- otherwise we may be being spoofed. If we suspect we are,
  246. * then we don't abort the connection but just emit a warning, and
  247. * change @p name_buf to be "UNKNOWN".
  248. *
  249. * We don't do anything with the service when checking the name,
  250. * because it doesn't seem that it could be spoofed in any way, and
  251. * getaddrinfo on random service names seems to cause problems on AIX.
  252. **/
  253. int check_name(int fd,
  254. const struct sockaddr_storage *ss,
  255. char *name_buf, size_t name_buf_size)
  256. {
  257. struct addrinfo hints, *res, *res0;
  258. int error;
  259. int ss_family = get_sockaddr_family(ss);
  260. memset(&hints, 0, sizeof hints);
  261. hints.ai_family = ss_family;
  262. hints.ai_flags = AI_CANONNAME;
  263. hints.ai_socktype = SOCK_STREAM;
  264. error = getaddrinfo(name_buf, NULL, &hints, &res0);
  265. if (error) {
  266. rprintf(FLOG, "forward name lookup for %s failed: %s\n",
  267. name_buf, gai_strerror(error));
  268. strlcpy(name_buf, default_name, name_buf_size);
  269. return error;
  270. }
  271. /* Given all these results, we expect that one of them will be
  272. * the same as ss. The comparison is a bit complicated. */
  273. for (res = res0; res; res = res->ai_next) {
  274. if (!compare_addrinfo_sockaddr(res, ss))
  275. break; /* OK, identical */
  276. }
  277. if (!res0) {
  278. /* We hit the end of the list without finding an
  279. * address that was the same as ss. */
  280. rprintf(FLOG, "no known address for \"%s\": "
  281. "spoofed address?\n", name_buf);
  282. strlcpy(name_buf, default_name, name_buf_size);
  283. } else if (res == NULL) {
  284. /* We hit the end of the list without finding an
  285. * address that was the same as ss. */
  286. rprintf(FLOG, "%s is not a known address for \"%s\": "
  287. "spoofed address?\n", client_addr(fd), name_buf);
  288. strlcpy(name_buf, default_name, name_buf_size);
  289. }
  290. freeaddrinfo(res0);
  291. return 0;
  292. }