Don't choke on responses larger than MAX_HESRESP in size. --- hesiod-3.0.2/hesiod.c 2002-10-02 16:40:35.000000000 -0400 +++ hesiod-3.0.2/hesiod.c 2002-10-02 16:40:35.000000000 -0400 @@ -336,7 +336,7 @@ const char *name) { HEADER *hp; - unsigned char qbuf[PACKETSZ], abuf[MAX_HESRESP], *p, *eom, *eor; + unsigned char qbuf[PACKETSZ], *abuf, *p, *eom, *eor; char *dst, **list; int ancount, qdcount, i, j, n, skip, type, class, len; @@ -351,8 +351,20 @@ return NULL; /* Send the query. */ - n = res_send(qbuf, n, abuf, MAX_HESRESP); - if (n < 0) + abuf = NULL; + len = 1024; + i = n; + do + { + abuf = realloc(abuf, len); + n = res_send(qbuf, i, abuf, len); + if (n < len) + { + break; + } + len = n + 1024; + } while(1); + if (n < sizeof(HEADER)) { errno = ECONNREFUSED; return NULL; @@ -372,6 +384,7 @@ if (skip < 0 || p + skip + QFIXEDSZ > eom) { errno = EMSGSIZE; + free(abuf); return NULL; } p += skip + QFIXEDSZ; @@ -382,6 +395,7 @@ if (!list) { errno = ENOMEM; + free(abuf); return NULL; } @@ -440,6 +454,7 @@ } *dst = 0; } + free(abuf); /* If we didn't terminate the loop normally, something went wrong. */ if (i < ancount) Ignore environment variables in setuid or setgid programs. --- hesiod-3.0.2/hesiod.c Wed Oct 3 14:53:37 2001 +++ hesiod-3.0.2/hesiod.c Wed Oct 3 14:55:02 2001 @@ -52,6 +52,7 @@ #include #include #include +#include #include #include "hesiod.h" #include "hesiod_p.h" @@ -79,13 +80,13 @@ if (ctx) { *context = ctx; - configname = getenv("HESIOD_CONFIG"); + configname = ((getuid() == geteuid()) && (getgid() == getegid())) ? getenv("HESIOD_CONFIG") : NULL; if (!configname) configname = SYSCONFDIR "/hesiod.conf"; if (read_config_file(ctx, configname) >= 0) { /* The default rhs can be overridden by an environment variable. */ - p = getenv("HES_DOMAIN"); + p = ((getuid() == geteuid()) && (getgid() == getegid())) ? getenv("HES_DOMAIN") : NULL; if (p) { if (ctx->rhs) Try to correctly find res_mkquery in libresolv, even in cases where a preprocessor-based rename in may screw us up. --- hesiod-3.0.2/configure.in 2002-09-25 17:21:41.000000000 -0400 +++ hesiod-3.0.2/configure.in 2002-09-25 17:24:58.000000000 -0400 @@ -14,7 +14,11 @@ AC_EGREP_HEADER(pw_change, pwd.h, AC_DEFINE(HAVE_PW_CHANGE)) AC_EGREP_HEADER(pw_expire, pwd.h, AC_DEFINE(HAVE_PW_EXPIRE)) -AC_CHECK_FUNC(res_mkquery, :, [AC_CHECK_LIB(resolv, res_mkquery)]) +AC_CHECK_FUNC(res_mkquery, :, [AC_CHECK_LIB(resolv, res_mkquery,,[ +saveLIBS="$LIBS" +LIBS="-lresolv $LIBS" +AC_TRY_LINK([#include ],[res_mkquery(0,NULL,0,0,NULL,0,NULL,NULL,0);],[AC_DEFINE(HAVE_RES_MKQUERY,1,[Define if your libresolv provides res_mkquery.])],[LIBS="$saveLIBS"]) +])]) AC_CHECK_FUNCS(strerror_r) AC_CONFIG_HEADER(config.h) --- hesiod-3.0.2/Makefile.in Fri Oct 5 15:43:35 2001 +++ hesiod-3.0.2/Makefile.in Fri Oct 5 15:47:42 2001 @@ -21,20 +21,24 @@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ LIBS=@LIBS@ -ALL_CFLAGS=-I. -DSYSCONFDIR=\"${sysconfdir}\" ${CPPFLAGS} ${CFLAGS} +ALL_CFLAGS=-I. -DSYSCONFDIR=\"${sysconfdir}\" ${CPPFLAGS} ${CFLAGS} -fPIC OBJS=hesiod.o hesmailhost.o hespwnam.o hesservbyname.o hescompat.o +SOVERSION=0 -all: libhesiod.a hesinfo hestest +all: libhesiod.a hesinfo hestest libhesiod.so.$(SOVERSION) + +libhesiod.so.$(SOVERSION): ${OBJS} + ${CC} -shared -fPIC -o $@ -Wl,-soname=$@ ${OBJS} ${LIBS} libhesiod.a: ${OBJS} ar cru $@ ${OBJS} ${RANLIB} $@ -hesinfo: hesinfo.o libhesiod.a - ${CC} ${LDFLAGS} -o $@ hesinfo.o libhesiod.a ${LIBS} +hesinfo: hesinfo.o libhesiod.so.$(SOVERSION) + ${CC} ${LDFLAGS} -o $@ hesinfo.o libhesiod.so.$(SOVERSION) ${LIBS} -hestest: hestest.o libhesiod.a - ${CC} ${LDFLAGS} -o $@ hestest.o libhesiod.a ${LIBS} +hestest: hestest.o libhesiod.so.$(SOVERSION) + ${CC} ${LDFLAGS} -o $@ hestest.o libhesiod.so.$(SOVERSION) ${LIBS} ${OBJS}: hesiod.h resscan.h @@ -42,6 +46,7 @@ ${CC} -c ${ALL_CFLAGS} $< check: + LD_LIBRARY_PATH="`pwd`":"$(LD_LIBRARY_PATH)" \ HESIOD_CONFIG=${srcdir}/hesiod.config.sample \ ./hestest ${srcdir}/hestest.conf @@ -55,6 +60,8 @@ ${INSTALL} -c -m 644 libhesiod.a ${DESTDIR}${libdir} ${RANLIB} ${DESTDIR}${libdir}/libhesiod.a chmod u-w ${DESTDIR}${libdir}/libhesiod.a + ${INSTALL} -c -m 755 libhesiod.so.$(SOVERSION) ${DESTDIR}${libdir} + ln -s libhesiod.so.$(SOVERSION) ${DESTDIR}${libdir}/libhesiod.so ${INSTALL_PROGRAM} -c -m 555 hesinfo ${DESTDIR}${lbindir} ${INSTALL} -c -m 444 ${srcdir}/hesiod.h ${DESTDIR}${includedir} ${INSTALL} -c -m 444 ${srcdir}/hesinfo.1 ${DESTDIR}${mandir}/man1 There are a few places where untrusted information could cause problems. There's a bug in the configuration file parser that might result in an LHS= modifying the rhs setting. The case-insensitive comparison routine is probably called safely (with the second argument at least as long as the first), but it looks weird. --- hesiod-3.0.2/hesiod.c Wed Oct 3 15:16:17 2001 +++ hesiod-3.0.2/hesiod.c Wed Oct 3 15:33:41 2001 @@ -138,7 +138,8 @@ const char *rhs; int len; - strcpy(bindname, name); + strncpy(bindname, name, sizeof(bindname) - 1); + bindname[sizeof(bindname) - 1] = 0; /* Find the right right hand side to use, possibly truncating bindname. */ p = strchr(bindname, '@'); @@ -288,7 +289,7 @@ if (cistrcmp(key, "lhs") == 0 || cistrcmp(key, "rhs") == 0) { - which = (strcmp(key, "lhs") == 0) ? &ctx->lhs : &ctx->rhs; + which = (cistrcmp(key, "lhs") == 0) ? &ctx->lhs : &ctx->rhs; *which = malloc(strlen(data) + 1); if (!*which) { @@ -462,7 +463,7 @@ static int cistrcmp(const char *s1, const char *s2) { - while (*s1 && tolower(*s1) == tolower(*s2)) + while (*s1 && *s2 && tolower(*s1) == tolower(*s2)) { s1++; s2++; --- hesiod-3.0.2/hespwnam.c Wed Oct 3 15:29:40 2001 +++ hesiod-3.0.2/hespwnam.c Wed Oct 3 15:29:43 2001 @@ -39,9 +39,16 @@ struct passwd *hesiod_getpwuid(void *context, uid_t uid) { - char uidstr[16]; + char uidstr[32]; - sprintf(uidstr, "%d", uid); - return getpwcommon(context, uidstr, 1); + if (snprintf(uidstr, sizeof(uidstr), "%ld", (long)uid) < sizeof(uidstr)) + { + return getpwcommon(context, uidstr, 1); + } + else + { + errno = ERANGE; + return NULL; + } } --- hesiod-3.0.2/hesservbyname.c Wed Oct 3 15:33:25 2001 +++ hesiod-3.0.2/hesservbyname.c Wed Oct 3 15:33:22 2001 @@ -188,7 +188,7 @@ static int cistrcmp(const char *s1, const char *s2) { - while (*s1 && tolower(*s1) == tolower(*s2)) + while (*s1 && *s2 && tolower(*s1) == tolower(*s2)) { s1++; s2++;