sure. ok
On Tuesday, 6 October 2015, Alexander Bluhm <[email protected]> wrote:
> On Fri, Sep 25, 2015 at 11:27:49PM +0200, Alexander Bluhm wrote:
> > If syslogd is started with -S, it accepts TLS connections to receive
> > encrypted traffic. The server certificates are taken from /etc/ssl
> > like relayd does.
>
> Anyone?
>
> bluhm
>
> Index: usr.sbin/syslogd/evbuffer_tls.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/evbuffer_tls.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 evbuffer_tls.c
> --- usr.sbin/syslogd/evbuffer_tls.c 20 Sep 2015 21:49:54 -0000 1.8
> +++ usr.sbin/syslogd/evbuffer_tls.c 6 Oct 2015 16:10:11 -0000
> @@ -260,6 +260,19 @@ buffertls_set(struct buffertls *buftls,
> }
>
> void
> +buffertls_accept(struct buffertls *buftls, int fd)
> +{
> + struct bufferevent *bufev = buftls->bt_bufev;
> +
> + event_del(&bufev->ev_read);
> + event_del(&bufev->ev_write);
> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb,
> buftls);
> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb,
> + buftls);
> + bufferevent_add(&bufev->ev_read, bufev->timeout_read);
> +}
> +
> +void
> buffertls_connect(struct buffertls *buftls, int fd)
> {
> struct bufferevent *bufev = buftls->bt_bufev;
> Index: usr.sbin/syslogd/evbuffer_tls.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/evbuffer_tls.h,v
> retrieving revision 1.4
> diff -u -p -r1.4 evbuffer_tls.h
> --- usr.sbin/syslogd/evbuffer_tls.h 10 Sep 2015 18:32:06 -0000 1.4
> +++ usr.sbin/syslogd/evbuffer_tls.h 6 Oct 2015 16:10:11 -0000
> @@ -31,6 +31,7 @@ struct buffertls {
>
> void buffertls_set(struct buffertls *, struct bufferevent *, struct tls
> *,
> int);
> +void buffertls_accept(struct buffertls *, int);
> void buffertls_connect(struct buffertls *, int);
>
> #endif /* _EVBUFFER_TLS_H_ */
> Index: usr.sbin/syslogd/privsep.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
> retrieving revision 1.54
> diff -u -p -r1.54 privsep.c
> --- usr.sbin/syslogd/privsep.c 7 Jul 2015 17:53:04 -0000 1.54
> +++ usr.sbin/syslogd/privsep.c 6 Oct 2015 16:10:11 -0000
> @@ -184,6 +184,8 @@ priv_init(char *conf, int numeric, int l
> close(fd_bind);
> if (fd_listen != -1)
> close(fd_listen);
> + if (fd_tls != -1)
> + close(fd_tls);
> for (i = 0; i < nunix; i++)
> if (fd_unix[i] != -1)
> close(fd_unix[i]);
> Index: usr.sbin/syslogd/syslogd.8
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.8,v
> retrieving revision 1.38
> diff -u -p -r1.38 syslogd.8
> --- usr.sbin/syslogd/syslogd.8 7 Jul 2015 21:43:35 -0000 1.38
> +++ usr.sbin/syslogd/syslogd.8 6 Oct 2015 16:10:11 -0000
> @@ -45,6 +45,7 @@
> .Op Fl f Ar config_file
> .Op Fl m Ar mark_interval
> .Op Fl p Ar log_socket
> +.Op Fl S Ar listen_address
> .Op Fl s Ar reporting_socket
> .Op Fl T Ar listen_address
> .Op Fl U Ar bind_address
> @@ -108,6 +109,25 @@ the symbolic local host name.
> Specify the pathname of an alternate log socket to be used instead;
> the default is
> .Pa /dev/log .
> +.It Fl S Ar listen_address
> +Create a TLS listen socket for receiving encrypted messages and
> +bind it to the specified address.
> +A port number may be specified using the
> +.Ar host:port
> +syntax.
> +The syslog server will attempt to look up a private key in
> +.Pa /etc/ssl/private/host:port.key
> +and a public certificate in
> +.Pa /etc/ssl/host:port.crt ,
> +where
> +.Ar host
> +is the specified host name or IP address and
> +.Ar port
> +is the specified port if given on the command line.
> +If these files are not present, syslogd will continue to look in
> +.Pa /etc/ssl/private/host.key
> +and
> +.Pa /etc/ssl/host.crt .
> .It Fl s Ar reporting_socket
> Specify path to an
> .Dv AF_LOCAL
> Index: usr.sbin/syslogd/syslogd.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
> retrieving revision 1.190
> diff -u -p -r1.190 syslogd.c
> --- usr.sbin/syslogd/syslogd.c 29 Sep 2015 03:19:23 -0000 1.190
> +++ usr.sbin/syslogd/syslogd.c 6 Oct 2015 16:10:11 -0000
> @@ -50,7 +50,7 @@
> * extensive changes by Ralph Campbell
> * more extensive changes by Eric Allman (again)
> * memory buffer logging by Damien Miller
> - * IPv6, libevent, sending over TCP and TLS by Alexander Bluhm
> + * IPv6, libevent, syslog over TCP and TLS by Alexander Bluhm
> */
>
> #define MAXLINE 8192 /* maximum line length */
> @@ -219,9 +219,13 @@ char *bind_host = NULL; /* bind UDP rece
> char *bind_port = NULL;
> char *listen_host = NULL; /* listen on TCP receive socket */
> char *listen_port = NULL;
> +char *tls_hostport = NULL; /* listen on TLS receive socket */
> +char *tls_host = NULL;
> +char *tls_port = NULL;
> char *path_ctlsock = NULL; /* Path to control socket */
>
> -struct tls_config *tlsconfig = NULL;
> +struct tls *server_ctx;
> +struct tls_config *client_config, *server_config;
> const char *CAfile = "/etc/ssl/cert.pem"; /* file containing CA
> certificates */
> int NoVerify = 0; /* do not verify TLS server x509
> certificate */
> int tcpbuf_dropped = 0; /* count messages dropped from TCP or TLS
> */
> @@ -273,12 +277,14 @@ size_t ctl_reply_offset = 0; /* Number o
> char *linebuf;
> int linesize;
>
> -int fd_ctlsock, fd_ctlconn, fd_klog, fd_sendsys,
> - fd_udp, fd_udp6, fd_bind, fd_listen, fd_unix[MAXUNIX];
> +int fd_ctlsock, fd_ctlconn, fd_klog, fd_sendsys, fd_udp,
> fd_udp6,
> + fd_bind, fd_listen, fd_tls, fd_unix[MAXUNIX];
> struct event *ev_ctlaccept, *ev_ctlread, *ev_ctlwrite;
>
> struct peer {
> + struct buffertls p_buftls;
> struct bufferevent *p_bufev;
> + struct tls *p_ctx;
> char *p_peername;
> char *p_hostname;
> int p_fd;
> @@ -341,15 +347,15 @@ int
> main(int argc, char *argv[])
> {
> struct timeval to;
> - struct event *ev_klog, *ev_sendsys,
> - *ev_udp, *ev_udp6, *ev_bind, *ev_listen, *ev_unix,
> + struct event *ev_klog, *ev_sendsys, *ev_udp, *ev_udp6,
> + *ev_bind, *ev_listen, *ev_tls, *ev_unix,
> *ev_hup, *ev_int, *ev_quit, *ev_term, *ev_mark;
> const char *errstr;
> char *p;
> int ch, i;
> int lockpipe[2] = { -1, -1}, pair[2], nullfd, fd;
>
> - while ((ch = getopt(argc, argv, "46a:C:dFf:hm:np:s:T:U:uV")) != -1)
> + while ((ch = getopt(argc, argv, "46a:C:dFf:hm:np:S:s:T:U:uV")) !=
> -1)
> switch (ch) {
> case '4': /* disable IPv6 */
> Family = PF_INET;
> @@ -389,6 +395,13 @@ main(int argc, char *argv[])
> case 'p': /* path */
> path_unix[0] = optarg;
> break;
> + case 'S': /* allow tls and listen on address
> */
> + tls_hostport = optarg;
> + if ((p = strdup(optarg)) == NULL)
> + err(1, "strdup tls address");
> + if (loghost_parse(p, NULL, &tls_host, &tls_port)
> == -1)
> + errx(1, "bad tls address: %s", optarg);
> + break;
> case 's':
> path_ctlsock = optarg;
> break;
> @@ -470,6 +483,13 @@ main(int argc, char *argv[])
> if (!Debug)
> die(0);
> }
> + fd_tls = -1;
> + if (tls_host && socket_bind("tls", tls_host, tls_port, 0,
> + &fd_tls, &fd_tls) == -1) {
> + logerrorx("socket listen tls");
> + if (!Debug)
> + die(0);
> + }
>
> #ifndef SUN_LEN
> #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
> @@ -518,39 +538,133 @@ main(int argc, char *argv[])
>
> if (tls_init() == -1) {
> logerrorx("tls_init");
> - } else if ((tlsconfig = tls_config_new()) == NULL) {
> - logerror("tls_config_new");
> - } else if (NoVerify) {
> - tls_config_insecure_noverifycert(tlsconfig);
> - tls_config_insecure_noverifyname(tlsconfig);
> } else {
> + if ((client_config = tls_config_new()) == NULL)
> + logerror("tls_config_new client");
> + if (tls_hostport) {
> + if ((server_config = tls_config_new()) == NULL)
> + logerror("tls_config_new server");
> + if ((server_ctx = tls_server()) == NULL) {
> + logerror("tls_server");
> + close(fd_tls);
> + fd_tls = -1;
> + }
> + }
> + }
> + if (client_config) {
> + if (NoVerify) {
> + tls_config_insecure_noverifycert(client_config);
> + tls_config_insecure_noverifyname(client_config);
> + } else {
> + struct stat sb;
> +
> + fd = -1;
> + p = NULL;
> + if ((fd = open(CAfile, O_RDONLY)) == -1) {
> + logerror("open CAfile");
> + } else if (fstat(fd, &sb) == -1) {
> + logerror("fstat CAfile");
> + } else if (sb.st_size > 50*1024*1024) {
> + logerrorx("CAfile larger than 50MB");
> + } else if ((p = calloc(sb.st_size, 1)) == NULL) {
> + logerror("calloc CAfile");
> + } else if (read(fd, p, sb.st_size) != sb.st_size) {
> + logerror("read CAfile");
> + } else if (tls_config_set_ca_mem(client_config, p,
> + sb.st_size) == -1) {
> + logerrorx("tls_config_set_ca_mem");
> + } else {
> + dprintf("CAfile %s, size %lld\n",
> + CAfile, sb.st_size);
> + }
> + free(p);
> + close(fd);
> + }
> + tls_config_set_protocols(client_config, TLS_PROTOCOLS_ALL);
> + if (tls_config_set_ciphers(client_config, "compat") != 0)
> + logerror("tls set client ciphers");
> + }
> + if (server_config && server_ctx) {
> struct stat sb;
> + char *path;
>
> fd = -1;
> p = NULL;
> - if ((fd = open(CAfile, O_RDONLY)) == -1) {
> - logerror("open CAfile");
> + path = NULL;
> + if (asprintf(&path, "/etc/ssl/private/%s.key",
> tls_hostport)
> + == -1 || (fd = open(path, O_RDONLY)) == -1) {
> + free(path);
> + path = NULL;
> + if (asprintf(&path, "/etc/ssl/private/%s.key",
> tls_host)
> + == -1 || (fd = open(path, O_RDONLY)) == -1) {
> + free(path);
> + path = NULL;
> + }
> + }
> + if (fd == -1) {
> + logerror("open keyfile");
> } else if (fstat(fd, &sb) == -1) {
> - logerror("fstat CAfile");
> - } else if (sb.st_size > 50*1024*1024) {
> - logerrorx("CAfile larger than 50MB");
> + logerror("fstat keyfile");
> + } else if (sb.st_size > 50*1024) {
> + logerrorx("keyfile larger than 50KB");
> } else if ((p = calloc(sb.st_size, 1)) == NULL) {
> - logerror("calloc CAfile");
> + logerror("calloc keyfile");
> } else if (read(fd, p, sb.st_size) != sb.st_size) {
> - logerror("read CAfile");
> - } else if (tls_config_set_ca_mem(tlsconfig, p, sb.st_size)
> - == -1) {
> - logerrorx("tls_config_set_ca_mem");
> + logerror("read keyfile");
> + } else if (tls_config_set_key_mem(server_config, p,
> + sb.st_size) == -1) {
> + logerrorx("tls_config_set_key_mem");
> } else {
> - dprintf("CAfile %s, size %lld\n", CAfile,
> sb.st_size);
> + dprintf("Keyfile %s, size %lld\n", path,
> sb.st_size);
> }
> free(p);
> close(fd);
> - }
> - if (tlsconfig) {
> - tls_config_set_protocols(tlsconfig, TLS_PROTOCOLS_ALL);
> - if (tls_config_set_ciphers(tlsconfig, "compat") != 0)
> - logerror("tls set ciphers");
> + free(path);
> +
> + fd = -1;
> + p = NULL;
> + path = NULL;
> + if (asprintf(&path, "/etc/ssl/%s.crt", tls_hostport)
> + == -1 || (fd = open(path, O_RDONLY)) == -1) {
> + free(path);
> + path = NULL;
> + if (asprintf(&path, "/etc/ssl/%s.crt", tls_host)
> + == -1 || (fd = open(path, O_RDONLY)) == -1) {
> + free(path);
> + path = NULL;
> + }
> + }
> + if (fd == -1) {
> + logerror("open certfile");
> + } else if (fstat(fd, &sb) == -1) {
> + logerror("fstat certfile");
> + } else if (sb.st_size > 50*1024) {
> + logerrorx("certfile larger than 50KB");
> + } else if ((p = calloc(sb.st_size, 1)) == NULL) {
> + logerror("calloc certfile");
> + } else if (read(fd, p, sb.st_size) != sb.st_size) {
> + logerror("read certfile");
> + } else if (tls_config_set_cert_mem(server_config, p,
> + sb.st_size) == -1) {
> + logerrorx("tls_config_set_cert_mem");
> + } else {
> + dprintf("Certfile %s, size %lld\n",
> + path, sb.st_size);
> + }
> + free(p);
> + close(fd);
> + free(path);
> +
> + tls_config_set_protocols(server_config, TLS_PROTOCOLS_ALL);
> + if (tls_config_set_ciphers(server_config, "compat") != 0)
> + logerror("tls set server ciphers");
> + if (tls_configure(server_ctx, server_config) != 0) {
> + logerrorx("tls_configure server");
> + tls_free(server_ctx);
> + server_ctx = NULL;
> + close(fd_tls);
> + fd_tls = -1;
> + }
> }
>
> dprintf("off & running....\n");
> @@ -605,6 +719,7 @@ main(int argc, char *argv[])
> (ev_udp6 = malloc(sizeof(struct event))) == NULL ||
> (ev_bind = malloc(sizeof(struct event))) == NULL ||
> (ev_listen = malloc(sizeof(struct event))) == NULL ||
> + (ev_tls = malloc(sizeof(struct event))) == NULL ||
> (ev_unix = reallocarray(NULL,nunix,sizeof(struct event))) ==
> NULL ||
> (ev_hup = malloc(sizeof(struct event))) == NULL ||
> (ev_int = malloc(sizeof(struct event))) == NULL ||
> @@ -627,6 +742,7 @@ main(int argc, char *argv[])
> event_set(ev_bind, fd_bind, EV_READ|EV_PERSIST, udp_readcb,
> ev_bind);
> event_set(ev_listen, fd_listen, EV_READ|EV_PERSIST, tcp_acceptcb,
> ev_listen);
> + event_set(ev_tls, fd_tls, EV_READ|EV_PERSIST, tcp_acceptcb,
> ev_tls);
> for (i = 0; i < nunix; i++)
> event_set(&ev_unix[i], fd_unix[i], EV_READ|EV_PERSIST,
> unix_readcb, &ev_unix[i]);
> @@ -681,6 +797,8 @@ main(int argc, char *argv[])
> event_add(ev_bind, NULL);
> if (fd_listen != -1)
> event_add(ev_listen, NULL);
> + if (fd_tls != -1)
> + event_add(ev_tls, NULL);
> for (i = 0; i < nunix; i++)
> if (fd_unix[i] != -1)
> event_add(&ev_unix[i], NULL);
> @@ -722,7 +840,7 @@ socket_bind(const char *proto, const cha
> if (proto == NULL)
> proto = "udp";
> if (port == NULL)
> - port = "syslog";
> + port = strcmp(proto, "tls") == 0 ? "syslog-tls" : "syslog";
>
> memset(&hints, 0, sizeof(hints));
> hints.ai_family = Family;
> @@ -912,7 +1030,7 @@ reserve_accept4(int lfd, int event, stru
> }
>
> void
> -tcp_acceptcb(int fd, short event, void *arg)
> +tcp_acceptcb(int lfd, short event, void *arg)
> {
> struct event *ev = arg;
> struct peer *p;
> @@ -920,9 +1038,10 @@ tcp_acceptcb(int fd, short event, void *
> socklen_t sslen;
> char hostname[NI_MAXHOST],
> servname[NI_MAXSERV];
> char *peername, ebuf[ERRBUFSIZE];
> + int fd;
>
> sslen = sizeof(ss);
> - if ((fd = reserve_accept4(fd, event, ev, tcp_acceptcb,
> + if ((fd = reserve_accept4(lfd, event, ev, tcp_acceptcb,
> (struct sockaddr *)&ss, &sslen, SOCK_NONBLOCK)) == -1) {
> if (errno != ENFILE && errno != EMFILE &&
> errno != EINTR && errno != EWOULDBLOCK &&
> @@ -956,6 +1075,21 @@ tcp_acceptcb(int fd, short event, void *
> close(fd);
> return;
> }
> + p->p_ctx = NULL;
> + if (lfd == fd_tls) {
> + if (tls_accept_socket(server_ctx, &p->p_ctx, fd) < 0) {
> + snprintf(ebuf, sizeof(ebuf), "tls_accept_socket
> \"%s\"",
> + peername);
> + logerrorctx(ebuf, server_ctx);
> + bufferevent_free(p->p_bufev);
> + free(p);
> + close(fd);
> + return;
> + }
> + buffertls_set(&p->p_buftls, p->p_bufev, p->p_ctx, fd);
> + buffertls_accept(&p->p_buftls, fd);
> + dprintf("tcp accept callback: tls context success\n");
> + }
> if (!NoDNS && peername != hostname_unknown &&
> priv_getnameinfo((struct sockaddr *)&ss, ss.ss_len, hostname,
> sizeof(hostname)) != 0) {
> @@ -969,8 +1103,8 @@ tcp_acceptcb(int fd, short event, void *
> p->p_peername = peername;
> bufferevent_enable(p->p_bufev, EV_READ);
>
> - snprintf(ebuf, sizeof(ebuf), "syslogd: tcp logger \"%s\" accepted",
> - peername);
> + snprintf(ebuf, sizeof(ebuf), "syslogd: %s logger \"%s\" accepted",
> + p->p_ctx ? "tls" : "tcp", peername);
> logmsg(LOG_SYSLOG|LOG_INFO, ebuf, LocalHostName, ADDDATE);
> }
>
> @@ -1059,7 +1193,8 @@ tcp_readcb(struct bufferevent *bufev, vo
> int len;
>
> while (EVBUFFER_LENGTH(bufev->input) > 0) {
> - dprintf("tcp logger \"%s\"", p->p_peername);
> + dprintf("%s logger \"%s\"", p->p_ctx ? "tls" : "tcp",
> + p->p_peername);
> msg = NULL;
> len = octet_counting(bufev->input, &msg, 1);
> if (len < 0)
> @@ -1097,12 +1232,15 @@ tcp_closecb(struct bufferevent *bufev, s
> char ebuf[ERRBUFSIZE];
>
> if (event & EVBUFFER_EOF) {
> - snprintf(ebuf, sizeof(ebuf), "syslogd: tcp logger \"%s\" "
> - "connection close", p->p_peername);
> + snprintf(ebuf, sizeof(ebuf), "syslogd: %s logger \"%s\" "
> + "connection close", p->p_ctx ? "tls" : "tcp",
> + p->p_peername);
> logmsg(LOG_SYSLOG|LOG_INFO, ebuf, LocalHostName, ADDDATE);
> } else {
> - snprintf(ebuf, sizeof(ebuf), "syslogd: tcp logger \"%s\" "
> - "connection error: %s", p->p_peername,
> strerror(errno));
> + snprintf(ebuf, sizeof(ebuf), "syslogd: %s logger \"%s\" "
> + "connection error: %s", p->p_ctx ? "tls" : "tcp",
> + p->p_peername,
> + p->p_ctx ? tls_error(p->p_ctx) : strerror(errno));
> logmsg(LOG_SYSLOG|LOG_NOTICE, ebuf, LocalHostName,
> ADDDATE);
> }
>
> @@ -1263,8 +1401,8 @@ tcp_connectcb(int fd, short event, void
> logerror(ebuf);
> goto error;
> }
> - if (tlsconfig &&
> - tls_configure(f->f_un.f_forw.f_ctx, tlsconfig) == -1) {
> + if (client_config &&
> + tls_configure(f->f_un.f_forw.f_ctx, client_config) ==
> -1) {
> snprintf(ebuf, sizeof(ebuf), "tls_configure
> \"%s\"",
> f->f_un.f_forw.f_loghost);
> logerrorctx(ebuf, f->f_un.f_forw.f_ctx);
> @@ -1338,8 +1476,8 @@ usage(void)
>
> (void)fprintf(stderr,
> "usage: syslogd [-46dFhnuV] [-a path] [-C CAfile] [-f
> config_file]\n"
> - " [-m mark_interval] [-p log_socket] [-s
> reporting_socket]\n"
> - " [-T listen_address] [-U bind_address]\n");
> + " [-m mark_interval] [-p log_socket] [-S
> listen_address]\n"
> + " [-s reporting_socket] [-T listen_address] [-U
> bind_address]\n");
> exit(1);
> }
>
> Index: usr.sbin/syslogd/syslogd.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v
> retrieving revision 1.19
> diff -u -p -r1.19 syslogd.h
> --- usr.sbin/syslogd/syslogd.h 7 Jul 2015 17:53:04 -0000 1.19
> +++ usr.sbin/syslogd/syslogd.h 6 Oct 2015 16:10:11 -0000
> @@ -44,7 +44,7 @@ extern int nunix;
> extern char *path_unix[MAXUNIX];
> extern char *path_ctlsock;
> extern int fd_ctlsock, fd_ctlconn, fd_klog, fd_sendsys;
> -extern int fd_udp, fd_udp6, fd_bind, fd_listen, fd_unix[MAXUNIX];
> +extern int fd_udp, fd_udp6, fd_bind, fd_listen, fd_tls, fd_unix[MAXUNIX];
>
> #define dprintf(_f...) do { if (Debug) printf(_f); } while (0)
> extern int Debug;
>
>