diff -urP bind-4.9.10-REL/CHANGES bind-4.9.10-ow2/CHANGES --- bind-4.9.10-REL/CHANGES Thu Aug 8 06:50:26 2002 +++ bind-4.9.10-ow2/CHANGES Thu Nov 14 04:26:55 2002 @@ -1,4 +1,21 @@ -$Id: CHANGES,v 8.71 2002/08/08 02:50:26 marka Exp $ +$Id: CHANGES,v 8.74 2002/10/23 06:44:27 marka Exp $ + + --- 4.9.11-REL released --- + +825. [bug] the buffer used to construct the -ve record was not + big enough for all possible SOA records. use pointer + arithmetic to calculate the remaining size in this + buffer. + +824. [bug] use serial space arithmetic to determine if a SIG is + too old, in the future or has internally constistant + times. + +824. [bug] write buffer overflow in make_rr(). + +823. [bug] getnetbyname() was broken. + +822. [bug] write buffer overflows in getnetby{name,addr}(). --- 4.9.10-REL released --- diff -urP bind-4.9.10-REL/Makefile bind-4.9.10-ow2/Makefile --- bind-4.9.10-REL/Makefile Thu Aug 8 06:50:26 2002 +++ bind-4.9.10-ow2/Makefile Thu Nov 14 04:31:13 2002 @@ -52,7 +52,7 @@ ## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ## SOFTWARE. -VER = 4.9.10-REL +VER = 4.9.10-OW2 SHELL = /bin/sh MAKE = make DESTDIR = diff -urP bind-4.9.10-REL/named/Makefile bind-4.9.10-ow2/named/Makefile --- bind-4.9.10-REL/named/Makefile Sun Sep 22 04:13:10 1996 +++ bind-4.9.10-ow2/named/Makefile Thu Nov 14 04:27:42 2002 @@ -107,7 +107,7 @@ db_secure.o db_glue.o \ ns_forw.o ns_init.o ns_main.o ns_maint.o ns_req.o ns_resp.o \ ns_sort.o ns_stats.o ns_validate.o ns_ncache.o \ - storage.o tree.o ns_udp.o + storage.o tree.o ns_udp.o shuffle.o XFERSRCS= named-xfer.c XFEROBJ= named-xfer.o db_glue.o storage.o version.o @@ -148,7 +148,7 @@ chmod +x ndc named-xfer: ${XFEROBJ} ${RES} ${COMPLIB} - ${CC} ${CDEBUG} ${LDFLAGS} -o $@ ${XFEROBJ} \ + ${CC} ${CDEBUG} ${LDFLAGS} -static -o $@ ${XFEROBJ} \ ${RES} ${COMPLIB} ${LIBS} centerline_named: diff -urP bind-4.9.10-REL/named/db_defs.h bind-4.9.10-ow2/named/db_defs.h --- bind-4.9.10-REL/named/db_defs.h Mon Jun 2 00:34:34 1997 +++ bind-4.9.10-ow2/named/db_defs.h Thu Nov 14 04:26:55 2002 @@ -66,7 +66,7 @@ #define INVHASHSZ 919 /* size of inverse hash table */ /* max length of data in RR data field */ -#define MAXDATA 2048 +#define MAXDATA (3*MAXDNAME + 5*INT32SZ) #define DB_ROOT_TIMBUF 3600 #define TIMBUF 300 diff -urP bind-4.9.10-REL/named/db_func.h bind-4.9.10-ow2/named/db_func.h --- bind-4.9.10-REL/named/db_func.h Mon Jun 2 00:34:34 1997 +++ bind-4.9.10-ow2/named/db_func.h Thu Nov 14 04:27:42 2002 @@ -15,7 +15,7 @@ /* --from db_update.c-- */ /* ++from db_reload.c++ */ -extern void db_reload __P((void)); +extern void db_reload __P((int)); /* --from db_reload.c-- */ /* ++from db_save.c++ */ diff -urP bind-4.9.10-REL/named/db_load.c bind-4.9.10-ow2/named/db_load.c --- bind-4.9.10-REL/named/db_load.c Mon May 11 08:19:45 1998 +++ bind-4.9.10-ow2/named/db_load.c Thu Nov 14 04:27:42 2002 @@ -690,6 +690,7 @@ if (!getword((char *)buf, sizeof(buf), fp, 0)) goto err; n = strlen((char *)buf); + if (n >= MAXDATA / 8) goto err; *cp++ = n; bcopy(buf, (char *)cp, (int)n); cp += n; @@ -698,6 +699,7 @@ if (!getword((char *)buf, sizeof(buf), fp, 0)) goto err; n = strlen((char *)buf); + if (n >= MAXDATA / 8) goto err; *cp++ = n; bcopy(buf, (char *)cp, (int)n); cp += n; @@ -706,6 +708,7 @@ if (!getword((char *)buf, sizeof(buf), fp, 0)) goto err; n = strlen((char *)buf); + if (n >= MAXDATA / 8) goto err; *cp++ = n; bcopy(buf, (char *)cp, (int)n); cp += n; @@ -713,6 +716,7 @@ /* Replacement */ if (!getword((char *)buf, sizeof(buf), fp, 1)) goto err; + if (strlen(buf) >= MAXDATA / 8) goto err; (void) strcpy((char *)cp, (char *)buf); context = domain_ctx; MAKENAME_OK(cp); diff -urP bind-4.9.10-REL/named/db_reload.c bind-4.9.10-ow2/named/db_reload.c --- bind-4.9.10-REL/named/db_reload.c Tue Aug 27 12:33:23 1996 +++ bind-4.9.10-ow2/named/db_reload.c Thu Nov 14 04:27:42 2002 @@ -72,14 +72,16 @@ * Flush and reload data base. */ void -db_reload() +db_reload(reloadnets) + int reloadnets; { dprintf(3, (ddt, "reload()\n")); syslog(LOG_NOTICE, "reloading nameserver\n"); qflush(); sqflush(NULL); - getnetconf(); + if (reloadnets) + getnetconf(); #ifdef FORCED_RELOAD reloading = 1; /* to force transfer if secondary and backing up */ #endif diff -urP bind-4.9.10-REL/named/named-xfer.c bind-4.9.10-ow2/named/named-xfer.c --- bind-4.9.10-REL/named/named-xfer.c Sun Dec 17 01:54:43 2000 +++ bind-4.9.10-ow2/named/named-xfer.c Thu Nov 14 04:27:42 2002 @@ -214,10 +214,11 @@ #else openlog(ProgName, LOG_PID); #endif + axfr_src.s_addr = 0; #ifdef STUBS - while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qS")) != EOF) + while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qSx:")) != EOF) #else - while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:q")) != EOF) + while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qx:")) != EOF) #endif switch (c) { #ifdef GEN_AXFR @@ -281,6 +282,10 @@ case 'q': quiet++; break; + case 'x': + if (!inet_aton(optarg, &axfr_src)) + panic(-1, "bad -x addr"); + break; case '?': default: usage("unrecognized argument"); @@ -484,6 +489,7 @@ #ifdef GEN_AXFR "\t[-C class]\n", #endif + "\t[-x axfr-src]\n", "\tservers...\n", NULL }; @@ -598,15 +604,24 @@ } bufsize = 2 * PACKETSZ; } - bzero((char *)&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = (u_int16_t)port; - sin.sin_addr = zp->z_addr[cnt]; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_INFO, "socket: %m"); error++; break; } + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + if (axfr_src.s_addr != 0) { + sin.sin_port = 0; /* "ANY" */ + sin.sin_addr = axfr_src; + dprintf(2, (ddt, "binding to address [%s]\n", + inet_ntoa(sin.sin_addr))); + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) + syslog(LOG_INFO, "warning: bind(%s) failed", + inet_ntoa(axfr_src)); + } + sin.sin_port = (u_int16_t)port; + sin.sin_addr = zp->z_addr[cnt]; dprintf(2, (ddt, "connecting to server #%d [%s].%d\n", cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port))); diff -urP bind-4.9.10-REL/named/ns_forw.c bind-4.9.10-ow2/named/ns_forw.c --- bind-4.9.10-REL/named/ns_forw.c Sun Dec 17 01:59:16 2000 +++ bind-4.9.10-ow2/named/ns_forw.c Thu Nov 14 04:27:42 2002 @@ -306,8 +306,6 @@ dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint)); if (sysloginfo && queryname && !haveComplained(queryname, complaint)) { - char buf[999]; - a = ns = (char *)NULL; print_a = (a_rr->d_type == T_A); a_type = p_type(a_rr->d_type); @@ -340,9 +338,9 @@ a = zones[a_rr->d_zone].z_origin; } #endif - /* syslog only takes 5 params */ + /* XXX: syslog only takes 5 params on really broken systems */ if ( a != NULL || ns != NULL) - sprintf(buf, "%s: query(%s) %s (%s:%s) learnt (%s=%s:NS=%s)", + syslog(LOG_INFO, "%s: query(%.64s) %s (%.64s:%s) learnt (%s=%s:NS=%s)", sysloginfo, queryname, complaint, dname, print_a ? @@ -351,12 +349,11 @@ a ? a : "", ns ? ns : "" ); else - sprintf(buf, "%s: query(%s) %s (%s:%s)", + syslog(LOG_INFO, "%s: query(%.64s) %s (%.64s:%s)", sysloginfo, queryname, complaint, dname, print_a ? inet_ntoa(data_inaddr(a_rr->d_data)) : ""); - syslog(LOG_INFO, "%s", buf); } } diff -urP bind-4.9.10-REL/named/ns_glob.h bind-4.9.10-ow2/named/ns_glob.h --- bind-4.9.10-REL/named/ns_glob.h Mon Jun 2 00:34:34 1997 +++ bind-4.9.10-ow2/named/ns_glob.h Thu Nov 14 04:27:42 2002 @@ -195,6 +195,9 @@ DECL char *debugfile INIT(_PATH_DEBUG); #endif + /* default path to named-xfer */ +DECL char *NamedXfer INIT(_PATH_XFER); + #ifdef WANT_PIDFILE /* file to store current named PID */ #ifdef PIDFILE @@ -209,6 +212,9 @@ /* number of zones in use */ DECL int nzones INIT(0); + + /* bind() the axfr socket to this */ +DECL struct in_addr axfr_src INIT({0}); /* true on slave server */ DECL int forward_only INIT(0); diff -urP bind-4.9.10-REL/named/ns_main.c bind-4.9.10-ow2/named/ns_main.c --- bind-4.9.10-REL/named/ns_main.c Sun Dec 17 01:54:43 2000 +++ bind-4.9.10-ow2/named/ns_main.c Thu Nov 14 04:27:42 2002 @@ -100,6 +100,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,8 @@ usage() { fprintf(stderr, -"Usage: named [-d #] [-q] [-r] [-p port[/localport]] [[-b] bootfile]\n"); +"Usage: named [-d #] [-q] [-r] [-p port[/localport]] [[-b] bootfile]\n" +" [-t directory] [-u username] [-x axfr-src]\n"); exit(1); } @@ -179,7 +181,12 @@ fd_set tmpmask; struct timeval t, *tp; struct qstream *candidate = QSTREAM_NULL; - char **argp; + char **argp, *p; + char *chroot_dir = NULL; + char *user_name = NULL; + uid_t user_id; + gid_t group_id; + struct passwd *pw; #ifdef PID_FIX char oldpid[10]; #endif @@ -193,6 +200,9 @@ struct rlimit rl; #endif + user_id = getuid(); + group_id = getgid(); + local_ns_port = ns_port = htons(NAMESERVER_PORT); /* BSD has a better random number generator but it's not clear @@ -277,12 +287,45 @@ NoRecurse = 1; break; + case 't': + if (--argc <= 0) + usage(); + chroot_dir = savestr(*++argv); + break; + + case 'u': + if (--argc <= 0) + usage(); + user_name = *++argv; + if ((pw = getpwnam(user_name))) { + user_name = savestr(pw->pw_name); + user_id = pw->pw_uid; + group_id = pw->pw_gid; + } else { + fprintf(stderr, + "user \"%s\" unknown\n", + user_name); + exit(1); + } + break; + + case 'x': + --argc; + if (!*++argv || + !inet_aton(*argv, &axfr_src)) { + fprintf(stderr, + "bad -x addr: %s", *argv); + exit(1); + } + break; + default: usage(); } } else bootfile = savestr(*argv); } + endpwent(); #ifdef DEBUG if (!debug) @@ -311,6 +354,39 @@ openlog("named", LOG_PID); #endif + nsid_init(); + + /* + * Chroot if desired. + */ + if (chroot_dir != NULL) { + struct stat sb; + + tzset(); + + if (chroot(chroot_dir) < 0) { + fprintf(stderr, "chroot %s failed: %s\n", chroot_dir, + strerror(errno)); + exit(1); + } + if (chdir("/") < 0) { + fprintf(stderr, "chdir(\"/\") failed: %s\n", + strerror(errno)); + exit(1); + } + /* + * Paths to boot file, pid file and named-xfer may need to + * be relative. This is to allow chroot'ing to the named + * homedir. + */ + if (stat(bootfile, &sb) != 0 && (p = strrchr(bootfile, '/'))) + bootfile = p; + if (stat(PidFile, &sb) != 0 && (p = strrchr(PidFile, '/'))) + PidFile = p; + if (stat(NamedXfer, &sb) != 0 && (p = strrchr(NamedXfer, '/'))) + NamedXfer = p; + } + #ifdef RLIMIT_NOFILE rl.rlim_cur = rl.rlim_max = FD_SETSIZE; if (setrlimit(RLIMIT_NOFILE, &rl) == -1) @@ -339,13 +415,14 @@ #endif /*WANT_PIDFILE*/ syslog(LOG_NOTICE, "starting. %s", Version); + if (chroot_dir != NULL) + syslog(LOG_NOTICE, "chrooted to %s", chroot_dir); _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); nsaddr.sin_family = AF_INET; nsaddr.sin_addr.s_addr = INADDR_ANY; nsaddr.sin_port = local_ns_port; - nsid_init(); /* ** Open stream port. @@ -432,9 +509,10 @@ gettime(&tt); buildservicelist(); buildprotolist(); - ns_init(bootfile); + if (user_name == NULL) + ns_init(bootfile); #ifdef DEBUG - if (debug) { + if (user_name == NULL && debug) { fprintf(ddt, "Network and sort list:\n"); printnetinfo(nettab); } @@ -555,6 +633,30 @@ (void) my_fclose(fp); } #endif + /* + * Set user if desired. + */ + if (user_name != NULL) { + gid_t group_list[2]; + + if (setgid(group_id) != 0) { + syslog(LOG_ERR, "setgid(%d): %m", (int)group_id); + exit(1); + } + group_list[0] = group_list[1] = group_id; + if (setgroups(1, group_list) != 0) { + syslog(LOG_ERR, "initgroups(%s, %d): %m", user_name, + (int)group_id); + exit(1); + } + if (setuid(user_id) != 0) { + syslog(LOG_ERR, "setuid(%s): %m", user_name); + exit(1); + } + syslog(LOG_NOTICE, "user = %s", user_name); + + ns_init(bootfile); + } syslog(LOG_NOTICE, "Ready to answer queries.\n"); prime_cache(); @@ -582,7 +684,7 @@ #endif /* XSTATS */ if (needreload) { needreload = 0; - db_reload(); + db_reload((user_name == NULL)); } if (needStatsDump) { needStatsDump = 0; @@ -1040,6 +1142,7 @@ dqp->dq_addr = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr; dqp->dq_gen = my_generation; + /* XXX - this will fail on reload if we run as non-root */ opensocket(dqp); dprintf(1, (ddt, "listening [%s]\n", inet_ntoa(((struct sockaddr_in *) @@ -1669,21 +1772,20 @@ * allocation scheme to make it a little harder to predict them. Note * that the resolver will need the same protection so the cleverness * should be put there rather than here; this is just an interface layer. + * + * Only put the calls to shuffle_*() in here for now... -- 19991107 SD. */ void nsid_init() { - nsid_state = res_randomid(); + nsid_state = _shuffle_next(); } u_int16_t nsid_next() { - if (nsid_state == 65535) - nsid_state = 0; - else - nsid_state++; + nsid_state = _shuffle_next(); return (nsid_state); } diff -urP bind-4.9.10-REL/named/ns_maint.c bind-4.9.10-ow2/named/ns_maint.c --- bind-4.9.10-REL/named/ns_maint.c Sun Sep 22 04:13:10 1996 +++ bind-4.9.10-ow2/named/ns_maint.c Thu Nov 14 04:27:42 2002 @@ -398,10 +398,11 @@ #ifdef GEN_AXFR char class_str[10]; #endif + char src_str[20]; dprintf(1, (ddt, "startxfer() %s\n", zp->z_origin)); - argv[argc++] = _PATH_XFER; + argv[argc++] = NamedXfer; argv[argc++] = "-z"; argv[argc++] = zp->z_origin; argv[argc++] = "-f"; @@ -409,6 +410,10 @@ argv[argc++] = "-s"; sprintf(serial_str, "%lu", (u_long)zp->z_serial); argv[argc++] = serial_str; + if (axfr_src.s_addr != 0) { + argv[argc++] = "-x"; + argv[argc++] = strcpy(src_str, inet_ntoa(axfr_src)); + } #ifdef GEN_AXFR argv[argc++] = "-C"; sprintf(class_str, "%d", zp->z_class); @@ -489,8 +494,8 @@ if (pid == 0) { /* Child. */ - execv(_PATH_XFER, argv); - syslog(LOG_ERR, "can't exec %s: %m", _PATH_XFER); + execv(NamedXfer, argv); + syslog(LOG_ERR, "can't exec %s: %m", NamedXfer); _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */ } /* Parent. */ diff -urP bind-4.9.10-REL/named/ns_ncache.c bind-4.9.10-ow2/named/ns_ncache.c --- bind-4.9.10-REL/named/ns_ncache.c Tue Apr 7 08:59:45 1998 +++ bind-4.9.10-ow2/named/ns_ncache.c Thu Nov 14 04:26:55 2002 @@ -79,8 +79,8 @@ u_int16_t atype; u_char *tp = cp; u_char *cp1; - u_char data[MAXDNAME*2 + INT32SZ*5]; - size_t len = sizeof data; + u_char data[MAXDATA]; + u_char *eod = data + sizeof(data); /* we store NXDOMAIN as T_SOA regardless of the query type */ if (hp->rcode == NXDOMAIN) @@ -107,7 +107,7 @@ rdatap = tp; /* origin */ - n = dn_expand(msg, eom, tp, (char*)data, len); + n = dn_expand(msg, eom, tp, (char*)data, eod - data); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; @@ -115,9 +115,8 @@ tp += n; n = strlen((char*)data) + 1; cp1 = data + n; - len -= n; /* mail */ - n = dn_expand(msg, msg + msglen, tp, (char*)cp1, len); + n = dn_expand(msg, msg + msglen, tp, (char*)cp1, eod - cp1); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; @@ -125,20 +124,20 @@ tp += n; n = strlen((char*)cp1) + 1; cp1 += n; - len -= n; n = 5 * INT32SZ; + if (n > (eod - cp1)) /* Can't happen. See MAXDATA. */ + return; BOUNDS_CHECK(tp, n); bcopy(tp, cp1, n); /* serial, refresh, retry, expire, min */ cp1 += n; - len -= n; tp += n; if (tp != rdatap + dlen) { dprintf(3, (ddt, "ncache: form error 2\n")); return; } /* store the zone of the soa record */ - n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len); + n = dn_expand(msg, msg + msglen, cp, (char*)cp1, eod - cp1); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; diff -urP bind-4.9.10-REL/named/ns_req.c bind-4.9.10-ow2/named/ns_req.c --- bind-4.9.10-REL/named/ns_req.c Sun Dec 17 01:31:26 2000 +++ bind-4.9.10-ow2/named/ns_req.c Thu Nov 14 04:26:55 2002 @@ -1499,7 +1499,7 @@ /* first just copy over the type_covered, algorithm, */ /* labels, orig ttl, two timestamps, and the footprint */ - if ((dp->d_size - 18) > buflen) + if (buflen < 18) goto cleanup; bcopy( cp1, cp, 18 ); cp += 18; diff -urP bind-4.9.10-REL/named/ns_resp.c bind-4.9.10-ow2/named/ns_resp.c --- bind-4.9.10-REL/named/ns_resp.c Tue Apr 7 08:59:45 1998 +++ bind-4.9.10-ow2/named/ns_resp.c Thu Nov 14 04:27:42 2002 @@ -252,7 +252,7 @@ int buflen; int newmsglen; char name[MAXDNAME], qname[MAXDNAME], aname[MAXDNAME]; - char msgbuf[MAXDNAME]; + char msgbuf[MAXDNAME+100]; char *dname, tmpdomain[MAXDNAME]; const char *fname; const char *formerrmsg = "brain damage"; @@ -1669,7 +1669,7 @@ * to BOUNDS_CHECK() here. */ cp1 += (n = strlen((char *)cp1) + 1); - n1 = sizeof(data) - n; + n1 = sizeof(data) - n - INT16SZ; n = dn_expand(msg, eom, cp, (char *)cp1, n1); if (n < 0) { hp->rcode = FORMERR; @@ -1687,7 +1687,7 @@ break; case T_SIG: { - u_long origTTL, exptime, signtime, timetilexp, now; + u_int32_t origTTL, exptime, signtime, timetilexp, now; /* Check signature time, expiration, and adjust TTL. */ /* This code is similar to that in db_load.c. */ @@ -1708,8 +1708,18 @@ ttl = origTTL; } + /* + * Check that expire and signature times are internally + * consistant. + */ + if (!SEQ_GT(exptime, signtime) && exptime != signtime) { + dprintf(3, (ddt, + "ignoring SIG: signature expires before it was signed")); + return ((cp - rrp) + dlen); + } + /* Don't let bogus signers "sign" in the future. */ - if (signtime > now) { + if (SEQ_GT(signtime, now)) { dprintf(3, (ddt, "ignoring SIG: signature date %s is in the future\n", p_secstodate (signtime))); @@ -1717,7 +1727,7 @@ } /* Ignore received SIG RR's that are already expired. */ - if (exptime <= now) { + if (SEQ_GT(exptime, now)) { dprintf(3, (ddt, "ignoring SIG: expiration %s is in the past\n", p_secstodate (exptime))); diff -urP bind-4.9.10-REL/named/shuffle.c bind-4.9.10-ow2/named/shuffle.c --- bind-4.9.10-REL/named/shuffle.c Thu Jan 1 03:00:00 1970 +++ bind-4.9.10-ow2/named/shuffle.c Thu Nov 14 04:27:42 2002 @@ -0,0 +1,257 @@ +/* + * Written by Solar Designer and placed in the public domain. + */ + +#include +#include + +#ifdef __linux__ +#define DEVICE "/dev/urandom" +#else +#undef DEVICE +#endif + +#if defined(DEVICE) && defined(_LIBC) +#define CONSERVE_KERNEL_RANDOMNESS +#else +#undef CONSERVE_KERNEL_RANDOMNESS +#endif + +#ifdef DEVICE +#include +#endif + +#include +#include +#include +#include + +#ifdef TEST +#include +#endif + +#define DIV 0x8000 + +static unsigned char pool[0x100]; + +static struct { + unsigned int base, xor; + unsigned char s[0x80]; +} seed_c; +static unsigned char seed_f[0x100]; + +static struct { + unsigned int msb; + unsigned int a, b; + unsigned int n; +} state; + +static void pool_update(unsigned int seed) +{ + int i, x; + + srand(seed ^ rand()); + for (i = 0; i < sizeof(pool); i++) { + x = rand(); + pool[i] += (x >> 16) ^ x; + } +} + +#ifdef DEVICE +static int read_loop(int fd, char *buffer, int count) +{ + int offset, block; + + offset = 0; + while (count > 0) { + block = read(fd, &buffer[offset], count); + + if (block < 0) { + if (errno == EINTR) continue; + return block; + } + if (!block) return offset; + + offset += block; + count -= block; + } + + return offset; +} + +static int read_random(char *buffer, int count) +{ + int fd; +#ifdef CONSERVE_KERNEL_RANDOMNESS + unsigned int seed[2]; + + if (count > sizeof(pool)) + return -1; +#endif + + if ((fd = open(DEVICE, O_RDONLY)) < 0) + return -1; + +#ifdef CONSERVE_KERNEL_RANDOMNESS + if (read_loop(fd, (char *)seed, sizeof(seed)) != sizeof(seed)) { + close(fd); + return -1; + } + close(fd); + + memset(pool, 'X', sizeof(pool)); + pool_update(seed[0]); + pool_update(seed[1]); + + memcpy(buffer, pool, count); +#else + count = read_loop(fd, buffer, count); + close(fd); +#endif + + return count; +} +#else +#define read_random(buffer, count) (-1) +#endif + +static void shuffle_init() +{ + struct timeval tv; + + if (read_random((char *)seed_f, sizeof(seed_f)) != sizeof(seed_f)) { + memset(pool, 'X', sizeof(pool)); + pool_update(getpid()); + pool_update(getppid()); + if (!gettimeofday(&tv, NULL)) { + pool_update(tv.tv_sec); + pool_update(tv.tv_usec); + } + + memcpy(seed_f, pool, sizeof(seed_f)); + } + + state.msb = 0; + state.n = DIV; /* force a reseed() */ +} + +static void reseed() +{ + struct tms buf; + + if (read_random((char *)&seed_c, sizeof(seed_c)) != sizeof(seed_c)) { + pool_update(times(&buf)); + pool_update(buf.tms_utime); + pool_update(buf.tms_stime); + + memcpy(&seed_c, pool, sizeof(seed_c)); + } + + seed_c.base &= 0x1fff; + seed_c.base <<= 3; + seed_c.base += DIV + 3; + seed_c.xor &= (DIV - 1); + state.msb ^= 0x8000; + state.a = 1; + state.b = 1; + state.n = 0; +} + +/* + * Now, time for a puzzle. Think of division by DIV in seed_c.base. + * This is not as slow as it might appear: the inner loop needs only + * a few iterations per call, on average. + */ +static unsigned int shuffle_1_next() +{ + if (state.n >= DIV - 1) + reseed(); + + if (state.n && state.b <= state.a) { + do { + state.b = ++state.a; + do { + state.b *= seed_c.base; + state.b %= DIV; + } while (state.b > state.a); + } while (state.a != state.b); + } + + state.b *= seed_c.base; + state.b %= DIV; + state.n++; + + return state.b ^ seed_c.xor; +} + +/* + * The idea behind shuffle_2 is David Wagner's (any bugs are mine, + * of course). + */ +static unsigned int shuffle_2(unsigned int x) +{ + unsigned int i, sum; + + sum = 0; + for (i = 0; i < 8; i++) { + sum += 0x79b9; + x ^= ((unsigned int)seed_c.s[(x ^ sum) & 0x7f]) << 7; + x = ((x & 0xff) << 7) | (x >> 8); + } + + return x; +} + +/* + * A full 16-bit permutation. This one can't be re-seeded, but still + * makes some attacks quite a bit harder. + */ +static unsigned int shuffle_3(unsigned int x) +{ + unsigned int i, sum; + + sum = 0; + for (i = 0; i < 8; i++) { + sum += 0x79b9; + x ^= ((unsigned int)seed_f[(x ^ sum) & 0xff]) << 8; + x = ((x & 0xff) << 8) | (x >> 8); + } + + return x; +} + +unsigned int _shuffle_next() +{ + static int initialized = 0; + unsigned int pid, x; + +/* This isn't MT-safe, but the resolver itself isn't safe, anyway */ + if (!initialized) { + shuffle_init(); + initialized = 1; + } + +/* Make sure the sequence we generate changes after fork() */ + pid = getpid(); + + x = shuffle_1_next(); + x ^= pid & 0x7fff; + x = shuffle_2(x); + x |= state.msb; + x ^= (pid >> 15) & 0xffff; + x = shuffle_3(x); + + return x; +} + +#ifdef TEST +int main() +{ + int i; + + for (i = 0; i < 0xfffe; i++) + printf("%u\n", _shuffle_next()); + + return 0; +} +#endif diff -urP bind-4.9.10-REL/res/getnetnamadr.c bind-4.9.10-ow2/res/getnetnamadr.c --- bind-4.9.10-REL/res/getnetnamadr.c Fri Aug 9 03:02:55 2002 +++ bind-4.9.10-ow2/res/getnetnamadr.c Thu Nov 14 04:26:55 2002 @@ -41,7 +41,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03"; -static char rcsid[] = "$Id: getnetnamadr.c,v 8.11 2002/08/08 23:02:55 marka Exp $"; +static char rcsid[] = "$Id: getnetnamadr.c,v 8.14 2002/10/23 06:14:46 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -101,10 +101,11 @@ register int n; u_char *eom; int type, class, ancount, qdcount, haveanswer, i, nchar; - char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap, - *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0, *ep; -static struct netent net_entry; -static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; + char aux1[30], aux2[30], *in, *st, *pauxt, *bp, **ap, + *paux1 = &aux1[0], *paux2 = &aux2[0], *ep; + static struct netent net_entry; + static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; + static char ans[MAXDNAME]; /* * find first satisfactory answer @@ -134,8 +135,14 @@ h_errno = TRY_AGAIN; return (NULL); } - while (qdcount-- > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; + while (qdcount-- > 0) { + n = __dn_skipname(cp, eom); + if (n < 0 || (cp + n + QFIXEDSZ) > eom) { + h_errno = NO_RECOVERY; + return(NULL); + } + cp += n + QFIXEDSZ; + } ap = net_aliases; *ap = NULL; net_entry.n_aliases = net_aliases; @@ -146,7 +153,7 @@ break; cp += n; ans[0] = '\0'; - (void)strcpy(&ans[0], bp); + (void)strcpy(ans, bp); GETSHORT(type, cp); GETSHORT(class, cp); cp += INT32SZ; /* TTL */ @@ -158,11 +165,13 @@ return (NULL); } cp += n; - *ap++ = bp; - bp += strlen(bp) + 1; - net_entry.n_addrtype = - (class == C_IN) ? AF_INET : AF_UNSPEC; - haveanswer++; + if ((ap + 2) < &net_aliases[MAXALIASES]) { + *ap++ = bp; + bp += strlen(bp) + 1; + net_entry.n_addrtype = + (class == C_IN) ? AF_INET : AF_UNSPEC; + haveanswer++; + } } } if (haveanswer) { @@ -173,26 +182,33 @@ net_entry.n_net = 0L; break; case BYNAME: - in = *net_entry.n_aliases; - net_entry.n_name = &ans[0]; + ap = net_entry.n_aliases; + next_alias: + in = *ap++; + if (in == NULL) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + net_entry.n_name = ans; aux2[0] = '\0'; for (i = 0; i < 4; i++) { for (st = in, nchar = 0; - *st != '.'; + isdigit((unsigned char)*st); st++, nchar++) ; - if (nchar != 1 || *in != '0' || flag) { - flag = 1; - (void)strncpy(paux1, - (i==0) ? in : in-1, - (i==0) ?nchar : nchar+1); - paux1[(i==0) ? nchar : nchar+1] = '\0'; - pauxt = paux2; - paux2 = strcat(paux1, paux2); - paux1 = pauxt; - } + if (*st != '.' || nchar == 0 || nchar > 3) + goto next_alias; + if (i != 0) + nchar++; + (void)strncpy(paux1, in, nchar); + paux1[nchar] = '\0'; + pauxt = paux2; + paux2 = strcat(paux1, paux2); + paux1 = pauxt; in = ++st; } + if (strcasecmp(in, "IN-ADDR.ARPA") != 0) + goto next_alias; net_entry.n_net = inet_network(paux2); break; }