Add safety check for local --remove-source-files.
[rsync.git] / clientname.c
index 6a9f98b96a29c97e6179a60795a5ad16d205c796..ea94894bbf2a486968c36c1ae04f27bbabeff108 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002-2020 Wayne Davison
+ * Copyright (C) 2002-2022 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,7 +49,7 @@ static char ipaddr_buf[100];
 
 static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_len);
 static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, char *name_buf, size_t name_buf_size);
-static int valid_ipaddr(const char *s);
+static int valid_ipaddr(const char *s, int allow_scope);
 
 /* Return the IP addr of the client as a string. */
 char *client_addr(int fd)
@@ -73,7 +73,7 @@ char *client_addr(int fd)
                        if ((p = strchr(ipaddr_buf, ' ')) != NULL)
                                *p = '\0';
                }
-               if (valid_ipaddr(ipaddr_buf))
+               if (valid_ipaddr(ipaddr_buf, True))
                        return ipaddr_buf;
        }
 
@@ -139,7 +139,7 @@ char *client_name(const char *ipaddr)
                break;
 #endif
        default:
-               assert(0);
+               NOISY_DEATH("Unknown ai_family value");
        }
        freeaddrinfo(answer);
 
@@ -156,8 +156,8 @@ char *client_name(const char *ipaddr)
 }
 
 
-/* Try to read an haproxy header (V1 or V2). Returns 1 on success or 0 on failure. */
-int read_haproxy_header(int fd)
+/* Try to read a proxy protocol header (V1 or V2). Returns 1 on success or 0 on failure. */
+int read_proxy_protocol_header(int fd)
 {
        union {
                struct {
@@ -213,12 +213,14 @@ int read_haproxy_header(int fd)
                                if (size != sizeof hdr.v2.addr.ip4)
                                        return 0;
                                inet_ntop(AF_INET, hdr.v2.addr.ip4.src_addr, ipaddr_buf, sizeof ipaddr_buf);
-                               return valid_ipaddr(ipaddr_buf);
+                               return valid_ipaddr(ipaddr_buf, False);
+#ifdef INET6
                        case PROXY_FAM_TCPv6:
                                if (size != sizeof hdr.v2.addr.ip6)
                                        return 0;
                                inet_ntop(AF_INET6, hdr.v2.addr.ip6.src_addr, ipaddr_buf, sizeof ipaddr_buf);
-                               return valid_ipaddr(ipaddr_buf);
+                               return valid_ipaddr(ipaddr_buf, False);
+#endif
                        default:
                                break;
                        }
@@ -274,7 +276,7 @@ int read_haproxy_header(int fd)
                if ((sp = strchr(p, ' ')) == NULL)
                        return 0;
                *sp = '\0';
-               if (!valid_ipaddr(p))
+               if (!valid_ipaddr(p, False))
                        return 0;
                strlcpy(ipaddr_buf, p, sizeof ipaddr_buf); /* It will always fit when valid. */
 
@@ -282,7 +284,7 @@ int read_haproxy_header(int fd)
                if ((sp = strchr(p, ' ')) == NULL)
                        return 0;
                *sp = '\0';
-               if (!valid_ipaddr(p))
+               if (!valid_ipaddr(p, False))
                        return 0;
                /* Ignore destination address. */
 
@@ -325,8 +327,8 @@ static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_l
        }
 
 #ifdef INET6
-       if (GET_SOCKADDR_FAMILY(ss) == AF_INET6 &&
-           IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
+       if (GET_SOCKADDR_FAMILY(ss) == AF_INET6
+        && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
                /* OK, so ss is in the IPv6 family, but it is really
                 * an IPv4 address: something like
                 * "::ffff:10.130.1.2".  If we use it as-is, then the
@@ -349,8 +351,7 @@ static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_l
                /* There is a macro to extract the mapped part
                 * (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
                 * to be present in the Linux headers. */
-               memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
-                   sizeof sin->sin_addr);
+               memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12], sizeof sin->sin_addr);
        }
 #endif
 }
@@ -379,8 +380,7 @@ static int compare_addrinfo_sockaddr(const struct addrinfo *ai, const struct soc
                sin1 = (const struct sockaddr_in *) ss;
                sin2 = (const struct sockaddr_in *) ai->ai_addr;
 
-               return memcmp(&sin1->sin_addr, &sin2->sin_addr,
-                             sizeof sin1->sin_addr);
+               return memcmp(&sin1->sin_addr, &sin2->sin_addr, sizeof sin1->sin_addr);
        }
 
 #ifdef INET6
@@ -390,14 +390,13 @@ static int compare_addrinfo_sockaddr(const struct addrinfo *ai, const struct soc
                sin1 = (const struct sockaddr_in6 *) ss;
                sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
 
-               if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
+               if (ai->ai_addrlen < (int)sizeof (struct sockaddr_in6)) {
                        rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
                                fn, (int)ai->ai_addrlen);
                        return 1;
                }
 
-               if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
-                          sizeof sin1->sin6_addr))
+               if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof sin1->sin6_addr))
                        return 1;
 
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
@@ -467,7 +466,7 @@ static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, cha
 }
 
 /* Returns 1 for a valid IPv4 or IPv6 addr, or 0 for a bad one. */
-static int valid_ipaddr(const char *s)
+static int valid_ipaddr(const char *s, int allow_scope)
 {
        int i;
 
@@ -484,7 +483,12 @@ static int valid_ipaddr(const char *s)
 
                for (count = 0; count < 8; count++) {
                        if (!*s)
-                               return saw_double_colon && count < 7;
+                               return saw_double_colon;
+                       if (allow_scope && *s == '%') {
+                               if (saw_double_colon)
+                                       break;
+                               return 0;
+                       }
 
                        if (strchr(s, ':') == NULL && strchr(s, '.') != NULL) {
                                if ((!saw_double_colon && count != 6) || (saw_double_colon && count > 6))
@@ -510,8 +514,11 @@ static int valid_ipaddr(const char *s)
                        }
                }
 
-               if (!ipv4_at_end)
-                       return !*s;
+               if (!ipv4_at_end) {
+                       if (allow_scope && *s == '%')
+                               for (s++; isAlNum(s); s++) { }
+                       return !*s && s[-1] != '%';
+               }
        }
 
        /* IPv4 */