On Sat, Jan 24, 2015 at 07:05:43PM -0500, Ted Unangst wrote: > I think it would be better to do as ftp(1) does and have one > command line option that sets all the options, instead of exploding > getopt() with every possibility.
I have copied the -S ssl_options from ftp(1) except CA path, which does not work with privsep. When I tested it with bad cipers it crashed because the tls connect callback was not set when the error occured. So I fixed that in buffertls_connect(). ok? 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.1 diff -u -p -r1.1 evbuffer_tls.c --- usr.sbin/syslogd/evbuffer_tls.c 18 Jan 2015 19:37:59 -0000 1.1 +++ usr.sbin/syslogd/evbuffer_tls.c 26 Jan 2015 01:40:35 -0000 @@ -287,7 +287,8 @@ buffertls_connect(struct buffertls *buft event_del(&bufev->ev_write); buftls->bt_hostname = hostname; - buffertls_connectcb(fd, 0, buftls); + event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_connectcb, buftls); + bufferevent_add(&bufev->ev_write, bufev->timeout_write); } /* Index: usr.sbin/syslogd/syslogd.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v retrieving revision 1.144 diff -u -p -r1.144 syslogd.c --- usr.sbin/syslogd/syslogd.c 19 Jan 2015 16:40:49 -0000 1.144 +++ usr.sbin/syslogd/syslogd.c 26 Jan 2015 01:48:25 -0000 @@ -141,6 +141,7 @@ struct filed { struct buffertls f_buftls; struct bufferevent *f_bufev; struct tls *f_ctx; + char *f_host; int f_reconnectwait; } f_forw; /* forwarding address */ char f_fname[PATH_MAX]; @@ -215,6 +216,25 @@ int IncludeHostname = 0; /* include RFC char *path_ctlsock = NULL; /* Path to control socket */ +char *const ssl_verify_opts[] = { +#define SSL_CAFILE 0 + "cafile", +#define SSL_CIPHERS 1 + "ciphers", +#define SSL_DONTVERIFY 2 + "dont", +#define SSL_DOVERIFY 3 + "do", +#define SSL_VERIFYDEPTH 4 + "depth", + NULL +}; +struct tls_config *tls_config; +const char *CAfile = "/etc/ssl/cert.pem"; /* file containing certificates */ +const char *Ciphers = NULL; /* list of ciphers that may be used */ +int Verify = 1; /* do verify TLS server x509 certificate */ +int Depth = -1; /* TLS verify depth */ + #define CTL_READING_CMD 1 #define CTL_WRITING_REPLY 2 #define CTL_WRITING_CONT_REPLY 3 @@ -312,11 +332,11 @@ main(int argc, char *argv[]) { struct addrinfo hints, *res, *res0; struct timeval to; - char *p; + char *cp, *p; int ch, i; int lockpipe[2] = { -1, -1}, pair[2], nullfd, fd; - while ((ch = getopt(argc, argv, "46dhnuf:m:p:a:s:")) != -1) + while ((ch = getopt(argc, argv, "46dhnuf:m:p:a:s:S:")) != -1) switch (ch) { case '4': /* disable IPv6 */ IPv4Only = 1; @@ -349,8 +369,7 @@ main(int argc, char *argv[]) break; case 'a': if (nunix >= MAXUNIX) - fprintf(stderr, "syslogd: " - "out of descriptors, ignoring %s\n", + warnx("out of descriptors, ignoring %s\n", optarg); else path_unix[nunix++] = optarg; @@ -358,6 +377,49 @@ main(int argc, char *argv[]) case 's': path_ctlsock = optarg; break; + case 'S': + cp = optarg; + while (*cp) { + char *str; + const char *errstr; + + switch (getsubopt(&cp, ssl_verify_opts, &str)) { + case SSL_CAFILE: + if (str == NULL) + warnx("missing CA file"); + else + CAfile = str; + break; + case SSL_CIPHERS: + if (str == NULL) + warnx("missing cipher list"); + else + Ciphers = str; + break; + case SSL_DONTVERIFY: + Verify = 0; + break; + case SSL_DOVERIFY: + Verify = 1; + break; + case SSL_VERIFYDEPTH: + if (str == NULL) { + warnx("missing verify depth"); + break; + } + i = strtonum(str, 0, INT_MAX, &errstr); + if (errstr) + warnx("certificate validation " + "depth is %s", errstr); + else + Depth = i; + break; + default: + warnx("unknown -S suboption `%s'", + suboptarg ? suboptarg : ""); + } + } + break; default: usage(); } @@ -495,6 +557,52 @@ main(int argc, char *argv[]) } close(pair[1]); + if (tls_init() == -1) { + logerror("tls_init"); + } else if ((tls_config = tls_config_new()) == NULL) { + logerror("tls_config_new"); + } else { + if (!Verify) { + tls_config_insecure_noverifyhost(tls_config); + tls_config_insecure_noverifycert(tls_config); + } else { + struct stat sb; + + fd = -1; + p = NULL; + errno = 0; + if ((fd = open(CAfile, O_RDONLY)) == -1) { + logerror("open CAfile"); + } else if (fstat(fd, &sb) == -1) { + logerror("fstat CAfile"); + } else if (sb.st_size > 1024*1024*1024) { + logerror("CAfile larger than 1GB"); + } 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(tls_config, p, + sb.st_size) == -1) { + logerror("tls_config_set_ca_mem"); + } else { + dprintf("CAfile %s, size %lld\n", + CAfile, sb.st_size); + } + free(p); + close(fd); + + if (Depth != -1) + tls_config_set_verify_depth(tls_config, Depth); + } + if (Ciphers) { + errno = 0; + if (tls_config_set_ciphers(tls_config, Ciphers) != 0) + logerror("tls_config_set_ciphers"); + else + dprintf("Ciphers %s\n", Ciphers); + } + } + dprintf("off & running....\n"); chdir("/"); @@ -813,8 +921,8 @@ tcp_connectcb(int fd, short event, void 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); + buffertls_connect(&f->f_un.f_forw.f_buftls, s, + f->f_un.f_forw.f_host); } return; @@ -837,39 +945,23 @@ tcp_connectcb(int fd, short event, void 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); + if (tls_config) { + if (tls_configure(ctx, tls_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); } @@ -880,7 +972,7 @@ usage(void) (void)fprintf(stderr, "usage: syslogd [-46dhnu] [-a path] [-f config_file] [-m mark_interval]\n" - " [-p log_socket] [-s reporting_socket]\n"); + " [-p log_socket] [-s reporting_socket] [-S ssl_options]\n"); exit(1); } @@ -1474,6 +1566,7 @@ init(void) tls_close(f->f_un.f_forw.f_ctx); tls_free(f->f_un.f_forw.f_ctx); } + free(f->f_un.f_forw.f_host); /* FALLTHROUGH */ case F_FORWTCP: /* XXX Save messages in output buffer for reconnect. */ @@ -1869,6 +1962,7 @@ cfline(char *line, char *prog) break; } if (strncmp(proto, "tls", 3) == 0) { + f->f_un.f_forw.f_host = strdup(host); f->f_type = F_FORWTLS; } else { f->f_type = F_FORWTCP;