- style(9) fixes.

- Add length check for RDNSS and DNSSL option strings.
- Add check for resolv.conf(5) restriction (maximum number of entries).

Submitted by:	bz
This commit is contained in:
hrs 2011-06-03 01:49:04 +00:00
parent 54fd77efc9
commit 3de0851e49
4 changed files with 138 additions and 101 deletions

View File

@ -44,7 +44,9 @@
#include <net/route.h>
#include <net/if_dl.h>
#define __BSD_VISIBLE 1 /* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */
#include <netinet/in.h>
#undef __BSD_VISIBLE
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
@ -81,18 +83,20 @@ static const struct sockaddr_in6 sin6_allrouters = {
};
static void call_script(const int, const char *const *, void *);
static size_t dname_labeldec(char *, const char *);
static size_t dname_labeldec(char *, size_t, const char *);
static int safefile(const char *);
#define _ARGS_OTHER otherconf_script, ifi->ifname
#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname
#define _ARGS_RESDEL resolvconf_script, "-d", ifi->ifname
#define CALL_SCRIPT(name, sm_head) \
#define _ARGS_OTHER otherconf_script, ifi->ifname
#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname
#define _ARGS_RESDEL resolvconf_script, "-d", ifi->ifname
#define CALL_SCRIPT(name, sm_head) \
do { \
const char *const sarg[] = { _ARGS_##name, NULL }; \
call_script(sizeof(sarg), sarg, sm_head); \
} while(0);
#define ELM_MALLOC(p,error_action) \
} while(0)
#define ELM_MALLOC(p,error_action) \
do { \
p = malloc(sizeof(*p)); \
if (p == NULL) { \
@ -101,7 +105,7 @@ static int safefile(const char *);
error_action; \
} \
memset(p, 0, sizeof(*p)); \
} while(0);
} while(0)
int
sockopen(void)
@ -228,7 +232,7 @@ void
rtsol_input(int s)
{
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
int ifindex = 0, *hlimp = NULL;
int l, ifindex = 0, *hlimp = NULL;
ssize_t msglen;
struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL;
@ -364,26 +368,24 @@ rtsol_input(int s)
CALL_SCRIPT(OTHER, NULL);
}
#define RA_OPT_NEXT_HDR(x) (struct nd_opt_hdr *)((char *)x + \
(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
raoptp = (char *)icp + sizeof(struct nd_router_advert);
/* Initialize ra_opt per-interface structure. */
gettimeofday(&now, NULL);
if (!TAILQ_EMPTY(&ifi->ifi_ra_opt)) {
struct ra_opt *rao_tmp;
rao = TAILQ_FIRST(&ifi->ifi_ra_opt);
while (rao != NULL) {
rao_tmp = TAILQ_NEXT(rao, rao_next);
if (!TAILQ_EMPTY(&ifi->ifi_ra_opt))
while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
if (rao->rao_msg != NULL)
free(rao->rao_msg);
TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
free(rao);
rao = rao_tmp;
}
} else
else
TAILQ_INIT(&ifi->ifi_ra_opt);
warnmsg(LOG_DEBUG, __func__, "Processing RA");
#define RA_OPT_NEXT_HDR(x) (struct nd_opt_hdr *)((char *)x + \
(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
/* Process RA options. */
warnmsg(LOG_DEBUG, __func__, "Processing RA");
raoptp = (char *)icp + sizeof(struct nd_router_advert);
while (raoptp < (char *)icp + msglen) {
ndo = (struct nd_opt_hdr *)raoptp;
warnmsg(LOG_DEBUG, __func__, "ndo = %p", raoptp);
@ -411,21 +413,29 @@ rtsol_input(int s)
if (inet_ntop(AF_INET6, addr, ntopbuf,
INET6_ADDRSTRLEN) == NULL) {
warnmsg(LOG_INFO, __func__,
"an invalid address in RDNSS option "
"in RA from %s was ignored.",
inet_ntop(AF_INET6, &from.sin6_addr,
ntopbuf, INET6_ADDRSTRLEN));
"an invalid address in RDNSS option"
" in RA from %s was ignored.",
inet_ntop(AF_INET6, &from.sin6_addr,
ntopbuf, INET6_ADDRSTRLEN));
addr++;
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(addr))
/* XXX: % has to be escaped here */
sprintf(nsbuf, "%s%c%s",
ntopbuf,
l = snprintf(nsbuf, sizeof(nsbuf),
"%s%c%s", ntopbuf,
SCOPE_DELIMITER,
ifi->ifname);
else
sprintf(nsbuf, "%s", ntopbuf);
l = snprintf(nsbuf, sizeof(nsbuf),
"%s", ntopbuf);
if (l < 0 || (size_t)l >= sizeof(nsbuf)) {
warnmsg(LOG_ERR, __func__,
"address copying error in "
"RDNSS option: %d.", l);
addr++;
continue;
}
warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
nsbuf);
@ -438,6 +448,7 @@ rtsol_input(int s)
"strdup failed: %s",
strerror(errno));
free(rao);
addr++;
continue;
}
/* Set expiration timer */
@ -464,7 +475,8 @@ rtsol_input(int s)
}
p = raoptp + sizeof(*dnssl);
while (0 < (len = dname_labeldec(dname, p))) {
while (0 < (len = dname_labeldec(dname, sizeof(dname),
p))) {
warnmsg(LOG_DEBUG, __func__, "dname = %s",
dname);
@ -519,13 +531,16 @@ int
ra_opt_handler(struct ifinfo *ifi)
{
struct ra_opt *rao;
struct script_msg *smp;
struct script_msg *smp1, *smp2, *smp3;
struct timeval now;
TAILQ_HEAD(, script_msg) sm_rdnss_head =
TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
TAILQ_HEAD(, script_msg) sm_dnssl_head =
TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
int dcount, dlen;
dcount = 0;
dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
gettimeofday(&now, NULL);
TAILQ_FOREACH(rao, &ifi->ifi_ra_opt, rao_next) {
switch (rao->rao_type) {
@ -536,17 +551,15 @@ ra_opt_handler(struct ifinfo *ifi)
(char *)rao->rao_msg);
break;
}
ELM_MALLOC(smp, continue);
smp->sm_msg = resstr_ns_prefix;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
ELM_MALLOC(smp, continue);
smp->sm_msg = rao->rao_msg;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
ELM_MALLOC(smp, continue);
smp->sm_msg = resstr_nl;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
ELM_MALLOC(smp1, continue);
ELM_MALLOC(smp2, goto free1);
ELM_MALLOC(smp3, goto free2);
smp1->sm_msg = resstr_ns_prefix;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1, sm_next);
smp2->sm_msg = rao->rao_msg;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2, sm_next);
smp3->sm_msg = resstr_nl;
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3, sm_next);
break;
case ND_OPT_DNSSL:
@ -556,47 +569,63 @@ ra_opt_handler(struct ifinfo *ifi)
(char *)rao->rao_msg);
break;
}
if (TAILQ_EMPTY(&sm_dnssl_head)) {
ELM_MALLOC(smp, continue);
smp->sm_msg = resstr_sh_prefix;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
dcount++;
/* Check resolv.conf(5) restrictions. */
if (dcount > 6) {
warnmsg(LOG_INFO, __func__,
"dnssl entry exceeding maximum count (%d>6)"
": %s", dcount, (char *)rao->rao_msg);
break;
}
ELM_MALLOC(smp, continue);
smp->sm_msg = rao->rao_msg;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
ELM_MALLOC(smp, continue);
smp->sm_msg = resstr_sp;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
if (256 < dlen + strlen(rao->rao_msg) +
strlen(resstr_sp)) {
warnmsg(LOG_INFO, __func__,
"dnssl entry exceeding maximum length "
"(>256): %s", (char *)rao->rao_msg);
break;
}
ELM_MALLOC(smp1, continue);
ELM_MALLOC(smp2, goto free1);
if (TAILQ_EMPTY(&sm_dnssl_head)) {
ELM_MALLOC(smp3, goto free2);
smp3->sm_msg = resstr_sh_prefix;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
sm_next);
}
smp1->sm_msg = rao->rao_msg;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next);
smp2->sm_msg = resstr_sp;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2, sm_next);
dlen += strlen(rao->rao_msg) + strlen(resstr_sp);
break;
default:
break;
}
continue;
free2:
free(smp2);
free1:
free(smp1);
}
/* Add \n for DNSSL list. */
if (!TAILQ_EMPTY(&sm_dnssl_head)) {
ELM_MALLOC(smp, goto ra_opt_handler_freeit);
smp->sm_msg = resstr_nl;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
ELM_MALLOC(smp1, goto ra_opt_handler_freeit);
smp1->sm_msg = resstr_nl;
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next);
}
TAILQ_CONCAT(&sm_rdnss_head, &sm_dnssl_head, sm_next);
if (!TAILQ_EMPTY(&sm_rdnss_head)) {
CALL_SCRIPT(RESADD, &sm_rdnss_head);
} else {
CALL_SCRIPT(RESDEL, NULL);
}
if (!TAILQ_EMPTY(&sm_rdnss_head))
CALL_SCRIPT(RESADD, &sm_rdnss_head);
else
CALL_SCRIPT(RESDEL, NULL);
ra_opt_handler_freeit:
/* Clear script message queue. */
if (!TAILQ_EMPTY(&sm_rdnss_head)) {
struct script_msg *sm_tmp;
smp = TAILQ_FIRST(&sm_rdnss_head);
while(smp != NULL) {
sm_tmp = TAILQ_NEXT(smp, sm_next);
free(smp);
smp = sm_tmp;
while ((smp1 = TAILQ_FIRST(&sm_rdnss_head)) != NULL) {
TAILQ_REMOVE(&sm_rdnss_head, smp1, sm_next);
free(smp1);
}
}
return (0);
@ -609,13 +638,13 @@ call_script(const int argc, const char *const argv[], void *head)
int fd[2];
int error;
pid_t pid, wpid;
TAILQ_HEAD(, script_msg) *sm_head = NULL;
TAILQ_HEAD(, script_msg) *sm_head;
sm_head = head;
fd[0] = fd[1] = -1;
if ((scriptpath = argv[0]) == NULL)
return;
fd[0] = fd[1] = -1;
sm_head = head;
if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) {
error = pipe(fd);
if (error) {
@ -642,7 +671,7 @@ call_script(const int argc, const char *const argv[], void *head)
TAILQ_FOREACH(smp, sm_head, sm_next) {
len = strlen(smp->sm_msg);
warnmsg(LOG_DEBUG, __func__,
"write to child = %s(%d)",
"write to child = %s(%zd)",
smp->sm_msg, len);
if (write(fd[1], smp->sm_msg, len) != len) {
warnmsg(LOG_ERR, __func__,
@ -660,10 +689,9 @@ call_script(const int argc, const char *const argv[], void *head)
if (wpid < 0)
warnmsg(LOG_ERR, __func__,
"wait: %s", strerror(errno));
else {
else
warnmsg(LOG_DEBUG, __func__,
"script \"%s\" terminated", scriptpath);
}
} else { /* child */
int nullfd;
char **_argv;
@ -757,14 +785,15 @@ safefile(const char *path)
/* Decode domain name label encoding in RFC 1035 Section 3.1 */
static size_t
dname_labeldec(char *dst, const char *src)
dname_labeldec(char *dst, size_t dlen, const char *src)
{
size_t len;
const char *src_origin;
src_origin = src;
memset(dst, '\0', dlen);
while (*src && (len = (uint8_t)(*src++) & 0x3f) != 0) {
warnmsg(LOG_DEBUG, __func__, "labellen = %d", len);
warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
memcpy(dst, src, len);
src += len;
dst += len;
@ -772,5 +801,12 @@ dname_labeldec(char *dst, const char *src)
break;
}
/*
* XXX validate that domain name only contains valid characters
* for two reasons: 1) correctness, 2) we do not want to pass
* possible malicious, unescaped characters like `` to a script
* or program that could be exploited that way.
*/
return (src - src_origin);
}

View File

@ -239,8 +239,10 @@ Specifies a script to run when router advertisment options
.Dv RDNSS Pq Recursive DNS Server
or
.Dv DNSSL Pq DNS Search List
are encountered. The information of DNS servers and DNS search domains
will be sent to standard input of this script. The
are encountered.
The information of DNS servers and DNS search domains will be sent to
standard input of this script.
The
.Xr resolvconf 8
script is used by default.
.El

View File

@ -459,17 +459,14 @@ void
iflist_init(void)
{
struct ifinfo *ifi;
struct ifinfo *ifi_tmp;
ifi = TAILQ_FIRST(&ifinfo_head);
while (ifi != NULL) {
while ((ifi = TAILQ_FIRST(&ifinfo_head)) != NULL) {
TAILQ_REMOVE(&ifinfo_head, ifi, ifi_next);
if (ifi->sdl != NULL)
free(ifi->sdl);
if (ifi->rs_data != NULL)
free(ifi->rs_data);
ifi_tmp = TAILQ_NEXT(ifi, ifi_next);
free(ifi);
ifi = ifi_tmp;
}
}
@ -556,6 +553,7 @@ rtsol_check_timer(void)
static struct timeval returnval;
struct timeval now, rtsol_timer;
struct ifinfo *ifi;
struct ra_opt *rao;
int flags;
gettimeofday(&now, NULL);
@ -571,17 +569,11 @@ rtsol_check_timer(void)
ifi->state);
/* Remove all RA options. */
if (!TAILQ_EMPTY(&ifi->ifi_ra_opt)) {
struct ra_opt *rao;
struct ra_opt *rao_tmp;
rao = TAILQ_FIRST(&ifi->ifi_ra_opt);
while (rao != NULL) {
rao_tmp = TAILQ_NEXT(rao, rao_next);
free(rao_tmp->rao_msg);
free(rao_tmp);
rao = rao_tmp;
}
while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
if (rao->rao_msg != NULL)
free(rao->rao_msg);
TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
free(rao);
}
switch (ifi->state) {
case IFS_DOWN:
@ -650,7 +642,6 @@ rtsol_check_timer(void)
rtsol_timer_update(ifi);
} else {
/* Expiration check for RA options. */
struct ra_opt *rao;
struct ra_opt *rao_tmp;
int expire = 0;
@ -782,11 +773,15 @@ static void
usage(void)
{
#ifndef SMALL
fprintf(stderr, "usage: rtsold [-adDfFm1] [-O script-name] [-P pidfile] [-R script-name] interfaces...\n");
fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] [-P pidfile] [-R script-name] -a\n");
fprintf(stderr, "usage: rtsold [-adDfFm1] [-O script-name] "
"[-P pidfile] [-R script-name] interfaces...\n");
fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
"[-P pidfile] [-R script-name] -a\n");
#else
fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] [-P pidfile] [-R script-name] interfaces...\n");
fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] [-P pidfile] [-R script-name] -a\n");
fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
"[-P pidfile] [-R script-name] interfaces...\n");
fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
"[-P pidfile] [-R script-name] -a\n");
#endif
}

View File

@ -36,14 +36,16 @@ struct script_msg {
char *sm_msg;
};
struct ra_opt {
TAILQ_ENTRY(ra_opt) rao_next;
u_int8_t rao_type;
u_int8_t rao_type;
struct timeval rao_expire;
size_t rao_len;
void *rao_msg;
};
struct ifinfo {
TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
@ -100,9 +102,11 @@ extern TAILQ_HEAD(ifinfo_head_t, ifinfo) ifinfo_head;
#endif
#endif
#ifndef IN6ADDR_LINKLOCAL_ALLROUTERS_INIT
#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
#endif
/* rtsold.c */
extern struct timeval tm_max;