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;