From: Roy Marples Date: Wed, 4 Oct 2023 12:03:21 +0000 (+0100) Subject: options: introduce the uri option as opposed to a string X-Git-Tag: v10.0.3~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=500cd81362136f33f64e4a47496e7443ecbc2e7d;p=thirdparty%2Fdhcpcd.git options: introduce the uri option as opposed to a string Currently we don't attempt to validate a uri given, aside from not allowing any space characters within. If the option is `array uri` then the first two bytes are the length of the uri in network order and the rest is a uri element. The uri's are space separated for the variable because space is not allowed within the uri. This allows us to implement RFC 8572, Secure Zero Touch Provisioning. --- diff --git a/src/dhcp-common.c b/src/dhcp-common.c index 679af243..e5dd9efa 100644 --- a/src/dhcp-common.c +++ b/src/dhcp-common.c @@ -125,6 +125,8 @@ dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols) printf(" binhex"); else if (opt->type & OT_STRING) printf(" string"); + else if (opt->type & OT_URI) + printf(" uri"); if (opt->type & OT_RFC3361) printf(" rfc3361"); if (opt->type & OT_RFC3442) @@ -518,6 +520,10 @@ print_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl) errno = EINVAL; break; } + if (type & OT_URI && isspace(c)) { + errno = EINVAL; + break; + } if ((type & (OT_ESCSTRING | OT_ESCFILE) && (c == '\\' || !isascii(c) || !isprint(c))) || (type & OT_ESCFILE && (c == '/' || c == ' '))) @@ -675,7 +681,58 @@ print_option(FILE *fp, const char *prefix, const struct dhcp_opt *opt, return print_rfc3442(fp, data, dl); #endif - if (opt->type & OT_STRING) { + /* Produces a space separated list of URIs. + * This is valid as a URI cannot contain a space. */ + if ((opt->type & (OT_ARRAY | OT_URI)) == (OT_ARRAY | OT_URI)) { +#ifdef SMALL + errno = ENOTSUP; + return -1; +#else + char buf[UINT16_MAX + 1]; + uint16_t sz; + bool first = true; + + while (dl) { + if (dl < 2) { + errno = EINVAL; + goto err; + } + + memcpy(&u16, data, sizeof(u16)); + sz = ntohs(u16); + data += sizeof(u16); + dl -= sizeof(u16); + + if (sz == 0) + continue; + if (sz > dl) { + errno = EINVAL; + goto err; + } + + if (print_string(buf, sizeof(buf), + opt->type, data, sz) == -1) + goto err; + + if (first) + first = false; + else if (fputc(' ', fp) == EOF) + goto err; + + if (fprintf(fp, "%s", buf) == -1) + goto err; + + data += sz; + dl -= sz; + } + + if (fputc('\0', fp) == EOF) + goto err; + return 0; +#endif + } + + if (opt->type & (OT_STRING | OT_URI)) { char buf[1024]; if (print_string(buf, sizeof(buf), opt->type, data, dl) == -1) diff --git a/src/dhcp-common.h b/src/dhcp-common.h index 3b21c98e..51413140 100644 --- a/src/dhcp-common.h +++ b/src/dhcp-common.h @@ -80,6 +80,7 @@ #define OT_ESCFILE (1 << 26) #define OT_BITFLAG (1 << 27) #define OT_RESERVED (1 << 28) +#define OT_URI (1 << 29) #define DHC_REQ(r, n, o) \ (has_option_mask((r), (o)) && !has_option_mask((n), (o))) diff --git a/src/dhcpcd-definitions.conf b/src/dhcpcd-definitions.conf index 3c20eef3..d9de797c 100644 --- a/src/dhcpcd-definitions.conf +++ b/src/dhcpcd-definitions.conf @@ -254,6 +254,9 @@ define 141 array domain sip_ua_cs_list # DHCP ANDSF, RFC6153 define 142 array ipaddress andsf +# DHCP SZTP Redirect, RFC8572 +define 143 array uri sztp_redirect + # DHCP Coordinate LCI, RFC6225 # We have no means of expressing 6 bit lengths define 144 binhex geoloc @@ -339,7 +342,7 @@ define 249 rfc3442 ms_classless_static_routes # An expired RFC for Web Proxy Auto Discovery Protocol does define # Option 252 which is commonly used by major browsers. # Apparently the code was assigned by agreement of the DHC working group chair. -define 252 string wpad_url +define 252 uri wpad_url # Option 255 End @@ -544,7 +547,7 @@ define6 57 domain access_domain define6 58 array domain sip_ua_cs_list # DHCPv6 Network Boot, RFC5970 -define6 59 string bootfile_url +define6 59 uri bootfile_url # We presently cannot decode bootfile_param define6 60 binhex bootfile_param define6 61 array uint16 architecture_types @@ -648,7 +651,10 @@ encap 92 option define6 112 string mudurl # DHCP Captive Portal, RFC8910 -define6 103 string captive_portal_uri +define6 103 uri captive_portal_uri + +# DHCP SZTP Redirect, RFC8572 +define6 136 array uri sztp_redirect # DHCP DDoS Open Threat Signaling (DOTS) Agent Discovery, RFC8973 define6 141 domain dots_ri diff --git a/src/dhcpcd.conf.5.in b/src/dhcpcd.conf.5.in index 63837565..566b3727 100644 --- a/src/dhcpcd.conf.5.in +++ b/src/dhcpcd.conf.5.in @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 31, 2022 +.Dd October 4, 2023 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -927,6 +927,10 @@ A fixed value (1) to indicate that the option is present, 0 bytes. An RFC 3397 encoded string. .It Ic dname An RFC 1035 validated string. +.It Ic uri +If an array then the first two bytes are the URI length inside the option data. +Otherwise, the whole option data is the URI. +As a space is not allowed in the URI encoding, the URIs are space separated. .It Ic binhex Op : Ic length Binary data expressed as hexadecimal. .It Ic embed diff --git a/src/if-options.c b/src/if-options.c index bb1c1fca..9c930f38 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1833,6 +1833,8 @@ err_sla: t |= OT_ADDRIPV6; else if (strcasecmp(arg, "string") == 0) t |= OT_STRING; + else if (strcasecmp(arg, "uri") == 0) + t |= OT_URI; else if (strcasecmp(arg, "byte") == 0) t |= OT_UINT8; else if (strcasecmp(arg, "bitflags") == 0)