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
/\

Reply via email to