1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

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
This commit is contained in:
Brooks Davis 2005-08-30 18:20:46 +00:00
parent c313f09bfb
commit f954ec0bcf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=149639

View File

@ -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