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;

Reply via email to