On Wed, 2022-01-26 at 09:18 -0700, Theo de Raadt wrote:
> > However, as things stand interpretation can be broken with the base
> > tools. I can't fix garbage input.
> 
> Your proposal builds a mechanism which encourages making decisions based
> upon parsing garbage input.

So let's just focus on my original diff and let that one stand on its
own.

Say I have a sender with the following line:
sender$ tail -2 /etc/syslog.conf
!doas
*.*                                                     @100.64.2.2

and a receiver with:
receiver$ tail -6 /etc/syslog.conf 
+100.64.2.3
!doas
*.*                                                     /tmp/prog_doas

!sender
*.*                                                     /tmp/prog_sender

receiver runs syslogd with -U100.64.2.2

When running syslogd on sender without any flags and doing a simple
`doas ls`:
receiver$ tail /tmp/prog_*
==> /tmp/prog_doas <==
Jan 30 15:03:51 100.64.2.3 doas: martijn ran command ls as root from 
/home/martijn

==> /tmp/prog_sender <==
receiver$ 

When running syslogd on sender with -h and doing a simple `doas ls`:
receiver$ tail /tmp/prog_*
==> /tmp/prog_doas <==

==> /tmp/prog_sender <==
Jan 30 15:08:08 100.64.2.3 sender doas: martijn ran command ls as root from 
/home/martijn
receiver$ 

With my diff applied and without -h:
receiver$ tail /tmp/prog_*
==> /tmp/prog_doas <==
Jan 30 15:11:55 100.64.2.3 doas: martijn ran command ls as root from 
/home/martijn

==> /tmp/prog_sender <==
receiver$ 

With my diff applied and with -h:
receiver$ tail /tmp/prog_*
==> /tmp/prog_doas <==
Jan 30 15:12:47 100.64.2.3 doas: martijn ran command ls as root from 
/home/martijn

==> /tmp/prog_sender <==
receiver$ 

So no new mechanism is introduced, but I am trying to make sure that
existing mechanisms work more consistent with what we already offer
out of the box in base.

martijn@

Index: parsemsg.c
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/parsemsg.c,v
retrieving revision 1.1
diff -u -p -r1.1 parsemsg.c
--- parsemsg.c  13 Jan 2022 10:34:07 -0000      1.1
+++ parsemsg.c  30 Jan 2022 14:20:36 -0000
@@ -17,8 +17,14 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
 #include <ctype.h>
 #include <limits.h>
+#include <resolv.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -29,27 +35,42 @@
 
 size_t parsemsg_timestamp_bsd(const char *, char *);
 size_t parsemsg_timestamp_v1(const char *, char *);
+size_t parsemsg_hostname(const char *, char *);
 size_t parsemsg_prog(const char *, char *);
 
 struct msg *
 parsemsg(const char *msgstr, struct msg *msg)
 {
-       size_t n;
+       size_t timelen, proglen;
+       const char *hostname;
 
        msg->m_pri = -1;
        msgstr += parsemsg_priority(msgstr, &msg->m_pri);
        if (msg->m_pri &~ (LOG_FACMASK|LOG_PRIMASK))
                msg->m_pri = -1;
 
-       if ((n = parsemsg_timestamp_bsd(msgstr, msg->m_timestamp)) == 0)
-               n = parsemsg_timestamp_v1(msgstr, msg->m_timestamp);
-       msgstr += n;
+       if ((timelen = parsemsg_timestamp_bsd(msgstr, msg->m_timestamp)) == 0)
+               timelen = parsemsg_timestamp_v1(msgstr, msg->m_timestamp);
+       msgstr += timelen;
 
-       while (isspace(msgstr[0]))
+       while (isspace((unsigned char)msgstr[0]))
                msgstr++;
 
-       parsemsg_prog(msgstr, msg->m_prog);
+       hostname = msgstr;
+       msgstr += parsemsg_hostname(msgstr, msg->m_hostname);
+ 
+       while (isspace((unsigned char)msgstr[0]))
+               msgstr++;
 
+       proglen = parsemsg_prog(msgstr, msg->m_prog);
+
+       /*
+        * Without timestamp and tag, assume hostname as part of message.
+        */
+       if (!timelen && !proglen) {
+               msg->m_hostname[0] = '\0';
+               msgstr = hostname;
+       }
        strlcpy(msg->m_msg, msgstr, sizeof(msg->m_msg));
 
        return msg;
@@ -169,6 +190,47 @@ parsemsg_timestamp_v1(const char *msgstr
        return msg - msgstr;
 }
 
+/*
+ * Parse the ip address or hostname according to inet_pton and res_hnok and
+ * return the length of the hostname including the trailing space if available.
+ */
+size_t
+parsemsg_hostname(const char *msgstr, char *hostname)
+{
+       size_t len;
+       struct in_addr buf4;
+       struct in6_addr buf6;
+
+       if (msgstr[0] == '-' && (msgstr[1] == ' ' || msgstr[1] == '\0')) {
+               hostname[0] = '\0';
+               if (msgstr[1] == '\0')
+                       return 1;
+               return 2;
+       }
+
+       if ((len = strcspn(msgstr, " ")) > HOST_NAME_MAX)
+               return 0;
+       strlcpy(hostname, msgstr, len + 1);
+       if (msgstr[len] == ' ')
+               len++;
+
+       if (inet_pton(AF_INET, hostname, &buf4) == 1 ||
+           inet_pton(AF_INET6, hostname, &buf6) == 1) {
+               return len;
+       }
+
+       if (res_hnok(hostname) == 0) {
+               hostname[0] = '\0';
+               return 0;
+       }
+       return len;
+}
+
+/*
+ * Parse a program name of the form [[:alnum:]-._]{1,255}
+ * and which ends in [:[].
+ * It return the length of the tag up to the closing symbol.
+ */
 size_t
 parsemsg_prog(const char *msg, char *prog)
 {
@@ -179,6 +241,10 @@ parsemsg_prog(const char *msg, char *pro
                    msg[i] != '-' && msg[i] != '.' && msg[i] != '_')
                        break;
                prog[i] = msg[i];
+       }
+       if (msg[i] != ':' && msg[i] != '[') {
+               prog[0] = '\0';
+               return 0;
        }
        prog[i] = '\0';
 
Index: parsemsg.h
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/parsemsg.h,v
retrieving revision 1.1
diff -u -p -r1.1 parsemsg.h
--- parsemsg.h  13 Jan 2022 10:34:07 -0000      1.1
+++ parsemsg.h  30 Jan 2022 14:20:36 -0000
@@ -25,6 +25,7 @@
 struct msg {
        int             m_pri;
        char            m_timestamp[33];
+       char            m_hostname[HOST_NAME_MAX + 1];
        char            m_prog[NAME_MAX + 1];
        char            m_msg[LOG_MAXLINE + 1];
 };

Reply via email to