summaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2015-08-31 21:32:08 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2015-08-31 21:32:08 +0000
commitf5377c2e15db18ea9f9ada766ad2dce1e90cf3f1 (patch)
treef8fd86e7809a90253eb3a6e760c957e9d5d6d406 /sbin/dhclient
parent4604f5d4af6b5e5ae3af334c5752756fa087409a (diff)
Support deviant but historically blessed practice of accepting
multiple domain names in dhcp option 15 (Domain Name). This allows resolv.conf 'search' statements to be built with multiple entries. Adhere to the limits stated in resolv.conf(5) - no more than 6 domains and less than 1024 characters total length. Encountered in the wild and fix tested by beck@. Feedback from deraadt@
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/dhclient.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 9c74c776ccf..ee55e01713a 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.361 2015/05/18 14:59:42 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.362 2015/08/31 21:32:07 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -94,6 +94,7 @@ int findproto(char *, int);
struct sockaddr *get_ifa(char *, int);
void usage(void);
int res_hnok(const char *dn);
+int res_hnok_list(const char *dn);
void fork_privchld(int, int);
void get_ifname(char *);
@@ -1119,8 +1120,20 @@ packet_to_lease(struct in_addr client_addr, struct option_data *options)
if (strlen(pretty) == 0)
continue;
switch (i) {
- case DHO_HOST_NAME:
case DHO_DOMAIN_NAME:
+ /*
+ * Allow deviant but historically blessed
+ * practice of supplying multiple domain names
+ * with DHO_DOMAIN_NAME. Thus allowing multiple
+ * entries in the resolv.conf 'search' statement.
+ */
+ if (!res_hnok_list(pretty)) {
+ warning("Bogus data for option %s",
+ dhcp_options[i].name);
+ continue;
+ }
+ break;
+ case DHO_HOST_NAME:
case DHO_NIS_DOMAIN:
if (!res_hnok(pretty)) {
warning("Bogus data for option %s",
@@ -1903,6 +1916,39 @@ res_hnok(const char *name)
return (1);
}
+/*
+ * resolv_conf(5) says a max of 6 domains and total length of 1024 bytes are
+ * acceptable for the 'search' statement.
+ */
+int
+res_hnok_list(const char *names)
+{
+ char *hn, *inputstring;
+ int count;
+
+ if (strlen(names) >= 1024)
+ return (0);
+
+ inputstring = strdup(names);
+ if (inputstring == NULL)
+ error("Cannot copy domain name list");
+
+ count = 0;
+ while ((hn = strsep(&inputstring, " \t")) != NULL) {
+ if (strlen(hn) == 0)
+ continue;
+ if (res_hnok(hn) == 0)
+ break;
+ count++;
+ if (count > 6)
+ break;
+ }
+
+ free(inputstring);
+
+ return (count > 0 && count < 7 && hn == NULL);
+}
+
void
fork_privchld(int fd, int fd2)
{