On Fri, Jan 16, 2015 at 12:54 PM, Reyk Floeter <r...@openbsd.org> wrote: > On Fri, Jan 16, 2015 at 12:56:45PM +0100, Alexander Bluhm wrote: >> On Fri, Jan 16, 2015 at 01:46:09AM +0100, Alexander Bluhm wrote: >> > This diff enables sending syslog messages over TLS. >> >> Updated diff after sys/param.h commit. Only some context changed. >> >> bluhm >> > > Despite my scepticism about putting it into libevent - > > The diff looks and works fine (lightly tested). > > The evbuffer_tls.c code is similar enough to what we have in > relayd/httpd and libevent; so I don't see any problems here. > > Minor comments (not inline): > - The ebuf[100] looks a bit weird, but it is not a problem. > - I would prefer checking return value as -1 instead of < 0 > (tls_init() and other calls below). > - The manpage bits are missing. > > I'm fine with putting it in and to improve/discuss the API issues later. > > OK > > Reyk > >> Index: usr.sbin/syslogd/Makefile >> =================================================================== >> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/Makefile,v >> retrieving revision 1.6 >> diff -u -p -r1.6 Makefile >> --- usr.sbin/syslogd/Makefile 5 Oct 2014 18:14:01 -0000 1.6 >> +++ usr.sbin/syslogd/Makefile 16 Jan 2015 11:45:40 -0000 >> @@ -1,9 +1,9 @@ >> # $OpenBSD: Makefile,v 1.6 2014/10/05 18:14:01 bluhm Exp $ >> >> PROG= syslogd >> -SRCS= syslogd.c ttymsg.c privsep.c privsep_fdpass.c ringbuf.c >> +SRCS= syslogd.c ttymsg.c privsep.c privsep_fdpass.c ringbuf.c >> evbuffer_tls.c >> MAN= syslogd.8 syslog.conf.5 >> -LDADD= -levent >> -DPADD= ${LIBEVENT} >> +LDADD= -levent -ltls -lssl -lcrypto >> +DPADD= ${LIBEVENT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} >> >> .include <bsd.prog.mk> >> Index: usr.sbin/syslogd/evbuffer_tls.c >> =================================================================== >> RCS file: usr.sbin/syslogd/evbuffer_tls.c >> diff -N usr.sbin/syslogd/evbuffer_tls.c >> --- /dev/null 1 Jan 1970 00:00:00 -0000 >> +++ usr.sbin/syslogd/evbuffer_tls.c 16 Jan 2015 11:45:40 -0000 >> @@ -0,0 +1,357 @@ >> +/* $OpenBSD$ */ >> + >> +/* >> + * Copyright (c) 2002-2004 Niels Provos <pro...@citi.umich.edu> >> + * Copyright (c) 2014-2015 Alexander Bluhm <bl...@openbsd.org> >> + * All rights reserved. >> + * >> + * Redistribution and use in source and binary forms, with or without >> + * modification, are permitted provided that the following conditions >> + * are met: >> + * 1. Redistributions of source code must retain the above copyright >> + * notice, this list of conditions and the following disclaimer. >> + * 2. Redistributions in binary form must reproduce the above copyright >> + * notice, this list of conditions and the following disclaimer in the >> + * documentation and/or other materials provided with the distribution. >> + * 3. The name of the author may not be used to endorse or promote products >> + * derived from this software without specific prior written permission. >> + * >> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >> + */ >> + >> +#include <sys/types.h> >> +#include <sys/time.h> >> +#include <sys/ioctl.h> >> + >> +#include <errno.h> >> +#include <event.h> >> +#include <stdio.h> >> +#include <stdlib.h> >> +#include <string.h> >> +#include <stdarg.h> >> +#include <tls.h> >> + >> +#include "evbuffer_tls.h" >> + >> +/* prototypes */ >> + >> +void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void >> *); >> +int evtls_read(struct evbuffer *, int, int, struct tls *); >> +int evtls_write(struct evbuffer *, int, struct tls *); >> + >> +static int >> +bufferevent_add(struct event *ev, int timeout) >> +{ >> + struct timeval tv, *ptv = NULL; >> + >> + if (timeout) { >> + timerclear(&tv); >> + tv.tv_sec = timeout; >> + ptv = &tv; >> + } >> + >> + return (event_add(ev, ptv)); >> +} >> + >> +static void >> +buffertls_readcb(int fd, short event, void *arg) >> +{ >> + struct buffertls *buftls = arg; >> + struct bufferevent *bufev = buftls->bt_bufev; >> + struct tls *ctx = buftls->bt_ctx; >> + int res = 0; >> + short what = EVBUFFER_READ; >> + size_t len; >> + int howmuch = -1; >> + >> + if (event == EV_TIMEOUT) { >> + what |= EVBUFFER_TIMEOUT; >> + goto error; >> + } >> + >> + /* >> + * If we have a high watermark configured then we don't want to >> + * read more data than would make us reach the watermark. >> + */ >> + if (bufev->wm_read.high != 0) { >> + howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); >> + /* we might have lowered the watermark, stop reading */ >> + if (howmuch <= 0) { >> + struct evbuffer *buf = bufev->input; >> + event_del(&bufev->ev_read); >> + evbuffer_setcb(buf, >> + bufferevent_read_pressure_cb, bufev); >> + return; >> + } >> + } >> + >> + res = evtls_read(bufev->input, fd, howmuch, ctx); >> + switch (res) { >> + case TLS_READ_AGAIN: >> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, >> + buftls); >> + goto reschedule; >> + case TLS_WRITE_AGAIN: >> + event_set(&bufev->ev_read, fd, EV_WRITE, buffertls_readcb, >> + buftls); >> + goto reschedule; >> + case -1: >> + if (errno == EAGAIN || errno == EINTR) >> + goto reschedule; >> + /* error case */ >> + what |= EVBUFFER_ERROR; >> + break; >> + case 0: >> + /* eof case */ >> + what |= EVBUFFER_EOF; >> + break; >> + } >> + if (res <= 0) >> + goto error; >> + >> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls); >> + bufferevent_add(&bufev->ev_read, bufev->timeout_read); >> + >> + /* See if this callbacks meets the water marks */ >> + len = EVBUFFER_LENGTH(bufev->input); >> + if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) >> + return; >> + if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { >> + struct evbuffer *buf = bufev->input; >> + event_del(&bufev->ev_read); >> + >> + /* Now schedule a callback for us when the buffer changes */ >> + evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); >> + } >> + >> + /* Invoke the user callback - must always be called last */ >> + if (bufev->readcb != NULL) >> + (*bufev->readcb)(bufev, bufev->cbarg); >> + return; >> + >> + reschedule: >> + bufferevent_add(&bufev->ev_read, bufev->timeout_read); >> + return; >> + >> + error: >> + (*bufev->errorcb)(bufev, what, bufev->cbarg); >> +} >> + >> +static void >> +buffertls_writecb(int fd, short event, void *arg) >> +{ >> + struct buffertls *buftls = arg; >> + struct bufferevent *bufev = buftls->bt_bufev; >> + struct tls *ctx = buftls->bt_ctx; >> + int res = 0; >> + short what = EVBUFFER_WRITE; >> + >> + if (event == EV_TIMEOUT) { >> + what |= EVBUFFER_TIMEOUT; >> + goto error; >> + } >> + >> + if (EVBUFFER_LENGTH(bufev->output) != 0) { >> + res = evtls_write(bufev->output, fd, ctx); >> + switch (res) { >> + case TLS_READ_AGAIN: >> + event_set(&bufev->ev_write, fd, EV_READ, >> + buffertls_writecb, buftls); >> + goto reschedule; >> + case TLS_WRITE_AGAIN: >> + event_set(&bufev->ev_write, fd, EV_WRITE, >> + buffertls_writecb, buftls); >> + goto reschedule; >> + case -1: >> + if (errno == EAGAIN || errno == EINTR || >> + errno == EINPROGRESS) >> + goto reschedule; >> + /* error case */ >> + what |= EVBUFFER_ERROR; >> + break; >> + case 0: >> + /* eof case */ >> + what |= EVBUFFER_EOF; >> + break; >> + } >> + if (res <= 0) >> + goto error; >> + } >> + >> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); >> + if (EVBUFFER_LENGTH(bufev->output) != 0) >> + bufferevent_add(&bufev->ev_write, bufev->timeout_write); >> + >> + /* >> + * Invoke the user callback if our buffer is drained or below the >> + * low watermark. >> + */ >> + if (bufev->writecb != NULL && >> + EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) >> + (*bufev->writecb)(bufev, bufev->cbarg); >> + >> + return; >> + >> + reschedule: >> + if (EVBUFFER_LENGTH(bufev->output) != 0) >> + bufferevent_add(&bufev->ev_write, bufev->timeout_write); >> + return; >> + >> + error: >> + (*bufev->errorcb)(bufev, what, bufev->cbarg); >> +} >> + >> +static void >> +buffertls_connectcb(int fd, short event, void *arg) >> +{ >> + struct buffertls *buftls = arg; >> + struct bufferevent *bufev = buftls->bt_bufev; >> + struct tls *ctx = buftls->bt_ctx; >> + const char *hostname = buftls->bt_hostname; >> + int res = 0; >> + short what = EVBUFFER_CONNECT; >> + >> + if (event == EV_TIMEOUT) { >> + what |= EVBUFFER_TIMEOUT; >> + goto error; >> + } >> + >> + res = tls_connect_socket(ctx, fd, hostname); >> + switch (res) { >> + case TLS_READ_AGAIN: >> + event_set(&bufev->ev_write, fd, EV_READ, >> + buffertls_connectcb, buftls); >> + goto reschedule; >> + case TLS_WRITE_AGAIN: >> + event_set(&bufev->ev_write, fd, EV_WRITE, >> + buffertls_connectcb, buftls); >> + goto reschedule; >> + case -1: >> + if (errno == EAGAIN || errno == EINTR || >> + errno == EINPROGRESS) >> + goto reschedule; >> + /* error case */ >> + what |= EVBUFFER_ERROR; >> + break; >> + } >> + if (res < 0) >> + goto error; >> + >> + /* >> + * There might be data available in the tls layer. Try >> + * an read operation and setup the callbacks. Call the read >> + * callback after enabling the write callback to give the >> + * read error handler a chance to disable the write event. >> + */ >> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); >> + if (EVBUFFER_LENGTH(bufev->output) != 0) >> + bufferevent_add(&bufev->ev_write, bufev->timeout_write); >> + buffertls_readcb(fd, 0, buftls); >> + >> + return; >> + >> + reschedule: >> + bufferevent_add(&bufev->ev_write, bufev->timeout_write); >> + return; >> + >> + error: >> + (*bufev->errorcb)(bufev, what, bufev->cbarg); >> +} >> + >> +void >> +buffertls_set(struct buffertls *buftls, struct bufferevent *bufev, >> + struct tls *ctx, int fd) >> +{ >> + bufferevent_setfd(bufev, fd); >> + event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls); >> + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); >> + buftls->bt_bufev = bufev; >> + buftls->bt_ctx = ctx; >> +} >> + >> +void >> +buffertls_connect(struct buffertls *buftls, int fd, const char *hostname) >> +{ >> + struct bufferevent *bufev = buftls->bt_bufev; >> + >> + event_del(&bufev->ev_read); >> + event_del(&bufev->ev_write); >> + >> + buftls->bt_hostname = hostname; >> + buffertls_connectcb(fd, 0, buftls); >> +} >> + >> +/* >> + * Reads data from a file descriptor into a buffer. >> + */ >> + >> +#define EVBUFFER_MAX_READ 4096 >> + >> +int >> +evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx) >> +{ >> + u_char *p; >> + size_t len, oldoff = buf->off; >> + int n = EVBUFFER_MAX_READ; >> + >> + if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { >> + n = EVBUFFER_MAX_READ; >> + } else if (n > EVBUFFER_MAX_READ && n > howmuch) { >> + /* >> + * It's possible that a lot of data is available for >> + * reading. We do not want to exhaust resources >> + * before the reader has a chance to do something >> + * about it. If the reader does not tell us how much >> + * data we should read, we artifically limit it. >> + */ >> + if ((size_t)n > buf->totallen << 2) >> + n = buf->totallen << 2; >> + if (n < EVBUFFER_MAX_READ) >> + n = EVBUFFER_MAX_READ; >> + } >> + if (howmuch < 0 || howmuch > n) >> + howmuch = n; >> + >> + /* If we don't have FIONREAD, we might waste some space here */ >> + if (evbuffer_expand(buf, howmuch) == -1) >> + return (-1); >> + >> + /* We can append new data at this point */ >> + p = buf->buffer + buf->off; >> + >> + n = tls_read(ctx, p, howmuch, &len); >> + if (n < 0 || len == 0) >> + return (n); >> + >> + buf->off += len; >> + >> + /* Tell someone about changes in this buffer */ >> + if (buf->off != oldoff && buf->cb != NULL) >> + (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); >> + >> + return (len); >> +} >> + >> +int >> +evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx) >> +{ >> + size_t len; >> + int n; >> + >> + n = tls_write(ctx, buffer->buffer, buffer->off, &len); >> + if (n < 0 || len == 0) >> + return (n); >> + >> + evbuffer_drain(buffer, len); >> + >> + return (len); >> +} >> Index: usr.sbin/syslogd/evbuffer_tls.h >> =================================================================== >> RCS file: usr.sbin/syslogd/evbuffer_tls.h >> diff -N usr.sbin/syslogd/evbuffer_tls.h >> --- /dev/null 1 Jan 1970 00:00:00 -0000 >> +++ usr.sbin/syslogd/evbuffer_tls.h 16 Jan 2015 11:45:40 -0000 >> @@ -0,0 +1,37 @@ >> +/* $OpenBSD$ */ >> + >> +/* >> + * Copyright (c) 2014-2015 Alexander Bluhm <bl...@openbsd.org> >> + * >> + * Permission to use, copy, modify, and distribute this software for any >> + * purpose with or without fee is hereby granted, provided that the above >> + * copyright notice and this permission notice appear in all copies. >> + * >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >> + */ >> + >> +#ifndef _EVBUFFER_TLS_H_ >> +#define _EVBUFFER_TLS_H_ >> + >> +#define EVBUFFER_CONNECT 0x80 >> + >> +struct bufferevent; >> +struct tls; >> + >> +struct buffertls { >> + struct bufferevent *bt_bufev; >> + struct tls *bt_ctx; >> + const char *bt_hostname; >> +}; >> + >> +void buffertls_set(struct buffertls *, struct bufferevent *, struct tls *, >> + int); >> +void buffertls_connect(struct buffertls *, int, const char *); >> + >> +#endif /* _EVBUFFER_TLS_H_ */ >> Index: usr.sbin/syslogd/syslogd.c >> =================================================================== >> RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v >> retrieving revision 1.142 >> diff -u -p -r1.142 syslogd.c >> --- usr.sbin/syslogd/syslogd.c 16 Jan 2015 06:40:21 -0000 1.142 >> +++ usr.sbin/syslogd/syslogd.c 16 Jan 2015 11:45:40 -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 via TCP by Alexander Bluhm >> + * IPv6, libevent, sending over TCP and TLS by Alexander Bluhm >> */ >> >> #define MAXLINE 1024 /* maximum line length */ >> @@ -91,6 +91,7 @@ >> #include <stdio.h> >> #include <stdlib.h> >> #include <string.h> >> +#include <tls.h> >> #include <unistd.h> >> #include <limits.h> >> #include <utmp.h> >> @@ -102,6 +103,7 @@ >> #include <sys/syslog.h> >> >> #include "syslogd.h" >> +#include "evbuffer_tls.h" >> >> char *ConfFile = _PATH_LOGCONF; >> const char ctty[] = _PATH_CONSOLE; >> @@ -135,9 +137,11 @@ struct filed { >> struct { >> char >> f_loghost[1+4+3+1+HOST_NAME_MAX+1+1+NI_MAXSERV]; >> /* @proto46://[hostname]:servname\0 */ >> - struct sockaddr_storage f_addr; >> + struct sockaddr_storage f_addr; >> + struct buffertls f_buftls; >> struct bufferevent *f_bufev; >> - int f_reconnectwait; >> + struct tls *f_ctx; >> + int f_reconnectwait; >> } f_forw; /* forwarding address */ >> char f_fname[PATH_MAX]; >> struct { >> @@ -182,11 +186,12 @@ int repeatinterval[] = { 30, 120, 600 }; >> #define F_MEMBUF 7 /* memory buffer */ >> #define F_PIPE 8 /* pipe to external program */ >> #define F_FORWTCP 9 /* remote machine via TCP */ >> +#define F_FORWTLS 10 /* remote machine via TLS */ >> >> char *TypeNames[] = { >> "UNUSED", "FILE", "TTY", "CONSOLE", >> "FORWUDP", "USERS", "WALL", "MEMBUF", >> - "PIPE", "FORWTCP", >> + "PIPE", "FORWTCP", "FORWTLS", >> }; >> >> SIMPLEQ_HEAD(filed_list, filed) Files; >> @@ -271,6 +276,7 @@ void tcp_readcb(struct bufferevent *, v >> void tcp_writecb(struct bufferevent *, void *); >> void tcp_errorcb(struct bufferevent *, short, void *); >> void tcp_connectcb(int, short, void *); >> +struct tls *tls_socket(struct filed *); >> void die_signalcb(int, short, void *); >> void mark_timercb(int, short, void *); >> void init_signalcb(int, short, void *); >> @@ -715,8 +721,7 @@ tcp_readcb(struct bufferevent *bufev, vo >> * Drop data received from the forward log server. >> */ >> dprintf("loghost \"%s\" did send %zu bytes back\n", >> - f->f_un.f_forw.f_loghost, >> - EVBUFFER_LENGTH(f->f_un.f_forw.f_bufev->input)); >> + f->f_un.f_forw.f_loghost, EVBUFFER_LENGTH(bufev->input)); >> evbuffer_drain(bufev->input, -1); >> } >> >> @@ -745,10 +750,16 @@ tcp_errorcb(struct bufferevent *bufev, s >> else >> snprintf(ebuf, sizeof(ebuf), >> "syslogd: loghost \"%s\" connection error: %s", >> - f->f_un.f_forw.f_loghost, strerror(errno)); >> + f->f_un.f_forw.f_loghost, f->f_un.f_forw.f_ctx ? >> + tls_error(f->f_un.f_forw.f_ctx) : strerror(errno)); >> dprintf("%s\n", ebuf); >> >> /* The SIGHUP handler may also close the socket, so invalidate it. */ >> + if (f->f_un.f_forw.f_ctx) { >> + tls_close(f->f_un.f_forw.f_ctx); >> + tls_free(f->f_un.f_forw.f_ctx); >> + f->f_un.f_forw.f_ctx = NULL; >> + } >> close(f->f_file); >> f->f_file = -1; >> >> @@ -768,6 +779,7 @@ tcp_connectcb(int fd, short event, void >> { >> struct filed *f = arg; >> struct bufferevent *bufev = f->f_un.f_forw.f_bufev; >> + struct tls *ctx; >> struct timeval to; >> int s; >> >> @@ -780,8 +792,9 @@ tcp_connectcb(int fd, short event, void >> >> if ((s = tcp_socket(f)) == -1) >> goto retry; >> + dprintf("tcp connect callback: socket success, event %#x\n", event); >> + f->f_file = s; >> >> - dprintf("tcp connect callback: success, event %#x\n", event); >> bufferevent_setfd(bufev, s); >> bufferevent_setcb(bufev, tcp_readcb, tcp_writecb, tcp_errorcb, f); >> /* >> @@ -789,7 +802,20 @@ tcp_connectcb(int fd, short event, void >> * the socket to detect connection close and errors. >> */ >> bufferevent_enable(bufev, EV_READ|EV_WRITE); >> - f->f_file = s; >> + >> + if (f->f_type == F_FORWTLS) { >> + if ((ctx = tls_socket(f)) == NULL) { >> + close(f->f_file); >> + f->f_file = -1; >> + goto retry; >> + } >> + dprintf("tcp connect callback: TLS context success\n"); >> + f->f_un.f_forw.f_ctx = ctx; >> + >> + buffertls_set(&f->f_un.f_forw.f_buftls, bufev, ctx, s); >> + /* XXX no host given */ >> + buffertls_connect(&f->f_un.f_forw.f_buftls, s, NULL); >> + } >> >> return; >> >> @@ -808,6 +834,46 @@ tcp_connectcb(int fd, short event, void >> evtimer_add(&bufev->ev_write, &to); >> } >> >> +struct tls * >> +tls_socket(struct filed *f) >> +{ >> + static struct tls_config *config; >> + struct tls *ctx; >> + char ebuf[100]; >> + >> + if (config == NULL) { >> + if (tls_init() < 0) { >> + snprintf(ebuf, sizeof(ebuf), "tls_init \"%s\"", >> + f->f_un.f_forw.f_loghost); >> + logerror(ebuf); >> + return (NULL); >> + } >> + if ((config = tls_config_new()) == NULL) { >> + snprintf(ebuf, sizeof(ebuf), "tls_config_new \"%s\"", >> + f->f_un.f_forw.f_loghost); >> + logerror(ebuf); >> + return (NULL); >> + } >> + /* XXX No verify for now, ca certs are outside of privsep. */ >> + tls_config_insecure_noverifyhost(config); >> + tls_config_insecure_noverifycert(config); >> + } >> + if ((ctx = tls_client()) == NULL) { >> + snprintf(ebuf, sizeof(ebuf), "tls_client \"%s\"", >> + f->f_un.f_forw.f_loghost); >> + logerror(ebuf); >> + return (NULL); >> + } >> + if (tls_configure(ctx, config) < 0) { >> + snprintf(ebuf, sizeof(ebuf), "tls_configure \"%s\": %s", >> + f->f_un.f_forw.f_loghost, tls_error(ctx)); >> + logerror(ebuf); >> + tls_free(ctx); >> + return (NULL); >> + } >> + return (ctx); >> +} >> + >> void >> usage(void) >> { >> @@ -1114,6 +1180,7 @@ fprintlog(struct filed *f, int flags, ch >> break; >> >> case F_FORWTCP: >> + case F_FORWTLS: >> dprintf(" %s\n", f->f_un.f_forw.f_loghost); >> if (EVBUFFER_LENGTH(f->f_un.f_forw.f_bufev->output) >= >> MAX_TCPBUF) >> @@ -1402,6 +1469,12 @@ init(void) >> fprintlog(f, 0, (char *)NULL); >> >> switch (f->f_type) { >> + case F_FORWTLS: >> + if (f->f_un.f_forw.f_ctx) { >> + tls_close(f->f_un.f_forw.f_ctx); >> + tls_free(f->f_un.f_forw.f_ctx); >> + } >> + /* FALLTHROUGH */ >> case F_FORWTCP: >> /* XXX Save messages in output buffer for reconnect. */ >> bufferevent_free(f->f_un.f_forw.f_bufev); >> @@ -1542,6 +1615,7 @@ init(void) >> >> case F_FORWUDP: >> case F_FORWTCP: >> + case F_FORWTLS: >> printf("%s", f->f_un.f_forw.f_loghost); >> break; >> >> @@ -1604,9 +1678,10 @@ cfline(char *line, char *prog) >> { >> int i, pri; >> size_t rb_len; >> - char *bp, *p, *q, *proto, *host, *port; >> + char *bp, *p, *q, *proto, *host, *port, *ipproto; >> char buf[MAXLINE], ebuf[100]; >> struct filed *xf, *f, *d; >> + struct timeval to; >> >> dprintf("cfline(\"%s\", f, \"%s\")\n", line, prog); >> >> @@ -1714,11 +1789,13 @@ cfline(char *line, char *prog) >> } >> if (proto == NULL) >> proto = "udp"; >> + ipproto = proto; >> if (strcmp(proto, "udp") == 0) { >> if (fd_udp == -1) >> proto = "udp6"; >> if (fd_udp6 == -1) >> proto = "udp4"; >> + ipproto = proto; >> } else if (strcmp(proto, "udp4") == 0) { >> if (fd_udp == -1) { >> snprintf(ebuf, sizeof(ebuf), "no udp4 \"%s\"", >> @@ -1736,6 +1813,12 @@ cfline(char *line, char *prog) >> } else if (strcmp(proto, "tcp") == 0 || >> strcmp(proto, "tcp4") == 0 || strcmp(proto, "tcp6") == 0) { >> ; >> + } else if (strcmp(proto, "tls") == 0) { >> + ipproto = "tcp"; >> + } else if (strcmp(proto, "tls4") == 0) { >> + ipproto = "tcp4"; >> + } else if (strcmp(proto, "tls6") == 0) { >> + ipproto = "tcp6"; >> } else { >> snprintf(ebuf, sizeof(ebuf), "bad protocol \"%s\"", >> f->f_un.f_forw.f_loghost); >> @@ -1749,14 +1832,15 @@ cfline(char *line, char *prog) >> break; >> } >> if (port == NULL) >> - port = "syslog"; >> + port = strncmp(proto, "tls", 3) == 0 ? >> + "syslog-tls" : "syslog"; >> if (strlen(port) >= NI_MAXSERV) { >> snprintf(ebuf, sizeof(ebuf), "port too long \"%s\"", >> f->f_un.f_forw.f_loghost); >> logerror(ebuf); >> break; >> } >> - if (priv_getaddrinfo(proto, host, port, >> + if (priv_getaddrinfo(ipproto, 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\"", >> @@ -1775,7 +1859,7 @@ cfline(char *line, char *prog) >> break; >> } >> f->f_type = F_FORWUDP; >> - } else if (strncmp(proto, "tcp", 3) == 0) { >> + } else if (strncmp(ipproto, "tcp", 3) == 0) { >> if ((f->f_un.f_forw.f_bufev = bufferevent_new(-1, >> tcp_readcb, tcp_writecb, tcp_errorcb, f)) == NULL) >> { >> snprintf(ebuf, sizeof(ebuf), >> @@ -1784,8 +1868,23 @@ cfline(char *line, char *prog) >> logerror(ebuf); >> break; >> } >> - f->f_type = F_FORWTCP; >> - tcp_connectcb(-1, 0, f); >> + if (strncmp(proto, "tls", 3) == 0) { >> + f->f_type = F_FORWTLS; >> + } else { >> + f->f_type = F_FORWTCP; >> + } >> + /* >> + * If we try to connect to a TLS server immediately >> + * syslogd gets an SIGPIPE as the signal handlers have >> + * not been set up. Delay the connection until the >> + * event loop is started. We can reuse the write event >> + * for that as bufferevent is still disabled. >> + */ >> + to.tv_sec = 0; >> + to.tv_usec = 1; >> + evtimer_set(&f->f_un.f_forw.f_bufev->ev_write, >> + tcp_connectcb, f); >> + evtimer_add(&f->f_un.f_forw.f_bufev->ev_write, &to); >> } >> break; >> >> > > -- >
Dear Tech@openbsd.org Most of TLS client got a few parameters like : CRL,CA,and Client Certificat Just look at < Document how to send syslog messages over TCP or TLS. > (because this TLS feature is SO cool). So i guess the CA could be put in /etc/ssl but what if i'd like to authentify myself to the server ? is it in the roadmap ? is this already possible ? tls[46]://cert:/root/auth....@paranoidhost.com/ ??? Best regards and thanks again for the TLS feature ! -- --------------------------------------------------------------------------------------------------------------------- () ascii ribbon campaign - against html e-mail /\