#include "rsync.h"
-static int lookup_name(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);
+static const char default_name[] = "UNKNOWN";
-static int check_name(const struct sockaddr_storage *ss,
- socklen_t ss_len,
- const char *name_buf,
- const char *port_buf);
/* Establish a proxy connection on an open socket to a web roxy by
* using the CONNECT method. */
char *cp;
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
- if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
+ if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
rprintf(FERROR, "failed to write to proxy: %s\n",
strerror(errno));
return -1;
*
* 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.
**/
char *client_name(int fd)
{
if (initialised) return name_buf;
+ strcpy(name_buf, default_name);
initialised = 1;
if (getpeername(fd, (struct sockaddr *)&ss, &ss_len)) {
exit_cleanup(RERR_SOCKETIO);
}
- if (!lookup_name(&ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
- check_name(&ss, ss_len, name_buf, port_buf);
+ if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
+ check_name(fd, &ss, ss_len, name_buf, port_buf);
return name_buf;
}
/**
* Look up a name from @p ss into @p name_buf.
**/
-static int lookup_name(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)
+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)
{
int name_err;
- const char *def = "UNKNOWN";
#ifdef INET6
if (get_sockaddr_family(ss) == AF_INET6 &&
#endif
/* reverse lookup */
- if (!(name_err = getnameinfo((struct sockaddr *) ss, ss_len,
- name_buf, name_buf_len,
- port_buf, port_buf_len,
- NI_NAMEREQD | NI_NUMERICSERV))) {
- strcpy(name_buf, def);
- rprintf(FERROR, RSYNC_NAME ": reverse name lookup failed: %s\n",
+ name_err = getnameinfo((struct sockaddr *) ss, ss_len,
+ name_buf, name_buf_len,
+ port_buf, port_buf_len,
+ NI_NAMEREQD | NI_NUMERICSERV);
+ if (name_err != 0) {
+ strcpy(name_buf, default_name);
+ rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
+ client_addr(fd),
gai_strerror(name_err));
return name_err;
}
/* Do a forward lookup on name_buf and make sure it corresponds to ss
* -- otherwise we may be being spoofed. If we suspect we are, then
* we don't abort the connection but just emit a warning. */
-static int check_name(const struct sockaddr_storage *ss,
- socklen_t ss_len,
- const char *name_buf,
- const char *port_buf)
+int check_name(int fd,
+ const struct sockaddr_storage *ss,
+ socklen_t ss_len,
+ char *name_buf,
+ const char *port_buf)
{
struct addrinfo hints, *res, *res0;
int error;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
if (error) {
- /* We still use the name found by the reverse lookup,
- * but emit a warning. */
rprintf(FERROR,
RSYNC_NAME ": forward name lookup for %s:%s failed: %s\n",
name_buf, port_buf,
gai_strerror(error));
+ strcpy(name_buf, default_name);
return error;
}
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FERROR, RSYNC_NAME
- ": no address record for \"%s\" corresponds to peer name: spoofed address?\n",
+ ": %s is not a known address for \"%s\": "
+ "spoofed address?\n",
+ client_addr(fd),
name_buf);
+ strcpy(name_buf, default_name);
}
freeaddrinfo(res0);
}
-/*******************************************************************
-run a program on a local tcp socket, this is used to launch smbd
-when regression testing
-the return value is a socket which is attached to a subprocess
-running "prog". stdin and stdout are attached. stderr is left
-attached to the original stderr
- ******************************************************************/
+
+/**
+ * Run a program on a local tcp socket, so that we can talk to it's
+ * stdin and stdout. This is used to fake a connection to a daemon
+ * for testing -- not for the normal case of running SSH.
+ *
+ * @return a socket which is attached to a subprocess running
+ * "prog". stdin and stdout are attached. stderr is left attached to
+ * the original stderr
+ **/
int sock_exec(const char *prog)
{
int fd[2];
+
if (socketpair_tcp(fd) != 0) {
rprintf (FERROR, RSYNC_NAME
": socketpair_tcp failed (%s)\n",
close(1);
dup(fd[1]);
dup(fd[1]);
- if (verbose > 3)
+ if (verbose > 3) {
+ /* Can't use rprintf because we've forked. */
fprintf (stderr,
RSYNC_NAME ": execute socket program \"%s\"\n",
prog);
+ }
exit (system (prog));
}
close (fd[1]);