On Thu, Jan 22, 2015 at 12:54:46AM +0100, Alexander Bluhm wrote:
> 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.
Reyk has commited the libtls privsep support. Any oks?
>
> 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;