Skip site navigation (1)Skip section navigation (2)
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>