Date: Tue, 5 Dec 2017 19:54:55 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326573 - head/usr.sbin/syslogd Message-ID: <201712051954.vB5JstQS079839@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Tue Dec 5 19:54:55 2017 New Revision: 326573 URL: https://svnweb.freebsd.org/changeset/base/326573 Log: When parsing remote messages, require them to have standard timestamp field, and support properly parse out the hostname as described by RFC3164, which wasn't done before. However, don't discard message if it doesn't have hostname, for compatibility. Enable logging of the message supplied hostname instead of real hostname with -H switch. PR: 200933 Reported by: Konstantin Pavlov <thresh nginx.com> MFC after: 2 months Modified: head/usr.sbin/syslogd/syslogd.8 head/usr.sbin/syslogd/syslogd.c Modified: head/usr.sbin/syslogd/syslogd.8 ============================================================================== --- head/usr.sbin/syslogd/syslogd.8 Tue Dec 5 18:48:58 2017 (r326572) +++ head/usr.sbin/syslogd/syslogd.8 Tue Dec 5 19:54:55 2017 (r326573) @@ -28,7 +28,7 @@ .\" @(#)syslogd.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd March 3, 2017 +.Dd November 28, 2017 .Dt SYSLOGD 8 .Os .Sh NAME @@ -36,7 +36,7 @@ .Nd log systems messages .Sh SYNOPSIS .Nm -.Op Fl 468ACcdFkNnosTuv +.Op Fl 468ACcdFHkNnosTuv .Op Fl a Ar allowed_peer .Op Fl b Ar bind_address .Op Fl f Ar config_file @@ -229,6 +229,9 @@ and to run .Nm , and wants to monitor when and how it exits. +.It Fl H +When logging remote messages use hostname from the message (if supplied) +instead of using address from which the message was received. .It Fl k Disable the translation of messages received with facility Modified: head/usr.sbin/syslogd/syslogd.c ============================================================================== --- head/usr.sbin/syslogd/syslogd.c Tue Dec 5 18:48:58 2017 (r326572) +++ head/usr.sbin/syslogd/syslogd.c Tue Dec 5 19:54:55 2017 (r326573) @@ -173,7 +173,6 @@ static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INI #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 */ @@ -324,6 +323,7 @@ static int logflags = O_WRONLY|O_APPEND; /* flags used static char bootfile[MAXLINE+1]; /* booted kernel file */ static int RemoteAddDate; /* Always set the date on remote messages */ +static int RemoteHostname; /* Log remote hostname from the message */ static int UniquePriority; /* Only log specified priority? */ static int LogFacPri; /* Put facility and priority in log message: */ @@ -352,7 +352,7 @@ static void domark(int); static void fprintlog(struct filed *, int, const char *); static void init(int); static void logerror(const char *); -static void logmsg(int, const char *, const char *, int); +static void logmsg(int, const char *, const char *, const char *, int); static void log_deadchild(pid_t, int, const char *); static void markit(void); static int socksetup(struct peer *); @@ -361,7 +361,7 @@ static int socklist_recv_sock(struct socklist *); static int socklist_recv_signal(struct socklist *); static void sighandler(int); static int skip_message(const char *, const char *, int); -static void printline(const char *, char *, int); +static void parsemsg(const char *, char *); static void printsys(char *); static int p_open(const char *, pid_t *); static void reapchild(int); @@ -454,7 +454,7 @@ main(int argc, char *argv[]) if (madvise(NULL, 0, MADV_PROTECT) != 0) dprintf("madvise() failed: %s\n", strerror(errno)); - while ((ch = getopt(argc, argv, "468Aa:b:cCdf:Fkl:m:nNop:P:sS:Tuv")) + while ((ch = getopt(argc, argv, "468Aa:b:cCdf:FHkl:m:nNop:P:sS:Tuv")) != -1) switch (ch) { #ifdef INET @@ -518,6 +518,9 @@ main(int argc, char *argv[]) case 'F': /* run in foreground instead of daemon */ Foreground++; break; + case 'H': + RemoteHostname = 1; + break; case 'k': /* keep remote kern fac */ KeepKernFac = 1; break; @@ -772,7 +775,7 @@ socklist_recv_sock(struct socklist *sl) socklen_t sslen; const char *hname; char line[MAXLINE + 1]; - int date, len; + int len; sslen = sizeof(ss); len = recvfrom(sl->sl_socket, line, sizeof(line) - 1, 0, sa, &sslen); @@ -786,19 +789,17 @@ socklist_recv_sock(struct socklist *sl) } /* Received valid data. */ line[len] = '\0'; - if (sl->sl_ss.ss_family == AF_LOCAL) { + if (sl->sl_ss.ss_family == AF_LOCAL) hname = LocalHostName; - date = 0; - } else { + else { hname = cvthname(sa); unmapped(sa); if (validate(sa, hname) == 0) { dprintf("Message from %s was ignored.", hname); return (-1); } - date = RemoteAddDate ? ADDDATE : 0; } - printline(hname, line, date); + parsemsg(hname, line); return (0); } @@ -836,7 +837,7 @@ usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", - "usage: syslogd [-468ACcdFknosTuv] [-a allowed_peer]", + "usage: syslogd [-468ACcdFHknosTuv] [-a allowed_peer]", " [-b bind_address] [-f config_file]", " [-l [mode:]path] [-m mark_interval]", " [-P pid_file] [-p log_socket]", @@ -845,28 +846,43 @@ usage(void) } /* - * Take a raw input line, decode the message, and print the message - * on the appropriate log files. + * Take a raw input line, extract PRI, TIMESTAMP and HOSTNAME from the message, + * and print the message on the appropriate log files. */ static void -printline(const char *hname, char *msg, int flags) +parsemsg(const char *from, char *msg) { - char *p, *q; + const char *timestamp; + char *q; long n; - int c, pri; + int i, c, pri, msglen; char line[MAXLINE + 1]; - /* test for special codes */ - p = msg; - pri = DEFUPRI; - if (*p == '<') { - errno = 0; - n = strtol(p + 1, &q, 10); - if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { - p = q + 1; - pri = n; + /* Parse PRI. */ + if (msg[0] != '<' || !isdigit(msg[1])) { + dprintf("Invalid PRI from %s\n", from); + return; + } + for (i = 2; i <= 4; i++) { + if (msg[i] == '>') + break; + if (!isdigit(msg[i])) { + dprintf("Invalid PRI header from %s\n", from); + return; } } + if (msg[i] != '>') { + dprintf("Invalid PRI header from %s\n", from); + return; + } + errno = 0; + n = strtol(msg + 1, &q, 10); + if (errno != 0 || *q != msg[i] || n < 0 || n >= INT_MAX) { + dprintf("Invalid PRI %ld from %s: %s\n", + n, from, strerror(errno)); + return; + } + pri = n; if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFUPRI; @@ -878,9 +894,53 @@ printline(const char *hname, char *msg, int flags) if ((pri & LOG_FACMASK) == LOG_KERN && !KeepKernFac) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); - q = line; + /* + * The TIMESTAMP field is the local time and is in the format of + * "Mmm dd hh:mm:ss" (without the quote marks). + * A single space character MUST follow the TIMESTAMP field. + * + * XXXGL: the check can be improved. + */ + msg += i + 1; + msglen = strlen(msg); + if (msglen < MAXDATELEN || msg[3] != ' ' || msg[6] != ' ' || + msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') { + dprintf("Invalid TIMESTAMP from %s: %s\n", from, msg); + return; + } - while ((c = (unsigned char)*p++) != '\0' && + if (!RemoteAddDate) + timestamp = msg; + else + timestamp = NULL; + msg += MAXDATELEN; + msglen -= MAXDATELEN; + + /* + * A single space character MUST also follow the HOSTNAME field. + */ + for (i = 0; i < MIN(MAXHOSTNAMELEN, msglen); i++) { + if (msg[i] == ' ') { + if (RemoteHostname) { + msg[i] = '\0'; + from = msg; + } + msg += i + 1; + break; + } + /* + * Support non RFC compliant messages, without hostname. + */ + if (msg[i] == ':') + break; + } + if (i == MIN(MAXHOSTNAMELEN, msglen)) { + dprintf("Invalid HOSTNAME from %s: %s\n", from, msg); + return; + } + + q = line; + while ((c = (unsigned char)*msg++) != '\0' && q < &line[sizeof(line) - 4]) { if (mask_C1 && (c & 0x80) && c < 0xA0) { c &= 0x7F; @@ -902,7 +962,7 @@ printline(const char *hname, char *msg, int flags) } *q = '\0'; - logmsg(pri, line, hname, flags); + logmsg(pri, timestamp, line, from, 0); } /* @@ -956,7 +1016,7 @@ printsys(char *msg) long n; int flags, isprintf, pri; - flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */ + flags = ISKERNEL | SYNC_FILE; /* fsync after write */ p = msg; pri = DEFSPRI; isprintf = 1; @@ -977,7 +1037,7 @@ printsys(char *msg) flags |= IGN_CONS; if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFSPRI; - logmsg(pri, p, LocalHostName, flags); + logmsg(pri, NULL, p, LocalHostName, flags); } static time_t now; @@ -1032,40 +1092,21 @@ skip_message(const char *name, const char *spec, int c * the priority. */ static void -logmsg(int pri, const char *msg, const char *from, int flags) +logmsg(int pri, const char *timestamp, const char *msg, const char *from, + int flags) { struct filed *f; int i, fac, msglen, prilev; - const char *timestamp; char prog[NAME_MAX+1]; char buf[MAXLINE+1]; dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg); - /* - * Check to see if msg looks non-standard. - */ - msglen = strlen(msg); - if (msglen < MAXDATELEN || msg[3] != ' ' || msg[6] != ' ' || - msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') - flags |= ADDDATE; - (void)time(&now); - if (flags & ADDDATE) { + if (timestamp == NULL) timestamp = ctime(&now) + 4; - } else { - timestamp = msg; - msg += MAXDATELEN; - msglen -= MAXDATELEN; - } - /* skip leading blanks */ - while (isspace(*msg)) { - msg++; - msglen--; - } - /* extract facility and priority level */ if (flags & MARK) fac = LOG_NFACILITIES; @@ -1078,7 +1119,7 @@ logmsg(int pri, const char *msg, const char *from, int prilev = LOG_PRI(pri); - /* extract program name */ + /* Extract TAG part of the message (usually program name). */ for (i = 0; i < NAME_MAX; i++) { if (!isprint(msg[i]) || msg[i] == ':' || msg[i] == '[' || msg[i] == '/' || isspace(msg[i])) @@ -1092,8 +1133,8 @@ logmsg(int pri, const char *msg, const char *from, int snprintf(buf, sizeof(buf), "%s: %s", use_bootfile ? bootfile : "kernel", msg); msg = buf; - msglen = strlen(buf); } + msglen = strlen(msg); /* log the message to the particular outputs */ if (!Initialized) { @@ -1643,7 +1684,7 @@ logerror(const char *type) (void)snprintf(buf, sizeof buf, "syslogd: %s", type); errno = 0; dprintf("%s\n", buf); - logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); + logmsg(LOG_SYSLOG|LOG_ERR, NULL, buf, LocalHostName, 0); recursed--; } @@ -1987,7 +2028,7 @@ init(int signo) } } - logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); + logmsg(LOG_SYSLOG|LOG_INFO, NULL, "syslogd: restart", LocalHostName, 0); dprintf("syslogd: restarted\n"); /* * Log a change in hostname, but only on a restart. @@ -1996,7 +2037,7 @@ init(int signo) (void)snprintf(hostMsg, sizeof(hostMsg), "syslogd: hostname changed, \"%s\" to \"%s\"", oldLocalHostName, LocalHostName); - logmsg(LOG_SYSLOG|LOG_INFO, hostMsg, LocalHostName, ADDDATE); + logmsg(LOG_SYSLOG|LOG_INFO, NULL, hostMsg, LocalHostName, 0); dprintf("%s\n", hostMsg); } /* @@ -2006,7 +2047,7 @@ init(int signo) if (signo == 0 && !use_bootfile) { (void)snprintf(bootfileMsg, sizeof(bootfileMsg), "syslogd: kernel boot file is %s", bootfile); - logmsg(LOG_KERN|LOG_INFO, bootfileMsg, LocalHostName, ADDDATE); + logmsg(LOG_KERN|LOG_INFO, NULL, bootfileMsg, LocalHostName, 0); dprintf("%s\n", bootfileMsg); } } @@ -2315,8 +2356,7 @@ markit(void) now = time((time_t *)NULL); MarkSeq += TIMERINTVL; if (MarkSeq >= MarkInterval) { - logmsg(LOG_INFO, "-- MARK --", - LocalHostName, ADDDATE|MARK); + logmsg(LOG_INFO, NULL, "-- MARK --", LocalHostName, MARK); MarkSeq = 0; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712051954.vB5JstQS079839>