Date: Mon, 23 Jul 2001 22:39:04 -0700 From: Kris Kennaway <kris@obsecurity.org> To: audit@FreeBSD.org Subject: rwhod signal fixes Message-ID: <20010723223904.A1381@xor.obsecurity.org>
next in thread | raw e-mail | index | archive | help
--J2SCkAp4GZ/dPZZf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Another one from OpenBSD (modulo a few local changes). I can't test this; is anyone able to do so? Kris Index: rwhod.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /mnt/ncvs/src/usr.sbin/rwhod/rwhod.c,v retrieving revision 1.15 diff -u -r1.15 rwhod.c --- rwhod.c 2000/12/22 21:30:15 1.15 +++ rwhod.c 2001/07/24 05:35:56 @@ -63,6 +63,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <poll.h> #include <netdb.h> #include <paths.h> #include <stdio.h> @@ -149,16 +150,20 @@ struct servent *sp; int s, utmpf; =20 +int gothup; + #define WHDRSIZE (sizeof(mywd) - sizeof(mywd.wd_we)) =20 -void run_as __P((uid_t *, gid_t *)); int configure __P((int)); -void getboottime __P((int)); -void onalrm __P((int)); +void getboottime __P((void)); +void handleread __P((int s)); +void hup __P((int)); void quit __P((char *)); void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); -int verify __P((char *, int)); +void run_as __P((uid_t *, gid_t *)); +void timer __P((void)); static void usage __P((void)); +int verify __P((char *, int)); #ifdef DEBUG char *interval __P((int, char *)); void Sendto __P((int, const void *, size_t, int, @@ -166,17 +171,23 @@ #define sendto Sendto #endif =20 +void +hup(signo) + int signo; +{ + gothup =3D 1; +} + int main(argc, argv) int argc; char *argv[]; { - struct sockaddr_in from; - struct stat st; - char path[64]; + struct pollfd pfd[1]; int on =3D 1; char *cp; struct sockaddr_in sin; + struct timeval start, next, delta, now; uid_t unpriv_uid; gid_t unpriv_gid; =20 @@ -213,7 +224,7 @@ #ifndef DEBUG daemon(1, 0); #endif - (void) signal(SIGHUP, getboottime); + (void) signal(SIGHUP, hup); openlog("rwhod", LOG_PID, LOG_DAEMON); sp =3D getservbyname("who", "udp"); if (sp =3D=3D NULL) { @@ -240,7 +251,7 @@ syslog(LOG_ERR, "%s: %m", _PATH_UTMP); exit(1); } - getboottime(0); + getboottime(); if ((s =3D socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); @@ -263,74 +274,109 @@ if (!configure(s)) exit(1); if (!quiet_mode) { - signal(SIGALRM, onalrm); - onalrm(0); + timer(); + gettimeofday(&start, NULL); + delta.tv_sec =3D AL_INTERVAL; + delta.tv_usec =3D 0; + timeradd(&start, &delta, &next); } + + pfd[0].fd =3D s; + pfd[0].revents =3D POLLIN; for (;;) { - struct whod wd; - int cc, whod, len =3D sizeof(from); + int n; =20 - cc =3D recvfrom(s, (char *)&wd, sizeof(struct whod), 0, - (struct sockaddr *)&from, &len); - if (cc <=3D 0) { - if (cc < 0 && errno !=3D EINTR) - syslog(LOG_WARNING, "recv: %m"); - continue; - } - if (from.sin_port !=3D sp->s_port && !insecure_mode) { - syslog(LOG_WARNING, "%d: bad source port from %s", - ntohs(from.sin_port), inet_ntoa(from.sin_addr)); - continue; - } - if (cc < WHDRSIZE) { - syslog(LOG_WARNING, "short packet from %s", - inet_ntoa(from.sin_addr)); - continue; - } - if (wd.wd_vers !=3D WHODVERSION) - continue; - if (wd.wd_type !=3D WHODTYPE_STATUS) - continue; - if (!verify(wd.wd_hostname, sizeof wd.wd_hostname)) { - syslog(LOG_WARNING, "malformed host name from %s", - inet_ntoa(from.sin_addr)); - continue; - } - (void) snprintf(path, sizeof path, "whod.%s", wd.wd_hostname); - /* - * Rather than truncating and growing the file each time, - * use ftruncate if size is less than previous size. - */ - whod =3D open(path, O_WRONLY | O_CREAT, 0644); - if (whod < 0) { - syslog(LOG_WARNING, "%s: %m", path); - continue; + n =3D poll(pfd, 1, 1000); + + if (gothup) { + gothup =3D 0; + getboottime(); + } + + if (n =3D=3D 1) + handleread(s); + if (!quiet_mode) { + gettimeofday(&now, NULL); + if (timercmp(&now, &next, >)) { + timer(); + timeradd(&now, &delta, &next); + } } + =09 + } +} + +void +handleread(s) + int s; +{ + struct sockaddr_in from; + struct stat st; + char path[64]; + struct whod wd; + int cc, whod, len =3D sizeof(from); + + cc =3D recvfrom(s, (char *)&wd, sizeof(struct whod), 0, + (struct sockaddr *)&from, &len); + if (cc <=3D 0) { + if (cc < 0 && errno !=3D EINTR) + syslog(LOG_WARNING, "recv: %m"); + return; + } + if (from.sin_port !=3D sp->s_port && !insecure_mode) { + syslog(LOG_WARNING, "%d: bad source port from %s", + ntohs(from.sin_port), inet_ntoa(from.sin_addr)); + return; + } + if (cc < WHDRSIZE) { + syslog(LOG_WARNING, "short packet from %s", + inet_ntoa(from.sin_addr)); + return; + } + if (wd.wd_vers !=3D WHODVERSION) + return; + if (wd.wd_type !=3D WHODTYPE_STATUS) + return; + wd.wd_hostname[sizeof(wd.wd_hostname)-1] =3D '\0'; + if (!verify(wd.wd_hostname, sizeof wd.wd_hostname)) { + syslog(LOG_WARNING, "malformed host name from %s", + inet_ntoa(from.sin_addr)); + return; + } + (void) snprintf(path, sizeof path, "whod.%s", wd.wd_hostname); + /* + * Rather than truncating and growing the file each time, + * use ftruncate if size is less than previous size. + */ + whod =3D open(path, O_WRONLY | O_CREAT, 0644); + if (whod < 0) { + syslog(LOG_WARNING, "%s: %m", path); + return; + } #if ENDIAN !=3D BIG_ENDIAN - { - int i, n =3D (cc - WHDRSIZE)/sizeof(struct whoent); - struct whoent *we; - - /* undo header byte swapping before writing to file */ - wd.wd_sendtime =3D ntohl(wd.wd_sendtime); - for (i =3D 0; i < 3; i++) - wd.wd_loadav[i] =3D ntohl(wd.wd_loadav[i]); - wd.wd_boottime =3D ntohl(wd.wd_boottime); - we =3D wd.wd_we; - for (i =3D 0; i < n; i++) { - we->we_idle =3D ntohl(we->we_idle); - we->we_utmp.out_time =3D - ntohl(we->we_utmp.out_time); - we++; - } + { + int i, n =3D (cc - WHDRSIZE)/sizeof(struct whoent); + struct whoent *we; + + /* undo header byte swapping before writing to file */ + wd.wd_sendtime =3D ntohl(wd.wd_sendtime); + for (i =3D 0; i < 3; i++) + wd.wd_loadav[i] =3D ntohl(wd.wd_loadav[i]); + wd.wd_boottime =3D ntohl(wd.wd_boottime); + we =3D wd.wd_we; + for (i =3D 0; i < n; i++) { + we->we_idle =3D ntohl(we->we_idle); + we->we_utmp.out_time =3D + ntohl(we->we_utmp.out_time); + we++; } -#endif - (void) time((time_t *)&wd.wd_recvtime); - (void) write(whod, (char *)&wd, cc); - if (fstat(whod, &st) < 0 || st.st_size > cc) - ftruncate(whod, cc); - (void) close(whod); } +#endif + (void) time((time_t *)&wd.wd_recvtime); + (void) write(whod, (char *)&wd, cc); + if (fstat(whod, &st) < 0 || st.st_size > cc) + ftruncate(whod, cc); + (void) close(whod); } =20 static void @@ -391,8 +437,7 @@ int alarmcount; =20 void -onalrm(signo) - int signo; +timer() { register struct neighbor *np; register struct whoent *we =3D mywd.wd_we, *wlast; @@ -404,7 +449,7 @@ =20 now =3D time(NULL); if (alarmcount % 10 =3D=3D 0) - getboottime(0); + getboottime(); alarmcount++; (void) fstat(utmpf, &stb); if ((stb.st_mtime !=3D utmptime) || (stb.st_size > utmpsize)) { @@ -418,14 +463,14 @@ if (! utmp) { syslog(LOG_WARNING, "malloc failed"); utmpsize =3D 0; - goto done; + return; } } (void) lseek(utmpf, (off_t)0, L_SET); cc =3D read(utmpf, (char *)utmp, stb.st_size); if (cc < 0) { syslog(LOG_ERR, "read(%s): %m", _PATH_UTMP); - goto done; + return; } wlast =3D &mywd.wd_we[1024 / sizeof(struct whoent) - 1]; utmpent =3D cc / sizeof(struct utmp); @@ -493,13 +538,10 @@ syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR); exit(1); } -done: - (void) alarm(AL_INTERVAL); } =20 void -getboottime(signo) - int signo; +getboottime() { int mib[2]; size_t size; @@ -691,10 +733,10 @@ register struct whoent *we; struct sockaddr_in *sin =3D (struct sockaddr_in *)to; =20 - printf("sendto %x.%d\n", ntohl(sin->sin_addr.s_addr), - ntohs(sin->sin_port)); + printf("sendto %s.%d\n", inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port)); printf("hostname %s %s\n", w->wd_hostname, - interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up")); + interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up")); printf("load %4.2f, %4.2f, %4.2f\n", ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0, ntohl(w->wd_loadav[2]) / 100.0); @@ -702,9 +744,9 @@ for (we =3D w->wd_we, cc /=3D sizeof(struct whoent); cc > 0; cc--, we++) { time_t t =3D ntohl(we->we_utmp.out_time); printf("%-8.8s %s:%s %.12s", - we->we_utmp.out_name, - w->wd_hostname, we->we_utmp.out_line, - ctime(&t)+4); + we->we_utmp.out_name, + w->wd_hostname, we->we_utmp.out_line, + ctime(&t)+4); we->we_idle =3D ntohl(we->we_idle) / 60; if (we->we_idle) { if (we->we_idle >=3D 100*60) @@ -728,18 +770,19 @@ int days, hours, minutes; =20 if (time < 0 || time > 3*30*24*60*60) { - (void) sprintf(resbuf, " %s ??:??", updown); + (void) snprintf(resbuf, sizeof(resbuf), + " %s ??:??", updown); return (resbuf); } minutes =3D (time + 59) / 60; /* round to minutes */ hours =3D minutes / 60; minutes %=3D 60; days =3D hours / 24; hours %=3D 24; if (days) - (void) sprintf(resbuf, "%s %2d+%02d:%02d", - updown, days, hours, minutes); + (void) snprintf(resbuf, sizeof(resbuf), + "%s %2d+%02d:%02d", updown, days, hours, minutes); else - (void) sprintf(resbuf, "%s %2d:%02d", - updown, hours, minutes); + (void) snprintf(resbuf, sizeof(resbuf), + "%s %2d:%02d", updown, hours, minutes); return (resbuf); } #endif --J2SCkAp4GZ/dPZZf Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (FreeBSD) Comment: For info see http://www.gnupg.org iD8DBQE7XQn3Wry0BWjoQKURArY3AJsGycSh05K0Q3szHse/o8eRkOccIQCg4eoO 5O8+xbwyYyjp+nQfX4pFwYg= =H8VJ -----END PGP SIGNATURE----- --J2SCkAp4GZ/dPZZf-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010723223904.A1381>