Jan reported that the microsoft dhcp server sends the domain name option
as a C string (i.e. NUL terminated) on-wire.
This then ends up in /var/db/dhcpleased/$IF as e.g.

domain-name: example.com\^@

which the installer uses to form /etc/myname which then later on smtpd
complains about.

I'm fresh out of microsoft dhcp servers, but this scapy script
demonstrates the problem:

from scapy.all import DHCP_am
from scapy.base_classes import Net

dhcp_server = DHCP_am(iface='carp0', domain='example.com\0',
                      pool=Net('192.168.10.0/24'),
                      network='192.168.10.0/24',
                      gw='192.168.10.254',
                      renewal_time=600, lease_time=3600)
dhcp_server()


RFC 2132, 2. BOOTP Extension/DHCP Option Field Format

   Options containing NVT ASCII data SHOULD
   NOT include a trailing NULL; however, the receiver of such options
   MUST be prepared to delete trailing nulls if they exist.  The
   receiver MUST NOT require that a trailing null be included in the
   data.

OK?

p.s. I'm happy to entertain diffs that ensure that the hostname and
domainname follow the rules of RFC 1034, 3.5. Preferred name syntax.

diff --git engine.c engine.c
index fa25fbbf0b9..dad299a0a6e 100644
--- engine.c
+++ engine.c
@@ -727,7 +727,7 @@ parse_dhcp(struct dhcpleased_iface *iface, struct imsg_dhcp 
*dhcp)
        size_t                   rem, i;
        uint32_t                 sum, usum, lease_time = 0, renewal_time = 0;
        uint32_t                 rebinding_time = 0;
-       uint8_t                 *p, dho = DHO_PAD, dho_len;
+       uint8_t                 *p, dho = DHO_PAD, dho_len, slen;
        uint8_t                  dhcp_message_type = 0;
        int                      routes_len = 0, routers = 0, csr = 0;
        char                     from[sizeof("xx:xx:xx:xx:xx:xx")];
@@ -1016,7 +1016,11 @@ parse_dhcp(struct dhcpleased_iface *iface, struct 
imsg_dhcp *dhcp)
                case DHO_HOST_NAME:
                        if ( dho_len < 1)
                                goto wrong_length;
-                       strvisx(hostname, p, dho_len, VIS_SAFE);
+                       /* MUST delete trailing NUL, per RFC 2132 */
+                       slen = dho_len;
+                       while (p[slen - 1] == '\0')
+                               slen--;
+                       strvisx(hostname, p, slen, VIS_SAFE);
                        if (log_getverbose() > 1)
                                log_debug("DHO_HOST_NAME: %s", hostname);
                        p += dho_len;
@@ -1025,7 +1029,11 @@ parse_dhcp(struct dhcpleased_iface *iface, struct 
imsg_dhcp *dhcp)
                case DHO_DOMAIN_NAME:
                        if ( dho_len < 1)
                                goto wrong_length;
-                       strvisx(domainname, p, dho_len, VIS_SAFE);
+                       /* MUST delete trailing NUL, per RFC 2132 */
+                       slen = dho_len;
+                       while (p[slen - 1] == '\0')
+                               slen--;
+                       strvisx(domainname, p, slen, VIS_SAFE);
                        if (log_getverbose() > 1)
                                log_debug("DHO_DOMAIN_NAME: %s", domainname);
                        p += dho_len;


-- 
I'm not entirely sure you are real.

Reply via email to