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