From owner-svn-src-head@freebsd.org Tue Dec 5 19:54:56 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9BB6CE7675A; Tue, 5 Dec 2017 19:54:56 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 527416BE38; Tue, 5 Dec 2017 19:54:56 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vB5Jst1U079841; Tue, 5 Dec 2017 19:54:55 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vB5JstQS079839; Tue, 5 Dec 2017 19:54:55 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <201712051954.vB5JstQS079839@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Tue, 5 Dec 2017 19:54:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326573 - head/usr.sbin/syslogd X-SVN-Group: head X-SVN-Commit-Author: glebius X-SVN-Commit-Paths: head/usr.sbin/syslogd X-SVN-Commit-Revision: 326573 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Dec 2017 19:54:56 -0000 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 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; }