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;

Reply via email to