OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
Re: syslogd ipv6 loghost

From: Alexander Bluhm (alexander.bluhmgmx.net)
Date: Wed Aug 20 2014 - 17:47:00 CDT


On Tue, Aug 19, 2014 at 01:59:42AM +0200, Alexander Bluhm wrote:
> I will split this diff into smaller parts to make review and
> discussion easier.

Parse loghost in a separate function. Allow [] around hostname,
needed for IPv6 addresses. Print full loghost specifier in case
of error or debug. Make string sizes more precise.

ok?

bluhm

Index: usr.sbin/syslogd/privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/privsep.c,v
retrieving revision 1.38
diff -u -p -r1.38 privsep.c
--- usr.sbin/syslogd/privsep.c 20 Aug 2014 20:10:17 -0000 1.38
+++ usr.sbin/syslogd/privsep.c 20 Aug 2014 22:34:24 -0000
-103,7 +103,7 priv_init(char *conf, int numeric, int l
         int i, fd, socks[2], cmd, addr_len, result, restart;
         size_t path_len, hostname_len, servname_len;
         char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN];
- char servname[MAXHOSTNAMELEN];
+ char servname[NI_MAXSERV];
         struct sockaddr_storage addr;
         struct stat cf_stat;
         struct passwd *pw;
-662,7 +662,7 int
 priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr,
     size_t addr_len)
 {
- char hostcpy[MAXHOSTNAMELEN], servcpy[MAXHOSTNAMELEN];
+ char hostcpy[MAXHOSTNAMELEN], servcpy[NI_MAXSERV];
         int cmd, ret_len;
         size_t hostname_len, servname_len;
 
Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.114
diff -u -p -r1.114 syslogd.c
--- usr.sbin/syslogd/syslogd.c 20 Aug 2014 20:10:17 -0000 1.114
+++ usr.sbin/syslogd/syslogd.c 20 Aug 2014 22:34:24 -0000
-127,7 +127,8 struct filed {
         union {
                 char f_uname[MAXUNAMES][UT_NAMESIZE+1];
                 struct {
- char f_hname[MAXHOSTNAMELEN];
+ char f_loghost[1+2+MAXHOSTNAMELEN+1+NI_MAXSERV];
+ /* [hostname]:servname */
                         struct sockaddr_storage f_addr;
                 } f_forw; /* forwarding address */
                 char f_fname[MAXPATHLEN];
-268,6 +269,7 void reapchild(int);
 char *ttymsg(struct iovec *, int, char *, int);
 void usage(void);
 void wallmsg(struct filed *, struct iovec *);
+int loghost(char *, char **, char **);
 int getmsgbufsize(void);
 int unix_socket(char *, int, mode_t);
 void double_rbuf(int);
-905,7 +907,7 fprintlog(struct filed *f, int flags, ch
                 break;
 
         case F_FORW:
- dprintf(" %s\n", f->f_un.f_forw.f_hname);
+ dprintf(" %s\n", f->f_un.f_forw.f_loghost);
                 if ((l = snprintf(line, sizeof(line), "<%d>%.15s %s%s%s",
                     f->f_prevpri, (char *)iov[0].iov_base,
                     IncludeHostname ? LocalHostName : "",
-1349,7 +1351,7 init(void)
                                 break;
 
                         case F_FORW:
- printf("%s", f->f_un.f_forw.f_hname);
+ printf("%s", f->f_un.f_forw.f_loghost);
                                 break;
 
                         case F_USERS:
-1411,7 +1413,7 cfline(char *line, char *prog)
 {
         int i, pri;
         size_t rb_len;
- char *bp, *p, *q, *cp;
+ char *bp, *p, *q, *host, *port;
         char buf[MAXLINE], ebuf[100];
         struct filed *xf, *f, *d;
 
-1510,21 +1512,26 cfline(char *line, char *prog)
         case '':
                 if (!InetInuse)
                         break;
- if ((cp = strrchr(++p, ':')) != NULL)
- *cp++ = '\0';
- if ((strlcpy(f->f_un.f_forw.f_hname, p,
- sizeof(f->f_un.f_forw.f_hname)) >=
- sizeof(f->f_un.f_forw.f_hname))) {
- snprintf(ebuf, sizeof(ebuf), "hostname too long \"%s\"",
+ if ((strlcpy(f->f_un.f_forw.f_loghost, p,
+ sizeof(f->f_un.f_forw.f_loghost)) >=
+ sizeof(f->f_un.f_forw.f_loghost))) {
+ snprintf(ebuf, sizeof(ebuf), "loghost too long \"%s\"",
                             p);
                         logerror(ebuf);
                         break;
                 }
- if (priv_getaddrinfo(f->f_un.f_forw.f_hname,
- cp == NULL ? "syslog" : cp,
- (struct sockaddr *)&f->f_un.f_forw.f_addr,
+ if (loghost(++p, &host, &port) == -1) {
+ snprintf(ebuf, sizeof(ebuf), "bad loghost \"%s\"",
+ f->f_un.f_forw.f_loghost);
+ logerror(ebuf);
+ break;
+ }
+ if (priv_getaddrinfo(host,
+ port == NULL ? "syslog" : port,
+ (struct sockaddr*)&f->f_un.f_forw.f_addr,
                     sizeof(f->f_un.f_forw.f_addr)) != 0) {
- snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"", p);
+ snprintf(ebuf, sizeof(ebuf), "bad hostname \"%s\"",
+ f->f_un.f_forw.f_loghost);
                         logerror(ebuf);
                         break;
                 }
-1633,6 +1640,26 cfline(char *line, char *prog)
         return (f);
 }
 
+/*
+ * Parse the host and port parts from a loghost string.
+ */
+int
+loghost(char *str, char **host, char **port)
+{
+ *host = str;
+ if (**host == '[') {
+ (*host)++;
+ str = strchr(*host, ']');
+ if (str == NULL)
+ return (-1);
+ *str++ = '\0';
+ }
+ *port = strrchr(str, ':');
+ if (*port != NULL)
+ *(*port)++ = '\0';
+
+ return (0);
+}
 
 /*
  * Retrieve the size of the kernel message buffer, via sysctl.