diff options
author | 2014-08-25 18:19:18 +0000 | |
---|---|---|
committer | 2014-08-25 18:19:18 +0000 | |
commit | ad087aa9ef1f5a4c75f5d4df1ab118d45ff93129 (patch) | |
tree | 16116b84e77ae42664113c3946787b41cbbff6a3 | |
parent | Fix the gcc compiler warnings "comparison between signed and (diff) | |
download | wireguard-openbsd-ad087aa9ef1f5a4c75f5d4df1ab118d45ff93129.tar.xz wireguard-openbsd-ad087aa9ef1f5a4c75f5d4df1ab118d45ff93129.zip |
Allow to restrict syslogd to a protocol family with -4 and -6 command
line switches. If the log server is an FQDN, DNS chooses wether
to take the IPv4 or IPv6 route. Allow to prefix the log host with
udp4:// or udp6:// to choose a protocol.
OK henning@
-rw-r--r-- | usr.sbin/syslogd/privsep.c | 41 | ||||
-rw-r--r-- | usr.sbin/syslogd/syslogd.c | 68 | ||||
-rw-r--r-- | usr.sbin/syslogd/syslogd.h | 4 |
3 files changed, 91 insertions, 22 deletions
diff --git a/usr.sbin/syslogd/privsep.c b/usr.sbin/syslogd/privsep.c index 8b5da6562b1..783d2f20df7 100644 --- a/usr.sbin/syslogd/privsep.c +++ b/usr.sbin/syslogd/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.41 2014/08/25 18:05:30 bluhm Exp $ */ +/* $OpenBSD: privsep.c,v 1.42 2014/08/25 18:19:18 bluhm Exp $ */ /* * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org> @@ -101,8 +101,8 @@ int priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) { int i, fd, socks[2], cmd, addr_len, result, restart; - size_t path_len, hostname_len, servname_len; - char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN]; + size_t path_len, protoname_len, hostname_len, servname_len; + char path[MAXPATHLEN], protoname[5], hostname[MAXHOSTNAMELEN]; char servname[NI_MAXSERV]; struct sockaddr_storage addr; struct stat cf_stat; @@ -293,7 +293,14 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) case PRIV_GETADDRINFO: dprintf("[priv]: msg PRIV_GETADDRINFO received\n"); - /* Expecting: len, hostname, len, servname */ + /* Expecting: len, proto, len, host, len, serv */ + must_read(socks[0], &protoname_len, sizeof(size_t)); + if (protoname_len == 0 || + protoname_len > sizeof(protoname)) + _exit(1); + must_read(socks[0], &protoname, protoname_len); + protoname[protoname_len - 1] = '\0'; + must_read(socks[0], &hostname_len, sizeof(size_t)); if (hostname_len == 0 || hostname_len > sizeof(hostname)) @@ -309,8 +316,17 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) servname[servname_len - 1] = '\0'; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + if (strcmp(protoname, "udp") == 0) { + hints.ai_family = AF_UNSPEC; + } else if (strcmp(protoname, "udp4") == 0) { + hints.ai_family = AF_INET; + } else if (strcmp(protoname, "udp6") == 0) { + hints.ai_family = AF_INET6; + } else { + errx(1, "unknown protocol %s", protoname); + } hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; i = getaddrinfo(hostname, servname, &hints, &res0); if (i != 0 || res0 == NULL) { addr_len = 0; @@ -661,25 +677,30 @@ priv_config_parse_done(void) /* Name/service to address translation. Response is placed into addr. * Return 0 for success or < 0 for error like getaddrinfo(3) */ int -priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr, +priv_getaddrinfo(char *proto, char *host, char *serv, struct sockaddr *addr, size_t addr_len) { - char hostcpy[MAXHOSTNAMELEN], servcpy[NI_MAXSERV]; + char protocpy[5], hostcpy[MAXHOSTNAMELEN], servcpy[NI_MAXSERV]; int cmd, ret_len; - size_t hostname_len, servname_len; + size_t protoname_len, hostname_len, servname_len; if (priv_fd < 0) errx(1, "%s: called from privileged portion", __func__); - if (strlcpy(hostcpy, host, sizeof hostcpy) >= sizeof(hostcpy)) + if (strlcpy(protocpy, proto, sizeof(protocpy)) >= sizeof(protocpy)) + errx(1, "%s: overflow attempt in protoname", __func__); + protoname_len = strlen(protocpy) + 1; + if (strlcpy(hostcpy, host, sizeof(hostcpy)) >= sizeof(hostcpy)) errx(1, "%s: overflow attempt in hostname", __func__); hostname_len = strlen(hostcpy) + 1; - if (strlcpy(servcpy, serv, sizeof servcpy) >= sizeof(servcpy)) + if (strlcpy(servcpy, serv, sizeof(servcpy)) >= sizeof(servcpy)) errx(1, "%s: overflow attempt in servname", __func__); servname_len = strlen(servcpy) + 1; cmd = PRIV_GETADDRINFO; must_write(priv_fd, &cmd, sizeof(int)); + must_write(priv_fd, &protoname_len, sizeof(size_t)); + must_write(priv_fd, protocpy, protoname_len); must_write(priv_fd, &hostname_len, sizeof(size_t)); must_write(priv_fd, hostcpy, hostname_len); must_write(priv_fd, &servname_len, sizeof(size_t)); diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index 7077d984af8..ec47a343911 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: syslogd.c,v 1.118 2014/08/25 18:05:30 bluhm Exp $ */ +/* $OpenBSD: syslogd.c,v 1.119 2014/08/25 18:19:18 bluhm Exp $ */ /* * Copyright (c) 1983, 1988, 1993, 1994 @@ -127,8 +127,8 @@ struct filed { union { char f_uname[MAXUNAMES][UT_NAMESIZE+1]; struct { - char f_loghost[1+1+MAXHOSTNAMELEN+1+NI_MAXSERV]; - /* @[hostname]:servname\0 */ + char f_loghost[1+4+3+1+MAXHOSTNAMELEN+1+NI_MAXSERV]; + /* @proto46://[hostname]:servname\0 */ struct sockaddr_storage f_addr; } f_forw; /* forwarding address */ char f_fname[MAXPATHLEN]; @@ -195,6 +195,8 @@ int MarkInterval = 20 * 60; /* interval between marks in seconds */ int MarkSeq = 0; /* mark sequence number */ int SecureMode = 1; /* when true, speak only unix domain socks */ int NoDNS = 0; /* when true, will refrain from doing DNS lookups */ +int IPv4Only = 0; /* when true, disable IPv6 */ +int IPv6Only = 0; /* when true, disable IPv4 */ int IncludeHostname = 0; /* include RFC 3164 style hostnames when forwarding */ char *ctlsock_path = NULL; /* Path to control socket */ @@ -268,7 +270,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 loghost(char *, char **, char **, char **); int getmsgbufsize(void); int unix_socket(char *, int, mode_t); void double_rbuf(int); @@ -291,8 +293,16 @@ main(int argc, char *argv[]) struct addrinfo hints, *res, *res0; FILE *fp; - while ((ch = getopt(argc, argv, "dhnuf:m:p:a:s:")) != -1) + while ((ch = getopt(argc, argv, "46dhnuf:m:p:a:s:")) != -1) switch (ch) { + case '4': /* disable IPv6 */ + IPv4Only = 1; + IPv6Only = 0; + break; + case '6': /* disable IPv4 */ + IPv6Only = 1; + IPv4Only = 0; + break; case 'd': /* debug */ Debug++; break; @@ -387,9 +397,13 @@ main(int argc, char *argv[]) switch (res->ai_family) { case AF_INET: + if (IPv6Only) + continue; pfdp = &pfd[PFD_INET]; break; case AF_INET6: + if (IPv4Only) + continue; pfdp = &pfd[PFD_INET6]; break; default: @@ -641,7 +655,7 @@ usage(void) { (void)fprintf(stderr, - "usage: syslogd [-dhnu] [-a path] [-f config_file] [-m mark_interval]\n" + "usage: syslogd [-46dhnu] [-a path] [-f config_file] [-m mark_interval]\n" " [-p log_socket] [-s reporting_socket]\n"); exit(1); } @@ -1437,7 +1451,7 @@ cfline(char *line, char *prog) { int i, pri; size_t rb_len; - char *bp, *p, *q, *host, *port; + char *bp, *p, *q, *proto, *host, *port; char buf[MAXLINE], ebuf[100]; struct filed *xf, *f, *d; @@ -1542,12 +1556,39 @@ cfline(char *line, char *prog) logerror(ebuf); break; } - if (loghost(++p, &host, &port) == -1) { + if (loghost(++p, &proto, &host, &port) == -1) { snprintf(ebuf, sizeof(ebuf), "bad loghost \"%s\"", f->f_un.f_forw.f_loghost); logerror(ebuf); break; } + if (proto == NULL) + proto = "udp"; + if (strcmp(proto, "udp") == 0) { + if (pfd[PFD_INET].fd == -1) + proto = "udp6"; + if (pfd[PFD_INET6].fd == -1) + proto = "udp4"; + } else if (strcmp(proto, "udp4") == 0) { + if (pfd[PFD_INET].fd == -1) { + snprintf(ebuf, sizeof(ebuf), "no udp4 \"%s\"", + f->f_un.f_forw.f_loghost); + logerror(ebuf); + break; + } + } else if (strcmp(proto, "udp6") == 0) { + if (pfd[PFD_INET6].fd == -1) { + snprintf(ebuf, sizeof(ebuf), "no udp6 \"%s\"", + f->f_un.f_forw.f_loghost); + logerror(ebuf); + break; + } + } else { + snprintf(ebuf, sizeof(ebuf), "bad protocol \"%s\"", + f->f_un.f_forw.f_loghost); + logerror(ebuf); + break; + } if (strlen(host) >= MAXHOSTNAMELEN) { snprintf(ebuf, sizeof(ebuf), "host too long \"%s\"", f->f_un.f_forw.f_loghost); @@ -1562,7 +1603,7 @@ cfline(char *line, char *prog) logerror(ebuf); break; } - if (priv_getaddrinfo(host, port, + if (priv_getaddrinfo(proto, host, 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\"", @@ -1679,8 +1720,15 @@ cfline(char *line, char *prog) * Parse the host and port parts from a loghost string. */ int -loghost(char *str, char **host, char **port) +loghost(char *str, char **proto, char **host, char **port) { + *proto = NULL; + if ((*host = strchr(str, ':')) && + (*host)[1] == '/' && (*host)[2] == '/') { + *proto = str; + **host = '\0'; + str = *host + 3; + } *host = str; if (**host == '[') { (*host)++; diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h index e637bc43030..201d220bb04 100644 --- a/usr.sbin/syslogd/syslogd.h +++ b/usr.sbin/syslogd/syslogd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syslogd.h,v 1.11 2014/08/20 20:10:17 bluhm Exp $ */ +/* $OpenBSD: syslogd.h,v 1.12 2014/08/25 18:19:18 bluhm Exp $ */ /* * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org> @@ -28,7 +28,7 @@ FILE *priv_open_utmp(void); FILE *priv_open_config(void); void priv_config_parse_done(void); int priv_config_modified(void); -int priv_getaddrinfo(char *, char *, struct sockaddr *, size_t); +int priv_getaddrinfo(char *, char *, char *, struct sockaddr *, size_t); int priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t); /* Terminal message */ |