aboutsummaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorBrooks Davis <brooks@FreeBSD.org>2005-08-30 18:20:46 +0000
committerBrooks Davis <brooks@FreeBSD.org>2005-08-30 18:20:46 +0000
commitf954ec0bcfdb373a4161c1db3aad0c10430a4c8f (patch)
tree7b4686fbd67a0783431c6a825e4abf47e83b6f34 /sbin/dhclient
parentc313f09bfbaba40cc7a85d11f10dbb70f68621cd (diff)
downloadsrc-f954ec0bcfdb373a4161c1db3aad0c10430a4c8f.tar.gz
src-f954ec0bcfdb373a4161c1db3aad0c10430a4c8f.zip
Introduce a new helper function check_search() derived for res_hnok to
check the domain-name parameter according to the rules for "search" strings as documented in resolv.conf(5). Specifically, the string must be no more than 256 bytes long and contain no more than six valid domain names separated by white space. The previous unchecked values could result in a mangled resolv.conf file which could effectively deny access to local sites. This is not a security issue as rogue dhcp servers could already do this without sending invalid strings. Reviewed by: cperciva MFC After: 3 days
Notes
Notes: svn path=/head/; revision=149639
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/dhclient.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index bcf09a756b40..5a62c3de17e8 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
((c) >= 0x61 && (c) <= 0x7a))
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+#define whitechar(c) ((c) == ' ' || (c) == '\t')
#define borderchar(c) (alphachar(c) || digitchar(c))
#define middlechar(c) (borderchar(c) || hyphenchar(c))
@@ -116,6 +117,7 @@ void usage(void);
int check_option(struct client_lease *l, int option);
int ipv4addrs(char * buf);
int res_hnok(const char *dn);
+int check_search(const char *srch);
char *option_as_string(unsigned int code, unsigned char *data, int len);
int fork_privchld(int, int);
@@ -2250,6 +2252,14 @@ check_option(struct client_lease *l, int option)
}
return (1);
case DHO_DOMAIN_NAME:
+ if (!res_hnok(sbuf)) {
+ if (!check_search(sbuf)) {
+ warning("Bogus domain search list %d: %s (%s)",
+ option, sbuf, opbuf);
+ return (0);
+ }
+ }
+ return (1);
case DHO_PAD:
case DHO_TIME_OFFSET:
case DHO_BOOT_SIZE:
@@ -2325,6 +2335,52 @@ res_hnok(const char *dn)
return (1);
}
+int
+check_search(const char *srch)
+{
+ int pch = PERIOD, ch = *srch++;
+ int domains = 1;
+
+ /* 256 char limit re resolv.conf(5) */
+ if (strlen(srch) > 256)
+ return (0);
+
+ while (whitechar(ch))
+ ch = *srch++;
+
+ while (ch != '\0') {
+ int nch = *srch++;
+
+ if (periodchar(ch) || whitechar(ch)) {
+ ;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ if (!whitechar(ch)) {
+ pch = ch;
+ } else {
+ while (whitechar(nch)) {
+ nch = *srch++;
+ }
+ if (nch != '\0')
+ domains++;
+ pch = PERIOD;
+ }
+ ch = nch;
+ }
+ /* 6 domain limit re resolv.conf(5) */
+ if (domains > 6)
+ return (0);
+ return (1);
+}
+
/* Does buf consist only of dotted decimal ipv4 addrs?
* return how many if so,
* otherwise, return 0