Go to the source code of this file.
Functions | |
char * | client_addr (int fd) |
Return the IP addr of the client as a string. More... | |
int | get_sockaddr_family (const struct sockaddr_storage *ss) |
char * | client_name (int fd) |
Return the DNS name of the client. More... | |
void | client_sockaddr (int fd, struct sockaddr_storage *ss, socklen_t *ss_len) |
Get the sockaddr for the client. More... | |
int | lookup_name (int fd, const struct sockaddr_storage *ss, socklen_t ss_len, char *name_buf, size_t name_buf_len, char *port_buf, size_t port_buf_len) |
Look up a name from ss into name_buf . More... | |
int | compare_addrinfo_sockaddr (const struct addrinfo *ai, const struct sockaddr_storage *ss) |
Compare an addrinfo from the resolver to a sockinfo. More... | |
int | check_name (int fd, const struct sockaddr_storage *ss, char *name_buf) |
Do a forward lookup on name_buf and make sure it corresponds to ss -- otherwise we may be being spoofed. More... | |
Variables | |
const char | default_name [] = "UNKNOWN" |
This file is now converted to use the new-style getaddrinfo() interface, which supports IPv6 but is also supported on recent IPv4-only machines. On systems that don't have that interface, we emulate it using the KAME implementation.
Definition in file clientname.c.
|
Return the IP addr of the client as a string.
Definition at line 42 of file clientname.c. References client_sockaddr(), and getnameinfo(). Referenced by check_name(), log_formatted(), lookup_name(), and rsync_module().
00043 { 00044 struct sockaddr_storage ss; 00045 socklen_t length = sizeof ss; 00046 static char addr_buf[100]; 00047 static int initialised; 00048 00049 if (initialised) return addr_buf; 00050 00051 initialised = 1; 00052 00053 client_sockaddr(fd, &ss, &length); 00054 00055 getnameinfo((struct sockaddr *)&ss, length, 00056 addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); 00057 00058 return addr_buf; 00059 } |
|
Definition at line 62 of file clientname.c. Referenced by check_name(), client_sockaddr(), and compare_addrinfo_sockaddr().
00063 { 00064 return ((struct sockaddr *) ss)->sa_family; 00065 } |
|
Return the DNS name of the client. The name is statically cached so that repeated lookups are quick, so there is a limit of one lookup per customer. If anything goes wrong, including the name->addr->name check, then we just use "UNKNOWN", so you can use that value in hosts allow lines. After translation from sockaddr to name we do a forward lookup to make sure nobody is spoofing PTR records. Definition at line 81 of file clientname.c. References check_name(), client_sockaddr(), default_name, and lookup_name(). Referenced by log_formatted(), and rsync_module().
00082 { 00083 struct sockaddr_storage ss; 00084 socklen_t ss_len = sizeof ss; 00085 static char name_buf[100]; 00086 static char port_buf[100]; 00087 static int initialised; 00088 00089 if (initialised) return name_buf; 00090 00091 strcpy(name_buf, default_name); 00092 initialised = 1; 00093 00094 client_sockaddr(fd, &ss, &ss_len); 00095 00096 if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf, 00097 port_buf, sizeof port_buf)) 00098 check_name(fd, &ss, name_buf); 00099 00100 return name_buf; 00101 } |
|
Get the sockaddr for the client. If it comes in as an ipv4 address mapped into IPv6 format then we convert it back to a regular IPv4. Definition at line 111 of file clientname.c. References FERROR, get_sockaddr_family(), and rprintf(). Referenced by client_addr(), and client_name().
00114 { 00115 if (getpeername(fd, (struct sockaddr *) ss, ss_len)) { 00116 /* FIXME: Can we really not continue? */ 00117 rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n", 00118 fd, strerror(errno)); 00119 exit_cleanup(RERR_SOCKETIO); 00120 } 00121 00122 #ifdef INET6 00123 if (get_sockaddr_family(ss) == AF_INET6 && 00124 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) { 00125 /* OK, so ss is in the IPv6 family, but it is really 00126 * an IPv4 address: something like 00127 * "::ffff:10.130.1.2". If we use it as-is, then the 00128 * reverse lookup might fail or perhaps something else 00129 * bad might happen. So instead we convert it to an 00130 * equivalent address in the IPv4 address family. */ 00131 struct sockaddr_in6 sin6; 00132 struct sockaddr_in *sin; 00133 00134 memcpy(&sin6, ss, sizeof(sin6)); 00135 sin = (struct sockaddr_in *)ss; 00136 memset(sin, 0, sizeof(*sin)); 00137 sin->sin_family = AF_INET; 00138 *ss_len = sizeof(struct sockaddr_in); 00139 #ifdef HAVE_SOCKADDR_LEN 00140 sin->sin_len = *ss_len; 00141 #endif 00142 sin->sin_port = sin6.sin6_port; 00143 00144 /* There is a macro to extract the mapped part 00145 * (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem 00146 * to be present in the Linux headers. */ 00147 memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12], 00148 sizeof(sin->sin_addr)); 00149 } 00150 #endif 00151 } |
|
Look up a name from
Definition at line 159 of file clientname.c. References client_addr(), default_name, FERROR, gai_strerror(), getnameinfo(), and rprintf(). Referenced by client_name().
00163 { 00164 int name_err; 00165 00166 /* reverse lookup */ 00167 name_err = getnameinfo((struct sockaddr *) ss, ss_len, 00168 name_buf, name_buf_len, 00169 port_buf, port_buf_len, 00170 NI_NAMEREQD | NI_NUMERICSERV); 00171 if (name_err != 0) { 00172 strcpy(name_buf, default_name); 00173 rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n", 00174 client_addr(fd), 00175 gai_strerror(name_err)); 00176 return name_err; 00177 } 00178 00179 return 0; 00180 } |
|
Compare an addrinfo from the resolver to a sockinfo. Like strcmp, returns 0 for identical. Definition at line 189 of file clientname.c. References addrinfo::ai_family, FERROR, get_sockaddr_family(), and rprintf(). Referenced by check_name().
00191 { 00192 int ss_family = get_sockaddr_family(ss); 00193 const char fn[] = "compare_addrinfo_sockaddr"; 00194 00195 if (ai->ai_family != ss_family) { 00196 rprintf(FERROR, 00197 "%s: response family %d != %d\n", 00198 fn, ai->ai_family, ss_family); 00199 return 1; 00200 } 00201 00202 /* The comparison method depends on the particular AF. */ 00203 if (ss_family == AF_INET) { 00204 const struct sockaddr_in *sin1, *sin2; 00205 00206 sin1 = (const struct sockaddr_in *) ss; 00207 sin2 = (const struct sockaddr_in *) ai->ai_addr; 00208 00209 return memcmp(&sin1->sin_addr, &sin2->sin_addr, 00210 sizeof sin1->sin_addr); 00211 } 00212 #ifdef INET6 00213 else if (ss_family == AF_INET6) { 00214 const struct sockaddr_in6 *sin1, *sin2; 00215 00216 sin1 = (const struct sockaddr_in6 *) ss; 00217 sin2 = (const struct sockaddr_in6 *) ai->ai_addr; 00218 00219 return memcmp(&sin1->sin6_addr, &sin2->sin6_addr, 00220 sizeof sin1->sin6_addr); 00221 } 00222 #endif /* INET6 */ 00223 else { 00224 /* don't know */ 00225 return 1; 00226 } 00227 } |
|
Do a forward lookup on
If we suspect we are, then we don't abort the connection but just emit a warning, and change We don't do anything with the service when checking the name, because it doesn't seem that it could be spoofed in any way, and getaddrinfo on random service names seems to cause problems on AIX. Definition at line 240 of file clientname.c. References addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, addrinfo::ai_socktype, client_addr(), compare_addrinfo_sockaddr(), default_name, FERROR, gai_strerror(), get_sockaddr_family(), and rprintf(). Referenced by client_name().
00243 { 00244 struct addrinfo hints, *res, *res0; 00245 int error; 00246 int ss_family = get_sockaddr_family(ss); 00247 00248 memset(&hints, 0, sizeof(hints)); 00249 hints.ai_family = ss_family; 00250 hints.ai_flags = AI_CANONNAME; 00251 hints.ai_socktype = SOCK_STREAM; 00252 error = getaddrinfo(name_buf, NULL, &hints, &res0); 00253 if (error) { 00254 rprintf(FERROR, 00255 RSYNC_NAME ": forward name lookup for %s failed: %s\n", 00256 name_buf, gai_strerror(error)); 00257 strcpy(name_buf, default_name); 00258 return error; 00259 } 00260 00261 00262 /* Given all these results, we expect that one of them will be 00263 * the same as ss. The comparison is a bit complicated. */ 00264 for (res = res0; res; res = res->ai_next) { 00265 if (!compare_addrinfo_sockaddr(res, ss)) 00266 break; /* OK, identical */ 00267 } 00268 00269 if (!res0) { 00270 /* We hit the end of the list without finding an 00271 * address that was the same as ss. */ 00272 rprintf(FERROR, RSYNC_NAME 00273 ": no known address for \"%s\": " 00274 "spoofed address?\n", 00275 name_buf); 00276 strcpy(name_buf, default_name); 00277 } else if (res == NULL) { 00278 /* We hit the end of the list without finding an 00279 * address that was the same as ss. */ 00280 rprintf(FERROR, RSYNC_NAME 00281 ": %s is not a known address for \"%s\": " 00282 "spoofed address?\n", 00283 client_addr(fd), 00284 name_buf); 00285 strcpy(name_buf, default_name); 00286 } 00287 00288 freeaddrinfo(res0); 00289 return 0; 00290 } |
|
Definition at line 36 of file clientname.c. Referenced by check_name(), client_name(), and lookup_name(). |