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
[-- Attachment #1 --]
Another one from OpenBSD (modulo a few local changes). I can't test
this; is anyone able to do so?
Kris
Index: rwhod.c
===================================================================
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;
+int gothup;
+
#define WHDRSIZE (sizeof(mywd) - sizeof(mywd.wd_we))
-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
+void
+hup(signo)
+ int signo;
+{
+ gothup = 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 = 1;
char *cp;
struct sockaddr_in sin;
+ struct timeval start, next, delta, now;
uid_t unpriv_uid;
gid_t unpriv_gid;
@@ -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 = getservbyname("who", "udp");
if (sp == NULL) {
@@ -240,7 +251,7 @@
syslog(LOG_ERR, "%s: %m", _PATH_UTMP);
exit(1);
}
- getboottime(0);
+ getboottime();
if ((s = 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 = AL_INTERVAL;
+ delta.tv_usec = 0;
+ timeradd(&start, &delta, &next);
}
+
+ pfd[0].fd = s;
+ pfd[0].revents = POLLIN;
for (;;) {
- struct whod wd;
- int cc, whod, len = sizeof(from);
+ int n;
- cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0,
- (struct sockaddr *)&from, &len);
- if (cc <= 0) {
- if (cc < 0 && errno != EINTR)
- syslog(LOG_WARNING, "recv: %m");
- continue;
- }
- if (from.sin_port != 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 != WHODVERSION)
- continue;
- if (wd.wd_type != 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 = open(path, O_WRONLY | O_CREAT, 0644);
- if (whod < 0) {
- syslog(LOG_WARNING, "%s: %m", path);
- continue;
+ n = poll(pfd, 1, 1000);
+
+ if (gothup) {
+ gothup = 0;
+ getboottime();
+ }
+
+ if (n == 1)
+ handleread(s);
+ if (!quiet_mode) {
+ gettimeofday(&now, NULL);
+ if (timercmp(&now, &next, >)) {
+ timer();
+ timeradd(&now, &delta, &next);
+ }
}
+
+ }
+}
+
+void
+handleread(s)
+ int s;
+{
+ struct sockaddr_in from;
+ struct stat st;
+ char path[64];
+ struct whod wd;
+ int cc, whod, len = sizeof(from);
+
+ cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0,
+ (struct sockaddr *)&from, &len);
+ if (cc <= 0) {
+ if (cc < 0 && errno != EINTR)
+ syslog(LOG_WARNING, "recv: %m");
+ return;
+ }
+ if (from.sin_port != 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 != WHODVERSION)
+ return;
+ if (wd.wd_type != WHODTYPE_STATUS)
+ return;
+ wd.wd_hostname[sizeof(wd.wd_hostname)-1] = '\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 = open(path, O_WRONLY | O_CREAT, 0644);
+ if (whod < 0) {
+ syslog(LOG_WARNING, "%s: %m", path);
+ return;
+ }
#if ENDIAN != BIG_ENDIAN
- {
- int i, n = (cc - WHDRSIZE)/sizeof(struct whoent);
- struct whoent *we;
-
- /* undo header byte swapping before writing to file */
- wd.wd_sendtime = ntohl(wd.wd_sendtime);
- for (i = 0; i < 3; i++)
- wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]);
- wd.wd_boottime = ntohl(wd.wd_boottime);
- we = wd.wd_we;
- for (i = 0; i < n; i++) {
- we->we_idle = ntohl(we->we_idle);
- we->we_utmp.out_time =
- ntohl(we->we_utmp.out_time);
- we++;
- }
+ {
+ int i, n = (cc - WHDRSIZE)/sizeof(struct whoent);
+ struct whoent *we;
+
+ /* undo header byte swapping before writing to file */
+ wd.wd_sendtime = ntohl(wd.wd_sendtime);
+ for (i = 0; i < 3; i++)
+ wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]);
+ wd.wd_boottime = ntohl(wd.wd_boottime);
+ we = wd.wd_we;
+ for (i = 0; i < n; i++) {
+ we->we_idle = ntohl(we->we_idle);
+ we->we_utmp.out_time =
+ 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);
}
static void
@@ -391,8 +437,7 @@
int alarmcount;
void
-onalrm(signo)
- int signo;
+timer()
{
register struct neighbor *np;
register struct whoent *we = mywd.wd_we, *wlast;
@@ -404,7 +449,7 @@
now = time(NULL);
if (alarmcount % 10 == 0)
- getboottime(0);
+ getboottime();
alarmcount++;
(void) fstat(utmpf, &stb);
if ((stb.st_mtime != utmptime) || (stb.st_size > utmpsize)) {
@@ -418,14 +463,14 @@
if (! utmp) {
syslog(LOG_WARNING, "malloc failed");
utmpsize = 0;
- goto done;
+ return;
}
}
(void) lseek(utmpf, (off_t)0, L_SET);
cc = read(utmpf, (char *)utmp, stb.st_size);
if (cc < 0) {
syslog(LOG_ERR, "read(%s): %m", _PATH_UTMP);
- goto done;
+ return;
}
wlast = &mywd.wd_we[1024 / sizeof(struct whoent) - 1];
utmpent = cc / sizeof(struct utmp);
@@ -493,13 +538,10 @@
syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR);
exit(1);
}
-done:
- (void) alarm(AL_INTERVAL);
}
void
-getboottime(signo)
- int signo;
+getboottime()
{
int mib[2];
size_t size;
@@ -691,10 +733,10 @@
register struct whoent *we;
struct sockaddr_in *sin = (struct sockaddr_in *)to;
- 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 = w->wd_we, cc /= sizeof(struct whoent); cc > 0; cc--, we++) {
time_t t = 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 = ntohl(we->we_idle) / 60;
if (we->we_idle) {
if (we->we_idle >= 100*60)
@@ -728,18 +770,19 @@
int days, hours, minutes;
if (time < 0 || time > 3*30*24*60*60) {
- (void) sprintf(resbuf, " %s ??:??", updown);
+ (void) snprintf(resbuf, sizeof(resbuf),
+ " %s ??:??", updown);
return (resbuf);
}
minutes = (time + 59) / 60; /* round to minutes */
hours = minutes / 60; minutes %= 60;
days = hours / 24; hours %= 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
[-- Attachment #2 --]
-----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-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010723223904.A1381>
