Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH] add filter by host functionality to syslogd

2 views
Skip to first unread message

Gregory Edigarov

unread,
May 22, 2013, 5:08:03 AM5/22/13
to te...@openbsd.org
Hi,

the following diff adds filter by host function to syslogd like:

+host
* /var/log/host

or

+host2
mail.* /var/log/host2.mail

etc.

works for me, with only one limitation: now only for resolvable hosts, i.e one cannot have
+192.168.2.1
* /some/file

With best regards,
Gregory Edigarov

Index: syslogd.c
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.107
diff -u -r1.107 syslogd.c
--- syslogd.c 16 Apr 2013 19:24:55 -0000 1.107
+++ syslogd.c 22 May 2013 08:31:30 -0000
@@ -124,6 +124,7 @@
time_t f_time; /* time this was last written */
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
char *f_program; /* program this applies to */
+ char *f_host; /* host this applies to */
union {
char f_uname[MAXUNAMES][UT_NAMESIZE+1];
struct {
@@ -249,7 +250,7 @@
volatile sig_atomic_t WantDie;
volatile sig_atomic_t DoInit;

-struct filed *cfline(char *, char *);
+struct filed *cfline(char *, char *, char *);
void cvthname(struct sockaddr_in *, char *, size_t);
int decode(const char *, const CODE *);
void dodie(int);
@@ -775,6 +776,9 @@
if (f->f_program)
if (strcmp(prog, f->f_program) != 0)
continue;
+ if (f->f_host)
+ if (strcmp(from,f->f_host) != 0)
+ continue;

if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
continue;
@@ -1187,7 +1191,7 @@
void
init(void)
{
- char cline[LINE_MAX], prog[NAME_MAX+1], *p;
+ char cline[LINE_MAX], prog[NAME_MAX+1], host[NAME_MAX+1], *p;
struct filed *f, *next, **nextp, *mb, *m;
FILE *cf;
int i;
@@ -1223,6 +1227,10 @@
next = f->f_next;
if (f->f_program)
free(f->f_program);
+
+ if (f->f_host)
+ free(f->f_host);
+
if (f->f_type == F_MEMBUF) {
f->f_next = mb;
f->f_program = NULL;
@@ -1237,8 +1245,8 @@
/* open the configuration file */
if ((cf = priv_open_config()) == NULL) {
dprintf("cannot open %s\n", ConfFile);
- *nextp = cfline("*.ERR\t/dev/console", "*");
- (*nextp)->f_next = cfline("*.PANIC\t*", "*");
+ *nextp = cfline("*.ERR\t/dev/console", "*", "*");
+ (*nextp)->f_next = cfline("*.PANIC\t*", "*", "*");
Initialized = 1;
return;
}
@@ -1248,6 +1256,7 @@
*/
f = NULL;
strlcpy(prog, "*", sizeof(prog));
+ strlcpy(host, "*", sizeof(host));
while (fgets(cline, sizeof(cline), cf) != NULL) {
/*
* check for end-of-section, comments, strip off trailing
@@ -1274,6 +1283,24 @@
prog[i] = 0;
continue;
}
+ if (*p == '+') {
+ p++;
+ while (isspace(*p))
+ p++;
+ if (!*p || (*p == '*' && (!p[1] || isspace(p[1])))) {
+ strlcpy(host, "*", sizeof(host));
+ continue;
+ }
+ for (i = 0; i < NAME_MAX; i++) {
+ if (!isalnum(p[i]) && p[i] != '-' && p[i] != '!')
+ break;
+ host[i] = p[i];
+ }
+ host[i] = 0;
+ continue;
+ }
+
+
p = cline + strlen(cline);
while (p > cline)
if (!isspace(*--p)) {
@@ -1281,7 +1308,7 @@
break;
}
*p = '\0';
- f = cfline(cline, prog);
+ f = cfline(cline, prog, host);
if (f != NULL) {
*nextp = f;
nextp = &f->f_next;
@@ -1390,13 +1417,15 @@
case F_CONSOLE:
case F_PIPE:
if (strcmp(list->f_un.f_fname, f->f_un.f_fname) == 0 &&
- progmatches(list->f_program, f->f_program))
+ (progmatches(list->f_program, f->f_program) ||
+ progmatches(list->f_host, f->f_host)))
return (list);
break;
case F_MEMBUF:
if (strcmp(list->f_un.f_mb.f_mname,
f->f_un.f_mb.f_mname) == 0 &&
- progmatches(list->f_program, f->f_program))
+ (progmatches(list->f_program, f->f_program) ||
+ progmatches(list->f_host, f->f_host)))
return (list);
break;
}
@@ -1408,7 +1437,7 @@
* Crack a configuration file line
*/
struct filed *
-cfline(char *line, char *prog)
+cfline(char *line, char *prog, char *host)
{
int i, pri, addr_len;
size_t rb_len;
@@ -1416,7 +1445,7 @@
char buf[MAXLINE], ebuf[100];
struct filed *xf, *f, *d;

- dprintf("cfline(\"%s\", f, \"%s\")\n", line, prog);
+ dprintf("cfline(\"%s\", f, \"%s\",\"%s\")\n", line, prog, host);

errno = 0; /* keep strerror() stuff out of logerror messages */

@@ -1428,7 +1457,7 @@
f->f_pmask[i] = INTERNAL_NOPRI;

/* save program name if any */
- if (*prog == '!') {
+ if (*prog == '!' || *host == '!') {
f->f_quick = 1;
prog++;
} else
@@ -1440,7 +1469,13 @@
if (f->f_program)
strlcpy(f->f_program, prog, strlen(prog)+1);
}
-
+ if (!strcmp(host,"*"))
+ host = NULL;
+ else {
+ f->f_host = calloc(1, strlen(host)+1);
+ if (f->f_host)
+ strlcpy(f->f_host, host, strlen(host)+1);
+ }
/* scan through the list of selectors */
for (p = line; *p && *p != '\t';) {


Ted Unangst

unread,
May 22, 2013, 11:40:08 AM5/22/13
to Gregory Edigarov, te...@openbsd.org
On Wed, May 22, 2013 at 12:06, Gregory Edigarov wrote:
>
> works for me, with only one limitation: now only for resolvable hosts, i.e
> one cannot have
> +192.168.2.1
> * /some/file

Looking at the diff, I think it's not resolvable hosts, but whatever
hostname the sending machine decides to tell you?

My first thought is that we shouldn't rely on that, and syslogd should
refuse requests entirely from servers it doesn't like. My second
thought is that's what pf is for and spoofing syslog entries is
already pretty easy, so this is fine, but it needs to be documented as
such.

(I didn't look further at the diff to see if it was actually correct.)

Gregory Edigarov

unread,
May 23, 2013, 5:58:48 AM5/23/13
to te...@openbsd.org
On 05/22/2013 06:39 PM, Ted Unangst wrote:
> On Wed, May 22, 2013 at 12:06, Gregory Edigarov wrote:
>>
>> works for me, with only one limitation: now only for resolvable hosts, i.e
>> one cannot have
>> +192.168.2.1
>> * /some/file
>
> Looking at the diff, I think it's not resolvable hosts, but whatever
> hostname the sending machine decides to tell you?
no, it is really a resolvable hosts.
works correctly with name in /etc/hosts.


> My first thought is that we shouldn't rely on that, and syslogd should
> refuse requests entirely from servers it doesn't like. My second
> thought is that's what pf is for and spoofing syslog entries is
> already pretty easy, so this is fine, but it needs to be documented as
> such.


--

Theo de Raadt

unread,
May 23, 2013, 8:15:23 AM5/23/13
to Gregory Edigarov, te...@openbsd.org
> no, it is really a resolvable hosts.

It is unsafe.

Ted Unangst

unread,
May 23, 2013, 12:21:15 PM5/23/13
to Gregory Edigarov, te...@openbsd.org
On Thu, May 23, 2013 at 12:57, Gregory Edigarov wrote:
> On 05/22/2013 06:39 PM, Ted Unangst wrote:
>> On Wed, May 22, 2013 at 12:06, Gregory Edigarov wrote:
>>>
>>> works for me, with only one limitation: now only for resolvable hosts, i.e
>>> one cannot have
>>> +192.168.2.1
>>> * /some/file
>>
>> Looking at the diff, I think it's not resolvable hosts, but whatever
>> hostname the sending machine decides to tell you?
> no, it is really a resolvable hosts.
> works correctly with name in /etc/hosts.

I don't understand how that can be, since your patch isn't doing any
DNS resolution.

if (f->f_program)
if (strcmp(prog, f->f_program) != 0)
continue;
+ if (f->f_host)
+ if (strcmp(from,f->f_host) != 0)
+ continue;

That's just a string compare. The remote host can send any string it
wants.

Gregory Edigarov

unread,
May 23, 2013, 12:56:16 PM5/23/13
to te...@openbsd.org
yes, it doesn't do any host resolution itself and there is no need in this,
because syslogd already does this. (the resolution happens in main cycle, namely cvthname() function call).
the changes just compare the hostname given in configs and the hostname reported by cvthname, then act accordinly.


--
0 new messages