From ef603d85cd86ff88cc47d2d54d493df10042c89a Mon Sep 17 00:00:00 2001 From: florian Date: Wed, 4 May 2022 05:57:18 +0000 Subject: [PATCH] As found by n18fuhtm AT tutanota.com there are dhcp servers that send a domain name option with length 1 and a single \0. We strip trailing \0 and then end up with length 0. This is a protocol violation, the minimum length for domain name option is 1, and we ignore the lease. Since we are not going to get this fixed this server side, we might as well just pretend that we didn't receive a domain name (or host name). We only ever care about them in the installer anyway. Not getting a lease because of this corner case is not helpful. OK deraadt --- sbin/dhcpleased/engine.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sbin/dhcpleased/engine.c b/sbin/dhcpleased/engine.c index ae3f467ac3a..b587f3bf6d6 100644 --- a/sbin/dhcpleased/engine.c +++ b/sbin/dhcpleased/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.36 2022/02/16 10:35:57 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.37 2022/05/04 05:57:18 florian Exp $ */ /* * Copyright (c) 2017, 2021 Florian Obser @@ -882,6 +882,8 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) memset(&subnet_mask, 0, sizeof(subnet_mask)); memset(&routes, 0, sizeof(routes)); memset(&nameservers, 0, sizeof(nameservers)); + memset(hostname, 0, sizeof(hostname)); + memset(domainname, 0, sizeof(domainname)); while (rem > 0 && dho != DHO_END) { dho = *p; @@ -1014,14 +1016,18 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) rem -= dho_len; break; case DHO_HOST_NAME: - if (dho_len < 1) - goto wrong_length; + if (dho_len < 1) { + /* + * Protocol violation: minimum length is 1; + * pretend the option is not there + */ + break; + } /* MUST delete trailing NUL, per RFC 2132 */ slen = dho_len; while (slen > 0 && p[slen - 1] == '\0') slen--; - if (slen < 1) - goto wrong_length; + /* slen might be 0 here, pretend option is not there. */ strvisx(hostname, p, slen, VIS_SAFE); if (log_getverbose() > 1) log_debug("DHO_HOST_NAME: %s", hostname); @@ -1029,14 +1035,18 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp *dhcp) rem -= dho_len; break; case DHO_DOMAIN_NAME: - if (dho_len < 1) - goto wrong_length; + if (dho_len < 1) { + /* + * Protocol violation: minimum length is 1; + * pretend the option is not there + */ + break; + } /* MUST delete trailing NUL, per RFC 2132 */ slen = dho_len; while (slen > 0 && p[slen - 1] == '\0') slen--; - if (slen < 1) - goto wrong_length; + /* slen might be 0 here, pretend option is not there. */ strvisx(domainname, p, slen, VIS_SAFE); if (log_getverbose() > 1) log_debug("DHO_DOMAIN_NAME: %s", domainname); -- 2.20.1