summaryrefslogtreecommitdiffstats
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorbrooks <brooks@FreeBSD.org>2005-08-30 18:20:46 +0000
committerbrooks <brooks@FreeBSD.org>2005-08-30 18:20:46 +0000
commit40d25976f11fbf40e8b37a57763c0e2a223bc034 (patch)
tree7b4686fbd67a0783431c6a825e4abf47e83b6f34 /sbin/dhclient
parent42baca97e54dc0985cc6f2e8c148438572be0394 (diff)
downloadFreeBSD-src-40d25976f11fbf40e8b37a57763c0e2a223bc034.zip
FreeBSD-src-40d25976f11fbf40e8b37a57763c0e2a223bc034.tar.gz
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
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 bcf09a7..5a62c3d 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
OpenPOWER on IntegriCloud