Import NetBSD syslogd(8)

The primary reason for the import is a likely GPL taint of the
original MINIX3 syslogd.  As a result, this import may still
have some rough edges.

Change-Id: I5c8d26eca10fc2dd50ecc9eab44a1d483cf068a9
This commit is contained in:
David van Moolenbroek 2015-07-24 22:09:13 +00:00
parent 818c405ae1
commit 3e07920fe2
27 changed files with 10315 additions and 1557 deletions

View file

@ -499,7 +499,7 @@
./usr/bin/svrctl minix-sys
./usr/bin/swifi minix-sys
./usr/bin/synctree minix-sys
./usr/bin/syslogd minix-sys
./usr/bin/syslogd minix-sys obsolete
./usr/bin/sz minix-sys
./usr/bin/tail minix-sys
./usr/bin/tar minix-sys
@ -5310,6 +5310,7 @@
./usr/sbin/postinstall minix-sys
./usr/sbin/pwd_mkdb minix-sys
./usr/sbin/rdate minix-sys
./usr/sbin/syslogd minix-sys
./usr/sbin/traceroute minix-sys
./usr/sbin/unlink minix-sys
./usr/sbin/user minix-sys

View file

@ -9,10 +9,10 @@
*.alert /dev/log
## High severity errors
*.alert;*.crit /var/log/syslog
*.alert /var/log/syslog
## Every other message (errors/warning and informational)
*.info;*.notice;*.warning;*.err /var/log/messages
*.info;mark.info /var/log/messages
## Debug informations (tracing programs)
#*.debug /var/log/debug

View file

@ -24,7 +24,7 @@ SUBDIR= add_route arp at backup btrace \
rotate rsh rshd service setup \
slip spell sprofalyze sprofdiff srccrc \
svclog svrctl swifi synctree sysenv \
syslogd tcpd tcpdp tcpstat telnet \
tcpd tcpdp tcpstat telnet \
telnetd term termcap tget time \
truncate udpstat umount \
update version vol \

View file

@ -1,16 +0,0 @@
Version 1.1 Oct. 28, 2000
- first release for testing.
Version 1.2 Jan. 23, 2001
- Changed pidfile directory to '/usr/spool/locks'
so at boot old file is deleted.
- Changed the 'debug' variable to 'DbgOpt' so 'debug'
can be a preprocessor define from Makefile.
Version 1.3
- Changes for Minix 3.0
- Changed pidfile to /var/run/syslogd.pid and added code
for setting pathname from Makefile
- Merged code from usyslogd.c to handle kernel messages.
- Reworked Makefile to make a correct installation

View file

@ -1,12 +0,0 @@
##
## @(#)Makefile 1.00 Jan. 11, 2000
##
## Makefile for syslogd/klogd
PROG= syslogd
PIDFILE= -DPIDFILE=\"/var/run/syslogd.pid\"
CPPFLAGS+= -Ddebug=0 ${PIDFILE}
BINMODE= 700
MAN=
.include <bsd.prog.mk>

View file

@ -1,69 +0,0 @@
This is just syslogd and the test programs now. syslog() is in libc 4.2
syslogd has been changed to use /proc/kmsg for kernel messages. It also
avoids making any terminal it opens its controlling terminal. Otherwise
we have a dodgy race condition between processes connecting to terminals
which can result in the terminal having the wrong group at the wrong time.
The syslog() in libc 4.2 needs changing to use O_NOCTTY on its opens as
well.
Mike Jagdis Internet: jaggy@purplet.demon.co.uk
FidoNet: Mike Jagdis, 2:252/305
---------------------------------------------------------------------------
Syslogd and Syslog.o
These are the syslogd and syslog ported from 4.3BSD (that's the new one with
the *very* flexible config file).
Syslogd is essentially unchanged from the 4.3BSD, with the exception that
*nothing* is ever logged to the console (BAD thing to do on a UNIXpc). You
can configure it (via /etc/syslog.conf) to log messages in different
logfiles (depending upon the sender's facility code and the priority), log
to users' terminals (same dependancies), and if things get real bad, it can
do a wall (write-all; same dependancies).
Syslog is really only modified in that it uses UDP datagrams because I had
no luck at all using UNIX domain sockets on the 3B1. See syslog.h for
facility codes and priorities that can be used.
BUGS:
Messages from facilities LOG_KERN, LOG_USER, and LOG_PRT never can be
wall-ed, no matter how high the priority. I'm still trying to decide if
this is a bug or a feature. :-)
ALSO INCLUDED:
Syslog_test, sendlog (to use from shell scripts) and logger (for use in
shell script also).
NEEDED:
The resolver routines in libresolv.a are not needed, but allow you to log to
hosts not present in /etc/hosts and to accept logging from same.
-----------------------------------------------------------------------
Fixed up UNIX domain socket code, added Linux specific code to read messages
from the kernel.
The #ifdefs are now :-
SYSLOG_INET listen on a UDP socket (syslogd)
log via UDP (syslog library call)
SYSLOG_UNIXAF listen on a UNIX domain socker (syslogd)
log via UNIX domain (syslogd library)
SYSLOG_KERNEL fork a second copy to read kernel messages using
syslog system call.
syslogd should be built with one or more of these flags, libsyslog.a should
be built with SYSLOG_INET or SYSLOG_UNIXAF, SYSLOG_INET is used in preference
to SYSLOG_UNIXAF.
readlog is a program which reads from the kernel and records the messages
it finds in syslogd via the normal library call interface, it can be run
instead of building syslogd with SYSLOG_KERNEL.

View file

@ -1,26 +0,0 @@
This is the porting to Minix of the "syslogd" facility
available on many other *nix systems.
Since I' m still using an old 286 machine for my Minix
environment, I choosed to start from an old implementation
which has only the basic features. The result is a smaller
program, more suitable for 16 bits machines.
The file syslog.c should be included in C compiler library
(libc.a) or directly linked with prorams requiring syslog.
If you choose the former solution, you must recreate the
library. After having copied the file syslog.c to the
directory '/usr/src/libs/other' you have to modify the
Makefile in this directory adding syslog.c.
Then issue a 'make' command in the '/usr/src/libs' and wait
a while. Then issue 'make install' to install the new object.
NOTE: The network must be configured, up and running for
the package to work
Giovanni Falzoni <gfalzoni@inwind.it>

View file

@ -1,971 +0,0 @@
/*
** Copyright (c) 1983, 1988
** The Regents of the University of California. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. All advertising materials mentioning features or use of this software
** must display the following acknowledgement:
** This product includes software developed by the University of
** California, Berkeley and its contributors.
** 4. Neither the name of the University nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** #ifndef lint
** char copyright2[] =
** "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
** All rights reserved.\n";
** #endif
**
** #ifndef lint
** static char sccsid[] = "@(#)syslogd.c 5.27 (Berkeley) 10/10/88";
** #endif
**
** -----------------------------------------------------------------------
**
** SYSLOGD -- log system messages
** This program implements a system log.
** It takes a series of lines and outputs them according to the setup
** defined in the configuration file.
** Each line may have a priority, signified as "<n>" as
** the first characters of the line. If this is
** not present, a default priority is used.
**
** To kill syslogd, send a signal 15 (terminate).
** A signal 1 (hup) will cause it to reread its configuration file.
**
** Defined Constants:
** MAXLINE -- the maximimum line length that can be handled.
** MAXSVLINE -- the length of saved messages (for filtering)
** DEFUPRI -- the default priority for user messages
** DEFSPRI -- the default priority for kernel messages
**
** Author: Eric Allman
** extensive changes by Ralph Campbell
** more extensive changes by Eric Allman (again)
** changes by Steve Lord
**
** Extensive rewriting by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
**
** $Log$
** Revision 1.3 2006/04/04 14:22:40 beng
** Fix
**
** Revision 1.2 2006/04/04 14:18:16 beng
** Make syslogd work, even if it can only open klog and not udp or vice versa
** (but not neither)
**
** Revision 1.1 2006/04/03 13:07:42 beng
** Kick out usyslogd in favour of syslogd Giovanni's syslogd port
**
** Revision 1.3 2005/09/16 10:10:12 lsodgf0
** Rework for Minix 3. Adds kernel logs from /dev/klogd
*/
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <net/netlib.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/udp.h>
#include <net/gen/udp_io.h>
#include <netdb.h>
#define SYSLOG_NAMES
#include <syslog.h>
#define KLOGD 1
/** Define following values to your requirements **/
#define MAXLINE 512 /* maximum line length */
#define MAXSVLINE 256 /* maximum saved line length */
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
/* Flags to logmsg() */
#define IGN_CONS 0x001 /* don't print on console */
#define SYNC_FILE 0x002 /* do fsync on file after printing */
#define ADDDATE 0x004 /* add a date to the message */
#define MARK 0x008 /* this message is a mark */
#define CTTY "/dev/log" /* Minix log device (console) */
#define dprintf if(DbgOpt!=0)printf
#if debug == 0
#define DEBUG(statement)
#else
#define DEBUG(statement) statement
#endif
#if !defined PIDFILE
#define PIDFILE "/var/run/syslogd.pid"
#endif
#define UNAMESZ 8 /* length of a login name */
#define MAXUNAMES 20 /* maximum number of user names */
#define MAXFNAME 200 /* max file pathname length */
#define MAXHOSTNAMELEN 64 /* max length of FQDN host name */
/* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
* we move to the next interval until we reach the largest. */
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define INTERVAL1 30
#define INTERVAL2 60
#define MAXREPEAT ((sizeof(repeatinterval)/sizeof(repeatinterval[0]))-1)
#define REPEATTIME(f) ((f)->f_time+repeatinterval[(f)->f_repeatcount])
#define BACKOFF(f) {if(++(f)->f_repeatcount>MAXREPEAT)(f)->f_repeatcount=MAXREPEAT;}
/* Values for f_type */
#define F_UNUSED 0 /* unused entry */
#define F_FILE 1 /* regular file */
#define F_TTY 2 /* terminal */
#define F_CONSOLE 3 /* console terminal */
#define F_FORW 4 /* remote machine */
#define F_USERS 5 /* list of users */
#define F_WALL 6 /* everyone logged on */
#define max(a,b) ((a)>=(b)?(a):(b))
/* This structure represents the files that will have log copies printed */
struct filed {
struct filed *f_next; /* next in linked list */
short f_type; /* entry type, see below */
short f_file; /* file descriptor */
time_t f_time; /* time this was last written */
char f_pmask[LOG_NFACILITIES + 1]; /* priority mask */
union {
char f_uname[MAXUNAMES][UNAMESZ + 1];
char f_fname[MAXFNAME];
} f_un;
char f_prevline[MAXSVLINE]; /* last message logged */
char f_lasttime[16]; /* time of last occurrence */
char f_prevhost[MAXHOSTNAMELEN + 1]; /* host from which recd. */
int f_prevpri; /* pri of f_prevline */
int f_prevlen; /* length of f_prevline */
int f_prevcount; /* repetition cnt of prevline */
int f_repeatcount; /* number of "repeated" msgs */
int f_flags; /* store some additional flags */
};
static const char *const TypeNames[] =
{
"UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL", NULL,
};
static struct filed *Files = NULL;
static struct filed consfile;
static int DbgOpt = 0; /* debug flag */
static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
static int Initialized = 0; /* set when we have initialized ourselves */
static int MarkInterval = 20 * 60; /* interval between marks in seconds */
static int MarkSeq = 0; /* mark sequence number */
static time_t now;
static const char *ConfFile = "/etc/syslog.conf";
static const char *PidFile = PIDFILE; /* "/var/run/syslogd.pid" */
static const char ctty[] = CTTY;
static const char ProgName[] = "syslogd:";
static const char version[] = "1.3 (Minix)";
static const char usage[] =
/* */ "usage:\tsyslogd [-d] [-m markinterval] [-f conf-file]\n"
"\t\t[-p listeningport] [-v] [-?]\n" ;
static const int repeatinterval[] =
/* */ {INTERVAL1, INTERVAL2,}; /* # of secs before flush */
/*
** Name: void wallmsg(struct filed *fLog, char *message);
** Function: Write the specified message to either the entire
** world, or a list of approved users.
*/
void wallmsg(struct filed * fLog, char *message)
{
return;
}
/*
** Name: void fprintlog(struct filed *fLog, int flags, char *message);
** Function:
*/
void fprintlog(struct filed * fLog, int flags, char *message)
{
int len;
char line[MAXLINE + 1];
char repbuf[80];
if (message == NULL) {
if (fLog->f_prevcount > 1) {
sprintf(repbuf, "last message repeated %d times", fLog->f_prevcount);
message = repbuf;
} else
message = fLog->f_prevline;
}
snprintf(line, sizeof(line), "%s %s %s",
fLog->f_lasttime, fLog->f_prevhost, message);
DEBUG(dprintf("Logging to %s", TypeNames[fLog->f_type]);)
fLog->f_time = now;
switch (fLog->f_type) {
case F_UNUSED: /* */
DEBUG(dprintf("\n");)
break;
case F_CONSOLE:
if (flags & IGN_CONS) {
case F_FORW: /* */
DEBUG(dprintf(" (ignored)\n");)
break;
} /* else Fall Through */
case F_TTY:
case F_FILE:
DEBUG(dprintf(" %s\n", fLog->f_un.f_fname);)
strcat(line, fLog->f_type != F_FILE ? "\r\n" : "\n");
len = strlen(line);
if (write(fLog->f_file, line, len) != len) {
/* Handle errors */ ;
} else if (flags & SYNC_FILE)
sync();
break;
case F_USERS:
case F_WALL:
DEBUG(dprintf("\n");)
strcat(line, "\r\n");
wallmsg(fLog, line);
break;
}
fLog->f_prevcount = 0;
return;
}
/*
** Name: void logmsg(int pri, char *msg, char *from, int flags);
** Function: Log a message to the appropriate log files, users, etc.
** based on the priority.
*/
void logmsg(int pri, char *msg, char *from, int flags)
{
struct filed *f;
int fac, prilev;
int /*omask,*/ msglen;
char *timestamp;
DEBUG(dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);)
/*
omask = sigblock(__sigmask(SIGHUP) | __sigmask(SIGALRM));
*/
/* Check to see if msg looks non-standard. */
msglen = strlen(msg);
if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
flags |= ADDDATE;
time(&now);
if (flags & ADDDATE)
timestamp = ctime(&now) + 4;
else {
timestamp = msg;
msg += 16;
msglen -= 16;
}
/* Extract facility and priority level */
fac = (flags & MARK) ? LOG_NFACILITIES : LOG_FAC(pri);
prilev = LOG_PRI(pri);
/* Log the message to the particular outputs */
if (!Initialized) {
/* Not yet initialized. Every message goes to console */
f = &consfile;
f->f_file = open(ctty, O_WRONLY | O_NOCTTY);
if (f->f_file >= 0) {
if (!DbgOpt) setsid();
fprintlog(f, flags, msg);
close(f->f_file);
}
} else {
for (f = Files; f; f = f->f_next) {
/* Skip messages that are incorrect priority */
if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI)
continue;
if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue;
/* Don't output marks to recently written files */
if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
continue;
/* Suppress duplicate lines to this file */
if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
!strcmp(msg, f->f_prevline) &&
!strcmp(from, f->f_prevhost)) {
strncpy(f->f_lasttime, timestamp, 15);
f->f_prevcount += 1;
DEBUG(dprintf("msg repeated %d times, %d sec of %d\n",
f->f_prevcount, now - f->f_time,
repeatinterval[f->f_repeatcount]);)
/* If domark would have logged this by now,
* flush it now (so we don't hold isolated
* messages), but back off so we'll flush
* less often in the future. */
if (now > REPEATTIME(f)) {
fprintlog(f, flags, (char *) NULL);
BACKOFF(f);
}
} else {
/* New line, save it */
if (f->f_prevcount) fprintlog(f, 0, (char *) NULL);
f->f_repeatcount = 0;
strncpy(f->f_lasttime, timestamp, 15);
strncpy(f->f_prevhost, from, sizeof(f->f_prevhost));
if (msglen < MAXSVLINE) {
f->f_prevlen = msglen;
f->f_prevpri = pri;
strcpy(f->f_prevline, msg);
fprintlog(f, flags, (char *) NULL);
} else {
f->f_prevline[0] = 0;
f->f_prevlen = 0;
fprintlog(f, flags, msg);
}
}
}
}
/*
sigsetmask(omask);
*/
return;
}
/*
** Name: void logerror(char *type);
** Function: Prints syslogd errors in some place.
*/
void logerror(char *type)
{
char buf[100];
if (errno == 0) sprintf(buf, "%s %s", ProgName, type);
sprintf(buf, "%s %s - %s", ProgName, type, strerror(errno));
errno = 0;
dprintf("%s\n", buf);
logmsg(LOG_SYSLOG | LOG_ERR, buf, LocalHostName, ADDDATE);
return;
}
/*
** Name: void die(int sig);
** Function: Signal handler for kill signals.
*/
void die(int sig)
{
struct filed *f;
char buf[100];
for (f = Files; f != NULL; f = f->f_next) {
/* Flush any pending output */
if (f->f_prevcount) fprintlog(f, 0, NULL);
}
if (sig >= 0) {
DEBUG(dprintf("%s exiting on signal %d\n", ProgName, sig);)
sprintf(buf, "exiting on signal %d", sig);
errno = 0;
logerror(buf);
}
unlink(PidFile);
exit(sig == (-1) ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*
** Name: void domark(int sig);
** Function: Signal handler for alarm.
** Used for messages filtering and mark facility.
*/
void domark(int sig)
{
struct filed *f;
now = time(NULL);
MarkSeq += TIMERINTVL;
if (MarkSeq >= MarkInterval) {
logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE | MARK);
MarkSeq = 0;
}
for (f = Files; f; f = f->f_next) {
if (f->f_prevcount && now >= REPEATTIME(f)) {
DEBUG(dprintf("flush %s: repeated %d times, %d sec.\n",
TypeNames[f->f_type], f->f_prevcount,
repeatinterval[f->f_repeatcount]);)
fprintlog(f, 0, NULL);
BACKOFF(f);
}
}
signal(SIGALRM, domark);
alarm(TIMERINTVL);
return;
}
/*
** Name: int decode(char *name, struct _code *codetab);
** Function: Decode a symbolic name to a numeric value
*/
int decode(char *name, const struct _code *codetab)
{
const struct _code *c;
char *p;
char buf[40];
DEBUG(dprintf("symbolic name: %s", name);)
if (isdigit(*name)) return (atoi(name));
strcpy(buf, name);
for (p = buf; *p; p += 1) {
if (isupper(*p)) *p = tolower(*p);
}
for (c = codetab; c->c_name; c += 1) {
if (!strcmp(buf, c->c_name)) {
DEBUG(dprintf(" ==> %d\n", c->c_val);)
return (c->c_val);
}
}
return (-1);
}
/*
** Name: void cfline(char *line, struct filed *f);
** Function: Parse a configuration file line
*/
void cfline(char *line, struct filed * fLog)
{
char *p, *q, *bp;
int ix, pri;
char buf[MAXLINE];
char xbuf[200];
DEBUG(dprintf("cfline(%s)\n", line);)
/* Keep sys_errlist stuff out of logerror messages */
errno = 0;
/* Clear out file entry */
memset(fLog, 0, sizeof(*fLog));
for (ix = 0; ix <= LOG_NFACILITIES; ix += 1) /* */
fLog->f_pmask[ix] = INTERNAL_NOPRI;
/* Scan through the list of selectors */
for (p = line; *p && *p != '\t';) {
/* Find the end of this facility name list */
for (q = p; *q && *q != '\t' && *q++ != '.';) continue;
/* Collect priority name */
for (bp = buf; *q && !strchr("\t,;", *q);) *bp++ = *q++;
*bp = '\0';
/* Skip cruft */
while (strchr(", ;", *q)) q++;
/* Decode priority name */
pri = decode(buf, prioritynames);
if (pri < 0) {
sprintf(xbuf, "unknown priority name \"%s\"", buf);
logerror(xbuf);
return;
}
/* Scan facilities */
while (*p && !strchr("\t.;", *p)) {
for (bp = buf; *p && !strchr("\t,;.", *p);) *bp++ = *p++;
*bp = '\0';
if (*buf == '*') {
for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
if ((fLog->f_pmask[ix] < pri) ||
(fLog->f_pmask[ix] == INTERNAL_NOPRI)) {
fLog->f_pmask[ix] = pri;
}
} else {
ix = decode(buf, facilitynames);
if (ix < 0) {
sprintf(xbuf, "unknown facility name \"%s\"", buf);
logerror(xbuf);
return;
}
if ((fLog->f_pmask[ix >> 3] < pri) ||
(fLog->f_pmask[ix >> 3] == INTERNAL_NOPRI)) {
fLog->f_pmask[ix >> 3] = pri;
}
}
while (*p == ',' || *p == ' ') p++;
}
p = q;
}
/* Skip to action part */
while (*p == '\t' || *p == ' ') p++;
DEBUG(dprintf("leading char in action: %c\n", *p);)
switch (*p) {
case '@': /* Logging to a remote host */
break; /* NOT IMPLEMENTED */
case '/': /* Logging to a local file/device */
strcpy(fLog->f_un.f_fname, p);
DEBUG(dprintf("filename: %s\n", p); /* ASP */)
if ((fLog->f_file = open(p, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0644)) < 0) {
fLog->f_file = F_UNUSED;
sprintf(xbuf, "unknown file/device (%s)", p);
logerror(xbuf);
break;
}
if (isatty(fLog->f_file)) {
if (!DbgOpt) setsid();
fLog->f_type = F_TTY;
} else
fLog->f_type = F_FILE;
if (strcmp(p, ctty) == 0) fLog->f_type = F_CONSOLE;
break;
case '*': /* Logging to all users */
DEBUG(dprintf("write-all\n");)
fLog->f_type = F_WALL;
break;
default: /* Logging to selected users */
DEBUG(dprintf("users: %s\n", p); /* ASP */)
for (ix = 0; ix < MAXUNAMES && *p; ix += 1) {
for (q = p; *q && *q != ',';) q += 1;
strncpy(fLog->f_un.f_uname[ix], p, UNAMESZ);
if ((q - p) > UNAMESZ)
fLog->f_un.f_uname[ix][UNAMESZ] = '\0';
else
fLog->f_un.f_uname[ix][q - p] = '\0';
while (*q == ',' || *q == ' ') q++;
p = q;
}
fLog->f_type = F_USERS;
break;
}
}
/*
** Name: void printline(char *hname, char *msg);
** Function: Takes a raw input line, decodes the message and
** prints the message on the appropriate log files.
*/
void printline(char *hname, char *msg)
{
char line[MAXLINE + 1];
char *p = msg, *q = line;
int ch, pri = DEFUPRI;
/* Test for special codes */
if (*p == '<') {
pri = 0;
while (isdigit(*++p)) {
if ((*p - '0') < 8) {
/* Only 3 bits allocated for pri -- ASP */
pri = 10 * pri + (*p - '0');
} else
pri = 10 * pri + 7;
}
if (*p == '>') ++p;
}
if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) pri = DEFUPRI;
/* Does not allow users to log kernel messages */
if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
/* Copies message to local buffer, translating control characters */
while ((ch = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) {
if (ch == '\n') /* Removes newlines */
*q++ = ' ';
else if (iscntrl(ch)) { /* Translates control characters */
*q++ = '^';
*q++ = ch ^ 0100;
} else
*q++ = ch;
}
*q = '\0';
logmsg(pri, line, hname, 0);
return;
}
/*
** Name: void printkline(char *hname, char *msg);
** Function: Takes a raw input line from kernel and
** prints the message on the appropriate log files.
*/
void printkline(char *hname, char *msg)
{
char line[MAXLINE + 1];
/* Copies message to local buffer, adding source program tag */
snprintf(line, sizeof(line), "kernel: %s", msg);
logmsg(LOG_KERN | LOG_INFO, line, hname, ADDDATE);
return;
}
/*
** Name: void init(int sig);
** Function: Initialize syslogd from configuration file.
** Used at startup or after a SIGHUP signal.
*/
void init(int sig)
{
FILE *cf;
struct filed *fLog, *next, **nextp;
char *p;
char cline[BUFSIZ];
DEBUG(dprintf("init\n");)
/* Close all open log files. */
Initialized = 0;
for (fLog = Files; fLog != NULL; fLog = next) {
/* Flush any pending output */
if (fLog->f_prevcount) fprintlog(fLog, 0, NULL);
switch (fLog->f_type) {
case F_FILE:
case F_TTY:
case F_CONSOLE: close(fLog->f_file); break;
}
next = fLog->f_next;
free((char *) fLog);
}
Files = NULL;
nextp = &Files;
/* Open the configuration file */
if ((cf = fopen(ConfFile, "r")) != NULL) {
/* Foreach line in the configuration table, open that file. */
fLog = NULL;
while (fgets(cline, sizeof(cline), cf) != NULL) {
/* Check for end-of-section, comments, strip off
* trailing spaces and newline character. */
for (p = cline; isspace(*p); p += 1);
if (*p == '\0' || *p == '#') continue;
for (p = strchr(cline, '\0'); isspace(*--p););
*++p = '\0';
fLog = (struct filed *) calloc(1, sizeof(*fLog));
*nextp = fLog;
nextp = &fLog->f_next;
cfline(cline, fLog);
}
/* Close the configuration file */
fclose(cf);
Initialized = 1;
DEBUG (
if (DbgOpt) {
for (fLog = Files; fLog; fLog = fLog->f_next) {
int i;
for (i = 0; i <= LOG_NFACILITIES; i += 1)
if (fLog->f_pmask[i] == INTERNAL_NOPRI)
printf("X ");
else
printf("%d ", fLog->f_pmask[i]);
printf("%s: ", TypeNames[fLog->f_type]);
switch (fLog->f_type) {
case F_FILE:
case F_TTY:
case F_CONSOLE:
printf("%s", fLog->f_un.f_fname);
break;
case F_FORW:
break;
case F_USERS:
for (i = 0; i < MAXUNAMES && *fLog->f_un.f_uname[i]; i += 1)
printf("%s, ", fLog->f_un.f_uname[i]);
break;
}
printf("\n");
}
}
)
logmsg(LOG_SYSLOG | LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
signal(SIGHUP, init);
DEBUG(dprintf("%s restarted\n", ProgName);)
} else {
DEBUG(dprintf("cannot open %s\n", ConfFile);)
*nextp = (struct filed *) calloc(1, sizeof(*fLog));
cfline("*.ERR\t" CTTY, *nextp);
(*nextp)->f_next = (struct filed *) calloc(1, sizeof(*fLog));
cfline("*.PANIC\t*", (*nextp)->f_next);
Initialized = 1;
}
return;
}
/*
** Name: void daemonize(char *line);
** Function: Clone itself and becomes a daemon releasing unnecessay resources.
*/
void daemonize(char *line)
{
int lfd, len, pid;
if ((lfd = open(PidFile, O_CREAT | O_RDWR, 0600)) > 0) {
len = read(lfd, line, 10);
line[len] = '\0';
close(lfd);
if ((kill(len = atoi(line), 0) < 0 && errno == ESRCH) || len == 0) {
if (!DbgOpt) {
/* Parent ends and child becomes a daemon */
if ((pid = fork()) > 0) {
/* Write process id. in pid file */
lfd = open(PidFile, O_TRUNC | O_WRONLY);
len = sprintf(line, "%5d", pid);
write(lfd, line, len);
close(lfd);
/* Wait for initialization to complete */
exit(EXIT_SUCCESS);
}
sleep(1);
setsid(); /* Set as session leader */
chdir("/"); /* Change to the root directory */
/* Get rid of all open files */
for (lfd = STDERR_FILENO + 1; lfd < OPEN_MAX; lfd += 1)
close(lfd);
}
} else {
fprintf(stderr, "\n%s already running\n", ProgName);
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "\n%s can't open %s (%s)\n", ProgName, PidFile, strerror(errno));
exit(EXIT_FAILURE);
}
return;
}
int sockread(int *fd, char *buf, int maxlen)
{
int len;
/* Read a message from application programs */
len = read(*fd, buf, maxlen);
if (len > 0) { /* Got a message */
buf[len] = '\0';
dprintf("got a message (%d, %#x)\n", *fd, len);
printline(LocalHostName, buf);
} else if (len < 0) { /* Got an error or signal while reading */
if (errno != EINTR) /* */
{
logerror("Receive error from UDP channel");
close(*fd);
*fd= -1;
}
} else { /* (len == 0) Channel has been closed */
logerror("network channel has closed");
close(*fd);
die(-1);
}
return len;
}
/*
** Name: int main(int argc, char **argv);
** Function: Syslog daemon entry point
*/
int main(int argc, char **argv)
{
char *p, *udpdev, *eol;
int nfd, kfd, len, fdmax;
int ufd;
int ch, port = 0;
fd_set fdset;
struct nwio_udpopt udpopt;
struct servent *sp;
char line[MAXLINE + 1];
while ((ch = getopt(argc, argv, "df:m:p:v?")) != EOF) {
switch ((char) ch) {
case 'd': /* Debug */
DbgOpt += 1;
break;
case 'f': /* Set configuration file */
ConfFile = optarg;
break;
case 'm': /* Set mark interval */
MarkInterval = atoi(optarg) * 60;
break;
case 'p': /* Set listening port */
port = atoi(optarg);
break;
case 'v': /* Print version */
fprintf(stderr, "%s version %s\n", ProgName, version);
return EXIT_FAILURE;
case '?': /* Help */
default:
fprintf(stderr, usage);
return EXIT_FAILURE;
}
}
if (argc -= optind) {
fprintf(stderr, usage);
return EXIT_FAILURE;
}
daemonize(line);
/* Get the official name of local host. */
gethostname(LocalHostName, sizeof(LocalHostName) - 1);
if ((p = strchr(LocalHostName, '.'))) *p = '\0';
udpdev = (p = getenv("UDP_DEVICE")) ? p : UDP_DEVICE;
sp = getservbyname("syslog", "udp");
signal(SIGTERM, die);
signal(SIGINT, DbgOpt ? die : SIG_IGN);
signal(SIGQUIT, DbgOpt ? die : SIG_IGN);
signal(SIGALRM, domark);
alarm(TIMERINTVL);
/* Open UDP device */
nfd = open(udpdev, O_NONBLOCK | O_RDONLY);
/* Configures the UDP device */
udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_EN_LOC |
NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
NWUO_RWDATONLY | NWUO_DI_IPOPT;
udpopt.nwuo_locport = udpopt.nwuo_remport =
port == 0 ? sp->s_port : htons(port);
udpopt.nwuo_remaddr = udpopt.nwuo_locaddr = htonl(0x7F000001L);
if(nfd >= 0) {
while (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
if (errno == EAGAIN) {
sleep(1);
continue;
}
logerror("Set/Get UDP options failed");
return EXIT_FAILURE;
}
}
/* Open kernel log device */
kfd = open("/dev/klog", O_NONBLOCK | O_RDONLY);
if(kfd < 0 && nfd < 0) {
logerror("open /dev/klog and udp device failed - can't log anything");
return EXIT_FAILURE;
}
/* Open unix domain socket */
if((ufd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
perror("unix socket");
} else {
struct sockaddr_un uaddr;
memset(&uaddr, 0, sizeof(uaddr));
strncpy(uaddr.sun_path, _PATH_LOG, sizeof(uaddr.sun_path) - 1);
uaddr.sun_family = AF_UNIX;
if(bind(ufd, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
perror("unix socket bind");
close(ufd);
ufd = -1;
}
}
if(ufd < 0) exit(1);
DEBUG(dprintf("unix domain socket = %d, at %s....\n", ufd, _PATH_LOG);)
fdmax = max(max(nfd, kfd), ufd) + 1;
DEBUG(dprintf("off & running....\n");)
init(-1); /* Initilizes log data structures */
for (;;) { /* Main loop */
FD_ZERO(&fdset); /* Setup descriptors for select */
if(nfd >= 0) FD_SET(nfd, &fdset);
if(kfd >= 0) FD_SET(kfd, &fdset);
if(ufd >= 0) FD_SET(ufd, &fdset);
dprintf("select: nfd = %d, ufd = %d, fdmax = %d\n", nfd, ufd, fdmax);
if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
sleep(1);
continue;
}
if (nfd >= 0 && FD_ISSET(nfd, &fdset)) {
dprintf("got nfd message (%d)\n", nfd);
len = sockread(&nfd, line, MAXLINE);
}
if (ufd >= 0 && FD_ISSET(ufd, &fdset)) {
dprintf("got ufd message (%d)\n", ufd);
len = sockread(&ufd, line, MAXLINE);
}
if (kfd >= 0 && FD_ISSET(kfd, &fdset)) {
static char linebuf[5*1024];
/* Read a message from kernel (klog) */
len = read(kfd, linebuf, sizeof(linebuf)-2);
dprintf("got a message (%d, %#x)\n", kfd, len);
for (ch = 0; ch < len; ch += 1)
if (linebuf[ch] == '\0') linebuf[ch] = ' ';
if (linebuf[len - 1] == '\n') len -= 1;
linebuf[len] = '\n';
linebuf[len + 1] = '\0';
p = linebuf;
while((eol = strchr(p, '\n'))) {
*eol = '\0';
printkline(LocalHostName, p);
p = eol+1;
}
}
}
/* Control never gets here */
}
/** syslogd.c **/

View file

@ -1,7 +1,7 @@
MAN= boot.cfg.5 configfile.5 crontab.5 dhcp.conf.5 dir.5 ethers.5 \
fstab.5 hosts.5 httpd.conf.5 http_status.5 keymap.5 \
passwd.5 resolv.conf.5 resolver.5 rhosts.5 statvfs.5 serv.access.5 \
system.conf.5 syslog.conf.5 termcap.5 ttytab.5 TZ.5 utmp.5 \
system.conf.5 termcap.5 ttytab.5 TZ.5 utmp.5 \
pkg_install.conf.5 pkg_summary.5
MLINKS += passwd.5 group.5

View file

@ -1,245 +0,0 @@
.\" syslog.conf - syslogd(8) configuration file
.\" Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
.\"
.\" This file is part of the sysklogd package, a kernel and system log daemon.
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 2 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
.\"
.\" Local macros
.de Xr
.BR \\$1 (\\$2)\\$3
..
.de LB
.TP \\$1
\\fB\\$2\\fR
\\$3
..
.de LI
.TP \\$1
\\fI\\$2\\fR
\\$3
..
.de LR
.TP \\$1
\\fR\\$2\\fR
\\$3
..
.\" end local macros
.TH SYSLOG.CONF 5 "1 January 1998"
.SH NAME
syslog.conf \- syslogd(8) configuration file
.SH DESCRIPTION
The
.I syslog.conf
file is the main configuration file for the
.Xr syslogd 8
which logs system messages on *nix systems. This file specifies rules
for logging. For special features see the
.Xr syslogd 8
manpage.
Every rule consists of two fields, a
.I selector
field and an
.I action
field. These two fields are separated by one or more tabs.
The selector field specifies a pattern of facilities and
priorities belonging to the specified action.
Lines starting with a hash mark (``#'') and empty lines are ignored.
.SH SELECTORS
The selector field itself again consists of two parts, a
.I facility
and a
.IR priority ,
separated by a period (``.'').
Both parts are case insensitive and can also be specified as decimal
numbers, but don't do that, you have been warned. Both facilities and
priorities are described in
.BR syslog (3).
The names mentioned below correspond to the similar
.BR LOG_ -values
in
.IR /usr/include/syslog.h .
The
.I facility
is one of the following keywords:
.BR auth ", " authpriv ", " cron ", " daemon ", " kern ", " lpr ", "
.BR mail ", " mark ", " news ", " security " (same as " auth "), "
.BR syslog ", " user ", " uucp " and " local0 " through " local7 .
The keyword
.B security
should not be used anymore and
.B mark
is only for internal use and therefore should not be used in
applications. Anyway, you may want to specify and redirect these
messages here. The
.I facility
specifies the subsystem that produced the message, i.e. all mail
programs log with the mail facility
.BR "" ( LOG_MAIL )
if they log using syslog.
The
.I priority
is one of the following keywords, in ascending order:
.BR debug ", " info ", " notice ", " warning ", " warn " (same as "
.BR warning "), " err ", " error " (same as " err "), " crit ", "
.BR alert ", " emerg ", " panic " (same as " emerg ).
The keywords
.BR error ", " warn " and " panic
are deprecated and should not be used anymore. The
.I priority
defines the severity of the message
.PP
The behavior of the original BSD syslogd is that all messages of the
specified priority and higher are logged according to the given
action. This
.BR syslogd (8)
behaves the same, but has some extensions.
.PP
In addition to the above mentioned names the
.BR syslogd (8)
understands the following extensions:
.LB 5 "*" "An asterisk (``*'') before the period stands for all facilities.
.LB 5 "none" "The keyword none stands for no priority of the given facility.
.PP
Multiple selectors may be specified for a single
.I action
using the semicolon (``;'') separator. Remember that each selector in
the
.I selector
field is capable to overwrite the preceding ones. Using this
behavior you can exclude some priorities from the pattern.
.SH ACTIONS
The action field of a rule describes the abstract term
``logfile''. A ``logfile'' need not to be a real file, btw. The
.Xr syslogd 8
provides the following actions.
.SS Regular File
Typically messages are logged to real files. The file has to be
specified with full pathname, beginning with a slash ``/''.
.SS Terminal and Console
If the file you specified is a tty, special tty-handling is done, same
with
.IR /dev/console .
.SS Remote Machine
This release does not implement
remote logging, i.e. the ability to send messages to a remote host running
.Xr syslogd 8 .
To forward messages to another host, prepend the hostname
with the at sign (``@'').
.SS List of Users
Usually critical messages are also directed to ``root'' on that
machine. You can specify a list of users that shall get the message by
simply writing the login. You may specify more than one user by
separating them with commas (``,''). If they're logged in they
get the message. Don't think a mail would be sent, that might be too
late.
.SS Everyone logged on
Emergency messages often go to all users currently online to notify
them that something strange is happening with the system. To specify
this
.IR wall (1)-feature
use an asterisk (``*'').
.SH EXAMPLES
Here are some example, partially taken from a real existing site and
configuration. Hopefully they rub out all questions to the
configuration, if not, drop me (Joey) a line.
.IP
.nf
# Store critical stuff in critical
#
*.crit /var/adm/critical
.fi
.LP
This will store all messages with the priority
.B crit
in the file
.IR /var/adm/critical .
.IP
.nf
# The tcp wrapper loggs with mail.info, we display
# all the connections on tty12
#
mail.info /dev/tty12
.fi
.LP
This directs all messages that uses
.BR mail.info " (in source " LOG_MAIL " | " LOG_INFO )
to
.IR /dev/tty12 ,
the 12th console.
.IP
.nf
# Log all mail.info and news.info messages to info
#
mail,news.info /var/adm/info
.fi
.LP
This will extract all messages that come either with
.BR mail.info " or with " news.info
and store them in the file
.IR /var/adm/info .
.IP
.nf
# Emergency messages will be displayed using wall
#
*.emerg *
.fi
.LP
This rule tells the
.B syslogd
to write all emergency messages to all currently logged in users. This
is the wall action.
.IP
.nf
# Messages of the priority alert will be directed
# to the operator
#
*.alert root,joey
.fi
.LP
This rule directs all messages with a priority of
.B alert
or higher to the terminals of the operator, i.e. of the users ``root''
and ``joey'' if they're logged in.
.IP
.nf
*.* @finlandia
.fi
.LP
This rule would redirect all messages to a remote host called
finlandia. This is useful especially in a cluster of machines where
all syslog messages will be stored on only one machine.
.SH FILES
.I /etc/syslog.conf
Configuration file for
.B syslogd
.SH BUGS
The effects of multiple selectors are sometimes not intuitive. For
example ``mail.crit,*.err'' will select ``mail'' facility messages at
the level of ``err'' or higher, not at the level of ``crit'' or
higher.
.SH SEE ALSO
.BR syslogd (8),
.BR logger (1),
.BR syslog (3)
.SH AUTHORS
The
.B syslogd
is taken from BSD sources, Greg Wettstein (greg@wind.rmcc.com)
performed the port to Linux, Martin Schulze (joey@linux.de)
made some bugfixes and added some new features.

View file

@ -8,7 +8,7 @@ MAN= add_route.8 backup.8 boot.8 btrace.8 \
printroot.8 pr_routes.8 pwdauth.8 rarpd.8 \
readclock.8 repartition.8 \
rshd.8 screendump.8 serial-ip.8 \
setup.8 shutdown.8 slip.8 srccrc.8 syslogd.8 tcpd.8 \
setup.8 shutdown.8 slip.8 srccrc.8 tcpd.8 \
unix.8 update.8 usage.8 vbfs.8
MLINKS += httpd.8 in.httpd.8

View file

@ -1,210 +0,0 @@
.\" Copyright 1994 Dr. Greg Wettstein, Enjellic Systems Development.
.\" May be distributed under the GNU General Public License
.\" Sun Aug 30 11:35:55 MET: Martin Schulze: Updates
.\"
.\" from SYSKLOGD 8 "13 December 1995" "Version 1.3" "Linux System Administration"
.\" Modified for Minix porting by G. Falzoni <gfalzoni@inwind.it>
.\"
.\" Local macros
.de Xr
.BR \\$1 (\\$2)\\$3
..
.de LB
.TP \\$1
\\fB\\$2\\fR
\\$3
..
.de LI
.TP \\$1
\\fI\\$2\\fR
\\$3
..
.de LR
.TP \\$1
\\fR\\$2\\fR
\\$3
..
.\" end local macros
.TH SYSLOGD 8 "Jan. 23, 2000"
.SH NAME
.PP
syslogd \- system logging daemon.
.SH SYNOPSIS
.PP
.B syslogd
.RB [ " \-d " ]
.RB [ " \-f "
.I config file
]
.RB [ " \-m "
.I interval
]
.RB [ " \-p"
.IB port
]
.RB [ " \-v " ]
.LP
.SH DESCRIPTION
.PP
System logging is provided by a version of
.BR syslogd (8)
derived from the
stock BSD sources.
.B Syslogd
provides the kind of logging that many modern programs use. Every logged
message contains at least a time, a hostname field and a
program name field, but that depends on how trusty the logging
program is.
.PP
While the syslogd sources have been heavily modified a couple of notes
are necessary. First of all there has been a systematic attempt to
insure that syslogd follows the default, standard BSD behavior.
The second important concept to note is that this version of syslogd
interacts transparently with the version of syslog found in the
standard libraries, so you must insure that the correct versions are installed.
.PP
The main configuration file
.I /etc/syslog.conf
or an alternative file, given with the
.B "\-f"
option, is read at startup. Any line that begins with the hash mark
(``#'') and empty lines are ignored. If an error occurs during parsing
the whole line is ignored.
.SH OPTIONS
.PP
.LB 9 "-d" "Turns on debug mode.
When using debug mode, the daemon will not proceed to
.BR fork (2)
to set itself in the background, but will stay in the
foreground and write much debug information on the current tty. See the
DEBUGGING section for more information.
.LB 9 "\-f config file" "Specify an alternative configuration file instead of
.IR /etc/syslog.conf ","
which is the default.
.LB 9 "\-m interval" "The syslogd logs a mark timestamp regularly. The default
.I interval
between two
.I \-\- MARK \-\-
lines is 20 minutes. This can be changed with this option.
.LB 9 "\-p port" "You can specify an alternative port instead of
.I syslog/udp
default service.
.LB 9 "\-v" "Print version and exit.
.SH SIGNALS
.PP
.B Syslogd
reacts to a set of signals. You may easily send a signal to it
using the following:
.IP
kill -SIGNAL `cat /usr/run/syslogd.pid`
.LB 9 SIGHUP "This lets syslogd perform a re-initialization.
All open files are closed, the configuration file (default
is '/etc/syslog.conf') will be reread.
.LB 9 SIGTERM "The syslogd will die.
.LB 9 "SIGINT SIGQUIT" "If debugging is enabled these are ignored, otherwise
syslogd will die.
.LB 9 SIGALRM "Every time syslogd receives this signal it will log
the mark line. Normally this is done by
.Xr alarm 2 .
.SH CONFIGURATION FILE SYNTAX DIFFERENCES
.PP
.B Syslogd
uses a slightly different syntax for its configuration file than
the original BSD sources. Originally all messages of a specific priority
and above were forwarded to the log file.
.PP
For example see the following sample file
.IP
## Sample syslog.conf
## Emergency messages (system may be unusable)
.br
*.emerg *
.br
*.alert /dev/log
## High severity errors
.br
*.alert;*.crit /usr/adm/syslog
## every other message (errors/warning and informational)
.br
*.info;*.notice;*.warning;*.err /usr/adm/messages
.br
*.debug /usr/adm/debug
.SH SUPPORT FOR REMOTE LOGGING
.PP
Not implemented.
.SH OUTPUT TO NAMED PIPES (FIFOs)
.PP
Not implemented.
.SH INSTALLATION CONCERNS
.PP
There is probably one important consideration when installing this
version of syslogd. This version of syslogd is dependent on proper
formatting of messages by the syslog function.
.PP
.B Syslogd
should be started by the rc sequence.
.SH DEBUGGING
.PP
When debugging is turned on using
.B "\-d"
option and syslogd is compiled with debug=1 then syslogd
will be very verbose by writing much of what it does on stdout.
Whenever
the configuration file is reread and re-parsed you'll see a tabular,
corresponding to the internal data structure. This tabular consists of
four fields:
.TP
.I number
This field contains a serial number starting by zero. This number
represents the position in the internal data structure (i.e. the
array). If one number is left out then there might be an error in the
corresponding line in
.IR /etc/syslog.conf .
.TP
.I pattern
This field is tricky and represents the internal structure
exactly. Every column stands for a facility (refer to
.BR syslog (3)).
As you can see, there are still some facilities left free for former
use, only the left most are used. Every field in a column represents
the priorities (refer to
.BR syslog (3)).
.TP
.I action
This field describes the particular action that takes place whenever a
message is received that matches the pattern. Refer to the
.BR syslog.conf (5)
manpage for all possible actions.
.TP
.I arguments
This field shows additional arguments to the actions in the last
field. For file-logging this is the filename for the logfile; for
user-logging this is a list of users; for remote logging this is the
hostname of the machine to log to; for console-logging this is the
used console; for tty-logging this is the specified tty; wall has no
additional arguments.
.PP
Note that if syslogd is compiled with debug=0 only a subset is printed.
.SH FILES
.PP
.LR 28 /etc/syslog.conf "Configuration file for syslogd. See
.Xr syslog.conf 5
for exact information.
.LR 28 /dev/log "The log device (console) for Minix.
.LR 28 /usr/run/syslogd.pid "The file containing the process id of syslogd.
.SH BUGS
.PP
If an error occurs in one line the whole rule is ignored.
.B Syslogd
doesn't change the filemode of opened logfiles at any stage of
process. If a file is created it is world readable. If you want to
avoid this, you have to create it and change permissions on your own.
.SH SEE ALSO
.BR syslog.conf (5),
.BR logger (1),
.BR syslog (3).
.\" .BR services (5),

View file

@ -24,9 +24,9 @@ SUBDIR= \
\
rdate \
\
\
syslogd \
traceroute \
\
\
unlink user \
vipw vnconfig \
\

38
usr.sbin/syslogd/Makefile Normal file
View file

@ -0,0 +1,38 @@
# $NetBSD: Makefile,v 1.24 2012/06/06 00:33:45 christos Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
.include <bsd.own.mk>
WARNS?=4
USE_FORT?= yes # network server
LINTFLAGS+=-X 132,247,135,259,117,298
PROG= syslogd
SRCS= syslogd.c utmpentry.c tls.c sign.c
MAN= syslogd.8 syslog.conf.5
DPADD+=${LIBUTIL} ${LIBEVENT}
LDADD+=-lutil -levent
#make symlink to old socket location for transitional period
.if !defined(__MINIX)
SYMLINKS= /var/run/log /dev/log
.endif # !defined(__MINIX)
.PATH.c: ${NETBSDSRCDIR}/usr.bin/who
CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/who -DSUPPORT_UTMPX -DSUPPORT_UTMP -Wredundant-decls
.if (${USE_INET6} != "no")
CPPFLAGS+=-DINET6
.endif
.if !defined(__MINIX)
CPPFLAGS+=-DLIBWRAP
LDADD+= -lwrap
DPADD+= ${LIBWRAP}
.endif # !defined(__MINIX)
.if ${MKCRYPTO} != "no"
LDADD+= -lssl -lcrypto
.else
CPPFLAGS+=-DDISABLE_TLS -DDISABLE_SIGN
.endif
.include <bsd.prog.mk>

91
usr.sbin/syslogd/extern.h Normal file
View file

@ -0,0 +1,91 @@
/* $NetBSD: extern.h,v 1.3 2010/06/09 21:55:42 riz Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Schütte.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* extern.h
*
* declarations for variables and functions from syslogd.c
* that are used in tls.c and sign.c
*/
#ifndef EXTERN_H_
#define EXTERN_H_
/* variables */
extern int Debug;
extern struct tls_global_options_t tls_opt;
extern struct TLS_Incoming TLS_Incoming_Head;
extern struct sign_global_t GlobalSign;
extern char *linebuf;
extern size_t linebufsize;
extern int RemoteAddDate;
extern bool BSDOutputFormat;
extern time_t now;
extern char timestamp[];
extern char appname[];
extern char *LocalFQDN;
extern char *include_pid;
/* functions */
extern void logerror(const char *, ...)
__attribute__((__format__(__printf__,1,2)));
extern void loginfo(const char *, ...)
__attribute__((__format__(__printf__,1,2)));
extern void printline(const char *, char *, int);
extern void die(int fd, short event, void *ev)
__attribute__((__noreturn__));
extern struct event *allocev(void);
extern void send_queue(int __unused, short __unused, void *);
extern void schedule_event(struct event **, struct timeval *,
void (*)(int, short, void *), void *);
extern char *make_timestamp(time_t *, bool);
#ifndef DISABLE_TLS
extern struct filed *get_f_by_conninfo(struct tls_conn_settings *conn_info);
#endif
extern bool message_queue_remove(struct filed *, struct buf_queue *);
extern void buf_msg_free(struct buf_msg *msg);
extern void message_queue_freeall(struct filed *);
extern bool copy_string(char **, const char *, const char *);
extern bool copy_config_value_quoted(const char *, char **, const char **);
extern size_t message_allqueues_purge(void);
extern bool format_buffer(struct buf_msg*, char**, size_t*, size_t*, size_t*,
size_t*);
extern void fprintlog(struct filed *, struct buf_msg *, struct buf_queue *);
extern struct buf_msg *buf_msg_new(const size_t);
#endif /*EXTERN_H_*/

View file

@ -0,0 +1,89 @@
<html>
<head>
<title>NetBSD &amp; Google's Summer of Code: Martin Schuette - Improve syslogd (syslogd)</title>
</head>
<body>
<h1>Testing syslogd</h1>
<h2>Compiling</h2>
<p>A (hopefully) stable version for testing is available by <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/src/">CVS</a> and as a <a href="syslogd-tls.tar.gz">.tar.gz archive</a>. It contains syslogd itself and all necessary files to build on NetBSD and FreeBSD.</p>
<p>To build just type <span style="font-family: monospace;">make</span>. Unless you have a complete NetBSD source tree -- then you can extract the files to <span style="font-family: monospace;">/usr/src/usr.sbin/syslogd</span> and replace the <span style="font-family: monospace;">Makefile</span> with <span style="font-family: monospace;">Makefile.NetBSD</span> and then type <span style="font-family: monospace;">make</span>.
<h3>Note on other BSDs</h3>
<p>I also tested syslogd on FreeBSD. There are just a few issues/differences:</p>
<ul>
<li>You have to install libevent first</li>
<li>No pidfile is written</li>
<li>The code for wallmsg() is only copied, not tested</li>
</ul>
<p>I assume the same holds for other BSDs but I have no live system to test them.</p>
<h2>Command line options</h2>
<p>syslogd has to be run as root (because it uses chroot()). You should start it with option "-u username" to drop privileges.</p>
<p>By default messages are written in syslog Protocol format. To get the BSD Syslog output like from previous versions use the "-o" option.</p>
<h2>syslog.conf</h2>
<p>To use TLS some additional configuration is required.</p>
<h3>X.509 certificates</h3>
<p>Every syslogd using TLS needs an X.509 certificate.
The files containing the private key, certificate, and CA are configured with:</p>
<pre>
tls_key="/etc/openssl/default.key"
tls_cert="/etc/openssl/default.crt"
tls_ca="/some/where/my.cacert"
</pre>
<p>If you do not already have a X.509 certificate then you can tell syslogd to generate one for you with</p>
<pre>
tls_gen_cert=on
</pre>
<h3>TLS client</h3>
<p>To send messages with configure a TLS destination. Here are three examples with different additional options required for authentication</p>
<pre>
# with CA
*.* @[logserver.example.org]:13245
*.* @[127.0.0.1]:13245(subject="logserver.example.org")
# without CA
*.* @[127.0.0.1]:13245(fingerprint="SHA1:E4:E1:A6:1C:D4:31:D7:D4:9B:B8:DC:DF:DD:CE:30:71:46:00:92:C9")
</pre>
<p>If using a CA then it is checked whether the server's certificate matches the hostname or a given subject. Assuming the logserver's certificate has "logserver.example.org" as its commonName or as a subjectAltName/dnsName the first line is sufficient. (Once a standard portnumber has been assigned the port becomes optional.) If we do not want to rely on DNS and configure the destination with "127.0.0.1" then the subject comparison will fail. The alternatives are either to configure the subject as an option (as in the example above) or to generate a new certificate with the server's IP as a commonName or subjectAltName/ipAddress.</p>
<p>Without a CA the easiest way to authenticate the peer's certificate is its fingerprint as in the last line in the example. syslogd logs the fingerprints of all certificates it loads or tries to connect with, but it can also be read from the shell with "openssl x509 -in /etc/openssl/default.crt -noout -fingerprint".</p>
<h3>TLS server</h3>
<p>To enable TLS server mode use these lines.</p>
<pre>
tls_server="on"
tls_bindhost="127.0.0.1"
tls_bindport="13245"
</pre>
<p>The bindhost is optional. The bindport is currently required (as long as there is no tcp port defined for the syslog service).</p>
<p>With a CA that is all -- there is no additional hostname check for clients.
Without a CA the server needs to be told which certificates to trust:</p>
<pre>
tls_allow_fingerprints = MD5:00:A2:A7:02:CA:A0:0E:00:DC:F1:91:BE:6A:AA:FF:27 "SHA1:E4:E1:A6:1C:D4:31:D7:D4:9B:B8:DC:DF:DD:CE:30:71:46:00:92:C9"
</pre>
<hr>
<table border=0>
<tr>
<td>
<a href="http://sourceforge.net"><img align="top" src="http://sourceforge.net/sflogo.php?group_id=141771&amp;type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a>
<td>
<table>
<tr> <td> Martin Sch&uuml;tte &lt;<tt>info@mschuette.name</tt>&gt; </td> </tr>
<tr> <td> $Id: howto.html,v 1.1 2008/10/31 16:12:19 christos Exp $ </td> </tr>
</table>
</tr>
</table>
</body>
</html>

161
usr.sbin/syslogd/index.html Normal file
View file

@ -0,0 +1,161 @@
<html>
<head>
<title>NetBSD &amp; Google's Summer of Code: Martin Schuette - Improve syslogd (syslogd)</title>
</head>
<body>
<center>
<table>
<tr>
<td><a href="http://www.NetBSD.org/"><img border=0 valign="top" src="../../NetBSD.png" alt="[NetBSD logo]" /></a></td>
<td><font size="+5">&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;</font></td>
<td><a href="http://www.google.com/"><img border=0 valign="bottom" src="http://www.google.com/intl/en/images/logo.gif" alt="[Google logo]" /></a></td>
</tr>
</table>
</center>
<h1>NetBSD-SoC: Improve syslogd</h1>
<h2>What is it?</h2>
<p>The syslog daemon handles most log messages of a unixoid system. It receives messages from shell-scripts, applications, daemons, the kernel, or by network and then writes them into logfiles, on user's consoles or forwards them to some other logserver -- all depending on its configuration and the message properties.</p>
<p>implemented the upcoming <a class="ext-link" href="http://tools.ietf.org/wg/syslog/">IETF
standards</a> for <a class="ext-link" href="http://www.netbsd.org/">NetBSD</a>'s syslog(3)
and syslogd(8):
</p>
<ul><li><a class="ext-link"
href="http://tools.ietf.org/html/draft-ietf-syslog-transport-tls"><span
class="icon">transport-tls</span></a> defines the network protocol to send
syslog data over TLS (instead of UDP), thus providing a reliable and
authenticated transport.
</li><li><a class="ext-link"
href="http://tools.ietf.org/html/draft-ietf-syslog-protocol"><span
class="icon">syslog-protocol</span></a> defines a new layout for syslog
lines; the most important additions are full timestamps (with year and timezone)
and structured data with name=value pairs. This enables all programs to declare
semantic content (uid, client IP, return codes, etc), making automatic
log-monitoring (or at least parsing) much easier.
</li><li><a class="ext-link"
href="http://tools.ietf.org/html/draft-ietf-syslog-sign"><span
class="icon">syslog-sign</span></a> defines signature messages to assert
authentication, integrity and correct sequencing of syslog messages.
</li></ul><p>
To my knowledge this is one of the first implementations of these
protocols. It will provide NetBSD (and hopefully the other BSDs as well) with
an advanced, reliable, and secure syslogd; thus saving admins the time and
effort to install custom logging solutions just to get secure transport to
their central logserver.
</p>
<h2>Current Status</h2>
<h3>Functions</h3>
<h4>TLS</h4>
<p>The TLS support is now working (tested with RSA and DSA keys).
It will read its configuration from syslog.conf, accept incoming TLS connections
to receive messages, establish connections to other TLS servers.</p>
<p>If a TLS server is temporarily not available then its messages will be buffered
and sent after reconnection.</p>
<h4>syslog-protocol</h4>
<p>A command line option determines whether syslogd output is in BSD Syslog or in syslog-protocol format. All received messages are converted accordingly.</p>
<p>I also modified syslog(3) in libc to send syslog-protocol messages.</p>
<p>While syslog(3) can only use the message field, a new syslogp(3) call is provided to add a MSGID and structured data to a message.</p>
<h4>syslog-sign</h4>
<p>syslogd(8) is now able to <a href="sign.html">digitally sign messages with syslog-sign.</a></p>
<h3>syslog.conf</h3>
<p>I extended the traditional configuration file format to support additionally fields for TLS.
A syslog.conf for TLS currently looks like this:</p>
<pre>
# TLS options
tls_ca="/etc/my.cacert"
tls_cert="/etc/localhost.crt"
tls_key="/etc/localhost.key"
tls_verify="off"
tls_bindhost="127.0.0.1"
tls_bindport="13245"
tls_server=on
# file destination
*.* /home/mschuett/test.log
# UDP destination
*.* @192.168.178.5
# TLS destination
*.* @[127.0.0.1]:5555(fingerprint="SHA1:E4:E1:A6:1C:D4:31:D7:D4:9B:B8:DC:DF:DD:CE:30:71:46:00:92:C9")
</pre>
<h3>Source Code</h3>
<p>To try syslogd fetch the latest <a href="http://mschuette.name/files/syslogd_080818.tar.gz">.tar.gz archive (2008-08-18)</a> (older versions: <a href="http://mschuette.name/files/syslogd_080805.tar.gz">2008-08-05</a>, <a href="http://mschuette.name/files/syslogd-tls.tar.gz">2008-08-05</a>).</p>
<p>The sources for <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/src/">syslogd</a>, the <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/src-libc_gen/">libc functions</a>, <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/src-newsyslog/">newsyslog</a>, and <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/src-logger/">logger</a> are also available from the <a href="http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/syslogd/">CVS on sourceforge</a>.</p>
<p>For development I used an own <a href="https://anonymous:anonymous@barney.cs.uni-potsdam.de/svn/syslogd/trunk/src/">SVN</a>; a detailed timeline of code changes is available in the <a href="https://barney.cs.uni-potsdam.de/trac/syslogd/timeline">on my Trac</a>.</p>
<p>The syslogd code needs <a href="http://www.openssl.org/ OpenSSL"></a> and <a href="http://www.monkey.org/~provos/libevent/">libevent</a>. The only system-dependent function is wallmsg() to write messages to users's terminals.<br/>
It was developed and tested on NetBSD and FreeBSD. I heard it does not compile on OpenBSD (I do not know about DragonflyBSD), probably due to different files under /usr/include. I would be interested if someone tried to compile on Linux; this will be some more work, because one will also need additional functions from BSDs libc that are not in glibc (most notably strlcat()).</p>
<h2>Deliverables</h2>
<p>
I got all my <b>mandatory components</b>:
</p>
<ul>
<li>Implement transport-tls in syslogd(8)</li>
<li>Implement syslog-protocol in syslogd(8)</li>
<li>Implement syslog-protocol in syslog(3)</li>
<li>Implement syslog-sign in syslogd(8)</li>
</ul>
<p>
...and parts of my <b>optional components</b>:
</p>
<ul>
<li>interoperability with other implementations: so far I could only test TLS-transport with rsyslog</li>
<li>Extended API to use new functions: with syslogp() I wrote a new API; but it is not really the extended API I had in mind here.</li>
</ul>
<h2>Documentation</h2>
<p>New manpages and description:</p>
<ul>
<li>my <a href="./doc/syslogd.8.html">syslogd(8)</a></li>
<li>my <a href="./doc/syslog.conf.5.html">syslog.conf(5)</a></li>
<li>my <a href="./doc/syslog.3.html">syslog(3)/syslogp(3)</a></li>
<li><a href="howto.html">How-To configure a TLS transport</a></li>
<li><a href="sign.html">Overview of syslog-sign and its usage</a></li>
</ul>
<p>Existing specifications and man-pages:</p>
<ul>
<li><a href="http://tools.ietf.org/html/rfc3164">RFC3164: The BSD syslog Protocol</a></li>
<li><a href="http://netbsd.gw.com/cgi-bin/man-cgi?syslogd++NetBSD-current">syslogd(8)</a></li>
<li><a href="http://netbsd.gw.com/cgi-bin/man-cgi?syslog.conf+5+NetBSD-current">syslog.conf(5)</a></li>
<li><a href="http://netbsd.gw.com/cgi-bin/man-cgi?syslog+3+NetBSD-current">syslog(3)</a></li>
<li><a href="http://www.opengroup.org/onlinepubs/009695399/basedefs/syslog.h.html">SUS on syslog.h</a></li>
<li><a href="http://www.opengroup.org/onlinepubs/009695399/functions/syslog.html">SUS on syslog()</a></li>
</ul>
<p>IETF documents:</p>
<ul>
<li><a href="http://tools.ietf.org/html/draft-ietf-syslog-transport-udp">Transmission of syslog messages over UDP (draft-ietf-syslog-transport-udp)</a></li>
<li><a href="http://tools.ietf.org/html/draft-ietf-syslog-transport-tls">TLS Transport Mapping for Syslog (draft-ietf-syslog-transport-tls)</a></li>
<li><a href="http://tools.ietf.org/html/draft-ietf-syslog-protocol">The syslog Protocol (draft-ietf-syslog-protocol)</a></li>
<li><a href="http://tools.ietf.org/html/draft-ietf-syslog-sign">Signed syslog Messages (draft-ietf-syslog-sign)</a></li>
</ul>
<hr>
<table border=0>
<tr>
<td>
<a href="http://sourceforge.net"><img align="top" src="http://sourceforge.net/sflogo.php?group_id=141771&amp;type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a>
<td>
<table>
<tr> <td> Martin Sch&uuml;tte &lt;<tt>info@mschuette.name</tt>&gt; </td> </tr>
<tr> <td> $Id: index.html,v 1.1 2008/10/31 16:12:19 christos Exp $ </td> </tr>
</table>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,37 @@
/* $NetBSD: pathnames.h,v 1.6 2003/08/07 11:25:44 agc Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/
#include <paths.h>
#define _PATH_KLOG "/dev/klog"
#define _PATH_LOGCONF "/etc/syslog.conf"

938
usr.sbin/syslogd/sign.c Normal file
View file

@ -0,0 +1,938 @@
/* $NetBSD: sign.c,v 1.5 2012/06/06 00:33:45 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Schütte.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* sign.c
* syslog-sign related code for syslogd
*
* Martin Schütte
*/
/*
* Issues with the current internet draft:
* 1. The draft is a bit unclear on the input format for the signature,
* so this might have to be changed later. Cf. sign_string_sign()
* 2. The draft only defines DSA signatures. I hope it will be extended
* to DSS, thus allowing DSA, RSA (ANSI X9.31) and ECDSA (ANSI X9.62)
* 3. The draft does not define the data format for public keys in CBs.
* This implementation sends public keys in DER encoding.
* 4. This current implementation uses high-level OpenSSL API.
* I am not sure if these completely implement the FIPS/ANSI standards.
* Update after WG discussion in August:
* 1. check; next draft will be clearer and specify the format as implemented.
* 2. check; definitely only DSA in this version.
* 3. remains a problem, so far no statement from authors or WG.
* 4. check; used EVP_dss1 method implements FIPS.
*/
/*
* Limitations of this implementation:
* - cannot use OpenPGP keys, only PKIX or DSA due to OpenSSL capabilities
* - only works for correctly formatted messages, because incorrect messages
* are reformatted (e.g. if it receives a message with two spaces between
* fields it might even be parsed, but the output will have only one space).
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: sign.c,v 1.5 2012/06/06 00:33:45 christos Exp $");
#ifndef DISABLE_SIGN
#include "syslogd.h"
#ifndef DISABLE_TLS
#include "tls.h"
#endif /* !DISABLE_TLS */
#include "sign.h"
#include "extern.h"
/*
* init all SGs for a given algorithm
*/
bool
sign_global_init(struct filed *Files)
{
DPRINTF((D_CALL|D_SIGN), "sign_global_init()\n");
if (!(GlobalSign.sg == 0 || GlobalSign.sg == 1
|| GlobalSign.sg == 2 || GlobalSign.sg == 3)) {
logerror("sign_init(): invalid SG %d", GlobalSign.sg);
return false;
}
if (!sign_get_keys())
return false;
/* signature algorithm */
/* can probably be merged with the hash algorithm/context but
* I leave the optimization for later until the RFC is ready */
GlobalSign.sigctx = EVP_MD_CTX_create();
EVP_MD_CTX_init(GlobalSign.sigctx);
/* the signature algorithm depends on the type of key */
if (EVP_PKEY_DSA == EVP_PKEY_type(GlobalSign.pubkey->type)) {
GlobalSign.sig = EVP_dss1();
GlobalSign.sig_len_b64 = SIGN_B64SIGLEN_DSS;
/* this is the place to add non-DSA key types and algorithms
} else if (EVP_PKEY_RSA == EVP_PKEY_type(GlobalSign.pubkey->type)) {
GlobalSign.sig = EVP_sha1();
GlobalSign.sig_len_b64 = 28;
*/
} else {
logerror("key type not supported for syslog-sign");
return false;
}
assert(GlobalSign.keytype == 'C' || GlobalSign.keytype == 'K');
assert(GlobalSign.pubkey_b64 && GlobalSign.privkey &&
GlobalSign.pubkey);
assert(GlobalSign.privkey->pkey.dsa->priv_key);
GlobalSign.gbc = 0;
STAILQ_INIT(&GlobalSign.SigGroups);
/* hash algorithm */
OpenSSL_add_all_digests();
GlobalSign.mdctx = EVP_MD_CTX_create();
EVP_MD_CTX_init(GlobalSign.mdctx);
/* values for SHA-1 */
GlobalSign.md = EVP_dss1();
GlobalSign.md_len_b64 = 28;
GlobalSign.ver = "0111";
if (!sign_sg_init(Files))
return false;
sign_new_reboot_session();
DPRINTF(D_SIGN, "length values: SIGN_MAX_SD_LENGTH %d, "
"SIGN_MAX_FRAG_LENGTH %d, SIGN_MAX_SB_LENGTH %d, "
"SIGN_MAX_HASH_NUM %d\n", SIGN_MAX_SD_LENGTH,
SIGN_MAX_FRAG_LENGTH, SIGN_MAX_SB_LENGTH, SIGN_MAX_HASH_NUM);
/* set just before return, so it indicates initialization */
GlobalSign.rsid = now;
return true;
}
/*
* get keys for syslog-sign
* either from the X.509 certificate used for TLS
* or by generating a new one
*
* sets the global variables
* GlobalSign.keytype, GlobalSign.pubkey_b64,
* GlobalSign.privkey, and GlobalSign.pubkey
*/
bool
sign_get_keys(void)
{
EVP_PKEY *pubkey = NULL, *privkey = NULL;
unsigned char *der_pubkey = NULL, *ptr_der_pubkey = NULL;
char *pubkey_b64 = NULL;
int der_len;
/* try PKIX/TLS key first */
#ifndef DISABLE_TLS
SSL *ssl;
if (tls_opt.global_TLS_CTX
&& (ssl = SSL_new(tls_opt.global_TLS_CTX))) {
X509 *cert;
DPRINTF(D_SIGN, "Try to get keys from TLS X.509 cert...\n");
if (!(cert = SSL_get_certificate(ssl))) {
logerror("SSL_get_certificate() failed");
FREE_SSL(ssl);
return false;
}
if (!(privkey = SSL_get_privatekey(ssl))) {
logerror("SSL_get_privatekey() failed");
FREE_SSL(ssl);
return false;
}
if (!(pubkey = X509_get_pubkey(cert))) {
logerror("X509_get_pubkey() failed");
FREE_SSL(ssl);
return false;
}
/* note:
* - privkey is just a pointer into SSL_CTX and
* must not be changed nor be free()d
* - but pubkey has to be freed with EVP_PKEY_free()
*/
FREE_SSL(ssl);
if (EVP_PKEY_DSA != EVP_PKEY_type(pubkey->type)) {
DPRINTF(D_SIGN, "X.509 cert has no DSA key\n");
EVP_PKEY_free(pubkey);
privkey = NULL;
pubkey = NULL;
} else {
DPRINTF(D_SIGN, "Got public and private key "
"from X.509 --> use type PKIX\n");
GlobalSign.keytype = 'C';
GlobalSign.privkey = privkey;
GlobalSign.pubkey = pubkey;
/* base64 certificate encoding */
der_len = i2d_X509(cert, NULL);
if (!(ptr_der_pubkey = der_pubkey = malloc(der_len))
|| !(pubkey_b64 = malloc(der_len*2))) {
free(der_pubkey);
logerror("malloc() failed");
return false;
}
if (i2d_X509(cert, &ptr_der_pubkey) <= 0) {
logerror("i2d_X509() failed");
return false;
}
b64_ntop(der_pubkey, der_len, pubkey_b64, der_len*2);
free(der_pubkey);
/* try to resize memory object as needed */
GlobalSign.pubkey_b64 = realloc(pubkey_b64,
strlen(pubkey_b64)+1);
if (!GlobalSign.pubkey_b64)
GlobalSign.pubkey_b64 = pubkey_b64;
}
}
#endif /* !DISABLE_TLS */
if (!(privkey && pubkey)) { /* PKIX not available --> generate key */
DSA *dsa;
DPRINTF(D_SIGN, "Unable to get keys from X.509 "
"--> use DSA with type 'K'\n");
if (!(privkey = EVP_PKEY_new())) {
logerror("EVP_PKEY_new() failed");
return false;
}
dsa = DSA_generate_parameters(SIGN_GENCERT_BITS, NULL, 0,
NULL, NULL, NULL, NULL);
if (!DSA_generate_key(dsa)) {
logerror("DSA_generate_key() failed");
return false;
}
if (!EVP_PKEY_assign_DSA(privkey, dsa)) {
logerror("EVP_PKEY_assign_DSA() failed");
return false;
}
GlobalSign.keytype = 'K'; /* public/private keys used */
GlobalSign.privkey = privkey;
GlobalSign.pubkey = privkey;
/* pubkey base64 encoding */
der_len = i2d_DSA_PUBKEY(dsa, NULL);
if (!(ptr_der_pubkey = der_pubkey = malloc(der_len))
|| !(pubkey_b64 = malloc(der_len*2))) {
free(der_pubkey);
logerror("malloc() failed");
return false;
}
if (i2d_DSA_PUBKEY(dsa, &ptr_der_pubkey) <= 0) {
logerror("i2d_DSA_PUBKEY() failed");
free(der_pubkey);
free(pubkey_b64);
return false;
}
b64_ntop(der_pubkey, der_len, pubkey_b64, der_len*2);
free(der_pubkey);
/* try to resize memory object as needed */
GlobalSign.pubkey_b64 = realloc(pubkey_b64,
strlen(pubkey_b64) + 1);
if (!GlobalSign.pubkey_b64)
GlobalSign.pubkey_b64 = pubkey_b64;
}
return true;
}
/*
* init SGs
*/
bool
sign_sg_init(struct filed *Files)
{
struct signature_group_t *sg, *newsg, *last_sg;
struct filed_queue *fq;
struct string_queue *sqentry, *last_sqentry;
struct filed *f;
unsigned int i;
/* note on SG 1 and 2:
* it is assumed that redundant signature groups
* and especially signature groups without an associated
* destination are harmless.
* this currently holds true because sign_append_hash()
* is called from fprintlog(), so only actually used
* signature group get hashes and need memory for them
*/
/* possible optimization for SGs 1 and 2:
* use a struct signature_group_t *newsg[IETF_NUM_PRIVALUES]
* for direct group lookup
*/
#define ALLOC_OR_FALSE(x) do { \
if(!((x) = calloc(1, sizeof(*(x))))) { \
logerror("Unable to allocate memory"); \
return false; \
} \
} while (/*CONSTCOND*/0)
#define ALLOC_SG(x) do { \
ALLOC_OR_FALSE(x); \
(x)->last_msg_num = 1; /* cf. section 4.2.5 */ \
STAILQ_INIT(&(x)->hashes); \
STAILQ_INIT(&(x)->files); \
} while (/*CONSTCOND*/0)
/* alloc(fq) and add to SGs file queue */
#define ASSIGN_FQ() do { \
ALLOC_OR_FALSE(fq); \
fq->f = f; \
f->f_sg = newsg; \
DPRINTF(D_SIGN, "SG@%p <--> f@%p\n", newsg, f); \
STAILQ_INSERT_TAIL(&newsg->files, fq, entries); \
} while (/*CONSTCOND*/0)
switch (GlobalSign.sg) {
case 0:
/* one SG, linked to all files */
ALLOC_SG(newsg);
newsg->spri = 0;
for (f = Files; f; f = f->f_next)
ASSIGN_FQ();
STAILQ_INSERT_TAIL(&GlobalSign.SigGroups,
newsg, entries);
break;
case 1:
/* every PRI gets one SG */
for (i = 0; i < IETF_NUM_PRIVALUES; i++) {
int fac, prilev;
fac = LOG_FAC(i);
prilev = LOG_PRI(i);
ALLOC_SG(newsg);
newsg->spri = i;
/* now find all destinations associated with this SG */
for (f = Files; f; f = f->f_next)
/* check priorities */
if (MATCH_PRI(f, fac, prilev))
ASSIGN_FQ();
STAILQ_INSERT_TAIL(&GlobalSign.SigGroups,
newsg, entries);
}
break;
case 2:
/* PRI ranges get one SG, boundaries given by the
* SPRI, indicating the largest PRI in the SG
*
* either GlobalSign.sig2_delims has a list of
* user configured delimiters, or we use a default
* and set up one SG per facility
*/
if (STAILQ_EMPTY(&GlobalSign.sig2_delims)) {
DPRINTF(D_SIGN, "sign_sg_init(): set default "
"values for SG 2\n");
for (i = 0; i < (IETF_NUM_PRIVALUES>>3); i++) {
ALLOC_OR_FALSE(sqentry);
sqentry->data = NULL;
sqentry->key = (i<<3);
STAILQ_INSERT_TAIL(&GlobalSign.sig2_delims,
sqentry, entries);
}
}
assert(!STAILQ_EMPTY(&GlobalSign.sig2_delims));
/* add one more group at the end */
last_sqentry = STAILQ_LAST(&GlobalSign.sig2_delims,
string_queue, entries);
if (last_sqentry->key < IETF_NUM_PRIVALUES) {
ALLOC_OR_FALSE(sqentry);
sqentry->data = NULL;
sqentry->key = IETF_NUM_PRIVALUES-1;
STAILQ_INSERT_TAIL(&GlobalSign.sig2_delims,
sqentry, entries);
}
STAILQ_FOREACH(sqentry, &GlobalSign.sig2_delims, entries) {
unsigned int min_pri = 0;
ALLOC_SG(newsg);
newsg->spri = sqentry->key;
/* check _all_ priorities in SG */
last_sg = STAILQ_LAST(&GlobalSign.SigGroups,
signature_group_t, entries);
if (last_sg)
min_pri = last_sg->spri + 1;
DPRINTF(D_SIGN, "sign_sg_init(): add SG@%p: SG=\"2\","
" SPRI=\"%d\" -- for msgs with "
"%d <= pri <= %d\n",
newsg, newsg->spri, min_pri, newsg->spri);
/* now find all destinations associated with this SG */
for (f = Files; f; f = f->f_next) {
bool match = false;
for (i = min_pri; i <= newsg->spri; i++) {
int fac, prilev;
fac = LOG_FAC(i);
prilev = LOG_PRI(i);
if (MATCH_PRI(f, fac, prilev)) {
match = true;
break;
}
}
if (match)
ASSIGN_FQ();
}
STAILQ_INSERT_TAIL(&GlobalSign.SigGroups,
newsg, entries);
}
break;
case 3:
/* every file (with flag) gets one SG */
for (f = Files; f; f = f->f_next) {
if (!(f->f_flags & FFLAG_SIGN)) {
f->f_sg = NULL;
continue;
}
ALLOC_SG(newsg);
newsg->spri = f->f_file; /* not needed but shows SGs */
ASSIGN_FQ();
STAILQ_INSERT_TAIL(&GlobalSign.SigGroups,
newsg, entries);
}
break;
}
DPRINTF((D_PARSE|D_SIGN), "sign_sg_init() set up these "
"Signature Groups:\n");
STAILQ_FOREACH(sg, &GlobalSign.SigGroups, entries) {
DPRINTF((D_PARSE|D_SIGN), "SG@%p with SG=\"%d\", SPRI=\"%d\","
" associated files:\n", sg, GlobalSign.sg, sg->spri);
STAILQ_FOREACH(fq, &sg->files, entries) {
DPRINTF((D_PARSE|D_SIGN), " f@%p with type %d\n",
fq->f, fq->f->f_type);
}
}
return true;
}
/*
* free all SGs for a given algorithm
*/
void
sign_global_free(void)
{
struct signature_group_t *sg, *tmp_sg;
struct filed_queue *fq, *tmp_fq;
DPRINTF((D_CALL|D_SIGN), "sign_global_free()\n");
STAILQ_FOREACH_SAFE(sg, &GlobalSign.SigGroups, entries, tmp_sg) {
if (!STAILQ_EMPTY(&sg->hashes)) {
/* send CB and SB twice to get minimal redundancy
* for the last few message hashes */
sign_send_certificate_block(sg);
sign_send_certificate_block(sg);
sign_send_signature_block(sg, true);
sign_send_signature_block(sg, true);
sign_free_hashes(sg);
}
fq = STAILQ_FIRST(&sg->files);
while (fq != NULL) {
tmp_fq = STAILQ_NEXT(fq, entries);
free(fq);
fq = tmp_fq;
}
STAILQ_REMOVE(&GlobalSign.SigGroups,
sg, signature_group_t, entries);
free(sg);
}
sign_free_string_queue(&GlobalSign.sig2_delims);
if (GlobalSign.privkey) {
GlobalSign.privkey = NULL;
}
if (GlobalSign.pubkey) {
EVP_PKEY_free(GlobalSign.pubkey);
GlobalSign.pubkey = NULL;
}
if(GlobalSign.mdctx) {
EVP_MD_CTX_destroy(GlobalSign.mdctx);
GlobalSign.mdctx = NULL;
}
if(GlobalSign.sigctx) {
EVP_MD_CTX_destroy(GlobalSign.sigctx);
GlobalSign.sigctx = NULL;
}
FREEPTR(GlobalSign.pubkey_b64);
}
/*
* create and send certificate block
*/
bool
sign_send_certificate_block(struct signature_group_t *sg)
{
struct filed_queue *fq;
struct buf_msg *buffer;
char *tstamp;
char payload[SIGN_MAX_PAYLOAD_LENGTH];
char sd[SIGN_MAX_SD_LENGTH];
size_t payload_len, sd_len, fragment_len;
size_t payload_index = 0;
/* do nothing if CBs already sent or if there was no message in SG */
if (!sg->resendcount
|| ((sg->resendcount == SIGN_RESENDCOUNT_CERTBLOCK)
&& STAILQ_EMPTY(&sg->hashes)))
return false;
DPRINTF((D_CALL|D_SIGN), "sign_send_certificate_block(%p)\n", sg);
tstamp = make_timestamp(NULL, true);
payload_len = snprintf(payload, sizeof(payload), "%s %c %s", tstamp,
GlobalSign.keytype, GlobalSign.pubkey_b64);
if (payload_len >= sizeof(payload)) {
DPRINTF(D_SIGN, "Buffer too small for syslog-sign setup\n");
return false;
}
while (payload_index < payload_len) {
if (payload_len - payload_index <= SIGN_MAX_FRAG_LENGTH)
fragment_len = payload_len - payload_index;
else
fragment_len = SIGN_MAX_FRAG_LENGTH;
/* format SD */
sd_len = snprintf(sd, sizeof(sd), "[ssign-cert "
"VER=\"%s\" RSID=\"%" PRIuFAST64 "\" SG=\"%d\" "
"SPRI=\"%d\" TBPL=\"%zu\" INDEX=\"%zu\" "
"FLEN=\"%zu\" FRAG=\"%.*s\" "
"SIGN=\"\"]",
GlobalSign.ver, GlobalSign.rsid, GlobalSign.sg,
sg->spri, payload_len, payload_index+1,
fragment_len, (int)fragment_len,
&payload[payload_index]);
assert(sd_len < sizeof(sd));
assert(sd[sd_len] == '\0');
assert(sd[sd_len-1] == ']');
assert(sd[sd_len-2] == '"');
if (!sign_msg_sign(&buffer, sd, sizeof(sd)))
return 0;
DPRINTF((D_CALL|D_SIGN), "sign_send_certificate_block(): "
"calling fprintlog()\n");
STAILQ_FOREACH(fq, &sg->files, entries) {
/* we have to preserve the f_prevcount */
int tmpcnt;
tmpcnt = fq->f->f_prevcount;
fprintlog(fq->f, buffer, NULL);
fq->f->f_prevcount = tmpcnt;
}
sign_inc_gbc();
DELREF(buffer);
payload_index += fragment_len;
}
sg->resendcount--;
return true;
}
/*
* determine the SG for a message
* returns NULL if -sign not configured or no SG for this priority
*/
struct signature_group_t *
sign_get_sg(int pri, struct filed *f)
{
struct signature_group_t *sg, *rc = NULL;
if (GlobalSign.rsid && f)
switch (GlobalSign.sg) {
case 0:
rc = f->f_sg;
break;
case 1:
case 2:
STAILQ_FOREACH(sg, &GlobalSign.SigGroups, entries) {
if (sg->spri >= (unsigned int)pri) {
rc = sg;
break;
}
}
break;
case 3:
if (f->f_flags & FFLAG_SIGN)
rc = f->f_sg;
else
rc = NULL;
break;
}
DPRINTF((D_CALL|D_SIGN), "sign_get_sg(%d, %p) --> %p\n", pri, f, rc);
return rc;
}
/*
* create and send signature block
*
* uses a sliding window for redundancy
* if force==true then simply send all available hashes, e.g. on shutdown
*
* sliding window checks implicitly assume that new hashes are appended
* to the SG between two calls. if that is not the case (e.g. with repeated
* messages) the queue size will shrink.
* this has no negative consequences except generating more and shorter SBs
* than expected and confusing the operator because two consecutive SBs will
* have same FMNn
*/
unsigned
sign_send_signature_block(struct signature_group_t *sg, bool force)
{
char sd[SIGN_MAX_SD_LENGTH];
size_t sd_len;
size_t sg_num_hashes = 0; /* hashes in SG queue */
size_t hashes_in_sb = 0; /* number of hashes in current SB */
size_t hashes_sent = 0; /* count of hashes sent */
struct string_queue *qentry, *old_qentry;
struct buf_msg *buffer;
struct filed_queue *fq;
size_t i;
if (!sg) return 0;
DPRINTF((D_CALL|D_SIGN), "sign_send_signature_block(%p, %d)\n",
sg, force);
STAILQ_FOREACH(qentry, &sg->hashes, entries)
sg_num_hashes++;
/* only act if a division is full */
if (!sg_num_hashes
|| (!force && (sg_num_hashes % SIGN_HASH_DIVISION_NUM)))
return 0;
/* if no CB sent so far then do now, just before first SB */
if (sg->resendcount == SIGN_RESENDCOUNT_CERTBLOCK)
sign_send_certificate_block(sg);
/* shortly after reboot we have shorter SBs */
hashes_in_sb = MIN(sg_num_hashes, SIGN_HASH_NUM);
DPRINTF(D_SIGN, "sign_send_signature_block(): "
"sg_num_hashes = %zu, hashes_in_sb = %zu, SIGN_HASH_NUM = %d\n",
sg_num_hashes, hashes_in_sb, SIGN_HASH_NUM);
if (sg_num_hashes > SIGN_HASH_NUM) {
DPRINTF(D_SIGN, "sign_send_signature_block(): sg_num_hashes"
" > SIGN_HASH_NUM -- This should not happen!\n");
}
/* now the SD */
qentry = STAILQ_FIRST(&sg->hashes);
sd_len = snprintf(sd, sizeof(sd), "[ssign "
"VER=\"%s\" RSID=\"%" PRIuFAST64 "\" SG=\"%d\" "
"SPRI=\"%d\" GBC=\"%" PRIuFAST64 "\" FMN=\"%" PRIuFAST64 "\" "
"CNT=\"%zu\" HB=\"",
GlobalSign.ver, GlobalSign.rsid, GlobalSign.sg,
sg->spri, GlobalSign.gbc, qentry->key,
hashes_in_sb);
while (hashes_sent < hashes_in_sb) {
assert(qentry);
sd_len += snprintf(sd+sd_len, sizeof(sd)-sd_len, "%s ",
qentry->data);
hashes_sent++;
qentry = STAILQ_NEXT(qentry, entries);
}
/* overwrite last space and close SD */
assert(sd_len < sizeof(sd));
assert(sd[sd_len] == '\0');
assert(sd[sd_len-1] == ' ');
sd[sd_len-1] = '\0';
sd_len = strlcat(sd, "\" SIGN=\"\"]", sizeof(sd));
if (sign_msg_sign(&buffer, sd, sizeof(sd))) {
DPRINTF((D_CALL|D_SIGN), "sign_send_signature_block(): calling"
" fprintlog(), sending %zu out of %zu hashes\n",
MIN(SIGN_MAX_HASH_NUM, sg_num_hashes), sg_num_hashes);
STAILQ_FOREACH(fq, &sg->files, entries) {
int tmpcnt;
tmpcnt = fq->f->f_prevcount;
fprintlog(fq->f, buffer, NULL);
fq->f->f_prevcount = tmpcnt;
}
sign_inc_gbc();
DELREF(buffer);
}
/* always drop the oldest division of hashes */
if (sg_num_hashes >= SIGN_HASH_NUM) {
qentry = STAILQ_FIRST(&sg->hashes);
for (i = 0; i < SIGN_HASH_DIVISION_NUM; i++) {
old_qentry = qentry;
qentry = STAILQ_NEXT(old_qentry, entries);
STAILQ_REMOVE(&sg->hashes, old_qentry,
string_queue, entries);
FREEPTR(old_qentry->data);
FREEPTR(old_qentry);
}
}
return hashes_sent;
}
void
sign_free_hashes(struct signature_group_t *sg)
{
DPRINTF((D_CALL|D_SIGN), "sign_free_hashes(%p)\n", sg);
sign_free_string_queue(&sg->hashes);
}
void
sign_free_string_queue(struct string_queue_head *sqhead)
{
struct string_queue *qentry, *tmp_qentry;
DPRINTF((D_CALL|D_SIGN), "sign_free_string_queue(%p)\n", sqhead);
STAILQ_FOREACH_SAFE(qentry, sqhead, entries, tmp_qentry) {
STAILQ_REMOVE(sqhead, qentry, string_queue, entries);
FREEPTR(qentry->data);
free(qentry);
}
assert(STAILQ_EMPTY(sqhead));
}
/*
* hash one syslog message
*/
bool
sign_msg_hash(char *line, char **hash)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned char md_b64[EVP_MAX_MD_SIZE*2];
/* TODO: exact expression for b64 length? */
unsigned md_len = 0;
DPRINTF((D_CALL|D_SIGN), "sign_msg_hash('%s')\n", line);
SSL_CHECK_ONE(EVP_DigestInit_ex(GlobalSign.mdctx, GlobalSign.md, NULL));
SSL_CHECK_ONE(EVP_DigestUpdate(GlobalSign.mdctx, line, strlen(line)));
SSL_CHECK_ONE(EVP_DigestFinal_ex(GlobalSign.mdctx, md_value, &md_len));
b64_ntop(md_value, md_len, (char *)md_b64, EVP_MAX_MD_SIZE*2);
*hash = strdup((char *)md_b64);
DPRINTF((D_CALL|D_SIGN), "sign_msg_hash() --> \"%s\"\n", *hash);
return true;
}
/*
* append hash to SG queue
*/
bool
sign_append_hash(char *hash, struct signature_group_t *sg)
{
struct string_queue *qentry;
/* if one SG is shared by several destinations
* prevent duplicate entries */
if ((qentry = STAILQ_LAST(&sg->hashes, string_queue, entries))
&& !strcmp(qentry->data, hash)) {
DPRINTF((D_CALL|D_SIGN), "sign_append_hash('%s', %p): "
"hash already in queue\n", hash, sg);
return false;
}
MALLOC(qentry, sizeof(*qentry));
qentry->key = sign_assign_msg_num(sg);
qentry->data = hash;
STAILQ_INSERT_TAIL(&sg->hashes, qentry, entries);
DPRINTF((D_CALL|D_SIGN), "sign_append_hash('%s', %p): "
"#%" PRIdFAST64 "\n", hash, sg, qentry->key);
return true;
}
/*
* sign one syslog-sign message
*
* requires a ssign or ssigt-cert SD element
* ending with ' SIGN=""]' in sd
* linesize is available memory (= sizeof(sd))
*
* function will calculate signature and return a new buffer
*/
bool
sign_msg_sign(struct buf_msg **bufferptr, char *sd, size_t linesize)
{
char *signature, *line;
size_t linelen, tlsprefixlen, endptr, newlinelen;
struct buf_msg *buffer;
DPRINTF((D_CALL|D_SIGN), "sign_msg_sign()\n");
endptr = strlen(sd);
assert(endptr < linesize);
assert(sd[endptr] == '\0');
assert(sd[endptr-1] == ']');
assert(sd[endptr-2] == '"');
/* set up buffer */
buffer = buf_msg_new(0);
buffer->timestamp = strdup(make_timestamp(NULL, !BSDOutputFormat));
buffer->prog = appname;
buffer->pid = include_pid;
buffer->recvhost = buffer->host = LocalFQDN;
buffer->pri = 110;
buffer->flags = IGN_CONS|SIGN_MSG;
buffer->sd = sd;
/* SD ready, now format and sign */
if (!format_buffer(buffer, &line, &linelen, NULL,
&tlsprefixlen, NULL)) {
DPRINTF((D_CALL|D_SIGN), "sign_send_signature_block():"
" format_buffer() failed\n");
buffer->sd = NULL;
DELREF(buffer);
return false;
}
if (!sign_string_sign(line+tlsprefixlen, &signature)) {
DPRINTF((D_CALL|D_SIGN), "sign_send_signature_block():"
" sign_string_sign() failed\n");
buffer->sd = NULL;
DELREF(buffer);
FREEPTR(line);
return false;
}
FREEPTR(line);
sd[endptr-2] = '\0';
newlinelen = strlcat(sd, signature, linesize);
newlinelen = strlcat(sd, "\"]", linesize);
if (newlinelen >= linesize) {
DPRINTF(D_SIGN, "sign_send_signature_block(): "
"buffer too small\n");
buffer->sd = NULL;
DELREF(buffer);
return false;
}
assert(newlinelen < linesize);
assert(sd[newlinelen] == '\0');
assert(sd[newlinelen-1] == ']');
assert(sd[newlinelen-2] == '"');
buffer->sd = strdup(sd);
*bufferptr = buffer;
return true;
}
/*
* sign one string
*/
bool
sign_string_sign(char *line, char **signature)
{
char buf[SIGN_MAX_LENGTH+1];
unsigned char sig_value[SIGN_B64SIGLEN_DSS];
unsigned char sig_b64[SIGN_B64SIGLEN_DSS];
unsigned sig_len = 0;
char *p, *q;
/*
* The signature is calculated over the completely formatted
* syslog-message, including all of the PRI, HEADER, and hashes
* in the hash block, excluding spaces between fields, and also
* excluding the signature field (SD Parameter Name "SIGN", "=",
* and corresponding value).
*
* -- I am not quite sure which spaces are to be removed.
* Only the ones inside the "ssign" element or those between
* header fields as well?
*/
/* removes the string ' SIGN=""' */
for (p = line, q = buf;
*p && (q - buf <= SIGN_MAX_LENGTH);) {
if (strncmp(p, " SIGN=\"\"", 8) == 0)
p += 8;
*q++ = *p++;
}
*q = '\0';
SSL_CHECK_ONE(EVP_SignInit(GlobalSign.sigctx, GlobalSign.sig));
SSL_CHECK_ONE(EVP_SignUpdate(GlobalSign.sigctx, buf, q-buf));
assert(GlobalSign.privkey);
SSL_CHECK_ONE(EVP_SignFinal(GlobalSign.sigctx, sig_value, &sig_len,
GlobalSign.privkey));
b64_ntop(sig_value, sig_len, (char *)sig_b64, sizeof(sig_b64));
*signature = strdup((char *)sig_b64);
DPRINTF((D_CALL|D_SIGN), "sign_string_sign('%s') --> '%s'\n",
buf, *signature);
return *signature != NULL;
}
void
sign_new_reboot_session(void)
{
struct signature_group_t *sg;
DPRINTF((D_CALL|D_SIGN), "sign_new_reboot_session()\n");
/* global counters */
GlobalSign.gbc = 0;
/* might be useful for later analysis:
* rebooted session IDs are sequential,
* normal IDs are almost always not */
GlobalSign.rsid++;
assert(GlobalSign.sg <= 3);
/* reset SGs */
STAILQ_FOREACH(sg, &GlobalSign.SigGroups, entries) {
sg->resendcount = SIGN_RESENDCOUNT_CERTBLOCK;
sg->last_msg_num = 1;
}
}
/* get msg_num, increment counter, check overflow */
uint_fast64_t
sign_assign_msg_num(struct signature_group_t *sg)
{
uint_fast64_t old;
old = sg->last_msg_num++;
if (sg->last_msg_num > SIGN_MAX_COUNT)
sign_new_reboot_session();
return old;
}
/* increment gbc, check overflow */
void
sign_inc_gbc(void)
{
if (++GlobalSign.gbc > SIGN_MAX_COUNT)
sign_new_reboot_session();
}
#endif /* !DISABLE_SIGN */

207
usr.sbin/syslogd/sign.h Normal file
View file

@ -0,0 +1,207 @@
/* $NetBSD: sign.h,v 1.2 2008/11/07 07:36:38 minskim Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Schütte.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* sign.h
*
*/
#ifndef SIGN_H_
#define SIGN_H_
#include <netinet/in.h>
#include <resolv.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
/* default Signature Group value,
* defines signature strategy:
* 0 one global SG
* 1 one SG per PRI
* 2 SGs for PRI ranges
* 3 other (SGs not defined by PRI)
*
* We use '3' and assign one SG to every destination (=struct filed)
*/
#define SIGN_SG 3
/* maximum value for several counters in -sign */
#define SIGN_MAX_COUNT 9999999999
/*
* many of these options could be made user configurable if desired,
* but I do not see the need for that
*/
/* redundancy options */
/*
* note on the implementation of redundancy:
* - certificate blocks: sending the first CB just before first SB.
* after that domark() triggers resends until resend count is reached.
* - signature blocks: to send every hash n times I use a sliding window.
* the hashes in every SB are grouped into n divisions:
* * the 1st hashcount/n hashes are sent for the 1st time
* * the 2nd hashcount/n hashes are sent for the 2nd time
* * ...
* * the n-th hashcount/n hashes are sent for the n-th time
* (and deleted thereafter)
*/
#define SIGN_RESENDCOUNT_CERTBLOCK 2
#define SIGN_RESENDCOUNT_HASHES 3
/* maximum length of syslog-sign messages should be <= 2048 by standard
* and should be >= 1024 to be long enough.
* be careful with small values because there is no check for a lower bound
* thus the following derived values would become negative.
*/
#define SIGN_MAX_LENGTH 2048
/* the length we can use for the SD and keep the
* message length with header below 2048 octets */
#define SIGN_MAX_SD_LENGTH (SIGN_MAX_LENGTH - 1 - HEADER_LEN_MAX)
/* length of signature, currently only for DSA */
#define SIGN_B64SIGLEN_DSS 64+1
/* the maximum length of one payload fragment:
* max.SD len - text - max. field lengths - sig len */
#define SIGN_MAX_FRAG_LENGTH (SIGN_MAX_SD_LENGTH - 82 - 38 - SIGN_B64SIGLEN_DSS)
/* the maximum length of one signature block:
* max.SD len - text - max. field lens - sig len */
#define SIGN_MAX_SB_LENGTH (SIGN_MAX_SD_LENGTH - 72 - 40 - SIGN_B64SIGLEN_DSS)
/* the maximum number of hashes pec signature block */
#define SIGN_MAX_HASH_NUM (SIGN_MAX_SB_LENGTH / (GlobalSign.md_len_b64+1))
/* number of hashes in one signature block */
#define SIGN_HASH_NUM_WANT 100
/* make sure to consider SIGN_MAX_HASH_NUM and
* to have a SIGN_HASH_NUM that is a multiple of SIGN_HASH_DIVISION_NUM */
#define SIGN_HASH_DIVISION_NUM (MIN(SIGN_HASH_NUM_WANT, SIGN_MAX_HASH_NUM) \
/ SIGN_RESENDCOUNT_HASHES)
#define SIGN_HASH_NUM (SIGN_HASH_DIVISION_NUM * SIGN_RESENDCOUNT_HASHES)
/* the length of payload strings
* since the payload is fragmented there is no technical limit
* it just has to be big enough to hold big b64 encoded PKIX certificates
*/
#define SIGN_MAX_PAYLOAD_LENGTH 20480
/* length of generated DSA keys for signing */
#define SIGN_GENCERT_BITS 1024
#define SSL_CHECK_ONE(exp) do { \
if ((exp) != 1) { \
DPRINTF(D_SIGN, #exp " failed in %d: %s\n", __LINE__, \
ERR_error_string(ERR_get_error(), NULL)); \
return 1; \
} \
} while (/*CONSTCOND*/0)
/* structs use uint_fast64_t in different places because the standard
* requires values in interval [0:9999999999 = SIGN_MAX_COUNT] */
/* queue of C-Strings (here used for hashes) */
struct string_queue {
uint_fast64_t key;
char *data;
STAILQ_ENTRY(string_queue) entries;
};
STAILQ_HEAD(string_queue_head, string_queue);
/* queue of destinations (used associate SGs and fileds) */
struct filed_queue {
struct filed *f;
STAILQ_ENTRY(filed_queue) entries;
};
STAILQ_HEAD(filed_queue_head, filed_queue);
/* queue of Signature Groups */
struct signature_group_t {
unsigned spri;
unsigned resendcount;
uint_fast64_t last_msg_num;
struct string_queue_head hashes;
struct filed_queue_head files;
STAILQ_ENTRY(signature_group_t) entries;
};
STAILQ_HEAD(signature_group_head, signature_group_t);
/* all global variables for sign */
/* note that there is one object of this type which might only be
* partially filled.
* The fields .sg and .sig2_delims are set by init() and are always
* valid. A value >0 in field .rsid indicates whether the rest of the
* structure was already set by sign_global_init().
*/
struct sign_global_t {
/* params for signature block, named as in RFC nnnn */
const char *ver;
uint_fast64_t rsid;
int sg;
uint_fast64_t gbc;
struct signature_group_head SigGroups;
struct string_queue_head sig2_delims;
EVP_PKEY *privkey;
EVP_PKEY *pubkey;
char *pubkey_b64;
char keytype;
EVP_MD_CTX *mdctx; /* hashing context */
const EVP_MD *md; /* hashing method/algorithm */
unsigned md_len_b64; /* length of b64 hash value */
EVP_MD_CTX *sigctx; /* signature context */
const EVP_MD *sig; /* signature method/algorithm */
unsigned sig_len_b64; /* length of b64 signature */
};
bool sign_global_init(struct filed*);
bool sign_sg_init(struct filed*);
bool sign_get_keys(void);
void sign_global_free(void);
struct signature_group_t* sign_get_sg(int, struct filed*);
bool sign_send_certificate_block(struct signature_group_t*);
unsigned sign_send_signature_block(struct signature_group_t*, bool);
void sign_free_hashes(struct signature_group_t*);
void sign_free_string_queue(struct string_queue_head*);
bool sign_msg_hash(char*, char**);
bool sign_append_hash(char*, struct signature_group_t*);
bool sign_msg_sign(struct buf_msg**, char*, size_t);
bool sign_string_sign(char*, char**);
void sign_new_reboot_session(void);
void sign_inc_gbc(void);
uint_fast64_t sign_assign_msg_num(struct signature_group_t*);
#endif /* SIGN_H_ */

146
usr.sbin/syslogd/sign.html Normal file
View file

@ -0,0 +1,146 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title>NetBSD &amp; Google's Summer of Code: Martin Schuette - Improve syslogd (syslogd)</title>
</head>
<body>
<h1>syslog-sign</h1>
<p><a href="http://tools.ietf.org/html/draft-ietf-syslog-sign">syslog-sign</a> defines digital signatures for logfiles. This provides end-to-end authentication for network transports, enables the detection of lost UDP messages, and also makes it possible to check a log archive for later modifications (assuming the private key was kept safe).</p>
<h2>Signature Groups</h2>
<p>A basic concept of syslog-sign is the signature group which describes a set of messages that are grouped and signed together. Their purpose becomes clear with an example: assume you split your messages to two logservers <em>serverA</em> and <em>serverB</em>. Now if all messages were singed as one stream, then a) where do the signatures go to? and b) how could <em>serverA</em>, having only hashes and signatures, decide which message are missing and which are on <em>serverB</em>?<br>
Thus the messages are selected into two signature groups containing all signatures for messages to <em>serverA</em> and <em>serverB</em> respectively. Then every server has its own messages and its own signatures to verify them.</p>
<p>There are three predefined and one custom signature groups:</p>
<ol start="0">
<li>one global signature group, useful if all messages go to one central logserver anyway</li>
<li>every syslog priority (=combination of facility and severity) gets its own group, i.e. 192 of them, useful if there are lots of different destinations which all receive messages with different priorities</li>
<li>take the priorities and split them into intervals, useful to define bigger subsets, e.g. one signature group for the mail facility and two for everything else</li>
<li>not defined and reserved for custom strategy. I use this to have one signature group for every configured destination. In this case the selector in syslog.conf will determine which messages go into one group; it is also the only strategy that allows a message to be in multiple groups.</li>
</ol>
<p>Every signature group has several attributes and only the combination of several values determines one signature group unambiguously. Currently the key to identify a signature group is the tuple (hostname, reboot session ID, SG value, SPRI value). <!-- In a later draft the program name or process ID might be added to allow multiple syslog-sign senders per host.--></p>
<h2>Configuration/Activation</h2>
<p>syslog-sign is enabled with the option "sign_sg" in syslog.conf. The value selects the signature group strategy, so for example the line "sign_sg=0" enables syslog-sign with one signature group.</p>
<p>The SG="2" strategy is the only one that might require additional configuration. When selected (with "sign_sg=2") the default is to use one signature group per facility (kernel, user, mail, ...). To allow custom configuration there is an additional option "sign_sg2_delim" to specify the numerical SPRI values, i.e. the boundaries betwen the signature groups.<br>
Example: With "sign_sg2_delim = 15 31" syslogd will set up three signature groups: one for all priorities x &le; 15 (kernel.*,user.*), one for priorities 15 &lt; x &le; 31 (mail.*), and one for all priorities x &gt; 31.</p>
<h2>Key, Signature, and Hash Types</h2>
<p>The current internet draft defines two values for the VERsion field for using either SHA-1 or SHA-256 hashes. Both versions mandate DSA keys and signatures.<br>
There are several alternatives for sending the public key in the initial Certificate Block. If a X.509 certificate is available (for TLS connections) then syslogd will use key type 'C' (PKIX) and send the certificate in DER encoding. Otherwise it generates a new DSA key and uses key type 'K' (public key) to send the public key in DER encoding.</p>
<h2>Redundancy</h2>
<p>As mentioned above one design target of syslog-sign is the detection of lost messages, e.g. due to UDP datagram loss. So one has to take extra precaution to prevent lost signature messages and send them multiple times.<br>
This implementation sends the first Certificate block only on demand, just before the first Signature Block. After that it is resent <em>n</em> times with several seconds delay. The Signature Blocks are not repeated but use a sliding window so that every message hash is included in <em>m</em> sequential Signature Blocks.</p>
<h2>Verification</h2>
<p>Sending signatures is only half of the job, -- they have to be verified as well. I used Perl to write an <a href="verify-sign/verify.pl">offline verification</a> tool that reads a complete logfile and prints all messages in their correct order. See the example below for a sample usage and output.</p>
<h2>Example</h2>
<p>Here is an example of a signed message sequence. I let syslogd generate me a DSA key for a self-signed X.509 certificate and use that for signing. I also changed one message so you can see the resulting verification output below.</p>
<pre>
$ cat test.log
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg0
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg1
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg2
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg3
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg4
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg5
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg6
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg7
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg8
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg9
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg10
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg11
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - modified msg12
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg13
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg14
<110>1 2008-08-02T01:09:27.773505+02:00 host.example.org syslogd - - [ssign-cert VER="0111" RSID="1217632162" SG="3" SPRI="0" TBPL="1059" INDEX="1" FLEN="1059" FRAG="2008-08-02T01:09:27.773464+02:00 C MIIC+jCCArmgAwIBAwIBATAJBgcqhkjOOAQDMCIxIDAeBgNVBAMTF2NvcmRlbGlhLm1zY2h1ZXR0ZS5uYW1lMB4XDTA4MDczMDIyMDYyMloXDTA5MDczMDIyMDYyMlowIjEgMB4GA1UEAxMXY29yZGVsaWEubXNjaHVldHRlLm5hbWUwggG3MIIBKwYHKoZIzjgEATCCAR4CgYEA92S335Kxy2TTMfdg9Vi/CJvyDCHMHpPYxWwEkEI26xEdKybzLghTfbG/RZw/nnFuhRTH4Xe6GVvlFi2zIzySSClXr+zyXg/D9uHyiVL5TEsu8uQT2IREmGOB8pu70FukL9nQGOr82YxuRFQzZ1p6KltIggivi5ffR4B33+1xoSkCFQDYe5GJKM9Cw6nkLngHkzFGRmcXIQKBgDbHeOLBKYLkRZyRpXd0aTNU2igcKTWyWlUTySJuv/iTAeB09p9WyTIPyAhtqN77CIwX8Ui2jGu6NYT6TWEYJVvL+C/TvddAvAMyefv+w+HPNF2L77IVrjNVRCneERoNKlWc6IzjKH3otl/Lh2D7NAWRid55vxF6Z0oO459+4vpRA4GFAAKBgQCzcJVR343IRntcQs8aENs/QMxoxHN6JVdpSLB9moY5/RC9ooxz32fkakSL0s8zLITLt/y+yzf0F/9JhmTC1XeD8gvPBesE6dc0ZzPCos0hg8WpKUWR0YqXFDOC//uBwIa94DncC8xZ0mCwavno6gtkz57S7ywSwnmrdjhmpdAZuqOBgDB+MBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkYXV0by1nZW5lcmF0ZWQgYnkgdGhlIE5ldEJTRCBzeXNsb2dkMCYGCWCGSAGG+EIBDAQZFhdjb3JkZWxpYS5tc2NodWV0dGUubmFtZTAMBgNVHRMBAf8EAjAAMAkGByqGSM44BAMDMAAwLQIUZcsHdrbuyx9lR3tyyeiJvClj0B8CFQC+5+NlulgCd/yoSlLPZgsTHYmCYA==" SIGN="MC0CFFEHx8UX391lbmhbisJNS0zLGD/WAhUAuMfCO0BWtARt2vEWHbM2mAe2k+o="]
<110>1 2008-08-02T01:09:27.778347+02:00 host.example.org syslogd - - [ssign VER="0111" RSID="1217632162" SG="3" SPRI="0" GBC="1" FMN="1" CNT="15" HB="siUJM358eYFHOS2K0MTlveWeH/U= zTxfthW8WqmtFhOG4k/+ZxkirTA= j9dubU1GNVp7qWShwph/w32nD08= XQDLZ/NuwirmLdMORtm84r9kIW4= RNDFNCo7hiCsK/EKumsPBbFHNZA= ANiE3KbY948J6cEB640fAtWXuO4= e2M/OqjHDfxLVUSPt1CsNJHm9wU= Y+racQst7F1gR8eEUh8O7o+M53s= JAMULRxjMPbOO5EhhKbsUkAwbl0= pd+N5kmlnyQ0BoItELd/KWQrcMg= dsMQSzPHIS6S3Vaa23/t7U8JAJ4= i4rE3x7N4qyQGTkmaWHsWDFP9SY= qgTqV4EgfUFd3uZXNPvJ25erzBI= XW0YrME5kQEh+fxhg1fetnWxfIc= 7YPcRHsDwXWnQuGRWaJtFWw9hus=" SIGN="MCwCFF5hS5GTLxLDwsDCUmOnHhzkmWzbAhRJ0io+LBKM6Ux/cM7eqZ6eRAI11Q=="]
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg15
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg16
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg17
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg18
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg19
<110>1 2008-08-02T01:09:32.399406+02:00 host.example.org syslogd - - [ssign VER="0111" RSID="1217632162" SG="3" SPRI="0" GBC="4" FMN="1" CNT="20" HB="siUJM358eYFHOS2K0MTlveWeH/U= zTxfthW8WqmtFhOG4k/+ZxkirTA= j9dubU1GNVp7qWShwph/w32nD08= XQDLZ/NuwirmLdMORtm84r9kIW4= RNDFNCo7hiCsK/EKumsPBbFHNZA= ANiE3KbY948J6cEB640fAtWXuO4= e2M/OqjHDfxLVUSPt1CsNJHm9wU= Y+racQst7F1gR8eEUh8O7o+M53s= JAMULRxjMPbOO5EhhKbsUkAwbl0= pd+N5kmlnyQ0BoItELd/KWQrcMg= dsMQSzPHIS6S3Vaa23/t7U8JAJ4= i4rE3x7N4qyQGTkmaWHsWDFP9SY= qgTqV4EgfUFd3uZXNPvJ25erzBI= XW0YrME5kQEh+fxhg1fetnWxfIc= 7YPcRHsDwXWnQuGRWaJtFWw9hus= PIvLm0mh+he5+PDihG1p7sQlx8k= lPzUvx0I1VwSGWV7yKF9W//Yb2U= X+PWYcx5AXnsDVSNAHLZUGk5ioY= okXY88MGG4QybrYMf8HJN23WO1Y= HcaPyHfQ2s1SuSciTKw4woYWuMg=" SIGN="MCwCFFr0i6taT1vWowR7yc5bEQxFfY7/AhQBCK+rBNPgzR0vUgxPeARvD24kIQ=="]
</pre>
<p>Just in case you wonder about the different timestamps: The messages were send with a normal syslog(3), so the syslogd received them in BSD Syslog format without subsecond resolution.</p>
<hr>
<pre>
$ perl verify.pl --help
syslog-sign verifier
reads logfile and verifies message signatures
Notes:
- By default uses only SHA-1 hashes. Use option "--sha256" to use only
SHA-256 and "--sha1 --sha256"to use both types.
- Some status messages are printed to stderr.
Use option "--quiet" to disable them.
- All verified messages are printed with their identifying signature group.
Every line starts with a comma-separated tuple: hostname, reboot session ID,
SG value, SPRI value, and message number.
- If only one hash is used then all messages not signed are printed as well.
Limitations: handles only key types 'C' (PKIX) and 'K' (public key)
with DSA keys and signatures
Command Line Options:
-i --in input file (default: stdin)
-o --out output file for verified messages (default: stdout)
-u --unsigned output file for unsigned messages (default: stdout)
--sha1 use SHA-1 hashes (default)
--sha256 use SHA-256 hashes
-v --verbose shows some internals (every CB,SB,hash,...)
-q --quiet no status messages to stderr
-h --help this help
$ perl verify.pl -i test.log
reading input...
processing CBs...
decoding SGs...
got PKIX DSA key
verifying CBs...
verified CB and got key for SG: (host.example.org,1217632162,0111,3,0), start: 2008-08-02T01:09:27.773464+02:00
now process SBs
signed messages:
host.example.org,1217632162,0111,3,0,1 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg0
host.example.org,1217632162,0111,3,0,2 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg1
host.example.org,1217632162,0111,3,0,3 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg2
host.example.org,1217632162,0111,3,0,4 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg3
host.example.org,1217632162,0111,3,0,5 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg4
host.example.org,1217632162,0111,3,0,6 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg5
host.example.org,1217632162,0111,3,0,7 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg6
host.example.org,1217632162,0111,3,0,8 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg7
host.example.org,1217632162,0111,3,0,9 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg8
host.example.org,1217632162,0111,3,0,10 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg9
host.example.org,1217632162,0111,3,0,11 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg10
host.example.org,1217632162,0111,3,0,12 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg11
host.example.org,1217632162,0111,3,0,13 **** msg lost
host.example.org,1217632162,0111,3,0,14 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg13
host.example.org,1217632162,0111,3,0,15 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg14
host.example.org,1217632162,0111,3,0,16 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg15
host.example.org,1217632162,0111,3,0,17 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg16
host.example.org,1217632162,0111,3,0,18 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg17
host.example.org,1217632162,0111,3,0,19 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg18
host.example.org,1217632162,0111,3,0,20 <15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - msg19
messages without signature:
<15>1 2008-08-02T02:09:27+02:00 host.example.org test 6255 - - modified msg12
</pre>
<hr>
<table border=0>
<tr>
<td>
<a href="http://sourceforge.net"><img align="top" src="http://sourceforge.net/sflogo.php?group_id=141771&amp;type=2" width="125" height="37" border="0" alt="SourceForge.net Logo"></a>
<td>
<table>
<tr> <td> Martin Sch&uuml;tte &lt;<tt>info@mschuette.name</tt>&gt; </td> </tr>
<tr> <td> $Id: sign.html,v 1.1 2008/10/31 16:12:19 christos Exp $ </td> </tr>
</table>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,652 @@
.\" $NetBSD: syslog.conf.5,v 1.21 2013/11/10 00:13:50 wiz Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93
.\"
.Dd November 9, 2013
.Dt SYSLOG.CONF 5
.Os
.Sh NAME
.Nm syslog.conf
.Nd
.Xr syslogd 8
configuration file
.Sh DESCRIPTION
The
.Nm
file is the configuration file for the
.Xr syslogd 8
program.
It consists of extended options (lines with one key="value" assignment)
and blocks of lines separated by
.Em program
and
.Em hostname
specifications, with each line containing two fields: the
.Em selector
field which specifies the types of messages and priorities to which the
line applies, and an
.Em action
field which specifies the action to be taken if a message
.Xr syslogd 8
receives matches the selection criteria.
The
.Em selector
field is separated from the
.Em action
field by one or more tab characters.
.Pp
The
.Em Selectors
function
are encoded as a
.Em facility ,
a period
.Pq Sq \&. ,
an optional set of comparison flags
.Pq Bo ! Bc Bq \*[Lt]=\*[Gt] ,
and a
.Em level ,
with no intervening white-space.
Both the
.Em facility
and the
.Em level
are case insensitive.
.Pp
The
.Em facility
describes the part of the system generating the message, and is one of
the following keywords: auth, authpriv, cron, ftp, daemon, kern, lpr,
mail, mark, news, syslog, user, uucp and local0 through local7.
These keywords (with the exception of mark) correspond to the
similar
.Dq Dv LOG_
values specified to the
.Xr openlog 3
and
.Xr syslog 3
library routines.
.Pp
The
.Em comparison flags
may be used to specify exactly what levels are logged.
If unspecified, the default comparison is
.Sq \*[Gt]=
.Pq greater than or equal to ,
or, if the
.Fl U
option is passed to
.Xr syslogd 8 ,
.Sq =
.Pq equal to .
Comparison flags beginning with
.So ! Sc
will have their logical sense inverted.
Thus,
.Sq !=info
means all levels except info and
.Sq !notice
has the same meaning as
.Sq \*[Lt]notice .
.Pp
The
.Em level
describes the severity of the message, and is a keyword from the
following ordered list (higher to lower): emerg, alert, crit, err,
warning, notice, info and debug.
These keywords correspond to the
similar
.Pq Dv LOG_
values specified to the
.Xr syslog 3
library routine.
.Pp
Each block of lines is separated from the previous block by a
.Em program
or
.Em hostname
specification.
A block will only log messages corresponding to the most recent
.Em program
and
.Em hostname
specifications given.
Consider the case of a block that selects
.Ql pppd
as the
.Em program ,
directly followed by a block that selects messages from the
.Em hostname
.Ql dialhost .
The second block will log only messages from the
.Xr pppd 8
program from the host
.Sq dialhost .
.Pp
A
.Em program
specification of the form
.Ql #!+prog1,prog2
or
.Ql !+prog1,prog2
will cause subsequent blocks to be applied to messages logged by the
specified programs.
A
.Em program
specification of the form
.Ql #!-prog1,prog2
or
.Ql !-prog1,prog2
will cause subsequent blocks to be applied to messages logged by programs
other than the ones specified.
A
.Em program
specification of the form
.Ql #!prog1,prog2
or
.Ql !prog1,prog2
is equivalent to
.Ql !+prog1,prog2 .
Program selectors may also match kernel-generated messages.
For example, a program specification of
.Ql !+subsys
will match kernel-generated messages of the form
.Ql subsys: here is a message .
The special specification
.Ql !*
will cause subsequent blocks to apply to all programs.
.Pp
A
.Em hostname
specification of the form
.Ql #+host1,host2
or
.Ql +host1,host2
will cause subsequent blocks to be applied to messages received from
the specified hosts.
A
.Em hostname
specification of the form
.Ql #-host1,host2
or
.Ql -host1,host2
will cause subsequent blocks to be applied to messages from hosts other
than the ones specified.
If the hostname is given as
.Ql @ ,
the local hostname will be used.
The special specification
.Ql +*
will cause subsequent blocks to apply to all hosts.
.Pp
See
.Xr syslog 3
for a further descriptions of both the
.Em facility
and
.Em level
keywords and their significance.
It is preferred that selections be made based on
.Em facility
rather than
.Em program ,
since the latter can vary in a networked environment.
However, there are cases where a
.Em facility
may be too broadly defined.
.Pp
If a received message matches the specified
.Em facility ,
and the specified
.Em level
comparison is true,
and the first word in the message after the date matches the
.Em program ,
the action specified in the
.Em action
field will be taken.
.Pp
Multiple
.Em selectors
may be specified for a single
.Em action
by separating them with semicolon
.Pq Sq \&;
characters.
It is important to note, however, that each
.Em selector
can modify the ones preceding it.
.Pp
Multiple
.Em facilities
may be specified for a single
.Em level
by separating them with comma
.Pq Sq \&,
characters.
.Pp
An asterisk
.Pq Sq \&*
can be used to specify all
.Em facilities
or all
.Em levels .
.Pp
The special
.Em facility
.Dq mark
receives a message at priority
.Dq info
every 20 minutes
(see
.Xr syslogd 8 ) .
This is not enabled by a
.Em facility
field containing an asterisk.
.Pp
The special
.Em level
.Dq none
disables a particular
.Em facility .
.Pp
The
.Em action
field of each line specifies the action to be taken when the
.Em selector
field selects a message.
There are five forms:
.Bl -bullet
.It
A pathname (beginning with a leading slash).
Selected messages are appended to the file, unless
pathname points to an existing FIFO special file.
.Xr syslogd 8
treats FIFO specially by opening them in non-blocking mode and
discarding messages sent when no reader is listening on the other side.
.Pp
To ensure that kernel messages are written to disk promptly,
.Xr syslogd 8
calls
.Xr fsync 2
after writing messages from the kernel.
Other messages are not synced explcitly.
You may disable syncing of files specified to receive kernel messages
by prefixing the pathname with a minus sign
.Ql - .
Note that use of this option may cause the loss of log information in
the event of a system crash immediately following the write attempt.
However, using this option may prove to be useful if your system's
kernel is logging many messages.
.Pp
Normally the priority and version is not written to file.
In order to use syslog-sign you may prefix a pathname with the plus sign
.Ql + .
If both switches are used the order has to be
.Ql +- .
.It
A hostname (preceded by an at
.Pq Sq @
sign).
Selected messages are forwarded to the
.Xr syslogd 8
program on the named host with UDP.
.It
A hostname preceded by an at
.Pq Sq @
sign and enclosed in brackets
.Pq Sq []
.
Selected messages are forwarded with TLS to the
.Xr syslogd 8
program on the named host.
After the closing bracket a colon
.Pq Sq \&:
and a port or service name may be appended.
Additional options are configured in parantheses in the form of key="value".
Recognized keywords are
.Ar subject ,
.Ar fingerprint ,
.Ar cert ,
and
.Ar verify .
.It
A comma separated list of users.
Selected messages are written to those users
if they are logged in.
.It
An asterisk.
Selected messages are written to all logged-in users.
.It
A vertical bar
.Pq Sq |
followed by a command to which to pipe the selected messages.
The command string is passed to
.Pa /bin/sh
for evaluation, so the usual shell metacharacters or input/output
redirection can occur.
(Note that redirecting
.Xr stdio 3
buffered output from the invoked command can cause additional delays,
or even lost output data in case a logging subprocess exits with a
signal.)
The command itself runs with
.Em stdout
and
.Em stderr
redirected to
.Pa /dev/null .
Upon receipt of a
.Dv SIGHUP ,
.Xr syslogd 8
will close the pipe to the process.
If the process does not exit voluntarily, it will be sent a
.Dv SIGTERM
signal after a grace period of up to 60 seconds.
.Pp
The command will only be started once data arrives that should be
piped to it.
If the command exits, it will be restarted as necessary.
.Pp
If it is desired that the subprocess should receive exactly one line of
input, this can be achieved by exiting after reading and processing the
single line.
A wrapper script can be used to achieve this effect, if necessary.
Note that this method can be very resource-intensive if many log messages
are being piped through the filter.
.Pp
Unless the command is a full pipeline, it may be useful to
start the command with
.Em exec
so that the invoking shell process does not wait for the command to
complete.
Note that the command is started with the UID of the
.Xr syslogd 8
process, normally the superuser.
.Pp
Just like with files a plus sign
.Ql +
will leave the priority and version information intact.
.El
.Pp
Blank lines and lines whose first non-blank character is a hash
.Pq Sq #
character are ignored.
.Sh "TLS OPTIONS"
Additional options are used for TLS configuration:
.Bl -ohang
.It Em tls_server
Enables TLS server mode.
.It Em tls_bindport
Service name or port number to bind to.
Default is
.Sq syslog .
.Em As long as no official port is assigned this option is required
.Em for TLS servers.
.It Em tls_bindhost
Hostname or IP to bind to.
.It Em tls_gen_cert
Automatically generate a private key and certificate.
.It Em tls_key
File with private key.
Default is
.Sq /etc/openssl/default.key
.It Em tls_cert
File with certificate to use.
Default is
.Sq /etc/openssl/default.crt
.It Em tls_ca
File with CA certificate to use.
.It Em tls_cadir
Directory containing CA certificates.
.It Em tls_verify
If set to
.Sq off
then certificate authentication is skipped.
.It Em tls_allow_fingerprints
List of fingerprints of trusted client certificates.
.It Em tls_allow_clientcerts
List of filenames with trusted client certificates.
.El
.Sh "TLS AUTHENTICATION"
One function of TLS is mutual authentication of client and server.
Unless authentication is disabled by setting
.Sq tls_verify=off
the following rules are used:
.Ss "As client:"
A client can be configured not to check a server's certificate by setting the
parameter
.Ar verify
to
.Sq off .
If the server's certificate is signed by a trusted CA then it is checked
if its hostname or IP is given in its certificate (as a CommonName, as a
DNS SubjectAltName, or as an IP SubjectAltName).
If any match is found then the server is authenticated.
If a
.Ar subject
parameter is given then it is can satisfy this test as well.
This allows DNS-independent configurations using the server's IP address in the
destination and adding its hostname as
.Ar subject
to authenticate the TLS connection without having to add the IP to the X.509
certificate.
.Pp
If no CA is used or no trust path between CA and server certificate exists, then
hash value of the server's certificate is compared with the hash given in
.Ar fingerprint
and the hash of the certificate in
.Ar cert .
If the hashes are equal then the server is authenticated.
.Ss "As server:"
If using a CA and the client's certificate is signed by it then the client is
authenticated.
Otherwise the hash of the client's certificate is compared with the hashes given
in
.Ar tls_allow_fingerprints
and the hashes of the certificates given in
.Ar tls_allow_clientcerts .
On any match the client is authenticated.
.Sh BUFFERING
.Xr syslogd 8
is able to buffer temporary not writeable messages in memory.
To limit the memory consumed for this buffering the following optons may be
given:
.Bl -ohang
.It Em file_queue_length
.It Em pipe_queue_length
.It Em tls_queue_length
The maximum number of messages buffered for one destination of type tls, file,
or pipe respectively.
Defaults are
.Sq 1024 ,
.Sq 1024 ,
and
.Sq -1
(no limit).
.It Em file_queue_size
.It Em pipe_queue_size
.It Em tls_queue_size
The maximum memory usage in bytes of messages buffered for one destination.
Defaults are
.Sq 1M ,
.Sq 1M ,
and
.Sq 16M .
.El
.Sh SIGNING
.Xr syslogd 8
is able to digitally sign all processed messages.
The used protocol is defined by RFC 5848 (syslog-sign):
at the start of a session the signing sender sends so called certificate
blocks containing its public key; after that it periodically sends a signed
message containing hashes of previous messages.
.Pp
To detect later manipulation one has to keep a copy of the key used for
signing (otherwise an attacker could alter the logs and sign them with his
his own key).
If TLS is used with a DSA key then the same key will be used for signing.
This is the recommended setup because it makes it easy to have copies of
the certificate (with the public key) in backups.
Otherwise new keys are generated on every restart and for certain verification
it is necessary to have copies of all used keys.
So logging only to a local file is not secure; at least the used keys should
be logged to another host.
.Bl -ohang
.It Em sign_sg
Enables signing.
Set this option to enable syslog-sign and select how to assign
messages to signature groups (subsets of messages that are signed together).
To enable later signature verification and detection of lost messages the
assignment should be chosen such that all messages of one signature group
are written to the same file.
Four possible values for this option are:
.Bl -hang -offset indent
.It Em 0
Use one global signature group for all messages.
.It Em 1
Use one signature group per priority.
.It Em 2
Use signature groups for ranges of priorities.
.It Em 3
Use one signature group per destination.
This is a custom strategy not defined by the standard.
With this setting one signature group is set up for
every file and network action.
.El
.It Em sign_delim_sg2
This option is only evaluated with
.Sq sign_sg=2
and allows to configure the priority ranges for signature groups.
The parameters are numerical values used as the maximum priority for one group.
The default is to use one signature groups per facility, which is equal to
setting
.Sq sign_delim_sg2=7 15 23 31 39 ... .
.El
.Sh FILES
.Bl -tag -width /etc/syslog.conf -compact
.It Pa /etc/syslog.conf
The
.Xr syslogd 8
configuration file.
.It Pa /usr/share/examples/syslogd/verify.pl
Example script to verify message signatures.
(Requires Perl and modules not part of NetBSD.)
.El
.Sh EXAMPLES
A configuration file might appear as follows:
.Bd -literal
# Log all kernel messages, authentication messages of
# level notice or higher and anything of level err or
# higher to the console.
# Don't log private authentication messages!
*.err;kern.*;auth.notice;authpriv.none /dev/console
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none /var/log/messages
# Log daemon messages at debug level only
daemon.=debug /var/log/daemon.debug
# The authpriv file has restricted access.
# Write logs with priority for later verification with syslog-sign.
authpriv.* +/var/log/secure
# Log all the mail messages in one place.
mail.* /var/log/maillog
# Everybody gets emergency messages, plus log them on another
# machine.
*.emerg *
*.emerg @arpa.berkeley.edu
# Log all messages of level info or higher to another
# machine using TLS with an alternative portname and a
# fingerprint for athentication
*.info @[logserver]:1234(fingerprint="SHA1:01:02:...")
# Root and Eric get alert and higher messages.
*.alert root,eric
# Save mail and news errors of level err and higher in a
# special file.
mail,news.err /var/log/spoolerr
# Pipe all authentication messages to a filter.
auth.* |exec /usr/local/sbin/authfilter
# Log kernel messages to a separate file without syncing each message.
kern.* -/var/log/kernlog
# Save ftpd transactions along with mail and news.
!ftpd
*.* /var/log/spoolerr
# Send all error messages from a RAID array through a filter.
!raid0
kern.err |exec /usr/local/sbin/raidfilter
# Save pppd messages from dialhost to a separate file.
!pppd
+dialhost
*.* /var/log/dialhost-pppd
# Save non-local log messages from all programs to a separate file.
!*
-@
*.* /var/log/foreign
# Generate digital signatures for all messages
# to each file or network destination.
sign_sg=3
.Ed
.Sh SEE ALSO
.Xr syslog 3 ,
.Xr syslogd 8
.Sh HISTORY
The
.Nm
file appeared in
.Bx 4.3 ,
along with
.Xr syslogd 8 .
.Sh BUGS
The effects of multiple selectors are sometimes not intuitive.
For example
.Dq mail.crit;*.err
will select
.Dq mail
facility messages at
the level of
.Dq err
or higher, not at the level of
.Dq crit
or higher.

272
usr.sbin/syslogd/syslogd.8 Normal file
View file

@ -0,0 +1,272 @@
.\" $NetBSD: syslogd.8,v 1.54 2013/01/14 03:05:41 dholland Exp $
.\"
.\" Copyright (c) 1983, 1986, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)syslogd.8 8.1 (Berkeley) 6/6/93
.\"
.Dd March 28, 2012
.Dt SYSLOGD 8
.Os
.Sh NAME
.Nm syslogd
.Nd log systems messages
.Sh SYNOPSIS
.Nm
.Op Fl dnrSsTUv
.Op Fl b Ar bind_address
.Op Fl f Ar config_file
.Op Fl g Ar group
.Op Fl m Ar mark_interval
.Op Fl o Ar output_format
.Op Fl P Ar file_list
.Oo
.Fl p Ar log_socket
.Op Fl p Ar log_socket2 ...
.Oc
.Op Fl t Ar chroot_dir
.Op Fl u Ar user
.Sh DESCRIPTION
.Nm
reads and logs messages to the system console, log files, other
machines and/or users as specified by its configuration file.
The options are as follows:
.Bl -tag -width 15n
.It Fl b Ar bind_address
Specify one specific IP address or hostname to bind to.
If a hostname is specified, the IPv4 or IPv6 address
which corresponds to it is used.
.It Fl d
Enable debugging to the standard output,
and do not disassociate from the controlling terminal.
.It Fl f Ar config_file
Specify the pathname of an alternative configuration file;
the default is
.Pa /etc/syslog.conf .
.It Fl g Ar group
Set GID to
.Ar group
after the sockets and log files have been opened.
.It Fl m Ar mark_interval
Select the number of minutes between ``mark'' messages;
the default is 20 minutes.
.It Fl n
Do not perform hostname lookups; report only numeric addresses.
.It Fl o Ar output_format
Select output message format.
.Bl -hang
.It Em bsd , rfc3164
traditional BSD Syslog format (default)
.It Em syslog , rfc5424
new syslog-protocol format
.El
.It Fl P
Specify the pathname of a file containing a list of sockets to be
created.
The format of the file is simply one socket per line.
.It Fl p Ar log_socket
Specify the pathname of a log socket.
Multiple
.Fl p
options create multiple log sockets.
If no
.Fl p
arguments are given, the default socket of
.Pa /var/run/log
is used.
.It Fl r
Disable the compression of repeated instances of the same line
into a single line of the form
.Dq last message repeated N times .
.It Fl S
Sync kernel messages to disk immediately.
.It Fl s
Select
.Dq secure
mode, in which
.Nm
does not listen on a UDP socket but only communicates over a
.Ux
domain socket.
This is valuable when the machine on
which
.Nm
runs is subject to attack over the network and it is desired
that the machine be protected from attempts to remotely fill logs
and similar attacks.
.It Fl t Ar chroot_dir
.Xr chroot 2
to
.Ar chroot_dir
after the sockets and log files have been opened.
.It Fl T
Always use the local time and date for messages received from the
network, instead of the timestamp field supplied in the message
by the remote host.
This is useful if some of the originating hosts can't keep time
properly or are unable to generate a correct timestamp.
.It Fl u Ar user
Set UID to
.Ar user
after the sockets and log files have been opened.
.It Fl U
Unique priority logging.
Only log messages at the priority specified by the selector in the
configuration file.
Without this option, messages at the specified priority or higher are
logged.
This option changes the default priority comparison from
.Sq \*[Gt]=
to
.Sq = .
.It Fl v
Verbose logging.
If specified once, the numeric facility and priority are logged with
each locally-written message.
If specified more than once, the names of the facility and priority are
logged with each locally-written message.
.El
.Pp
.Nm
reads its configuration file when it starts up and whenever it
receives a hangup signal.
For information on the format of the configuration file,
see
.Xr syslog.conf 5 .
.Pp
.Nm
reads messages from the
.Ux
domain socket
.Pa /var/run/log ,
from an Internet domain socket specified in
.Pa /etc/services ,
and from the special device
.Pa /dev/klog
(to read kernel messages).
.Pp
.Nm
creates the file
.Pa /var/run/syslogd.pid ,
and stores its process
id there.
This can be used to kill or reconfigure
.Nm .
.Pp
By using multiple
.Fl p
options, one can set up many chroot environments by passing the pathname
to the log socket
.Pa ( /var/run/log )
in each chroot area to
.Nm .
For example:
.Dl syslogd -p /var/run/log -p /web/var/run/log -p /ftp/var/run/log
.Pp
Note: the normal log socket must now also be passed to
.Nm .
.Pp
The logged message includes the date, time, and hostname (or pathname of
the log socket).
Commonly, the program name and the process id is included.
.Pp
The date and time are taken from the received message.
If the format of the timestamp field is incorrect, time obtained from
the local host is used instead.
This can be overridden by the
.Fl T
flag.
.Pp
Accesses from UDP socket can be filtered by libwrap configuration files, like
.Pa /etc/hosts.deny .
Specify
.Dq Li syslogd
in
.Ar daemon_list
portion of the configuration files.
Refer to
.Xr hosts_access 5
for details.
.Ss SYSLOG PROTOCOL NOTES
.Nm
accepts messages in traditional BSD Syslog or in newer Syslog Protocol
format.
See RFC 3164 (BSD Syslog) and RFC 5424 (Syslog Protocol) for detailed
description of the message format.
Messages from the local kernel that are not tagged with a priority code
receive the default facility
.Dv LOG_KERN
and priority
.Dv LOG_NOTICE .
All other untagged messages receive the default facility
.Dv LOG_USER
and priority
.Dv LOG_NOTICE .
.Sh FILES
.Bl -tag -width /var/run/syslogd.pid -compact
.It Pa /etc/syslog.conf
The configuration file.
.It Pa /var/run/syslogd.pid
The process id of current
.Nm .
.It Pa /var/run/log
Name of the
.Ux
domain datagram log socket.
.It Pa /dev/klog
The kernel log device.
.El
.Sh SEE ALSO
.Xr logger 1 ,
.Xr syslog 3 ,
.Xr services 5 ,
.Xr syslog.conf 5 ,
.Xr newsyslog 8
.Rs
.%R RFC
.%N 3164
.%D August 2001
.%T The BSD syslog Protocol
.Re
.Rs
.%R RFC
.%N 5424
.%D March 2009
.%T The Syslog Protocol
.Re
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 .
Support for multiple log sockets appeared in
.Nx 1.4 .
libwrap support appeared in
.Nx 1.6 .
Support for RFC 5424, TLS encryption and authentication, signed messages
appeared in
.Nx 6.0 .

4853
usr.sbin/syslogd/syslogd.c Normal file

File diff suppressed because it is too large Load diff

438
usr.sbin/syslogd/syslogd.h Normal file
View file

@ -0,0 +1,438 @@
/* $NetBSD: syslogd.h,v 1.4 2013/05/27 23:15:51 christos Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Schütte.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSLOGD_H_
#define SYSLOGD_H_
/*
* hold common data structures and prototypes
* for syslogd.c and tls.c
*
*/
#include <sys/cdefs.h>
#define MAXLINE 1024 /* maximum line length */
#define MAXSVLINE 120 /* maximum saved line length */
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_NOTICE)
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define TTYMSGTIME 1 /* timeout passed to ttymsg */
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/queue.h>
#include <netinet/in.h>
#include <sys/event.h>
#include <event.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <locale.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <utmp.h>
#ifdef __NetBSD_Version__
#include <util.h>
#include "utmpentry.h"
#endif /* __NetBSD_Version__ */
#ifdef __FreeBSD_version
#include <libutil.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <limits.h>
#endif /* __FreeBSD_version */
#ifndef DISABLE_TLS
#include <netinet/tcp.h>
#include <openssl/ssl.h>
#endif /* !DISABLE_TLS */
#include <sys/stdint.h>
#include <sys/resource.h>
#include "pathnames.h"
#include <sys/syslog.h>
/* some differences between the BSDs */
#ifdef __FreeBSD_version
#undef _PATH_UNIX
#define _PATH_UNIX "kernel"
#define HAVE_STRNDUP 0
#endif /* __FreeBSD_version */
#ifdef __NetBSD_Version__
#define HAVE_STRNDUP 1
#define HAVE_DEHUMANIZE_NUMBER 1
#endif /* __NetBSD_Version__ */
#ifdef __minix
#undef _PATH_UNIX
#define _PATH_UNIX "kernel"
#endif /* __minix */
#ifndef HAVE_DEHUMANIZE_NUMBER /* not in my 4.0-STABLE yet */
extern int dehumanize_number(const char *str, int64_t *size);
#endif /* !HAVE_DEHUMANIZE_NUMBER */
#if !HAVE_STRNDUP
char *strndup(const char *str, size_t n);
#endif /* !HAVE_STRNDUP */
#ifndef __minix
#ifdef LIBWRAP
#include <tcpd.h>
#endif
#endif /* !__minix */
#define FDMASK(fd) (1 << (fd))
#define A_CNT(x) (sizeof((x)) / sizeof((x)[0]))
/* debug messages with categories */
#define D_NONE 0
#define D_CALL 1 /* function calls */
#define D_DATA 2 /* syslog message reading/formatting */
#define D_NET 4 /* sockets/network */
#define D_FILE 8 /* local files */
#define D_TLS 16 /* TLS */
#define D_PARSE 32 /* configuration/parsing */
#define D_EVENT 64 /* libevent */
#define D_BUFFER 128 /* message queues */
#define D_MEM 256 /* malloc/free */
#define D_MEM2 1024 /* every single malloc/free */
#define D_SIGN 2048 /* -sign */
#define D_MISC 4096 /* everything else */
#define D_ALL (D_CALL | D_DATA | D_NET | D_FILE | D_TLS | D_PARSE | \
D_EVENT | D_BUFFER | D_MEM | D_MEM2 | D_SIGN | D_MISC)
#define D_DEFAULT (D_CALL | D_NET | D_FILE | D_TLS | D_MISC)
/* build with -DNDEBUG to remove all assert()s and DPRINTF()s */
#ifdef NDEBUG
#define DPRINTF(x, ...) (void)0
#else
#define DPRINTF(x, ...) /*LINTED null effect */(void)(Debug & (x) \
? (printf("%s:%s:%s:%.4d\t", make_timestamp(NULL, true), \
__FILE__, __func__, __LINE__), printf(__VA_ARGS__)) : 0)
#endif
/* shortcuts for libevent */
#define EVENT_ADD(x) do { \
DPRINTF(D_EVENT, "event_add(%s@%p)\n", #x, x); \
if (event_add(x, NULL) == -1) { \
DPRINTF(D_EVENT, "Failure in event_add()\n"); \
} \
} while (/*CONSTCOND*/0)
#define RETRYEVENT_ADD(x) do { \
struct timeval _tv; \
_tv.tv_sec = 0; \
_tv.tv_usec = TLS_RETRY_EVENT_USEC; \
DPRINTF(D_EVENT, "retryevent_add(%s@%p)\n", #x, x); \
if (event_add(x, &_tv) == -1) { \
DPRINTF(D_EVENT, "Failure in event_add()\n"); \
} \
} while (/*CONSTCOND*/0)
#define DEL_EVENT(x) do { \
DPRINTF(D_MEM2, "DEL_EVENT(%s@%p)\n", #x, x); \
if ((x) && (event_del(x) == -1)) { \
DPRINTF(D_EVENT, "Failure in event_del()\n"); \
} \
} while (/*CONSTCOND*/0)
/* safe calls to free() */
#define FREEPTR(x) if (x) { \
DPRINTF(D_MEM2, "free(%s@%p)\n", #x, x); \
free(x); x = NULL; }
#define FREE_SSL(x) if (x) { \
DPRINTF(D_MEM2, "SSL_free(%s@%p)\n", #x, x); \
SSL_free(x); x = NULL; }
#define FREE_SSL_CTX(x) if (x) { \
DPRINTF(D_MEM2, "SSL_CTX_free(%s@%p)\n", #x, x); \
SSL_CTX_free(x); x = NULL; }
/* reference counting macros for buffers */
#define NEWREF(x) ((x) ? (DPRINTF(D_BUFFER, "inc refcount of " #x \
" @ %p: %zu --> %zu\n", (x), (x)->refcount, \
(x)->refcount + 1), (x)->refcount++, (x))\
: (DPRINTF(D_BUFFER, "inc refcount of NULL!\n"), NULL))
#define DELREF(x) /*LINTED null effect*/(void)((x) ? (DPRINTF(D_BUFFER, "dec refcount of " #x \
" @ %p: %zu --> %zu\n", (x), (x)->refcount, \
(x)->refcount - 1), buf_msg_free(x), NULL) \
: (DPRINTF(D_BUFFER, "dec refcount of NULL!\n"), NULL))
/* assumption:
* - malloc()/calloc() only fails if not enough memory available
* - once init() has set up all global variables etc.
* the bulk of available memory is used for buffers
* and can be freed if necessary
*/
#define MALLOC(ptr, size) do { \
while(!(ptr = malloc(size))) { \
DPRINTF(D_MEM, "Unable to allocate memory"); \
message_allqueues_purge(); \
} \
DPRINTF(D_MEM2, "MALLOC(%s@%p, %zu)\n", #ptr, ptr, size); \
} while (/*CONSTCOND*/0)
#define CALLOC(ptr, size) do { \
while(!(ptr = calloc(1, size))) { \
DPRINTF(D_MEM, "Unable to allocate memory"); \
message_allqueues_purge(); \
} \
DPRINTF(D_MEM2, "CALLOC(%s@%p, %zu)\n", #ptr, ptr, size); \
} while (/*CONSTCOND*/0)
/* define strlen(NULL) to be 0 */
#define SAFEstrlen(x) ((x) ? strlen(x) : 0)
/* shorthand to block/restore signals for the duration of one function */
#define BLOCK_SIGNALS(omask, newmask) do { \
sigemptyset(&newmask); \
sigaddset(&newmask, SIGHUP); \
sigaddset(&newmask, SIGALRM); \
sigprocmask(SIG_BLOCK, &newmask, &omask); \
} while (/*CONSTCOND*/0)
#define RESTORE_SIGNALS(omask) sigprocmask(SIG_SETMASK, &omask, NULL)
/* small optimization to call send_queue() only if queue has elements */
#define SEND_QUEUE(f) do { \
if ((f)->f_qelements) \
send_queue(0, 0, f); \
} while (/*CONSTCOND*/0)
#define MAXUNAMES 20 /* maximum number of user names */
#define BSD_TIMESTAMPLEN 14+1
#define MAX_TIMESTAMPLEN 31+1
/* maximum field lengths in syslog-protocol */
#define PRI_MAX 5
#define HOST_MAX 255
#define APPNAME_MAX 48
#define PROCID_MAX 128
#define MSGID_MAX 32
/* longest possible header length */
#define HEADER_LEN_MAX (PRI_MAX + 1 + 1 + MAX_TIMESTAMPLEN + 1 + HOST_MAX \
+ 1 + APPNAME_MAX + 1 + PROCID_MAX + 1 + MSGID_MAX)
/* allowed number of priorities by IETF standards */
#define IETF_NUM_PRIVALUES 192
/* check if message with fac/sev belogs to a destination f */
#define MATCH_PRI(f, fac, sev) \
( (((f)->f_pcmp[fac] & PRI_EQ) && ((f)->f_pmask[fac] == (sev))) \
||(((f)->f_pcmp[fac] & PRI_LT) && ((f)->f_pmask[fac] < (sev))) \
||(((f)->f_pcmp[fac] & PRI_GT) && ((f)->f_pmask[fac] > (sev))) \
)
/* shorthand to test Byte Order Mark which indicates UTF-8 content */
#define IS_BOM(p) ( \
(p)[0] != '\0' && (unsigned char)(p)[0] == (unsigned char)0xEF && \
(p)[1] != '\0' && (unsigned char)(p)[1] == (unsigned char)0xBB && \
(p)[2] != '\0' && (unsigned char)(p)[2] == (unsigned char)0xBF)
/* message buffer container used for processing, formatting, and queueing */
struct buf_msg {
size_t refcount;
int pri;
int flags;
char *timestamp;
char *recvhost;
char *host;
char *prog;
char *pid;
char *msgid;
char *sd; /* structured data */
char *msg; /* message content */
char *msgorig; /* in case we advance *msg beyond header fields
we still want to free() the original ptr */
size_t msglen; /* strlen(msg) */
size_t msgsize; /* allocated memory size */
size_t tlsprefixlen; /* bytes for the TLS length prefix */
size_t prilen; /* bytes for priority and version */
};
/* queue of messages */
struct buf_queue {
struct buf_msg* msg;
STAILQ_ENTRY(buf_queue) entries;
};
STAILQ_HEAD(buf_queue_head, buf_queue);
/* a pair of a socket and an associated event object */
struct socketEvent {
int fd;
int af;
struct event *ev;
};
/*
* Flags to logmsg().
*/
#define IGN_CONS 0x001 /* don't print on console */
#define SYNC_FILE 0x002 /* do fsync on file after printing */
#define ADDDATE 0x004 /* add a date to the message */
#define MARK 0x008 /* this message is a mark */
#define ISKERNEL 0x010 /* kernel generated message */
#define BSDSYSLOG 0x020 /* line in traditional BSD Syslog format */
#define SIGN_MSG 0x040 /* syslog-sign data, not signed again */
/* strategies for message_queue_purge() */
#define PURGE_OLDEST 1
#define PURGE_BY_PRIORITY 2
/*
* This structure represents the files that will have log
* copies printed.
* We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY,
* or if f_type is F_PIPE and f_pid > 0.
*/
struct filed {
struct filed *f_next; /* next in linked list */
short f_type; /* entry type, see below */
short f_file; /* file descriptor */
time_t f_time; /* time this was last written */
char *f_host; /* host from which to record */
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
u_char f_pcmp[LOG_NFACILITIES+1]; /* compare priority */
#define PRI_LT 0x1
#define PRI_EQ 0x2
#define PRI_GT 0x4
char *f_program; /* program this applies to */
union {
char f_uname[MAXUNAMES][UT_NAMESIZE+1];
struct {
char f_hname[MAXHOSTNAMELEN];
struct addrinfo *f_addr;
} f_forw; /* UDP forwarding address */
#ifndef DISABLE_TLS
struct {
SSL *ssl; /* SSL object */
struct tls_conn_settings *tls_conn; /* certificate info */
} f_tls; /* TLS forwarding address */
#endif /* !DISABLE_TLS */
char f_fname[MAXPATHLEN];
struct {
char f_pname[MAXPATHLEN];
pid_t f_pid;
} f_pipe;
} f_un;
#ifndef DISABLE_SIGN
struct signature_group_t *f_sg; /* one signature group */
#endif /* !DISABLE_SIGN */
struct buf_queue_head f_qhead; /* undelivered msgs queue */
size_t f_qelements; /* elements in queue */
size_t f_qsize; /* size of queue in bytes */
struct buf_msg *f_prevmsg; /* last message logged */
struct event *f_sq_event; /* timer for send_queue() */
int f_prevcount; /* repetition cnt of prevmsg */
int f_repeatcount; /* number of "repeated" msgs */
int f_lasterror; /* last error on writev() */
int f_flags; /* file-specific flags */
#define FFLAG_SYNC 0x01 /* for F_FILE: fsync after every msg */
#define FFLAG_FULL 0x02 /* for F_FILE | F_PIPE: write PRI header */
#define FFLAG_SIGN 0x04 /* for syslog-sign with SG="3":
* sign the messages to this destination */
};
#ifndef DISABLE_TLS
/* linked list for allowed TLS peer credentials
* (one for fingerprint, one for cert-files)
*/
SLIST_HEAD(peer_cred_head, peer_cred);
struct peer_cred {
SLIST_ENTRY(peer_cred) entries;
char *data;
};
/* config options for TLS server-side */
struct tls_global_options_t {
SSL_CTX *global_TLS_CTX;
struct peer_cred_head fprint_head; /* trusted client fingerprints */
struct peer_cred_head cert_head; /* trusted client cert files */
char *keyfile; /* file with private key */
char *certfile; /* file with own certificate */
char *CAfile; /* file with CA certificate */
char *CAdir; /* alternative: path to directory with CA certs */
char *x509verify; /* level of peer verification */
char *bindhost; /* hostname/IP to bind to */
char *bindport; /* port/service to bind to */
char *server; /* if !NULL: do not listen to incoming TLS */
char *gen_cert; /* if !NULL: generate self-signed certificate */
};
/* TLS needs three sets of sockets:
* - listening sockets: a fixed size array TLS_Listen_Set, just like finet for UDP.
* - outgoing connections: managed as part of struct filed.
* - incoming connections: variable sized, thus a linked list TLS_Incoming.
*/
/* every connection has its own input buffer with status
* variables for message reading */
SLIST_HEAD(TLS_Incoming, TLS_Incoming_Conn);
struct TLS_Incoming_Conn {
SLIST_ENTRY(TLS_Incoming_Conn) entries;
struct tls_conn_settings *tls_conn;
int socket;
char *inbuf; /* input buffer */
size_t inbuflen;
size_t cur_msg_len; /* length of current msg */
size_t cur_msg_start; /* beginning of current msg */
size_t read_pos; /* ring buffer position to write to */
size_t errorcount; /* to close faulty connections */
bool closenow; /* close connection as soon as buffer processed */
bool dontsave; /* for receiving oversized messages w/o saving them */
};
#endif /* !DISABLE_TLS */
#endif /*SYSLOGD_H_*/

2188
usr.sbin/syslogd/tls.c Normal file

File diff suppressed because it is too large Load diff

196
usr.sbin/syslogd/tls.h Normal file
View file

@ -0,0 +1,196 @@
/* $NetBSD: tls.h,v 1.2 2008/11/07 07:36:38 minskim Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Martin Schütte.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* tls.h
*
*/
#ifndef _TLS_H
#define _TLS_H
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
/* initial size for TLS inbuf, minimum prefix + linelength
* guaranteed to be accepted */
#define TLS_MIN_LINELENGTH (2048 + 5)
/* usually the inbuf is enlarged as needed and then kept.
* if bigger than TLS_PERSIST_LINELENGTH, then shrink
* to TLS_LARGE_LINELENGTH immediately */
#define TLS_LARGE_LINELENGTH 8192
#define TLS_PERSIST_LINELENGTH 32768
/* timeout to call non-blocking TLS operations again */
#define TLS_RETRY_EVENT_USEC 20000
/* reconnect to lost server after n sec (initial value) */
#define TLS_RECONNECT_SEC 10
/* backoff connection attempts */
#define TLS_RECONNECT_BACKOFF_FACTOR 15/10
#define TLS_RECONNECT_BACKOFF(x) (x) = (x) * TLS_RECONNECT_BACKOFF_FACTOR
/* abandon connection attempts after n sec
* This has to be <= 5h (with 10sec initial interval),
* otherwise a daily SIGHUP from newsylog will reset
* all timers and the giveup time will never be reached
*
* set here: 2h, reached after ca. 7h of reconnecting
*/
#define TLS_RECONNECT_GIVEUP 60*60*2
/* default algorithm for certificate fingerprints */
#define DEFAULT_FINGERPRINT_ALG "sha-1"
/* default X.509 files */
#define DEFAULT_X509_CERTFILE "/etc/openssl/default.crt"
#define DEFAULT_X509_KEYFILE "/etc/openssl/default.key"
/* options for peer certificate verification */
#define X509VERIFY_ALWAYS 0
#define X509VERIFY_IFPRESENT 1
#define X509VERIFY_NONE 2
/* attributes for self-generated keys/certificates */
#define TLS_GENCERT_BITS 1024
#define TLS_GENCERT_SERIAL 1
#define TLS_GENCERT_DAYS 5*365
/* TLS connection states */
#define ST_NONE 0
#define ST_TLS_EST 1
#define ST_TCP_EST 2
#define ST_CONNECTING 3
#define ST_ACCEPTING 4
#define ST_READING 5
#define ST_WRITING 6
#define ST_EOF 7
#define ST_CLOSING0 8
#define ST_CLOSING1 9
#define ST_CLOSING2 10
/* backlog for listen */
#define TLSBACKLOG 4
/* close TLS connection after multiple 'soft' errors */
#define TLS_MAXERRORCOUNT 4
/*
* holds TLS related settings for one connection to be
* included in the SSL object and available in callbacks
*
* Many fields have a slightly different semantic for
* incoming and outgoing connections:
* - for outgoing connections it contains the values from syslog.conf and
* the server's cert is checked against these values by check_peer_cert()
* - for incoming connections it is not used for checking, instead
* dispatch_tls_accept() fills in the connected hostname/port and
* check_peer_cert() fills in subject and fingerprint from the peer cert
*/
struct tls_conn_settings {
unsigned send_queue:1, /* currently sending buffer */
errorcount:4, /* counter [0;TLS_MAXERRORCOUNT] */
accepted:1, /* workaround cf. check_peer_cert*/
shutdown:1, /* fast connection close on exit */
x509verify:2, /* kind of validation needed */
incoming:1, /* set if we are server */
state:4; /* outgoing connection state */
struct event *event; /* event for read/write activity */
struct event *retryevent; /* event for retries */
SSL *sslptr; /* active SSL object */
char *hostname; /* hostname or IP we connect to */
char *port; /* service name or port number */
char *subject; /* configured hostname in cert */
char *fingerprint; /* fingerprint of peer cert */
char *certfile; /* filename of peer cert */
unsigned reconnect; /* seconds between reconnects */
};
/* argument struct only used for tls_send() */
struct tls_send_msg {
struct filed *f;
struct buf_queue *qentry;
char *line; /* formatted message */
size_t linelen;
size_t offset; /* in case of partial writes */
};
/* return values for TLS_examine_error() */
#define TLS_OK 0 /* no real problem, just ignore */
#define TLS_RETRY_READ 1 /* just retry, non-blocking operation not finished yet */
#define TLS_RETRY_WRITE 2 /* just retry, non-blocking operation not finished yet */
#define TLS_TEMP_ERROR 4 /* recoverable error condition, but try again */
#define TLS_PERM_ERROR 8 /* non-recoverable error condition, closed TLS and socket */
/* global TLS setup and utility */
char *init_global_TLS_CTX(void);
struct socketEvent *socksetup_tls(const int, const char *, const char *);
int check_peer_cert(int, X509_STORE_CTX *);
int accept_cert(const char* , struct tls_conn_settings *, char *, char *);
int deny_cert(struct tls_conn_settings *, char *, char *);
bool read_certfile(X509 **, const char *);
bool write_x509files(EVP_PKEY *, X509 *, const char *, const char *);
bool mk_x509_cert(X509 **, EVP_PKEY **, int, int, int);
bool x509_cert_add_subjectAltName(X509 *, X509V3_CTX *);
int tls_examine_error(const char *, const SSL *, struct tls_conn_settings *, const int);
bool get_fingerprint(const X509 *, char **, const char *);
bool get_commonname(X509 *, char **);
bool match_hostnames(X509 *, const char *, const char *);
bool match_fingerprint(const X509 *, const char *);
bool match_certfile(const X509 *, const char *);
/* configuration & parsing */
bool parse_tls_destination(const char *, struct filed *, size_t);
/* event callbacks */
void dispatch_socket_accept(int, short, void *);
void dispatch_tls_accept(int, short, void *);
void dispatch_tls_read(int, short, void *);
void dispatch_tls_send(int, short, void *);
void dispatch_tls_eof(int, short, void *);
void dispatch_SSL_connect(int, short, void *);
void dispatch_SSL_shutdown(int, short, void *);
void dispatch_force_tls_reconnect(int, short, void *);
bool tls_connect(struct tls_conn_settings *);
void tls_reconnect(int, short, void *);
bool tls_send(struct filed *, char *, size_t, struct buf_queue*);
void tls_split_messages(struct TLS_Incoming_Conn *);
void free_tls_conn(struct tls_conn_settings *);
void free_tls_sslptr(struct tls_conn_settings *);
void free_tls_send_msg(struct tls_send_msg *);
#endif /* !_TLS_H */