Subject: fixing syslogd so that outbound forwarding works with -s...
To: None <tech-security@netbsd.org>
From: Luke Mewburn <lukem@cs.rmit.edu.au>
List: tech-security
Date: 02/18/2000 11:30:08
by redmail.netbsd.org with SMTP; 18 Feb 2000 00:30:12 -0000
by wombat.cs.rmit.edu.au (8.9.3/8.9.3/cshub) with ESMTP id LAA17209
for <tech-security@netbsd.org>; Fri, 18 Feb 2000 11:30:08 +1100 (EST)
Message-Id: <200002180030.LAA17209@wombat.cs.rmit.edu.au>
From: Luke Mewburn <lukem@cs.rmit.edu.au>
Reply-to: lukem@cs.rmit.edu.au
To: tech-security@netbsd.org
Subject: fixing syslogd so that outbound forwarding works with -s...
Date: Fri, 18 Feb 2000 11:30:08 +1100
the -s option on syslogd (`secure') stops it listening on internet
sockets. it has the side effect of preventing outbound forwarding
from working as well, which is rather annoying when you have a cluster
of machines and a loghost (where the loghost has filter rules to limit
the clients).
i've whipped up a patch against -current, but i'm not 100% sure it
will prevent DoS attacks against the machine by people trying to fill
up the incoming socket buffers. i've done a shutdown(, SHUT_RD) on the
sockets, but i understand some kernel work will be required to ensure
that this works for UDP.
or should i just listen on the socket, read any data, and toss it if -s
is set? (which probably involves more CPU time in syslogd; i think it's
better if the kernel does the tossing away)
any other problems/comments about what i'm doing?
btw; i still keep doing the `bind' because you may want the outgoing
syslogd packets to originate from the syslog port rather than an
ephemeral port, to allow tigher outgoing ipfilter rules.
Index: syslogd.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.33
diff -p -p -r1.33 syslogd.c
*** syslogd.c 1999/12/13 04:25:08 1.33
--- syslogd.c 2000/02/18 00:16:09
*************** struct filed consfile;
*** 187,194 ****
int Debug; /* debug flag */
char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
char *LocalDomain; /* our local domain name */
! int InetInuse = 0; /* non-zero if INET sockets are being used */
! int *finet; /* Internet datagram socket */
int Initialized = 0; /* set when we have initialized ourselves */
int MarkInterval = 20 * 60; /* interval between marks in seconds */
int MarkSeq = 0; /* mark sequence number */
--- 187,193 ----
int Debug; /* debug flag */
char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
char *LocalDomain; /* our local domain name */
! int *finet; /* Internet datagram sockets */
int Initialized = 0; /* set when we have initialized ourselves */
int MarkInterval = 20 * 60; /* interval between marks in seconds */
int MarkSeq = 0; /* mark sequence number */
*************** main(argc, argv)
*** 320,333 ****
dprintf("listening on unix dgram socket %s\n", *pp);
}
! if (!SecureMode)
! finet = socksetup(PF_UNSPEC);
! else
! finet = NULL;
!
! if (finet && *finet) {
! dprintf("listening on inet and/or inet6 socket\n");
! InetInuse = 1;
}
if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) {
--- 319,336 ----
dprintf("listening on unix dgram socket %s\n", *pp);
}
! finet = socksetup(PF_UNSPEC);
! if (finet) {
! if (SecureMode) {
! for (j = 0; j < *finet; j++) {
! if (shutdown(finet[j+1], SHUT_RD) < 0) {
! logerror("shutdown");
! die(0);
! }
! }
! } else
! dprintf("listening on inet and/or inet6 socket\n");
! dprintf("sending on inet and/or inet6 socket\n");
}
if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) {
*************** main(argc, argv)
*** 358,364 ****
readfds[nfklogix].fd = fklog;
readfds[nfklogix].events = POLLIN | POLLPRI;
}
! if (finet) {
nfinetix = malloc(*finet * sizeof(*nfinetix));
for (j = 0; j < *finet; j++) {
nfinetix[j] = nfds++;
--- 361,367 ----
readfds[nfklogix].fd = fklog;
readfds[nfklogix].events = POLLIN | POLLPRI;
}
! if (finet && !SecureMode) {
nfinetix = malloc(*finet * sizeof(*nfinetix));
for (j = 0; j < *finet; j++) {
nfinetix[j] = nfds++;
*************** main(argc, argv)
*** 418,433 ****
logerror(buf);
}
}
! if (finet) {
for (j = 0; j < *finet; j++) {
! if (readfds[nfinetix[j]].revents & (POLLIN | POLLPRI)) {
dprintf("inet socket active\n");
len = sizeof(frominet);
! i = recvfrom(finet[j+1], line, MAXLINE, 0,
! (struct sockaddr *)&frominet, &len);
if (i > 0) {
line[i] = '\0';
! printline(cvthname(&frominet), line);
} else if (i < 0 && errno != EINTR)
logerror("recvfrom inet");
}
--- 421,439 ----
logerror(buf);
}
}
! if (finet && !SecureMode) {
for (j = 0; j < *finet; j++) {
! if (readfds[nfinetix[j]].revents &
! (POLLIN | POLLPRI)) {
dprintf("inet socket active\n");
len = sizeof(frominet);
! i = recvfrom(finet[j+1], line, MAXLINE,
! 0, (struct sockaddr *)&frominet,
! &len);
if (i > 0) {
line[i] = '\0';
! printline(cvthname(&frominet),
! line);
} else if (i < 0 && errno != EINTR)
logerror("recvfrom inet");
}
*************** main(argc, argv)
*** 439,447 ****
void
usage()
{
(void)fprintf(stderr,
! "usage: syslogd [-f conffile] [-m markinterval] [-p logpath1] [-p logpath2 ..]\n");
exit(1);
}
--- 445,455 ----
void
usage()
{
+ extern char *__progname;
(void)fprintf(stderr,
! "usage: %s [-f conffile] [-m markinterval] [-p logpath1] [-p logpath2 ..]\n",
! __progname);
exit(1);
}
*************** fprintlog(f, flags, msg)
*** 765,771 ****
case F_FORW:
dprintf(" %s\n", f->f_un.f_forw.f_hname);
! /* check for local vs remote messages (from FreeBSD PR#bin/7055) */
if (strcmp(f->f_prevhost, LocalHostName)) {
l = snprintf(line, sizeof(line) - 1,
"<%d>%.15s [%s]: %s",
--- 773,782 ----
case F_FORW:
dprintf(" %s\n", f->f_un.f_forw.f_hname);
! /*
! * check for local vs remote messages
! * (from FreeBSD PR#bin/7055)
! */
if (strcmp(f->f_prevhost, LocalHostName)) {
l = snprintf(line, sizeof(line) - 1,
"<%d>%.15s [%s]: %s",
*************** fprintlog(f, flags, msg)
*** 778,791 ****
}
if (l > MAXLINE)
l = MAXLINE;
! if (finet && *finet) {
for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) {
for (j = 0; j < *finet; j++) {
#if 0
! /* should we check AF first, or just trial and error? FWD */
! if (r->ai_family == address_family_of(finet[j+1]))
#endif
! lsent = sendto(finet[j+1], line, l, 0, r->ai_addr, r->ai_addrlen);
if (lsent == l)
break;
}
--- 789,807 ----
}
if (l > MAXLINE)
l = MAXLINE;
! if (finet) {
for (r = f->f_un.f_forw.f_addr; r; r = r->ai_next) {
for (j = 0; j < *finet; j++) {
#if 0
! /*
! * should we check AF first, or just
! * trial and error? FWD
! */
! if (r->ai_family ==
! address_family_of(finet[j+1]))
#endif
! lsent = sendto(finet[j+1], line, l, 0,
! r->ai_addr, r->ai_addrlen);
if (lsent == l)
break;
}
*************** init(signo)
*** 1115,1121 ****
break;
case F_USERS:
! for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
printf("%s, ", f->f_un.f_uname[i]);
break;
}
--- 1131,1138 ----
break;
case F_USERS:
! for (i = 0;
! i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
printf("%s, ", f->f_un.f_uname[i]);
break;
}
*************** cfline(line, f)
*** 1211,1224 ****
switch (*p)
{
case '@':
! if (!InetInuse)
break;
(void)strcpy(f->f_un.f_forw.f_hname, ++p);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
! error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints, &res);
if (error) {
logerror(gai_strerror(error));
break;
--- 1228,1242 ----
switch (*p)
{
case '@':
! if (!finet)
break;
(void)strcpy(f->f_un.f_forw.f_hname, ++p);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = 0;
! error = getaddrinfo(f->f_un.f_forw.f_hname, "syslog", &hints,
! &res);
if (error) {
logerror(gai_strerror(error));
break;
*************** socksetup(af)
*** 1331,1337 ****
}
/* Count max number of sockets we may open */
! for (maxs = 0, r = res; r; r = r->ai_next, maxs++);
socks = malloc ((maxs+1) * sizeof(int));
if (!socks) {
logerror("couldn't allocate memory for sockets");
--- 1349,1356 ----
}
/* Count max number of sockets we may open */
! for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
! continue;
socks = malloc ((maxs+1) * sizeof(int));
if (!socks) {
logerror("couldn't allocate memory for sockets");