]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix PROXYv2 header read and consume, it checks the header
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 3 Jun 2026 12:37:37 +0000 (14:37 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 3 Jun 2026 12:37:37 +0000 (14:37 +0200)
  size. Thanks to Qifan Zhang, Palo Alto Networks for
  the report.

doc/Changelog
util/netevent.c
util/proxy_protocol.c
util/proxy_protocol.h

index bd181216531e24d87c5af732344693fd06443269..2dce57cacc6ca6af3b3c3bb6e3b3ef57bc6c4f10 100644 (file)
@@ -17,6 +17,9 @@
        - Fix ipset module to use larger domain name buffers, and
          check buffer lengths. Thanks to Qifan Zhang, Palo Alto
          Networks for the report.
+       - Fix PROXYv2 header read and consume, it checks the header
+         size. Thanks to Qifan Zhang, Palo Alto Networks for
+         the report.
 
 3 June 2026: Yorgos
        - Fix const as reported by newest compiler warnings.
index 8e4228edc1d09fd3c9f02e2d4dc231fc2dabcad8..3c395ad18fb345bb8044e127fa93a9070383f68d 100644 (file)
@@ -951,6 +951,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
                        {
                        struct sockaddr_in* addr =
                                (struct sockaddr_in*)&rep->client_addr;
+                       if(ntohs(header->len) < PP2_HEADER_LEN_INET) {
+                               verbose(VERB_OPS, "proxy_protocol: header too short for IPv4 address");
+                               return 0;
+                       }
                        addr->sin_family = AF_INET;
                        addr->sin_addr.s_addr = header->addr.addr4.src_addr;
                        addr->sin_port = header->addr.addr4.src_port;
@@ -963,6 +967,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
                        {
                        struct sockaddr_in6* addr =
                                (struct sockaddr_in6*)&rep->client_addr;
+                       if(ntohs(header->len) < PP2_HEADER_LEN_INET6) {
+                               verbose(VERB_OPS, "proxy_protocol: header too short for IPv6 address");
+                               return 0;
+                       }
                        memset(addr, 0, sizeof(*addr));
                        addr->sin6_family = AF_INET6;
                        memcpy(&addr->sin6_addr,
index 235538b6251536467e331f1bb543984dd29addad..689745ee917488176f7440eb27e6d299892b44e2 100644 (file)
@@ -185,14 +185,23 @@ pp2_read_header(uint8_t* buf, size_t buflen)
                (header->ver_cmd & 0xF) != PP2_CMD_PROXY) {
                return PP_PARSE_UNKNOWN_CMD;
        }
-       /* Check for supported family and protocol */
-       if(header->fam_prot != PP2_UNSPEC_UNSPEC &&
-               header->fam_prot != PP2_INET_STREAM &&
-               header->fam_prot != PP2_INET_DGRAM &&
-               header->fam_prot != PP2_INET6_STREAM &&
-               header->fam_prot != PP2_INET6_DGRAM &&
-               header->fam_prot != PP2_UNIX_STREAM &&
-               header->fam_prot != PP2_UNIX_DGRAM) {
+       /* Check for supported family and protocol, and that len covers
+        * the per-family address block (proxy-protocol.txt s2.2). */
+       switch(header->fam_prot) {
+       case PP2_UNSPEC_UNSPEC:
+               break;
+       case PP2_INET_STREAM:
+       case PP2_INET_DGRAM:
+               if(ntohs(header->len) < PP2_HEADER_LEN_INET)
+                       return PP_PARSE_SIZE;
+               break;
+       case PP2_INET6_STREAM:
+       case PP2_INET6_DGRAM:
+               if(ntohs(header->len) < PP2_HEADER_LEN_INET6)
+                       return PP_PARSE_SIZE;
+               break;
+       default:
+               /* PP2_UNIX_STREAM, PP2_UNIX_DGRAM, others. */
                return PP_PARSE_UNKNOWN_FAM_PROT;
        }
        /* We have a correct header */
index ca81065bf49aab13c2c526633fca770e79f2d3a5..52a0128156ebb7b5414c93c05c39196520536663 100644 (file)
 /** PROXYv2 version (protocol value) */
 #define PP2_VERSION 0x2
 
+/** PROXYv2 minimum header.len value for TCP/UDP over IPv4 */
+#define PP2_HEADER_LEN_INET 12
+
+/** PROXYv2 minimum header.len value for TCP/UDP over IPv6 */
+#define PP2_HEADER_LEN_INET6 36
+
+/** PROXYv2 minimum header.len value for TCP/UDP over AF_UNIX */
+#define PP2_HEADER_LEN_UNIX 216
+
 /**
  * PROXYv2 command (protocol value).
  */