Hi,
With this diff, syslogd verifies the x509 certificate of the TLS
server before sending any messages to it.
Note that you also need Reyk's extensions to libtls and libssl to
use the CA file with privsep. So I will not commit before Reyk.
ok?
bluhm
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 21 Jan 2015 23:17:20 -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,10 @@ int IncludeHostname = 0; /* include RFC
char *path_ctlsock = NULL; /* Path to control socket */
+struct tls_config *tlsconfig;
+const char *CAfile = "/etc/ssl/cert.pem"; /* file containing CA certificates */
+int NoVerify = 0; /* do not verify TLS server x509 certificate */
+
#define CTL_READING_CMD 1
#define CTL_WRITING_REPLY 2
#define CTL_WRITING_CONT_REPLY 3
@@ -316,7 +321,7 @@ main(int argc, char *argv[])
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, "46C:dhnuf:m:p:a:s:V")) != -1)
switch (ch) {
case '4': /* disable IPv6 */
IPv4Only = 1;
@@ -326,6 +331,9 @@ main(int argc, char *argv[])
IPv6Only = 1;
IPv4Only = 0;
break;
+ case 'C': /* file containing CA certificates */
+ CAfile = optarg;
+ break;
case 'd': /* debug */
Debug++;
break;
@@ -358,6 +366,9 @@ main(int argc, char *argv[])
case 's':
path_ctlsock = optarg;
break;
+ case 'V': /* do not verify certificates */
+ NoVerify = 1;
+ break;
default:
usage();
}
@@ -495,6 +506,39 @@ main(int argc, char *argv[])
}
close(pair[1]);
+ if (tls_init() == -1) {
+ logerror("tls_init");
+ } else if ((tlsconfig = tls_config_new()) == NULL) {
+ logerror("tls_config_new");
+ } else if (NoVerify) {
+ tls_config_insecure_noverifyhost(tlsconfig);
+ tls_config_insecure_noverifycert(tlsconfig);
+ } 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(tlsconfig, 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);
+ }
+
dprintf("off & running....\n");
chdir("/");
@@ -813,8 +857,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 +881,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 (tlsconfig) {
+ if (tls_configure(ctx, tlsconfig) < 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);
}
@@ -879,8 +907,8 @@ usage(void)
{
(void)fprintf(stderr,
- "usage: syslogd [-46dhnu] [-a path] [-f config_file] [-m
mark_interval]\n"
- " [-p log_socket] [-s reporting_socket]\n");
+ "usage: syslogd [-46dhnuV] [-a path] [-C CAfile] [-f config_file]\n"
+ " [-m mark_interval] [-p log_socket] [-s
reporting_socket]\n");
exit(1);
}
@@ -1474,6 +1502,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 +1898,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;